Dashboard sipadu mbip
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

aui-scheduler-event.js 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. AUI.add('aui-scheduler-event', function(A) {
  2. var Lang = A.Lang,
  3. isString = Lang.isString,
  4. isDate = Lang.isDate,
  5. isFunction = Lang.isFunction,
  6. isObject = Lang.isObject,
  7. isBoolean = Lang.isBoolean,
  8. isNumber = Lang.isNumber,
  9. ColorUtil = A.ColorUtil,
  10. DateMath = A.DataType.DateMath,
  11. _toInitialCap = A.cached(function(str) {
  12. return str.substring(0, 1).toUpperCase() + str.substring(1);
  13. }),
  14. DASH = '-',
  15. NDASH = '–',
  16. DOT = '.',
  17. EMPTY_STR = '',
  18. SPACE = ' ',
  19. UNDERLINE = '_',
  20. _PROPAGATE_SET = '_propagateSet',
  21. ACTIVE_VIEW = 'activeView',
  22. BORDER_COLOR = 'borderColor',
  23. BORDER_COLOR_RGB = 'borderColorRGB',
  24. BORDER_STYLE = 'borderStyle',
  25. BORDER_WIDTH = 'borderWidth',
  26. CHANGE = 'Change',
  27. COLOR = 'color',
  28. COLOR_BRIGHTNESS_FACTOR = 'colorBrightnessFactor',
  29. COLOR_SATURATION_FACTOR = 'colorSaturationFactor',
  30. CONTENT = 'content',
  31. DISABLED = 'disabled',
  32. DURATION = 'duration',
  33. END_DATE = 'endDate',
  34. EVENT_CLASS = 'eventClass',
  35. EVENT_STACK = 'eventStack',
  36. EVENTS = 'events',
  37. HIDDEN = 'hidden',
  38. HSB_COLOR = 'hsbColor',
  39. ICON = 'icon',
  40. ICONS = 'icons',
  41. ID = 'id',
  42. INHERIT = 'inherit',
  43. ISO_TIME = 'isoTime',
  44. LOCALE = 'locale',
  45. NEVER = 'never',
  46. NODE = 'node',
  47. OVERLAY = 'overlay',
  48. PARENT_EVENT = 'parentEvent',
  49. RECORDER = 'recorder',
  50. REPEAT = 'repeat',
  51. REPEATED = 'repeated',
  52. REPEATED_EVENTS = 'repeatedEvents',
  53. REPEATER = 'repeater',
  54. SCHEDULER = 'scheduler',
  55. SCHEDULER_EVENT = 'scheduler-event',
  56. SCHEDULER_EVENT_RECORDER = 'scheduler-event-recorder',
  57. START_DATE = 'startDate',
  58. TEMPLATE = 'template',
  59. TITLE = 'title',
  60. TITLE_DATE_FORMAT = 'titleDateFormat',
  61. VISIBLE = 'visible',
  62. TITLE_DT_FORMAT_ISO = '%H:%M',
  63. TITLE_DT_FORMAT_US = '%I:%M',
  64. getCN = A.getClassName,
  65. CSS_ICON = getCN(ICON),
  66. CSS_SCHEDULER_EVENT = getCN(SCHEDULER_EVENT),
  67. CSS_SCHEDULER_EVENT_CONTENT = getCN(SCHEDULER_EVENT, CONTENT),
  68. CSS_SCHEDULER_EVENT_HIDDEN = getCN(SCHEDULER_EVENT, HIDDEN),
  69. CSS_SCHEDULER_EVENT_DISABLED = getCN(SCHEDULER_EVENT, DISABLED),
  70. CSS_SCHEDULER_EVENT_RECORDER = getCN(SCHEDULER_EVENT, RECORDER),
  71. CSS_SCHEDULER_EVENT_REPEATED = getCN(SCHEDULER_EVENT, REPEATED),
  72. CSS_SCHEDULER_EVENT_REPEATER = getCN(SCHEDULER_EVENT, REPEATER),
  73. CSS_SCHEDULER_EVENT_TITLE = getCN(SCHEDULER_EVENT, TITLE),
  74. CSS_SCHEDULER_EVENT_ICONS = getCN(SCHEDULER_EVENT, ICONS),
  75. CSS_SCHEDULER_EVENT_ICON_DISABLED = getCN(SCHEDULER_EVENT, ICON, DISABLED),
  76. CSS_SCHEDULER_EVENT_ICON_REPEATED = getCN(SCHEDULER_EVENT, ICON, REPEATED),
  77. CSS_SCHEDULER_EVENT_ICON_REPEATER = getCN(SCHEDULER_EVENT, ICON, REPEATER);
  78. var SchedulerEvent = A.Component.create({
  79. NAME: SCHEDULER_EVENT,
  80. ATTRS: {
  81. allDay: {
  82. setter: A.DataType.Boolean.parse,
  83. value: false
  84. },
  85. borderStyle: {
  86. value: 'solid',
  87. validator: isString
  88. },
  89. borderWidth: {
  90. value: '1px',
  91. validator: isString
  92. },
  93. colorBrightnessFactor: {
  94. value: 0.75,
  95. validator: isNumber
  96. },
  97. colorSaturationFactor: {
  98. value: 1.5,
  99. validator: isNumber
  100. },
  101. content: {
  102. value: '(no title)',
  103. validator: isString
  104. },
  105. color: {
  106. lazyAdd: false,
  107. setter: '_setColor',
  108. value: '#D96666',
  109. validator: isString
  110. },
  111. titleDateFormat: {
  112. getter: '_getTitleDateFormat',
  113. validator: isString
  114. },
  115. endDate: {
  116. setter: '_setDate',
  117. valueFn: function() {
  118. var date = DateMath.clone(this.get(START_DATE));
  119. date.setHours(date.getHours() + 1);
  120. return date;
  121. }
  122. },
  123. eventClass: {
  124. valueFn: function() {
  125. return A.SchedulerEvent;
  126. }
  127. },
  128. disabled: {
  129. value: false,
  130. validator: isBoolean
  131. },
  132. node: {
  133. valueFn: function() {
  134. return A.NodeList.create(A.Node.create(this.EVENT_NODE_TEMPLATE).setData(SCHEDULER_EVENT, this));
  135. }
  136. },
  137. parentEvent: {
  138. },
  139. repeat: {
  140. value: EMPTY_STR,
  141. setter: '_setRepeat'
  142. },
  143. scheduler: {
  144. lazyAdd: false,
  145. setter: '_setScheduler'
  146. },
  147. startDate: {
  148. setter: '_setDate',
  149. valueFn: function() {
  150. return new Date();
  151. }
  152. },
  153. visible: {
  154. value: true,
  155. validator: isBoolean
  156. }
  157. },
  158. EXTENDS: A.Base,
  159. PROPAGATE_ATTRS: [START_DATE, END_DATE, CONTENT, COLOR, COLOR_BRIGHTNESS_FACTOR, COLOR_SATURATION_FACTOR, BORDER_STYLE, BORDER_WIDTH, TITLE_DATE_FORMAT, VISIBLE, DISABLED],
  160. prototype: {
  161. EVENT_NODE_TEMPLATE: '<div class="' + CSS_SCHEDULER_EVENT + '">' +
  162. '<div class="' + CSS_SCHEDULER_EVENT_TITLE + '"></div>' +
  163. '<div class="' + CSS_SCHEDULER_EVENT_CONTENT + '"></div>' +
  164. '<div class="' + CSS_SCHEDULER_EVENT_ICONS + '">' +
  165. '<span class="' + [CSS_ICON, CSS_SCHEDULER_EVENT_ICON_REPEATED].join(SPACE) + '"></span>' +
  166. '<span class="' + [CSS_ICON, CSS_SCHEDULER_EVENT_ICON_REPEATER].join(SPACE) + '"></span>' +
  167. '<span class="' + [CSS_ICON, CSS_SCHEDULER_EVENT_ICON_DISABLED].join(SPACE) + '"></span>' +
  168. '</div>' +
  169. '</div>',
  170. eventStack: null,
  171. initializer: function() {
  172. var instance = this;
  173. var node = instance.get(NODE);
  174. instance[EVENT_STACK] = {};
  175. A.Array.each(instance.get(EVENT_CLASS).PROPAGATE_ATTRS, function(attrName) {
  176. instance.after(attrName+CHANGE, instance._propagateAttrChange);
  177. });
  178. instance._bindUIAttrs();
  179. instance.syncNodeUI(true);
  180. },
  181. destroy: function() {
  182. var instance = this;
  183. instance.eachRepeatedEvent(function(evt, uid) {
  184. evt.destroy();
  185. });
  186. instance[EVENT_STACK] = {};
  187. instance.get(NODE).remove(true);
  188. },
  189. addPaddingNode: function() {
  190. var instance = this;
  191. instance.get(NODE).push(A.Node.create(instance.EVENT_NODE_TEMPLATE).setData(SCHEDULER_EVENT, instance));
  192. instance.syncNodeUI();
  193. },
  194. copyDates: function(evt) {
  195. var instance = this;
  196. instance.set(END_DATE, DateMath.clone(evt.get(END_DATE)));
  197. instance.set(START_DATE, DateMath.clone(evt.get(START_DATE)));
  198. },
  199. copyPropagateAttrValues: function(evt, dontCopyMap) {
  200. var instance = this;
  201. instance.copyDates(evt);
  202. A.Array.each(instance.get(EVENT_CLASS).PROPAGATE_ATTRS, function(attrName) {
  203. if ( !((dontCopyMap || {}).hasOwnProperty(attrName)) ) {
  204. var value = evt.get(attrName);
  205. if (!isObject(value)) {
  206. instance.set(attrName, value);
  207. }
  208. }
  209. });
  210. },
  211. getBorderColor: function() {
  212. var instance = this;
  213. return instance[BORDER_COLOR_RGB].hex;
  214. },
  215. getDaysDuration: function() {
  216. var instance = this;
  217. return DateMath.getDayOffset(
  218. instance.get(END_DATE), instance.get(START_DATE));
  219. },
  220. getHoursDuration: function() {
  221. var instance = this;
  222. return DateMath.getHoursOffset(
  223. instance.get(END_DATE), instance.get(START_DATE));
  224. },
  225. getMinutesDuration: function() {
  226. var instance = this;
  227. return DateMath.getMinutesOffset(
  228. instance.get(END_DATE), instance.get(START_DATE));
  229. },
  230. getSecondsDuration: function() {
  231. var instance = this;
  232. return DateMath.getSecondsOffset(
  233. instance.get(END_DATE), instance.get(START_DATE));
  234. },
  235. sameEndDate: function(evt) {
  236. var instance = this;
  237. return DateMath.compare(instance.get(END_DATE), evt.get(END_DATE));
  238. },
  239. sameStartDate: function(evt) {
  240. var instance = this;
  241. return DateMath.compare(
  242. instance.get(START_DATE), evt.get(START_DATE));
  243. },
  244. isAfter: function(evt) {
  245. var instance = this;
  246. var startDate = instance.get(START_DATE);
  247. var evtStartDate = evt.get(START_DATE);
  248. return DateMath.after(startDate, evtStartDate);
  249. },
  250. isBefore: function(evt) {
  251. var instance = this;
  252. var startDate = instance.get(START_DATE);
  253. var evtStartDate = evt.get(START_DATE);
  254. return DateMath.before(startDate, evtStartDate);
  255. },
  256. repeatByDate: function(date) {
  257. var instance = this;
  258. var uid = instance.uidByDate(date);
  259. if (!instance[EVENT_STACK][uid]) {
  260. var startDate = DateMath.clone(date);
  261. var endDate = DateMath.clone(date);
  262. DateMath.copyHours(startDate, instance.get(START_DATE));
  263. DateMath.copyHours(endDate, instance.get(END_DATE));
  264. var newEvt = new instance.get(EVENT_CLASS)({
  265. endDate: endDate,
  266. parentEvent: instance,
  267. scheduler: instance.get(SCHEDULER),
  268. startDate: startDate
  269. });
  270. newEvt.copyPropagateAttrValues(instance);
  271. instance[EVENT_STACK][uid] = newEvt;
  272. }
  273. return instance[EVENT_STACK][uid];
  274. },
  275. intersects: function(evt) {
  276. var instance = this;
  277. var endDate = instance.get(END_DATE);
  278. var startDate = instance.get(START_DATE);
  279. var evtStartDate = evt.get(START_DATE);
  280. return (instance.sameStartDate(evt) ||
  281. DateMath.between(evtStartDate, startDate, endDate));
  282. },
  283. intersectHours: function(evt) {
  284. var instance = this;
  285. var endDate = instance.get(END_DATE);
  286. var startDate = instance.get(START_DATE);
  287. var evtModifiedStartDate = DateMath.clone(startDate);
  288. DateMath.copyHours(evtModifiedStartDate, evt.get(START_DATE));
  289. return (DateMath.compare(startDate, evtModifiedStartDate) ||
  290. DateMath.between(evtModifiedStartDate, startDate, endDate));
  291. },
  292. isDayBoundaryEvent: function() {
  293. var instance = this;
  294. return DateMath.isDayBoundary(
  295. instance.get(START_DATE), instance.get(END_DATE));
  296. },
  297. isDayOverlapEvent: function() {
  298. var instance = this;
  299. return DateMath.isDayOverlap(
  300. instance.get(START_DATE), instance.get(END_DATE));
  301. },
  302. isRepeatableDate: function(date) {
  303. var instance = this;
  304. var repeat = instance.get(REPEAT);
  305. return (repeat && repeat.validate(instance, date));
  306. },
  307. getClearEndDate: function() {
  308. var instance = this;
  309. return DateMath.safeClearTime(instance.get(END_DATE));
  310. },
  311. getClearStartDate: function() {
  312. var instance = this;
  313. return DateMath.safeClearTime(instance.get(START_DATE));
  314. },
  315. move: function(date) {
  316. var instance = this;
  317. var duration = instance.getMinutesDuration();
  318. instance.set(START_DATE, date);
  319. instance.set(END_DATE, DateMath.add(DateMath.clone(date), DateMath.MINUTES, duration));
  320. },
  321. uidByDate: function(date) {
  322. var instance = this;
  323. date = isDate(date) ?
  324. DateMath.safeClearTime(date) : instance.getClearStartDate();
  325. return [SCHEDULER_EVENT, date.getTime()].join(UNDERLINE);
  326. },
  327. setContent: function(content, propagate) {
  328. var instance = this;
  329. instance.get(NODE).each(function(node) {
  330. var contentNode = node.one(_DOT+CSS_SCHEDULER_EVENT_CONTENT);
  331. contentNode.setContent(content);
  332. });
  333. if (propagate) {
  334. instance.eachRepeatedEvent(function(evt, uid) {
  335. evt.setContent(content);
  336. });
  337. }
  338. },
  339. setTitle: function(content, propagate) {
  340. var instance = this;
  341. instance.get(NODE).each(function(node) {
  342. var titleNode = node.one(_DOT+CSS_SCHEDULER_EVENT_TITLE);
  343. titleNode.setContent(content);
  344. });
  345. if (propagate) {
  346. instance.eachRepeatedEvent(function(evt, uid) {
  347. evt.setTitle(content);
  348. });
  349. }
  350. },
  351. syncNodeUI: function(propagate) {
  352. var instance = this;
  353. instance._syncUIAttrs();
  354. instance.syncNodeColorUI(propagate);
  355. instance.syncNodeTitleUI(propagate);
  356. instance.syncNodeContentUI(propagate);
  357. },
  358. syncNodeColorUI: function(propagate) {
  359. var instance = this;
  360. var node = instance.get(NODE);
  361. var borderColor = instance.getBorderColor();
  362. if (node) {
  363. var styles = {
  364. borderWidth: instance.get(BORDER_WIDTH),
  365. borderColor: borderColor,
  366. backgroundColor: instance.get(COLOR),
  367. borderStyle: instance.get(BORDER_STYLE),
  368. color: INHERIT
  369. };
  370. node.setStyles(styles);
  371. }
  372. if (propagate) {
  373. instance.eachRepeatedEvent(function(evt, uid) {
  374. evt.syncNodeColorUI();
  375. });
  376. }
  377. },
  378. syncNodeContentUI: function(propagate) {
  379. var instance = this;
  380. instance.setContent(instance.get(CONTENT), propagate);
  381. },
  382. syncNodeTitleUI: function(propagate) {
  383. var instance = this;
  384. var sDate = instance._formatDate(instance.get(START_DATE));
  385. var eDate = instance._formatDate(instance.get(END_DATE));
  386. instance.setTitle([sDate, eDate].join(SPACE+NDASH+SPACE), propagate);
  387. },
  388. split: function() {
  389. var instance = this,
  390. s1 = DateMath.clone(instance.get(START_DATE)),
  391. e1 = DateMath.clone(instance.get(END_DATE));
  392. if (instance.isDayOverlapEvent() && !instance.isDayBoundaryEvent()) {
  393. var s2 = DateMath.clone(s1);
  394. s2.setHours(24,0,0,0);
  395. return [ [ s1, DateMath.toMidnight(DateMath.clone(s1)) ], [ s2, DateMath.clone(e1) ] ];
  396. }
  397. return [ [ s1, e1 ] ];
  398. },
  399. eachRepeatedEvent: function(fn) {
  400. var instance = this;
  401. A.each(instance[EVENT_STACK], fn, instance);
  402. },
  403. unlink: function() {
  404. var instance = this;
  405. if (instance.get(PARENT_EVENT)) {
  406. instance.set(PARENT_EVENT, null);
  407. }
  408. else {
  409. instance.eachRepeatedEvent(function(evt, uid) {
  410. evt.unlink();
  411. });
  412. }
  413. instance[EVENT_STACK] = {};
  414. instance.syncNodeUI();
  415. },
  416. _afterDisabledChange: function(event) {
  417. var instance = this;
  418. instance._uiSetDisabled(event.newVal);
  419. },
  420. _afterVisibleChange: function(event) {
  421. var instance = this;
  422. instance._uiSetVisible(event.newVal);
  423. },
  424. _afterRepeatChange: function(event) {
  425. var instance = this;
  426. instance._uiSetRepeat(event.newVal);
  427. },
  428. _afterParentEventChange: function(event) {
  429. var instance = this;
  430. instance._uiSetParentEvent(event.newVal);
  431. },
  432. _bindUIAttrs: function() {
  433. var instance = this;
  434. instance.after({
  435. disabledChange: instance._afterDisabledChange,
  436. visibleChange: instance._afterVisibleChange,
  437. parentEventChange: instance._afterParentEventChange,
  438. repeatChange: instance._afterRepeatChange
  439. });
  440. instance._syncUIAttrs();
  441. },
  442. _propagateAttrChange: function(event) {
  443. var instance = this;
  444. var attrName = event.attrName;
  445. var newVal = event.newVal;
  446. instance.eachRepeatedEvent(function(evt, uid) {
  447. var propFn = evt[_PROPAGATE_SET+_toInitialCap(attrName)];
  448. if (propFn) {
  449. propFn.apply(instance, [evt, attrName, newVal]);
  450. }
  451. else {
  452. evt.set(attrName, event.newVal);
  453. }
  454. evt.syncNodeUI();
  455. });
  456. instance.syncNodeUI();
  457. },
  458. _propagateSetEndDate: function(evt, attrName, val) {
  459. var endDate = DateMath.clone(evt.get(END_DATE));
  460. DateMath.copyHours(endDate, val);
  461. evt.set(END_DATE, endDate);
  462. },
  463. _propagateSetStartDate: function(evt, attrName, val) {
  464. var startDate = DateMath.clone(evt.get(START_DATE));
  465. DateMath.copyHours(startDate, val);
  466. evt.set(START_DATE, startDate);
  467. },
  468. _setColor: function(val) {
  469. var instance = this;
  470. instance[HSB_COLOR] = ColorUtil.rgb2hsb(ColorUtil.getRGB(val));
  471. instance[BORDER_COLOR] = A.clone(instance[HSB_COLOR]);
  472. instance[BORDER_COLOR].b *= instance.get(COLOR_BRIGHTNESS_FACTOR);
  473. instance[BORDER_COLOR].s *= instance.get(COLOR_SATURATION_FACTOR);
  474. instance[BORDER_COLOR_RGB] = ColorUtil.hsb2rgb(instance[BORDER_COLOR]);
  475. return val;
  476. },
  477. _setDate: function(val) {
  478. var instance = this;
  479. if (isNumber(val)) {
  480. val = new Date(val);
  481. }
  482. return val;
  483. },
  484. _setRepeat: function(val) {
  485. var instance = this;
  486. if (isString(val)) {
  487. val = A.SchedulerEventRepeat[val];
  488. }
  489. return isObject(val) ? val : null;
  490. },
  491. _setScheduler: function(val) {
  492. var instance = this;
  493. var scheduler = instance.get(SCHEDULER);
  494. if (scheduler) {
  495. instance.removeTarget(scheduler);
  496. }
  497. instance.addTarget(val);
  498. return val;
  499. },
  500. _syncUIAttrs: function() {
  501. var instance = this;
  502. instance._uiSetDisabled(
  503. instance.get(DISABLED)
  504. );
  505. instance._uiSetVisible(
  506. instance.get(VISIBLE)
  507. );
  508. instance._uiSetParentEvent(
  509. instance.get(PARENT_EVENT)
  510. );
  511. instance._uiSetRepeat(
  512. instance.get(REPEAT)
  513. );
  514. },
  515. _formatDate: function(date, format) {
  516. var instance = this;
  517. var locale = instance.get(LOCALE);
  518. format = format || instance.get(TITLE_DATE_FORMAT);
  519. return A.DataType.Date.format(date, {
  520. format: format,
  521. locale: locale
  522. });
  523. },
  524. _getTitleDateFormat: function(val) {
  525. var instance = this;
  526. if (!isString(val)) {
  527. var scheduler = instance.get(SCHEDULER);
  528. val = (scheduler && scheduler.get(ACTIVE_VIEW).get(ISO_TIME)) ? TITLE_DT_FORMAT_ISO : TITLE_DT_FORMAT_US;
  529. }
  530. return val;
  531. },
  532. _uiSetDisabled: function(val) {
  533. var instance = this;
  534. instance.get(NODE).toggleClass(CSS_SCHEDULER_EVENT_DISABLED, !!val);
  535. },
  536. _uiSetParentEvent: function(val) {
  537. var instance = this;
  538. instance.get(NODE).toggleClass(CSS_SCHEDULER_EVENT_REPEATED, !!val);
  539. },
  540. _uiSetRepeat: function(val) {
  541. var instance = this;
  542. var value = !!val && val !== A.SchedulerEventRepeat[NEVER];
  543. instance.get(NODE).toggleClass(CSS_SCHEDULER_EVENT_REPEATER, value);
  544. },
  545. _uiSetVisible: function(val) {
  546. var instance = this;
  547. instance.get(NODE).toggleClass(CSS_SCHEDULER_EVENT_HIDDEN, !val);
  548. }
  549. }
  550. });
  551. A.SchedulerEvent = SchedulerEvent;
  552. A.SchedulerEventRepeat = {
  553. never: {
  554. description: 'Never repeat',
  555. validate: function(evt, date) {
  556. return false;
  557. },
  558. value: 'never'
  559. },
  560. daily: {
  561. description: 'Every day',
  562. validate: function(evt, date) {
  563. return true;
  564. },
  565. value: 'daily'
  566. },
  567. monthly: {
  568. description: 'Every month',
  569. validate: function(evt, date) {
  570. var endDate = evt.get(END_DATE);
  571. var startDate = evt.get(START_DATE);
  572. return (startDate.getDate() === date.getDate());
  573. },
  574. value: 'monthly'
  575. },
  576. monWedFri: {
  577. description: 'Every Monday, Wednesday and Friday',
  578. validate: function(evt, date) {
  579. return DateMath.isMonWedOrFri(date);
  580. },
  581. value: 'monWedFri'
  582. },
  583. tuesThurs: {
  584. description: 'Every Tuesday and Thursday',
  585. validate: function(evt, date) {
  586. return DateMath.isTueOrThu(date);
  587. },
  588. value: 'tuesThurs'
  589. },
  590. weekDays: {
  591. description: 'Every week days',
  592. validate: function(evt, date) {
  593. return DateMath.isWeekDay(date);
  594. },
  595. value: 'weekDays'
  596. },
  597. weekly: {
  598. description: 'Every week',
  599. validate: function(evt, date) {
  600. var endDate = evt.get(END_DATE);
  601. var startDate = evt.get(START_DATE);
  602. return (startDate.getDay() === date.getDay());
  603. },
  604. value: 'weekly'
  605. },
  606. yearly: {
  607. description: 'Every year',
  608. validate: function(evt, date) {
  609. var endDate = evt.get(END_DATE);
  610. var startDate = evt.get(START_DATE);
  611. return ((startDate.getMonth() === date.getMonth()) && (startDate.getDay() === date.getDay()));
  612. },
  613. value: 'yearly'
  614. }
  615. };
  616. var L = A.Lang,
  617. isArray = L.isArray,
  618. isObject = L.isObject,
  619. ACTIVE_VIEW = 'activeView',
  620. ALL_DAY = 'allDay',
  621. ARROW = 'arrow',
  622. BODY = 'body',
  623. BODY_CONTENT = 'bodyContent',
  624. BOUNDING_BOX = 'boundingBox',
  625. CANCEL = 'cancel',
  626. CLICK = 'click',
  627. CONTENT = 'content',
  628. DATE = 'date',
  629. DATE_FORMAT = 'dateFormat',
  630. DELETE = 'delete',
  631. DESCRIPTION = 'description',
  632. EDIT = 'edit',
  633. EVENT = 'event',
  634. EVENT_CLASS = 'eventClass',
  635. FOOTER_CONTENT = 'footerContent',
  636. FORM = 'form',
  637. HEADER = 'header',
  638. HIDE = 'hide',
  639. ISO_TIME = 'isoTime',
  640. LINK = 'link',
  641. NODE = 'node',
  642. OFFSET_HEIGHT = 'offsetHeight',
  643. OFFSET_WIDTH = 'offsetWidth',
  644. OVERLAY = 'overlay',
  645. OVERLAY_OFFSET = 'overlayOffset',
  646. RECORDER = 'recorder',
  647. RENDERED = 'rendered',
  648. REPEAT = 'repeat',
  649. SAVE = 'save',
  650. SCHEDULER = 'scheduler',
  651. SCHEDULER_CHANGE = 'schedulerChange',
  652. SCHEDULER_EVENT = 'scheduler-event',
  653. SCHEDULER_EVENT_RECORDER = 'scheduler-event-recorder',
  654. SHADOW = 'shadow',
  655. SHOW = 'show',
  656. START_DATE_CHANGE = 'startDateChange',
  657. STRINGS = 'strings',
  658. TEMPLATE = 'template',
  659. TITLE = 'title',
  660. TL = 'tl',
  661. TOOLBAR = 'toolbar',
  662. SUBMIT = 'submit',
  663. VALUE = 'value',
  664. VISIBLE_CHANGE = 'visibleChange',
  665. WHEN = 'when',
  666. X = 'x',
  667. Y = 'y',
  668. EV_SCHEDULER_EVENT_RECORDER_CANCEL = 'cancel',
  669. EV_SCHEDULER_EVENT_RECORDER_DELETE = 'delete',
  670. EV_SCHEDULER_EVENT_RECORDER_EDIT = 'edit',
  671. EV_SCHEDULER_EVENT_RECORDER_SAVE = 'save',
  672. _DASH = '-',
  673. _DOT = '.',
  674. _EMPTY_STR = '',
  675. _POUND = '#',
  676. _serialize = A.IO.prototype._serialize,
  677. getCN = A.getClassName,
  678. CSS_SCHEDULER_EVENT = getCN(SCHEDULER, EVENT),
  679. CSS_SCHEDULER_EVENT_RECORDER = getCN(SCHEDULER, EVENT, RECORDER),
  680. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY),
  681. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_ARROW = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, ARROW),
  682. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_ARROW_SHADOW = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, ARROW, SHADOW),
  683. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_BODY = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, BODY),
  684. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_CONTENT = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, CONTENT),
  685. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_DATE = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, DATE),
  686. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_FORM = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, FORM),
  687. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_HEADER = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, HEADER),
  688. CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_REPEAT = getCN(SCHEDULER, EVENT, RECORDER, OVERLAY, REPEAT),
  689. CSS_SCHEDULER_EVENT_TITLE = getCN(SCHEDULER, EVENT, TITLE),
  690. TPL_OVERLAY_BODY_CONTENT = new A.Template(
  691. '<div class="', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_ARROW_SHADOW, ' ', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_ARROW, '"></div>',
  692. '<div class="', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_ARROW, '"></div>',
  693. '<input type="hidden" name="startDate" value="{startDate}" />',
  694. '<input type="hidden" name="endDate" value="{endDate}" />',
  695. '<div class="', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_HEADER, '">',
  696. '<input class="', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_CONTENT, '" name="content" value="{content}" />',
  697. '</div>',
  698. '<div class="', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_BODY, '">',
  699. '<label class="', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_DATE, '">{date}</label>',
  700. '<select class="', CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_REPEAT, '" name="repeat">',
  701. '<tpl for="eventRepeat">',
  702. '<option {[ (parent.repeat && parent.repeat.value) == parent.eventRepeat[$i].value ? \'selected="selected"\' : "" ]} value="{value}">{description}</option>',
  703. '</tpl>',
  704. '</select>',
  705. '</div>'
  706. ),
  707. TPL_OVERLAY_FORM = '<form class="' + CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_FORM + '" id="schedulerEventRecorderForm"></form>';
  708. var SchedulerEventRecorder = A.Component.create({
  709. NAME: SCHEDULER_EVENT_RECORDER,
  710. ATTRS: {
  711. allDay: {
  712. value: false
  713. },
  714. content: {
  715. value: _EMPTY_STR
  716. },
  717. duration: {
  718. value: 60
  719. },
  720. dateFormat: {
  721. validator: isString,
  722. value: '%a, %B %d,'
  723. },
  724. event: {
  725. },
  726. eventClass: {
  727. valueFn: function() {
  728. return A.SchedulerEvent;
  729. }
  730. },
  731. strings: {
  732. value: {},
  733. setter: function(val) {
  734. return A.merge(
  735. {
  736. 'delete': 'Delete',
  737. 'description-hint': 'e.g., Dinner at Brian\'s',
  738. 'no-repeat': 'No repeat',
  739. cancel: 'Cancel',
  740. description: 'Description',
  741. edit: 'Edit',
  742. repeat: 'Repeat',
  743. save: 'Save',
  744. when: 'When'
  745. },
  746. val || {}
  747. );
  748. },
  749. validator: isObject
  750. },
  751. overlay: {
  752. validator: isObject,
  753. value: {
  754. align: {
  755. points: [ TL, TL ]
  756. },
  757. visible: false,
  758. width: 300,
  759. zIndex: 500
  760. }
  761. },
  762. // See #2530972
  763. overlayOffset: {
  764. value: [15, -38],
  765. validator: isArray
  766. },
  767. template: {
  768. value: TPL_OVERLAY_BODY_CONTENT
  769. },
  770. toolbar: {
  771. setter: function(val) {
  772. var instance = this;
  773. var strings = instance.get(STRINGS);
  774. return A.merge({
  775. children: [
  776. {
  777. handler: A.bind(instance._handleSaveEvent, instance),
  778. label: strings[SAVE]
  779. },
  780. {
  781. handler: A.bind(instance._handleCancelEvent, instance),
  782. label: strings[CANCEL]
  783. },
  784. {
  785. handler: A.bind(instance._handleDeleteEvent, instance),
  786. label: strings[DELETE]
  787. }
  788. ]
  789. }, val || {});
  790. },
  791. validator: isObject,
  792. value: {}
  793. }
  794. },
  795. EXTENDS: A.SchedulerEvent,
  796. prototype: {
  797. initializer: function() {
  798. var instance = this;
  799. instance.get(NODE).addClass(CSS_SCHEDULER_EVENT_RECORDER);
  800. instance.publish(EV_SCHEDULER_EVENT_RECORDER_CANCEL, {
  801. defaultFn: instance._defCancelEventFn
  802. });
  803. instance.publish(EV_SCHEDULER_EVENT_RECORDER_DELETE, {
  804. defaultFn: instance._defDeleteEventFn
  805. });
  806. instance.publish(EV_SCHEDULER_EVENT_RECORDER_EDIT, {
  807. defaultFn: instance._defEditEventFn
  808. });
  809. instance.publish(EV_SCHEDULER_EVENT_RECORDER_SAVE, {
  810. defaultFn: instance._defSaveEventFn
  811. });
  812. instance.after(SCHEDULER_CHANGE, instance._afterSchedulerChange);
  813. instance[OVERLAY] = new A.Overlay(instance.get(OVERLAY));
  814. instance[TOOLBAR] = new A.Toolbar(instance.get(TOOLBAR));
  815. },
  816. _afterSchedulerChange: function(event) {
  817. var instance = this;
  818. var scheduler = event.newVal;
  819. var schedulerBB = scheduler.get(BOUNDING_BOX);
  820. schedulerBB.delegate(CLICK, A.bind(instance._onClickSchedulerEvent, instance), _DOT + CSS_SCHEDULER_EVENT);
  821. },
  822. _defCancelEventFn: function(event) {
  823. var instance = this;
  824. instance.get(NODE).remove();
  825. instance.hideOverlay();
  826. },
  827. _defDeleteEventFn: function(event) {
  828. var instance = this;
  829. var scheduler = instance.get(SCHEDULER);
  830. scheduler.removeEvent(instance.get(EVENT));
  831. instance.hideOverlay();
  832. scheduler.syncEventsUI();
  833. },
  834. _defEditEventFn: function(event) {
  835. var instance = this;
  836. var scheduler = instance.get(SCHEDULER);
  837. instance.hideOverlay();
  838. scheduler.syncEventsUI();
  839. },
  840. _defSaveEventFn: function(event) {
  841. var instance = this;
  842. var scheduler = instance.get(SCHEDULER);
  843. scheduler.addEvent(event.newSchedulerEvent);
  844. instance.hideOverlay();
  845. scheduler.syncEventsUI();
  846. },
  847. _handleCancelEvent: function(event) {
  848. var instance = this;
  849. instance.fire(EV_SCHEDULER_EVENT_RECORDER_CANCEL);
  850. event.preventDefault();
  851. },
  852. _handleDeleteEvent: function(event) {
  853. var instance = this;
  854. instance.fire(EV_SCHEDULER_EVENT_RECORDER_DELETE, {
  855. schedulerEvent: instance.get(EVENT)
  856. });
  857. event.preventDefault();
  858. },
  859. _handleSaveEvent: function(event) {
  860. var instance = this;
  861. instance.fire(
  862. instance.get(EVENT) ? EV_SCHEDULER_EVENT_RECORDER_EDIT : EV_SCHEDULER_EVENT_RECORDER_SAVE,
  863. {
  864. newSchedulerEvent: instance.getEventCopy()
  865. }
  866. );
  867. event.preventDefault();
  868. },
  869. _onClickSchedulerEvent: function(event) {
  870. var instance = this;
  871. var evt = event.currentTarget.getData(SCHEDULER_EVENT);
  872. if (evt) {
  873. instance.set(EVENT, evt);
  874. instance.showOverlay([event.pageX, event.pageY]);
  875. instance.get(NODE).remove();
  876. }
  877. },
  878. _onOverlayVisibleChange: function(event) {
  879. var instance = this;
  880. if (event.newVal) {
  881. instance.populateForm();
  882. if (!instance.get(EVENT)) {
  883. var overlayBB = instance[OVERLAY].get(BOUNDING_BOX);
  884. var contentNode = overlayBB.one(_DOT + CSS_SCHEDULER_EVENT_RECORDER_OVERLAY_CONTENT);
  885. setTimeout(function() {
  886. contentNode.selectText();
  887. }, 0);
  888. }
  889. }
  890. else {
  891. instance.set(EVENT, null);
  892. instance.get(NODE).remove();
  893. }
  894. },
  895. _onSubmitForm: function(event) {
  896. var instance = this;
  897. instance._handleSaveEvent(event);
  898. },
  899. _renderOverlay: function() {
  900. var instance = this;
  901. var strings = instance.get(STRINGS);
  902. instance[OVERLAY].render();
  903. instance[TOOLBAR].render();
  904. var overlayBB = instance[OVERLAY].get(BOUNDING_BOX);
  905. overlayBB.addClass(CSS_SCHEDULER_EVENT_RECORDER_OVERLAY);
  906. instance[OVERLAY].set(FOOTER_CONTENT, instance[TOOLBAR].get(BOUNDING_BOX));
  907. instance[OVERLAY].on(VISIBLE_CHANGE, A.bind(instance._onOverlayVisibleChange, instance));
  908. instance.formNode = A.Node.create(TPL_OVERLAY_FORM);
  909. instance[OVERLAY].set(BODY_CONTENT, instance.formNode);
  910. instance.formNode.on(SUBMIT, A.bind(instance._onSubmitForm, instance));
  911. },
  912. getEventCopy: function() {
  913. var instance = this;
  914. var newEvt = instance.get(EVENT);
  915. if (!newEvt) {
  916. newEvt = new (instance.get(EVENT_CLASS))({
  917. allDay: instance.get(ALL_DAY),
  918. endDate: instance.get(END_DATE),
  919. scheduler: instance.get(SCHEDULER),
  920. startDate: instance.get(START_DATE)
  921. });
  922. // copying propagatable attrs
  923. newEvt.copyPropagateAttrValues(instance, { content: true });
  924. }
  925. var values = instance.serializeForm();
  926. newEvt.set(CONTENT, values[CONTENT]);
  927. newEvt.set(REPEAT, values[REPEAT]);
  928. return newEvt;
  929. },
  930. getFormattedDate: function() {
  931. var instance = this;
  932. var dateFormat = instance.get(DATE_FORMAT);
  933. var evt = (instance.get(EVENT) || instance);
  934. var endDate = evt.get(END_DATE);
  935. var scheduler = evt.get(SCHEDULER);
  936. var startDate = evt.get(START_DATE);
  937. var fmtHourFn = (scheduler.get(ACTIVE_VIEW).get(ISO_TIME) ? DateMath.toIsoTimeString : DateMath.toUsTimeString);
  938. return [ evt._formatDate(startDate, dateFormat), fmtHourFn(startDate), DASH, fmtHourFn(endDate) ].join(SPACE);
  939. },
  940. getTemplateData: function() {
  941. var instance = this;
  942. var strings = instance.get(STRINGS);
  943. var evt = (instance.get(EVENT) || instance);
  944. return {
  945. content: evt.get(CONTENT) || strings['description-hint'],
  946. date: instance.getFormattedDate(),
  947. endDate: evt.get(END_DATE).getTime(),
  948. eventRepeat: instance.eventRepeatArray,
  949. repeat: evt.get(REPEAT),
  950. startDate: evt.get(START_DATE).getTime()
  951. };
  952. },
  953. hideOverlay: function() {
  954. var instance = this;
  955. instance[OVERLAY].hide();
  956. },
  957. populateForm: function() {
  958. var instance = this;
  959. if (!instance.eventRepeatArray) {
  960. instance.eventRepeatArray = [];
  961. A.each(A.SchedulerEventRepeat, function(item) {
  962. instance.eventRepeatArray.push({
  963. description: item[DESCRIPTION],
  964. value: item[VALUE]
  965. });
  966. });
  967. }
  968. instance.formNode.setContent(
  969. instance.get(TEMPLATE).parse(instance.getTemplateData())
  970. );
  971. },
  972. serializeForm: function() {
  973. var instance = this;
  974. return A.QueryString.parse(_serialize(instance.formNode.getDOM()));
  975. },
  976. showOverlay: function(xy, offset) {
  977. var instance = this;
  978. var defaultOffset = instance.get(OVERLAY_OFFSET);
  979. if (!instance[OVERLAY].get(RENDERED)) {
  980. instance._renderOverlay();
  981. }
  982. instance[OVERLAY].show();
  983. if (!xy) {
  984. var eventNode = (instance.get(EVENT) || instance).get(NODE);
  985. var titleNode = eventNode.one(_DOT + CSS_SCHEDULER_EVENT_TITLE);
  986. offset = [defaultOffset[0] + titleNode.get(OFFSET_WIDTH), defaultOffset[1] + titleNode.get(OFFSET_HEIGHT) / 2];
  987. xy = titleNode.getXY();
  988. }
  989. // Since #2530972 is not yet done, manually putting an offset to the alignment
  990. offset = offset || defaultOffset;
  991. xy[0] += offset[0];
  992. xy[1] += offset[1];
  993. instance[OVERLAY].set('xy', xy);
  994. }
  995. }
  996. });
  997. A.SchedulerEventRecorder = SchedulerEventRecorder;
  998. }, '@VERSION@' ,{skinnable:true, requires:['aui-base','aui-color-util','aui-datatype','aui-template','aui-toolbar','io-form','querystring','overlay']});