Dashboard sipadu mbip
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

aui-scheduler-base-debug.js 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. AUI.add('aui-scheduler-base', function(A) {
  2. var Lang = A.Lang,
  3. isString = Lang.isString,
  4. isArray = Lang.isArray,
  5. isDate = Lang.isDate,
  6. isFunction = Lang.isFunction,
  7. isNumber = Lang.isNumber,
  8. isObject = Lang.isObject,
  9. isScheduler = function(val) {
  10. return (val instanceof A.Scheduler);
  11. },
  12. isSchedulerView = function(val) {
  13. return (val instanceof A.SchedulerView);
  14. },
  15. isSchedulerEvent = function(val) {
  16. return (val instanceof A.SchedulerEvent);
  17. },
  18. isSchedulerCalendar = function(val) {
  19. return (A.SchedulerCalendar && (val instanceof A.SchedulerCalendar));
  20. },
  21. DateMath = A.DataType.DateMath,
  22. WidgetStdMod = A.WidgetStdMod,
  23. DOT = '.',
  24. EMPTY_STR = '',
  25. SPACE = ' ',
  26. SCHEDULER_BASE = 'scheduler-base',
  27. DATA_VIEW_NAME = 'data-view-name',
  28. ACTIVE_VIEW = 'activeView',
  29. CLEARFIX = 'clearfix',
  30. CONTROLS = 'controls',
  31. CONTROLS_NODE = 'controlsNode',
  32. CURRENT = 'current',
  33. CURRENT_DATE = 'currentDate',
  34. CURRENT_DATE_NODE = 'currentDateNode',
  35. DATE = 'date',
  36. END_DATE = 'endDate',
  37. EVENT_CLASS = 'eventClass',
  38. EVENT_RECORDER = 'eventRecorder',
  39. EVENTS = 'events',
  40. HD = 'hd',
  41. HEADER = 'header',
  42. HEADER_NODE = 'headerNode',
  43. HELPER = 'helper',
  44. ICON = 'icon',
  45. ICON_NEXT_NODE = 'iconNextNode',
  46. ICON_PREV_NODE = 'iconPrevNode',
  47. LOCALE = 'locale',
  48. NAME = 'name',
  49. NAV = 'nav',
  50. NAV_NODE = 'navNode',
  51. NAVIGATION_DATE_FORMATTER = 'navigationDateFormatter',
  52. NEXT = 'next',
  53. NEXT_DATE = 'nextDate',
  54. PREV = 'prev',
  55. PREV_DATE = 'prevDate',
  56. RENDERED = 'rendered',
  57. SCHEDULER = 'scheduler',
  58. START_DATE = 'startDate',
  59. STRINGS = 'strings',
  60. TODAY = 'today',
  61. TODAY_NODE = 'todayNode',
  62. TRIGGER_NODE = 'triggerNode',
  63. VIEW = 'view',
  64. VIEW_STACK = 'viewStack',
  65. VIEWS = 'views',
  66. VIEWS_NODE = 'viewsNode',
  67. getCN = A.getClassName,
  68. CSS_HELPER_CLEARFIX = getCN(HELPER, CLEARFIX),
  69. CSS_ICON = getCN(ICON),
  70. CSS_SCHEDULER_CONTROLS = getCN(SCHEDULER_BASE, CONTROLS),
  71. CSS_SCHEDULER_CURRENT_DATE = getCN(SCHEDULER_BASE, CURRENT, DATE),
  72. CSS_SCHEDULER_HD = getCN(SCHEDULER_BASE, HD),
  73. CSS_SCHEDULER_ICON_NEXT = getCN(SCHEDULER_BASE, ICON, NEXT),
  74. CSS_SCHEDULER_ICON_PREV = getCN(SCHEDULER_BASE, ICON, PREV),
  75. CSS_SCHEDULER_NAV = getCN(SCHEDULER_BASE, NAV),
  76. CSS_SCHEDULER_TODAY = getCN(SCHEDULER_BASE, TODAY),
  77. CSS_SCHEDULER_VIEW = getCN(SCHEDULER_BASE, VIEW),
  78. CSS_SCHEDULER_VIEW_ = getCN(SCHEDULER_BASE, VIEW, EMPTY_STR),
  79. CSS_SCHEDULER_VIEWS = getCN(SCHEDULER_BASE, VIEWS),
  80. TPL_SCHEDULER_CONTROLS = '<div class="'+CSS_SCHEDULER_CONTROLS+'"></div>',
  81. TPL_SCHEDULER_CURRENT_DATE = '<div class="'+CSS_SCHEDULER_CURRENT_DATE+'"></div>',
  82. TPL_SCHEDULER_HD = '<div class="'+CSS_SCHEDULER_HD+'"></div>',
  83. TPL_SCHEDULER_ICON_NEXT = '<a href="#" class="'+[ CSS_ICON, CSS_SCHEDULER_ICON_NEXT ].join(SPACE)+'">Next</a>',
  84. TPL_SCHEDULER_ICON_PREV = '<a href="#" class="'+[ CSS_ICON, CSS_SCHEDULER_ICON_PREV ].join(SPACE)+'">Prev</a>',
  85. TPL_SCHEDULER_NAV = '<div class="'+CSS_SCHEDULER_NAV+'"></div>',
  86. TPL_SCHEDULER_TODAY = '<a href="#" class="'+CSS_SCHEDULER_TODAY+'">{today}</a>',
  87. TPL_SCHEDULER_VIEW = '<a href="#" class="'+[ CSS_SCHEDULER_VIEW, CSS_SCHEDULER_VIEW_ ].join(SPACE)+'{name}" data-view-name="{name}">{label}</a>',
  88. TPL_SCHEDULER_VIEWS = '<div class="'+CSS_SCHEDULER_VIEWS+'"></div>';
  89. var SchedulerEventSupport = function() {};
  90. SchedulerEventSupport.ATTRS = {
  91. eventClass: {
  92. valueFn: function() {
  93. return A.SchedulerEvent;
  94. }
  95. },
  96. events: {
  97. value: [],
  98. setter: '_setEvents',
  99. validator: isArray
  100. }
  101. };
  102. A.mix(SchedulerEventSupport.prototype, {
  103. addEvent: function(evt) {
  104. var instance = this;
  105. var events = instance.get(EVENTS);
  106. if (A.Array.indexOf(events, evt) > -1) {
  107. A.Array.removeItem(events, evt);
  108. }
  109. events.push(evt);
  110. instance.set(EVENTS, events);
  111. },
  112. addEvents: function(events) {
  113. var instance = this;
  114. A.Array.each(
  115. instance._normalizeEvents(events),
  116. A.bind(instance.addEvent, instance)
  117. );
  118. },
  119. eachEvent: function(fn) {
  120. var instance = this;
  121. var events = instance.get(EVENTS);
  122. A.Array.each(events, fn, instance);
  123. },
  124. removeEvent: function(evt) {
  125. var instance = this;
  126. var events = instance.get(EVENTS);
  127. if (events.length) {
  128. A.Array.removeItem(events, evt);
  129. instance.set(EVENTS, events);
  130. }
  131. },
  132. removeEvents: function(events) {
  133. var instance = this;
  134. A.Array.each(
  135. instance._normalizeEvents(events),
  136. A.bind(instance.removeEvent, instance)
  137. );
  138. },
  139. _normalizeEvents: function(events) {
  140. var instance = this;
  141. var output = [];
  142. events = A.Array(events);
  143. A.Array.each(events, function(evt) {
  144. if (isSchedulerEvent(evt)) {
  145. output.push(evt);
  146. }
  147. else if (isSchedulerCalendar(evt)) {
  148. if (isScheduler(instance)) {
  149. evt.set(SCHEDULER, instance);
  150. }
  151. // get events from the calendar
  152. output = output.concat(
  153. instance._normalizeEvents(evt.get(EVENTS))
  154. );
  155. }
  156. else {
  157. evt = new (instance.get(EVENT_CLASS))(evt);
  158. output.push(evt);
  159. }
  160. if (isScheduler(instance)) {
  161. evt.set(SCHEDULER, instance);
  162. evt.set(EVENT_CLASS, instance.get(EVENT_CLASS));
  163. }
  164. });
  165. return output;
  166. },
  167. _setEvents: function(val) {
  168. var instance = this;
  169. return instance._normalizeEvents(val);
  170. }
  171. });
  172. A.SchedulerEventSupport = SchedulerEventSupport;
  173. var SchedulerBase = A.Component.create({
  174. NAME: SCHEDULER_BASE,
  175. ATTRS: {
  176. activeView: {
  177. validator: isSchedulerView
  178. },
  179. eventRecorder: {
  180. setter: '_setEventRecorder'
  181. },
  182. strings: {
  183. value: {
  184. day: 'Day',
  185. month: 'Month',
  186. today: 'Today',
  187. week: 'Week',
  188. year: 'Year'
  189. }
  190. },
  191. /**
  192. * The function to format the navigation header date.
  193. *
  194. * @attribute navigationDateFormatter
  195. * @default %A - %d %b %Y
  196. * @type Function
  197. */
  198. navigationDateFormatter: {
  199. value: function(date) {
  200. var instance = this;
  201. return A.DataType.Date.format(
  202. date,
  203. {
  204. format: '%B %d, %Y',
  205. locale: instance.get(LOCALE)
  206. }
  207. );
  208. },
  209. validator: isFunction
  210. },
  211. views: {
  212. setter: '_setViews',
  213. value: []
  214. },
  215. currentDate: {
  216. valueFn: function() {
  217. return new Date();
  218. },
  219. validator: isDate
  220. },
  221. /**
  222. * First day of the week: Sunday is 0, Monday is 1.
  223. *
  224. * @attribute firstDayOfWeek
  225. * @default 0
  226. * @type Number
  227. */
  228. firstDayOfWeek: {
  229. value: 0,
  230. validator: isNumber
  231. },
  232. /*
  233. * HTML_PARSER attributes
  234. */
  235. controlsNode: {
  236. valueFn: function() {
  237. return A.Node.create(TPL_SCHEDULER_CONTROLS);
  238. }
  239. },
  240. currentDateNode: {
  241. valueFn: function() {
  242. return A.Node.create(TPL_SCHEDULER_CURRENT_DATE);
  243. }
  244. },
  245. headerNode: {
  246. valueFn: function() {
  247. return A.Node.create(TPL_SCHEDULER_HD);
  248. }
  249. },
  250. iconNextNode: {
  251. valueFn: function() {
  252. return A.Node.create(TPL_SCHEDULER_ICON_NEXT);
  253. }
  254. },
  255. iconPrevNode: {
  256. valueFn: function() {
  257. return A.Node.create(TPL_SCHEDULER_ICON_PREV);
  258. }
  259. },
  260. navNode: {
  261. valueFn: function() {
  262. return A.Node.create(TPL_SCHEDULER_NAV);
  263. }
  264. },
  265. todayNode: {
  266. valueFn: function() {
  267. return A.Node.create(
  268. this._processTemplate(TPL_SCHEDULER_TODAY)
  269. );
  270. }
  271. },
  272. viewsNode: {
  273. valueFn: function() {
  274. return A.Node.create(TPL_SCHEDULER_VIEWS);
  275. }
  276. }
  277. },
  278. HTML_PARSER: {
  279. controlsNode: DOT+CSS_SCHEDULER_CONTROLS,
  280. currentDateNode: DOT+CSS_SCHEDULER_CURRENT_DATE,
  281. headerNode: DOT+CSS_SCHEDULER_HD,
  282. iconNextNode: DOT+CSS_SCHEDULER_ICON_NEXT,
  283. iconPrevNode: DOT+CSS_SCHEDULER_ICON_PREV,
  284. navNode: DOT+CSS_SCHEDULER_NAV,
  285. todayNode: DOT+CSS_SCHEDULER_TODAY,
  286. viewsNode: DOT+CSS_SCHEDULER_VIEWS
  287. },
  288. UI_ATTRS: [CURRENT_DATE],
  289. AUGMENTS: [A.SchedulerEventSupport, A.WidgetStdMod],
  290. prototype: {
  291. viewStack: null,
  292. initializer: function() {
  293. var instance = this;
  294. instance[VIEW_STACK] = {};
  295. instance[CONTROLS_NODE] = instance.get(CONTROLS_NODE);
  296. instance[CURRENT_DATE_NODE] = instance.get(CURRENT_DATE_NODE);
  297. instance[HEADER] = instance.get(HEADER_NODE);
  298. instance[ICON_NEXT_NODE] = instance.get(ICON_NEXT_NODE);
  299. instance[ICON_PREV_NODE] = instance.get(ICON_PREV_NODE);
  300. instance[NAV_NODE] = instance.get(NAV_NODE);
  301. instance[TODAY_NODE] = instance.get(TODAY_NODE);
  302. instance[VIEWS_NODE] = instance.get(VIEWS_NODE);
  303. instance.after({
  304. activeViewChange: instance._afterActiveViewChange,
  305. render: instance._afterRender
  306. });
  307. },
  308. bindUI: function() {
  309. var instance = this;
  310. instance._bindDelegate();
  311. },
  312. syncUI: function() {
  313. var instance = this;
  314. instance.syncStdContent();
  315. },
  316. flushEvents: function() {
  317. var instance = this;
  318. A.Array.each(instance.get(EVENTS), function(evt) {
  319. evt.eachRepeatedEvent(function(repeatedEvt) {
  320. delete repeatedEvt._filtered;
  321. });
  322. delete evt._filtered;
  323. });
  324. },
  325. getEventsByDay: function(date, includeOverlap) {
  326. var instance = this;
  327. date = DateMath.safeClearTime(date);
  328. return instance._getEvents(date, function(evt) {
  329. return DateMath.compare(evt.getClearStartDate(), date) ||
  330. (includeOverlap && DateMath.compare(evt.getClearEndDate(), date));
  331. });
  332. },
  333. getIntersectEvents: function(date) {
  334. var instance = this;
  335. date = DateMath.safeClearTime(date);
  336. return instance._getEvents(date, function(evt) {
  337. var startDate = evt.getClearStartDate();
  338. var endDate = evt.getClearEndDate();
  339. return (DateMath.compare(date, startDate) ||
  340. DateMath.compare(date, endDate) ||
  341. DateMath.between(date, startDate, endDate));
  342. });
  343. },
  344. sortEventsByDateAsc: function(events) {
  345. var instance = this;
  346. // sort events by start date and duration
  347. events.sort(function(evt1, evt2) {
  348. var endDate1 = evt1.get(END_DATE);
  349. var endDate2 = evt2.get(END_DATE);
  350. var startDate1 = evt1.get(START_DATE);
  351. var startDate2 = evt2.get(START_DATE);
  352. if (DateMath.after(startDate1, startDate2) ||
  353. (DateMath.compare(startDate1, startDate2) && DateMath.before(endDate1, endDate2))) {
  354. return 1;
  355. }
  356. else {
  357. return -1;
  358. }
  359. });
  360. },
  361. getViewByName: function(name) {
  362. var instance = this;
  363. return instance[VIEW_STACK][name];
  364. },
  365. getStrings: function() {
  366. var instance = this;
  367. return instance.get(STRINGS);
  368. },
  369. getString: function(key) {
  370. var instance = this;
  371. return instance.getStrings()[key];
  372. },
  373. renderView: function(view) {
  374. var instance = this;
  375. if (view) {
  376. view.show();
  377. if (!view.get(RENDERED)) {
  378. if (!instance.bodyNode) {
  379. instance.setStdModContent(WidgetStdMod.BODY, EMPTY_STR);
  380. }
  381. view.render(instance.bodyNode);
  382. }
  383. }
  384. },
  385. plotViewEvents: function(view) {
  386. var instance = this;
  387. view.plotEvents(
  388. instance.get(EVENTS)
  389. );
  390. },
  391. syncEventsUI: function() {
  392. var instance = this;
  393. instance.plotViewEvents(instance.get(ACTIVE_VIEW));
  394. },
  395. _afterActiveViewChange: function(event) {
  396. var instance = this;
  397. if (instance.get(RENDERED)) {
  398. var activeView = event.newVal;
  399. var lastActiveView = event.prevVal;
  400. if (lastActiveView) {
  401. lastActiveView.hide();
  402. }
  403. instance.renderView(activeView);
  404. var eventRecorder = instance.get(EVENT_RECORDER);
  405. if (eventRecorder) {
  406. eventRecorder.hideOverlay();
  407. }
  408. }
  409. },
  410. _afterRender: function(event) {
  411. var instance = this;
  412. instance.renderView(
  413. instance.get(ACTIVE_VIEW)
  414. );
  415. },
  416. _bindDelegate: function() {
  417. var instance = this;
  418. instance[VIEWS_NODE].delegate('click', instance._onClickViewTrigger, DOT+CSS_SCHEDULER_VIEW, instance);
  419. instance[CONTROLS_NODE].delegate('click', instance._onClickPrevIcon, DOT+CSS_SCHEDULER_ICON_PREV, instance);
  420. instance[CONTROLS_NODE].delegate('click', instance._onClickNextIcon, DOT+CSS_SCHEDULER_ICON_NEXT, instance);
  421. instance[CONTROLS_NODE].delegate('click', instance._onClickToday, DOT+CSS_SCHEDULER_TODAY, instance);
  422. },
  423. _createViewTriggerNode: function(view) {
  424. var instance = this;
  425. if (!view.get(TRIGGER_NODE)) {
  426. var name = view.get(NAME);
  427. view.set(
  428. TRIGGER_NODE,
  429. A.Node.create(
  430. Lang.sub(TPL_SCHEDULER_VIEW, {
  431. name: name,
  432. label: (instance.getString(name) || name)
  433. })
  434. )
  435. );
  436. }
  437. return view.get(TRIGGER_NODE);
  438. },
  439. _getEvents: function(date, filterFn) {
  440. var instance = this;
  441. var events = instance.get(EVENTS);
  442. var results = [];
  443. A.Array.each(events, function(evt) {
  444. if (filterFn.apply(instance, [evt])) {
  445. results.push(evt);
  446. }
  447. else if (evt.isRepeatableDate(date)) {
  448. var repeatedEvt = evt.repeatByDate(date);
  449. results.push(repeatedEvt);
  450. }
  451. });
  452. instance.sortEventsByDateAsc(results);
  453. return results;
  454. },
  455. _onClickToday: function(event) {
  456. var instance = this;
  457. instance.set(
  458. CURRENT_DATE,
  459. instance.get(ACTIVE_VIEW).getToday()
  460. );
  461. event.preventDefault();
  462. },
  463. _onClickNextIcon: function(event) {
  464. var instance = this;
  465. instance.set(
  466. CURRENT_DATE,
  467. instance.get(ACTIVE_VIEW).get(NEXT_DATE)
  468. );
  469. event.preventDefault();
  470. },
  471. _onClickPrevIcon: function(event) {
  472. var instance = this;
  473. instance.set(
  474. CURRENT_DATE,
  475. instance.get(ACTIVE_VIEW).get(PREV_DATE)
  476. );
  477. event.preventDefault();
  478. },
  479. _onClickViewTrigger: function(event) {
  480. var instance = this;
  481. var viewName = event.currentTarget.attr(DATA_VIEW_NAME);
  482. instance.set(ACTIVE_VIEW, instance.getViewByName(viewName));
  483. event.preventDefault();
  484. },
  485. _processTemplate: function(tpl) {
  486. var instance = this;
  487. return Lang.sub(tpl, instance.getStrings());
  488. },
  489. _setEventRecorder: function(val) {
  490. var instance = this;
  491. if (val) {
  492. val.set(SCHEDULER, instance);
  493. val.set(EVENT_CLASS, instance.get(EVENT_CLASS));
  494. }
  495. },
  496. _setViews: function(val) {
  497. var instance = this;
  498. var views = [];
  499. A.Array.each(val, function(view) {
  500. if (isSchedulerView(view) && !view.get(RENDERED)) {
  501. view.set(SCHEDULER, instance);
  502. view.set(EVENT_CLASS, instance.get(EVENT_CLASS));
  503. views.push(view);
  504. instance[VIEW_STACK][view.get(NAME)] = view;
  505. }
  506. });
  507. if (!instance.get(ACTIVE_VIEW)) {
  508. instance.set(ACTIVE_VIEW, val[0]);
  509. }
  510. return views;
  511. },
  512. /**
  513. * Sync SchedulerBase StdContent.
  514. *
  515. * @method syncStdContent
  516. * @protected
  517. */
  518. syncStdContent: function() {
  519. var instance = this;
  520. var views = instance.get(VIEWS);
  521. instance[NAV_NODE].append(instance[ICON_PREV_NODE]);
  522. instance[NAV_NODE].append(instance[ICON_NEXT_NODE]);
  523. instance[CONTROLS_NODE].append(instance[TODAY_NODE]);
  524. instance[CONTROLS_NODE].append(instance[NAV_NODE]);
  525. instance[CONTROLS_NODE].append(instance[CURRENT_DATE_NODE]);
  526. A.Array.each(views, function(view) {
  527. instance[VIEWS_NODE].append( instance._createViewTriggerNode(view) );
  528. });
  529. instance[HEADER].append(instance[CONTROLS_NODE]);
  530. instance[HEADER].append(instance[VIEWS_NODE]);
  531. instance[HEADER].addClass(CSS_HELPER_CLEARFIX);
  532. instance.setStdModContent(WidgetStdMod.HEADER, instance[HEADER].getDOM());
  533. },
  534. _uiSetCurrentDate: function(val) {
  535. var instance = this;
  536. var formatter = instance.get(NAVIGATION_DATE_FORMATTER);
  537. var navigationTitle = formatter.call(instance, val);
  538. if (instance.get(RENDERED)) {
  539. var activeView = instance.get(ACTIVE_VIEW);
  540. if (activeView) {
  541. activeView._uiSetCurrentDate(val);
  542. formatter = activeView.get(NAVIGATION_DATE_FORMATTER);
  543. navigationTitle = formatter.call(activeView, val);
  544. }
  545. instance[CURRENT_DATE_NODE].html(navigationTitle);
  546. instance.syncEventsUI();
  547. }
  548. }
  549. }
  550. });
  551. A.Scheduler = SchedulerBase;
  552. }, '@VERSION@' ,{skinnable:true, requires:['aui-scheduler-view','datasource']});