active_frontend 13.3.0 → 14.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/.fasterer.yml +19 -0
  4. data/.reek +27 -0
  5. data/.rubocop.yml +38 -0
  6. data/.scss-lint.yml +27 -0
  7. data/Rakefile +1 -1
  8. data/active_frontend.gemspec +21 -18
  9. data/app/.DS_Store +0 -0
  10. data/app/assets/.DS_Store +0 -0
  11. data/app/assets/fonts/.DS_Store +0 -0
  12. data/app/assets/fonts/dripicons/.DS_Store +0 -0
  13. data/app/assets/fonts/dripicons/dripicons.woff +0 -0
  14. data/app/assets/fonts/fakt-pro/.DS_Store +0 -0
  15. data/app/assets/fonts/fakt-pro/fakt-pro-bold.woff +0 -0
  16. data/app/assets/fonts/fakt-pro/fakt-pro-normal.woff +0 -0
  17. data/app/assets/fonts/fakt-pro/fakt-pro-semibold.woff +0 -0
  18. data/app/assets/fonts/fakt-pro/fakt-pro-semilight.woff +0 -0
  19. data/app/assets/fonts/fakt-soft-pro/.DS_Store +0 -0
  20. data/app/assets/fonts/fakt-soft-pro/fakt-soft-pro-bold.woff +0 -0
  21. data/app/assets/fonts/fakt-soft-pro/fakt-soft-pro-normal.woff +0 -0
  22. data/app/assets/fonts/fakt-soft-pro/fakt-soft-pro-semibold.woff +0 -0
  23. data/app/assets/fonts/fakt-soft-pro/fakt-soft-pro-semilight.woff +0 -0
  24. data/app/assets/images/.DS_Store +0 -0
  25. data/app/assets/images/.keep +0 -0
  26. data/app/assets/images/placeholders/.DS_Store +0 -0
  27. data/app/assets/images/placeholders/camera-large.png +0 -0
  28. data/app/assets/images/placeholders/camera-small.png +0 -0
  29. data/app/assets/images/placeholders/camera.png +0 -0
  30. data/app/assets/images/placeholders/document-large.png +0 -0
  31. data/app/assets/images/placeholders/document-small.png +0 -0
  32. data/app/assets/images/placeholders/document.png +0 -0
  33. data/app/assets/images/placeholders/photo-large.png +0 -0
  34. data/app/assets/images/placeholders/{picture-small.png → photo-small.png} +0 -0
  35. data/app/assets/images/placeholders/photo.png +0 -0
  36. data/app/assets/images/placeholders/store-large.png +0 -0
  37. data/app/assets/images/placeholders/store-small.png +0 -0
  38. data/app/assets/images/placeholders/store.png +0 -0
  39. data/app/assets/images/placeholders/user-large.png +0 -0
  40. data/app/assets/images/placeholders/user-small.png +0 -0
  41. data/app/assets/images/placeholders/user.png +0 -0
  42. data/app/helpers/active_frontend_helper.rb +22 -37
  43. data/lib/.DS_Store +0 -0
  44. data/lib/active_frontend.rb +3 -4
  45. data/lib/active_frontend/.DS_Store +0 -0
  46. data/lib/active_frontend/version.rb +1 -1
  47. data/lib/generators/active_frontend/install_generator.rb +3 -3
  48. data/lib/generators/active_frontend/templates/install.js +35 -30
  49. data/lib/generators/active_frontend/templates/install.scss +55 -58
  50. data/vendor/.DS_Store +0 -0
  51. data/vendor/assets/.DS_Store +0 -0
  52. data/vendor/assets/javascripts/.DS_Store +0 -0
  53. data/vendor/assets/javascripts/active_frontend.js +35 -30
  54. data/vendor/assets/javascripts/base/_affix.js +170 -0
  55. data/vendor/assets/javascripts/base/_alert.js +80 -0
  56. data/vendor/assets/javascripts/base/_animation.js +106 -0
  57. data/vendor/assets/javascripts/base/_button.js +123 -0
  58. data/vendor/assets/javascripts/base/_carousel.js +237 -0
  59. data/vendor/assets/javascripts/base/_collapse.js +200 -0
  60. data/vendor/assets/javascripts/base/_colorpicker.js +147 -0
  61. data/vendor/assets/javascripts/base/_datepicker.js +1411 -0
  62. data/vendor/assets/javascripts/base/_dropdown.js +154 -0
  63. data/vendor/assets/javascripts/base/_filepicker.js +235 -0
  64. data/vendor/assets/javascripts/base/_hoverdown.js +116 -0
  65. data/vendor/assets/javascripts/base/_layout.js +126 -0
  66. data/vendor/assets/javascripts/base/_list.js +103 -0
  67. data/vendor/assets/javascripts/{_modal.js → base/_modal.js} +170 -167
  68. data/vendor/assets/javascripts/base/_popover.js +101 -0
  69. data/vendor/assets/javascripts/base/_scrollspy.js +161 -0
  70. data/vendor/assets/javascripts/base/_switch.js +160 -0
  71. data/vendor/assets/javascripts/base/_tab.js +139 -0
  72. data/vendor/assets/javascripts/base/_table.js +224 -0
  73. data/vendor/assets/javascripts/base/_timeago.js +270 -0
  74. data/vendor/assets/javascripts/base/_timepicker.js +541 -0
  75. data/vendor/assets/javascripts/base/_tooltip.js +525 -0
  76. data/vendor/assets/javascripts/base/_tour.js +268 -0
  77. data/vendor/assets/javascripts/base/_transition.js +52 -0
  78. data/vendor/assets/javascripts/base/_typeahead.js +362 -0
  79. data/vendor/assets/javascripts/extensions/_calendar.js +4709 -0
  80. data/vendor/assets/javascripts/extensions/_chart.js +9371 -0
  81. data/vendor/assets/javascripts/extensions/_map.js +2153 -0
  82. data/vendor/assets/stylesheets/.DS_Store +0 -0
  83. data/vendor/assets/stylesheets/{_mixin.scss → _utility.scss} +96 -10
  84. data/vendor/assets/stylesheets/_variable.scss +201 -19
  85. data/vendor/assets/stylesheets/active_frontend.scss +55 -58
  86. data/vendor/assets/stylesheets/blocks/_anchor.scss +15 -0
  87. data/vendor/assets/stylesheets/blocks/_button.scss +278 -0
  88. data/vendor/assets/stylesheets/blocks/_code.scss +144 -0
  89. data/vendor/assets/stylesheets/blocks/_common.scss +127 -0
  90. data/vendor/assets/stylesheets/blocks/_form.scss +508 -0
  91. data/vendor/assets/stylesheets/blocks/_icon.scss +359 -0
  92. data/vendor/assets/stylesheets/blocks/_list.scss +76 -0
  93. data/vendor/assets/stylesheets/blocks/_multimedia.scss +62 -0
  94. data/vendor/assets/stylesheets/blocks/_reset.scss +179 -0
  95. data/vendor/assets/stylesheets/blocks/_table.scss +211 -0
  96. data/vendor/assets/stylesheets/blocks/_typography.scss +204 -0
  97. data/vendor/assets/stylesheets/components/_ad.scss +78 -0
  98. data/vendor/assets/stylesheets/components/_affix.scss +14 -0
  99. data/vendor/assets/stylesheets/components/_alert.scss +50 -0
  100. data/vendor/assets/stylesheets/components/_animation.scss +1670 -0
  101. data/vendor/assets/stylesheets/components/_breadcrumb.scss +17 -0
  102. data/vendor/assets/stylesheets/components/_calendar.scss +213 -0
  103. data/vendor/assets/stylesheets/components/_card.scss +30 -0
  104. data/vendor/assets/stylesheets/components/_carousel.scss +135 -0
  105. data/vendor/assets/stylesheets/components/_chart.scss +10 -0
  106. data/vendor/assets/stylesheets/components/_collapse.scss +17 -0
  107. data/vendor/assets/stylesheets/components/_colorpicker.scss +38 -0
  108. data/vendor/assets/stylesheets/components/_datepicker.scss +80 -0
  109. data/vendor/assets/stylesheets/components/_dropmenu.scss +151 -0
  110. data/vendor/assets/stylesheets/components/_footer.scss +11 -0
  111. data/vendor/assets/stylesheets/components/_grid.scss +144 -0
  112. data/vendor/assets/stylesheets/components/_header.scss +99 -0
  113. data/vendor/assets/stylesheets/components/_label_and_badge.scss +57 -0
  114. data/vendor/assets/stylesheets/components/_layout.scss +63 -0
  115. data/vendor/assets/stylesheets/components/_map.scss +14 -0
  116. data/vendor/assets/stylesheets/components/_milestone.scss +49 -0
  117. data/vendor/assets/stylesheets/components/_missive.scss +40 -0
  118. data/vendor/assets/stylesheets/components/_modal.scss +126 -0
  119. data/vendor/assets/stylesheets/components/_nav_and_tab.scss +202 -0
  120. data/vendor/assets/stylesheets/components/_navbar.scss +66 -0
  121. data/vendor/assets/stylesheets/components/_pagination.scss +79 -0
  122. data/vendor/assets/stylesheets/components/_placeholder.scss +23 -0
  123. data/vendor/assets/stylesheets/components/_popover.scss +167 -0
  124. data/vendor/assets/stylesheets/components/_progress.scss +62 -0
  125. data/vendor/assets/stylesheets/components/_sidebar.scss +74 -0
  126. data/vendor/assets/stylesheets/components/_spinner.scss +83 -0
  127. data/vendor/assets/stylesheets/components/_switch.scss +150 -0
  128. data/vendor/assets/stylesheets/components/_timepicker.scss +30 -0
  129. data/vendor/assets/stylesheets/components/_tooltip.scss +93 -0
  130. data/vendor/assets/stylesheets/components/_transition.scss +12 -0
  131. data/vendor/assets/stylesheets/components/_typeahead.scss +18 -0
  132. metadata +150 -94
  133. data/app/assets/fonts/gotham/gotham-bold.woff +0 -0
  134. data/app/assets/fonts/gotham/gotham-book.woff +0 -0
  135. data/app/assets/fonts/gotham/gotham-light.woff +0 -0
  136. data/app/assets/fonts/gotham/gotham-medium.woff +0 -0
  137. data/app/assets/fonts/gotham/gotham-rounded-bold.woff +0 -0
  138. data/app/assets/fonts/gotham/gotham-rounded-book.woff +0 -0
  139. data/app/assets/fonts/gotham/gotham-rounded-light.woff +0 -0
  140. data/app/assets/fonts/gotham/gotham-rounded-medium.woff +0 -0
  141. data/app/assets/images/placeholders/archive-large.png +0 -0
  142. data/app/assets/images/placeholders/archive-small.png +0 -0
  143. data/app/assets/images/placeholders/archive.png +0 -0
  144. data/app/assets/images/placeholders/picture-large.png +0 -0
  145. data/app/assets/images/placeholders/picture.png +0 -0
  146. data/vendor/assets/javascripts/_affix.js +0 -153
  147. data/vendor/assets/javascripts/_alert.js +0 -85
  148. data/vendor/assets/javascripts/_animation.js +0 -103
  149. data/vendor/assets/javascripts/_button.js +0 -107
  150. data/vendor/assets/javascripts/_carousel.js +0 -228
  151. data/vendor/assets/javascripts/_chart.js +0 -3742
  152. data/vendor/assets/javascripts/_collapse.js +0 -202
  153. data/vendor/assets/javascripts/_color_picker.js +0 -108
  154. data/vendor/assets/javascripts/_date_picker.js +0 -1650
  155. data/vendor/assets/javascripts/_dropdown.js +0 -156
  156. data/vendor/assets/javascripts/_file_input.js +0 -71
  157. data/vendor/assets/javascripts/_hoverdown.js +0 -109
  158. data/vendor/assets/javascripts/_inputmask.js +0 -341
  159. data/vendor/assets/javascripts/_loader.js +0 -361
  160. data/vendor/assets/javascripts/_map.js +0 -2401
  161. data/vendor/assets/javascripts/_popover.js +0 -99
  162. data/vendor/assets/javascripts/_scrollspy.js +0 -163
  163. data/vendor/assets/javascripts/_slider.js +0 -1572
  164. data/vendor/assets/javascripts/_sort.js +0 -1432
  165. data/vendor/assets/javascripts/_swoggle.js +0 -415
  166. data/vendor/assets/javascripts/_tab.js +0 -146
  167. data/vendor/assets/javascripts/_tablespy.js +0 -1883
  168. data/vendor/assets/javascripts/_time_ago.js +0 -206
  169. data/vendor/assets/javascripts/_time_picker.js +0 -1088
  170. data/vendor/assets/javascripts/_tooltip.js +0 -504
  171. data/vendor/assets/javascripts/_transition.js +0 -50
  172. data/vendor/assets/javascripts/_typeahead.js +0 -366
  173. data/vendor/assets/stylesheets/_ad.scss +0 -63
  174. data/vendor/assets/stylesheets/_affix.scss +0 -14
  175. data/vendor/assets/stylesheets/_alert.scss +0 -114
  176. data/vendor/assets/stylesheets/_animation.scss +0 -1370
  177. data/vendor/assets/stylesheets/_breadcrumb.scss +0 -100
  178. data/vendor/assets/stylesheets/_button.scss +0 -386
  179. data/vendor/assets/stylesheets/_canvas.scss +0 -182
  180. data/vendor/assets/stylesheets/_carousel.scss +0 -158
  181. data/vendor/assets/stylesheets/_chart.scss +0 -15
  182. data/vendor/assets/stylesheets/_code.scss +0 -150
  183. data/vendor/assets/stylesheets/_collapse.scss +0 -14
  184. data/vendor/assets/stylesheets/_color.scss +0 -55
  185. data/vendor/assets/stylesheets/_colorpicker.scss +0 -63
  186. data/vendor/assets/stylesheets/_datepicker.scss +0 -122
  187. data/vendor/assets/stylesheets/_dropdown.scss +0 -248
  188. data/vendor/assets/stylesheets/_footer.scss +0 -71
  189. data/vendor/assets/stylesheets/_form.scss +0 -661
  190. data/vendor/assets/stylesheets/_grid.scss +0 -184
  191. data/vendor/assets/stylesheets/_header.scss +0 -156
  192. data/vendor/assets/stylesheets/_icon.scss +0 -362
  193. data/vendor/assets/stylesheets/_image.scss +0 -33
  194. data/vendor/assets/stylesheets/_label_and_badge.scss +0 -104
  195. data/vendor/assets/stylesheets/_link.scss +0 -55
  196. data/vendor/assets/stylesheets/_list.scss +0 -122
  197. data/vendor/assets/stylesheets/_loader.scss +0 -71
  198. data/vendor/assets/stylesheets/_map.scss +0 -44
  199. data/vendor/assets/stylesheets/_missive.scss +0 -74
  200. data/vendor/assets/stylesheets/_modal.scss +0 -204
  201. data/vendor/assets/stylesheets/_nav_and_tab.scss +0 -230
  202. data/vendor/assets/stylesheets/_navbar.scss +0 -73
  203. data/vendor/assets/stylesheets/_pagination.scss +0 -79
  204. data/vendor/assets/stylesheets/_panel.scss +0 -80
  205. data/vendor/assets/stylesheets/_placeholder.scss +0 -63
  206. data/vendor/assets/stylesheets/_popover.scss +0 -128
  207. data/vendor/assets/stylesheets/_progress.scss +0 -86
  208. data/vendor/assets/stylesheets/_reset.scss +0 -140
  209. data/vendor/assets/stylesheets/_sidebar.scss +0 -148
  210. data/vendor/assets/stylesheets/_slider.scss +0 -151
  211. data/vendor/assets/stylesheets/_spinner.scss +0 -572
  212. data/vendor/assets/stylesheets/_subheader.scss +0 -112
  213. data/vendor/assets/stylesheets/_swoggle.scss +0 -120
  214. data/vendor/assets/stylesheets/_table.scss +0 -210
  215. data/vendor/assets/stylesheets/_timepicker.scss +0 -77
  216. data/vendor/assets/stylesheets/_toolbar.scss +0 -130
  217. data/vendor/assets/stylesheets/_tooltip.scss +0 -105
  218. data/vendor/assets/stylesheets/_transition.scss +0 -11
  219. data/vendor/assets/stylesheets/_trunk.scss +0 -147
  220. data/vendor/assets/stylesheets/_typeahead.scss +0 -18
  221. data/vendor/assets/stylesheets/_typography.scss +0 -233
@@ -0,0 +1,4709 @@
1
+ (function($, undefined) {
2
+
3
+ var defaults = {
4
+ defaultView: 'month',
5
+ aspectRatio: 1.35,
6
+ header: {
7
+ left: 'prev,title,next',
8
+ center: '',
9
+ right: 'month,agendaWeek,agendaDay'
10
+ },
11
+ weekends: true,
12
+ weekNumbers: false,
13
+ weekNumberCalculation: 'iso',
14
+ weekNumberTitle: 'W',
15
+ // editable: false,
16
+ // disableDragging: false,
17
+ // disableResizing: false,
18
+ allDayDefault: true,
19
+ ignoreTimezone: true,
20
+ lazyFetching: true,
21
+ startParam: 'start',
22
+ endParam: 'end',
23
+ titleFormat: {
24
+ month: 'MMMM yyyy',
25
+ week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}",
26
+ day: 'dddd, MMM d, yyyy'
27
+ },
28
+ columnFormat: {
29
+ month: 'ddd',
30
+ week: 'ddd M/d',
31
+ day: 'dddd M/d'
32
+ },
33
+ timeFormat: {
34
+ '': 'h(:mm)t'
35
+ },
36
+ firstDay: 0,
37
+ monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
38
+ monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
39
+ dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
40
+ dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
41
+ buttonText: {
42
+ prev: '<i class="icon-chevron-left"></i>',
43
+ next: '<i class="icon-chevron-right"></i>',
44
+ today: 'Today',
45
+ month: 'Month',
46
+ week: 'Week',
47
+ day: 'Day'
48
+ },
49
+ buttonIcons: {
50
+ prev: 'circle-triangle-w',
51
+ next: 'circle-triangle-e'
52
+ },
53
+ // selectable: false,
54
+ unselectAuto: true,
55
+ dropAccept: '*',
56
+ handleWindowResize: false
57
+ };
58
+
59
+ var fc = $.calendar = { version: '1.0.0' };
60
+ var fcViews = fc.views = {};
61
+
62
+ $.fn.calendar = function (options) {
63
+ if (typeof options === 'string') {
64
+ var args = Array.prototype.slice.call(arguments, 1);
65
+ var res;
66
+
67
+ this.each(function () {
68
+ var calendar = $.data(this, 'calendar');
69
+
70
+ if (calendar && $.isFunction(calendar[options])) {
71
+ var r = calendar[options].apply(calendar, args);
72
+
73
+ if (res === undefined) {
74
+ res = r;
75
+ }
76
+ if (options === 'destroy') $.removeData(this, 'calendar');
77
+ }
78
+ });
79
+
80
+ if (res !== undefined) return res;
81
+ return this;
82
+ }
83
+
84
+ options = options || {};
85
+
86
+ var eventSources = options.eventSources || [];
87
+ delete options.eventSources;
88
+
89
+ if (options.events) {
90
+ eventSources.push(options.events);
91
+ delete options.events;
92
+ }
93
+
94
+ options = $.extend(true, {},
95
+ defaults,
96
+ {},
97
+ options
98
+ );
99
+
100
+ this.each(function (i, _element) {
101
+ var element = $(_element);
102
+ var calendar = new Calendar(element, options, eventSources);
103
+
104
+ element.data('calendar', calendar);
105
+ calendar.render();
106
+ });
107
+
108
+ return this;
109
+ };
110
+
111
+ function setDefaults(d) {
112
+ $.extend(true, defaults, d);
113
+ }
114
+
115
+ function Calendar(element, options, eventSources) {
116
+ var t = this;
117
+
118
+ t.options = options;
119
+ t.render = render;
120
+ t.destroy = destroy;
121
+ t.refetchEvents = refetchEvents;
122
+ t.reportEvents = reportEvents;
123
+ t.reportEventChange = reportEventChange;
124
+ t.rerenderEvents = rerenderEvents;
125
+ t.changeView = changeView;
126
+ t.select = select;
127
+ t.unselect = unselect;
128
+ t.prev = prev;
129
+ t.next = next;
130
+ t.today = today;
131
+ t.gotoDate = gotoDate;
132
+ t.incrementDate = incrementDate;
133
+ t.formatDate = function (format, date) { return formatDate(format, date, options); };
134
+ t.formatDates = function (format, date1, date2) { return formatDates(format, date1, date2, options); };
135
+ t.getDate = getDate;
136
+ t.getView = getView;
137
+ t.option = option;
138
+ t.trigger = trigger;
139
+
140
+ EventManager.call(t, options, eventSources);
141
+ var isFetchNeeded = t.isFetchNeeded;
142
+ var fetchEvents = t.fetchEvents;
143
+ var _element = element[0];
144
+ var resizeUID = 0;
145
+ var ignoreWindowResize = 0;
146
+ var date = new Date();
147
+ var events = [];
148
+ var _dragElement, header, headerElement, content, currentView, elementOuterWidth, suggestedViewHeight;
149
+
150
+ setYMD(date, options.year, options.month, options.date);
151
+
152
+ function render(inc) {
153
+ if (!content) {
154
+ initialRender();
155
+ } else if (elementVisible()) {
156
+ calcSize();
157
+ _renderView(inc);
158
+ }
159
+ }
160
+
161
+ function initialRender() {
162
+ element.addClass('calendar');
163
+
164
+ content = $('<div class="calendar-content" style="position: relative;"/>').prependTo(element);
165
+ header = new Header(t, options);
166
+ headerElement = header.render();
167
+
168
+ if (headerElement) element.prepend(headerElement);
169
+
170
+ changeView(options.defaultView);
171
+
172
+ if (options.handleWindowResize) $(window).resize(windowResize);
173
+ if (!bodyVisible()) lateRender();
174
+ }
175
+
176
+ function lateRender() {
177
+ setTimeout(function () {
178
+ if (!currentView.start && bodyVisible()) renderView();
179
+ }, 0);
180
+ }
181
+
182
+ function destroy() {
183
+ if (currentView) {
184
+ trigger('viewDestroy', currentView, currentView, currentView.element);
185
+ currentView.triggerEventDestroy();
186
+ }
187
+
188
+ $(window).unbind('resize', windowResize);
189
+
190
+ header.destroy();
191
+ content.remove();
192
+ element.removeClass('calendar');
193
+ }
194
+
195
+ function elementVisible() {
196
+ return element.is(':visible');
197
+ }
198
+
199
+ function bodyVisible() {
200
+ return $('body').is(':visible');
201
+ }
202
+
203
+ function changeView(newViewName) {
204
+ if (!currentView || newViewName !== currentView.name) _changeView(newViewName);
205
+ }
206
+
207
+ function _changeView(newViewName) {
208
+ ignoreWindowResize++;
209
+
210
+ if (currentView) {
211
+ trigger('viewDestroy', currentView, currentView, currentView.element);
212
+ unselect();
213
+ currentView.triggerEventDestroy();
214
+ freezeContentHeight();
215
+ currentView.element.remove();
216
+ header.deactivateButton(currentView.name);
217
+ }
218
+
219
+ header.activateButton(newViewName);
220
+
221
+ currentView = new fcViews[newViewName](
222
+ $('<div class="calendar-view calendar-view-' + newViewName + '" style="position: relative;"/>').appendTo(content), t
223
+ );
224
+
225
+ renderView();
226
+ unfreezeContentHeight();
227
+
228
+ ignoreWindowResize--;
229
+ }
230
+
231
+ function renderView(inc) {
232
+ if (!currentView.start || inc || date < currentView.start || date >= currentView.end) {
233
+ if (elementVisible()) _renderView(inc);
234
+ }
235
+ }
236
+
237
+ function _renderView(inc) {
238
+ ignoreWindowResize++;
239
+
240
+ if (currentView.start) {
241
+ trigger('viewDestroy', currentView, currentView, currentView.element);
242
+ unselect();
243
+ clearEvents();
244
+ }
245
+
246
+ freezeContentHeight();
247
+
248
+ currentView.render(date, inc || 0);
249
+
250
+ setSize();
251
+ unfreezeContentHeight();
252
+
253
+ (currentView.afterRender || noop)();
254
+
255
+ updateTitle();
256
+ updateTodayButton();
257
+ trigger('viewRender', currentView, currentView, currentView.element);
258
+
259
+ currentView.trigger('viewDisplay', _element);
260
+
261
+ ignoreWindowResize--;
262
+
263
+ getAndRenderEvents();
264
+ }
265
+
266
+ function updateSize() {
267
+ if (elementVisible()) {
268
+ unselect();
269
+ clearEvents();
270
+ calcSize();
271
+ setSize();
272
+ renderEvents();
273
+ }
274
+ }
275
+
276
+ function calcSize() {
277
+ if (options.contentHeight) {
278
+ suggestedViewHeight = options.contentHeight;
279
+ } else if (options.height) {
280
+ suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content);
281
+ } else {
282
+ suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, 0.5));
283
+ }
284
+ }
285
+
286
+ function setSize() {
287
+ if (suggestedViewHeight === undefined) calcSize();
288
+
289
+ ignoreWindowResize++;
290
+
291
+ currentView.setHeight(suggestedViewHeight);
292
+ currentView.setWidth(content.width());
293
+
294
+ ignoreWindowResize--;
295
+
296
+ elementOuterWidth = element.outerWidth();
297
+ }
298
+
299
+ function windowResize() {
300
+ if (!ignoreWindowResize) {
301
+ if (currentView.start) {
302
+ var uid = ++resizeUID;
303
+
304
+ setTimeout(function () {
305
+ if (uid === resizeUID && !ignoreWindowResize && elementVisible()) {
306
+ if (elementOuterWidth !== (elementOuterWidth = element.outerWidth())) {
307
+ ignoreWindowResize++;
308
+
309
+ updateSize();
310
+ currentView.trigger('windowResize', _element);
311
+
312
+ ignoreWindowResize--;
313
+ }
314
+ }
315
+ }, 200);
316
+ } else {
317
+ lateRender();
318
+ }
319
+ }
320
+ }
321
+
322
+ function refetchEvents() {
323
+ clearEvents();
324
+ fetchAndRenderEvents();
325
+ }
326
+
327
+ function rerenderEvents(modifiedEventID) {
328
+ clearEvents();
329
+ renderEvents(modifiedEventID);
330
+ }
331
+
332
+ function renderEvents(modifiedEventID) {
333
+ if (elementVisible()) {
334
+ currentView.setEventData(events);
335
+ currentView.renderEvents(events, modifiedEventID);
336
+ currentView.trigger('eventAfterAllRender');
337
+ }
338
+ }
339
+
340
+ function clearEvents() {
341
+ currentView.triggerEventDestroy();
342
+ currentView.clearEvents();
343
+ currentView.clearEventData();
344
+ }
345
+
346
+ function getAndRenderEvents() {
347
+ if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) {
348
+ fetchAndRenderEvents();
349
+ } else {
350
+ renderEvents();
351
+ }
352
+ }
353
+
354
+ function fetchAndRenderEvents() {
355
+ fetchEvents(currentView.visStart, currentView.visEnd);
356
+ }
357
+
358
+ function reportEvents(_events) {
359
+ events = _events;
360
+ renderEvents();
361
+ }
362
+
363
+ function reportEventChange(eventID) {
364
+ rerenderEvents(eventID);
365
+ }
366
+
367
+ function updateTitle() {
368
+ header.updateTitle(currentView.title);
369
+ }
370
+
371
+ function updateTodayButton() {
372
+ var today = new Date();
373
+
374
+ if (today >= currentView.start && today < currentView.end) {
375
+ header.disableButton('today');
376
+ } else {
377
+ header.enableButton('today');
378
+ }
379
+ }
380
+
381
+ function select(start, end, allDay) {
382
+ currentView.select(start, end, allDay === undefined ? true : allDay);
383
+ }
384
+
385
+ function unselect() {
386
+ if (currentView) currentView.unselect();
387
+ }
388
+
389
+ function prev() {
390
+ renderView(-1);
391
+ }
392
+
393
+ function next() {
394
+ renderView(1);
395
+ }
396
+
397
+ function prevYear() {
398
+ addYears(date, -1);
399
+ renderView();
400
+ }
401
+
402
+ function nextYear() {
403
+ addYears(date, 1);
404
+ renderView();
405
+ }
406
+
407
+ function today() {
408
+ date = new Date();
409
+ renderView();
410
+ }
411
+
412
+ function gotoDate(year, month, dateOfMonth) {
413
+ if (year instanceof Date) {
414
+ date = cloneDate(year);
415
+ } else {
416
+ setYMD(date, year, month, dateOfMonth);
417
+ }
418
+
419
+ renderView();
420
+ }
421
+
422
+ function incrementDate(years, months, days) {
423
+ if (years !== undefined) addYears(date, years);
424
+ if (months !== undefined) addMonths(date, months);
425
+ if (days !== undefined) addDays(date, days);
426
+
427
+ renderView();
428
+ }
429
+
430
+ function getDate() {
431
+ return cloneDate(date);
432
+ }
433
+
434
+ function freezeContentHeight() {
435
+ content.css({
436
+ width: '100%',
437
+ height: content.height(),
438
+ overflow: 'hidden'
439
+ });
440
+ }
441
+
442
+ function unfreezeContentHeight() {
443
+ content.css({
444
+ width: '',
445
+ height: '',
446
+ overflow: ''
447
+ });
448
+ }
449
+
450
+ function getView() {
451
+ return currentView;
452
+ }
453
+
454
+ function option(name, value) {
455
+ if (value === undefined) return options[name];
456
+
457
+ if (name === 'height' || name === 'contentHeight' || name === 'aspectRatio') {
458
+ options[name] = value;
459
+ updateSize();
460
+ }
461
+ }
462
+
463
+ function trigger(name, thisObj) {
464
+ if (options[name]) {
465
+ return options[name].apply(
466
+ thisObj || _element,
467
+ Array.prototype.slice.call(arguments, 2)
468
+ );
469
+ }
470
+ }
471
+
472
+ if (options.droppable) {
473
+ $(document)
474
+ .bind('dragstart', function (ev, ui) {
475
+ var _e = ev.target;
476
+ var e = $(_e);
477
+
478
+ if (!e.parents('.calendar').length) {
479
+ var accept = options.dropAccept;
480
+
481
+ if ($.isFunction(accept) ? accept.call(_e, e) : e.is(accept)) {
482
+ _dragElement = _e;
483
+ currentView.dragStart(_dragElement, ev, ui);
484
+ }
485
+ }
486
+ })
487
+ .bind('dragstop', function (ev, ui) {
488
+ if (_dragElement) {
489
+ currentView.dragStop(_dragElement, ev, ui);
490
+ _dragElement = null;
491
+ }
492
+ });
493
+ }
494
+ }
495
+
496
+ function Header(calendar, options) {
497
+ var t = this;
498
+
499
+ t.render = render;
500
+ t.destroy = destroy;
501
+ t.updateTitle = updateTitle;
502
+ t.activateButton = activateButton;
503
+ t.deactivateButton = deactivateButton;
504
+ t.disableButton = disableButton;
505
+ t.enableButton = enableButton;
506
+
507
+ var element = $([]);
508
+
509
+ function render() {
510
+ var sections = options.header;
511
+
512
+ if (sections) {
513
+ element = $('<table class="calendar-header" style="width: 100%;"/>')
514
+ .append(
515
+ $('<tr/>')
516
+ .append(renderSection('left'))
517
+ .append(renderSection('center'))
518
+ .append(renderSection('right'))
519
+ );
520
+ return element;
521
+ }
522
+ }
523
+
524
+ function destroy() {
525
+ element.remove();
526
+ }
527
+
528
+ function renderSection(position) {
529
+ var e = $('<td class="calendar-header-' + position + '"/>');
530
+ var bg = $('<span class="btn-group"/>');
531
+ var buttonStr = options.header[position];
532
+
533
+ if (buttonStr) {
534
+ $.each(buttonStr.split(' '), function (i) {
535
+ if (i > 0) e.append("<span class='calendar-header-space'/>");
536
+
537
+ var prevButton;
538
+
539
+ $.each(this.split(','), function (j, buttonName) {
540
+ if (buttonName === 'title') {
541
+ e.append('<span class="calendar-header-title"><h6>&nbsp;</h6></span>');
542
+
543
+ prevButton = null;
544
+ } else {
545
+ var buttonClick;
546
+
547
+ if (calendar[buttonName]) {
548
+ buttonClick = calendar[buttonName];
549
+ } else if (fcViews[buttonName]) {
550
+ buttonClick = function () {
551
+ calendar.changeView(buttonName);
552
+ };
553
+ }
554
+
555
+ if (buttonClick) {
556
+ var buttonKlass = 'btn btn-size-s btn-outline';
557
+
558
+ if (buttonName === 'prev' || buttonName === 'next') {
559
+ buttonKlass = '';
560
+ }
561
+
562
+ var text = smartProperty(options.buttonText, buttonName);
563
+ var button = $(
564
+ '<span class="' + buttonKlass + ' btn-' + buttonName + '">' +
565
+ text +
566
+ '</span>'
567
+ )
568
+ .click(function () {
569
+ if (!button.hasClass('disabled')) buttonClick();
570
+ });
571
+
572
+
573
+ if (position === 'left') {
574
+ button.appendTo(e);
575
+ } else {
576
+ button.appendTo(bg);
577
+ }
578
+
579
+ disableTextSelection(button);
580
+
581
+ prevButton = button;
582
+ }
583
+ }
584
+ });
585
+
586
+ if (position !== 'center') bg.appendTo(e);
587
+ });
588
+ }
589
+
590
+ return e;
591
+ }
592
+
593
+ function updateTitle(html) {
594
+ element.find('h6')
595
+ .html(html);
596
+ }
597
+
598
+ function activateButton(buttonName) {
599
+ element.find('span.btn-' + buttonName)
600
+ .addClass('active');
601
+ }
602
+
603
+ function deactivateButton(buttonName) {
604
+ element.find('span.btn-' + buttonName)
605
+ .removeClass('active');
606
+ }
607
+
608
+ function disableButton(buttonName) {
609
+ element.find('span.btn-' + buttonName)
610
+ .addClass('disabled');
611
+ }
612
+
613
+ function enableButton(buttonName) {
614
+ element.find('span.btn-' + buttonName)
615
+ .removeClass('disabled');
616
+ }
617
+ }
618
+
619
+ fc.sourceNormalizers = [];
620
+ fc.sourceFetchers = [];
621
+
622
+ var eventGUID = 1;
623
+ var ajaxDefaults = {
624
+ dataType: 'json',
625
+ cache: false
626
+ };
627
+
628
+ function EventManager(options, _sources) {
629
+ var t = this;
630
+
631
+ t.isFetchNeeded = isFetchNeeded;
632
+ t.fetchEvents = fetchEvents;
633
+ t.addEventSource = addEventSource;
634
+ t.removeEventSource = removeEventSource;
635
+ t.updateEvent = updateEvent;
636
+ t.renderEvent = renderEvent;
637
+ t.removeEvents = removeEvents;
638
+ t.clientEvents = clientEvents;
639
+ t.normalizeEvent = normalizeEvent;
640
+
641
+ var trigger = t.trigger;
642
+ var getView = t.getView;
643
+ var reportEvents = t.reportEvents;
644
+ var stickySource = { events: [] };
645
+ var sources = [ stickySource ];
646
+ var currentFetchID = 0;
647
+ var pendingSourceCnt = 0;
648
+ var loadingLevel = 0;
649
+ var cache = [];
650
+ var rangeStart, rangeEnd;
651
+
652
+ for (var i = 0; i < _sources.length; i++) {
653
+ _addEventSource(_sources[i]);
654
+ }
655
+
656
+ function isFetchNeeded(start, end) {
657
+ return !rangeStart || start < rangeStart || end > rangeEnd;
658
+ }
659
+
660
+ function fetchEvents(start, end) {
661
+ rangeStart = start;
662
+ rangeEnd = end;
663
+ cache = [];
664
+
665
+ var fetchID = ++currentFetchID;
666
+ var len = sources.length;
667
+
668
+ pendingSourceCnt = len;
669
+
670
+ for (var i = 0; i < len; i++) {
671
+ fetchEventSource(sources[i], fetchID);
672
+ }
673
+ }
674
+
675
+ function fetchEventSource(source, fetchID) {
676
+ _fetchEventSource(source, function (events) {
677
+ if (fetchID === currentFetchID) {
678
+ if (events) {
679
+
680
+ if (options.eventDataTransform) {
681
+ events = $.map(events, options.eventDataTransform);
682
+ }
683
+ if (source.eventDataTransform) {
684
+ events = $.map(events, source.eventDataTransform);
685
+ }
686
+
687
+ for (var i = 0; i < events.length; i++) {
688
+ events[i].source = source;
689
+ normalizeEvent(events[i]);
690
+ }
691
+
692
+ cache = cache.concat(events);
693
+ }
694
+
695
+ pendingSourceCnt--;
696
+
697
+ if (!pendingSourceCnt) reportEvents(cache);
698
+ }
699
+ });
700
+ }
701
+
702
+ function _fetchEventSource(source, callback) {
703
+ var fetchers = fc.sourceFetchers;
704
+ var res;
705
+
706
+ for (var i = 0; i < fetchers.length; i++) {
707
+ res = fetchers[i](source, rangeStart, rangeEnd, callback);
708
+
709
+ if (res === true) {
710
+ return;
711
+ } else if (typeof res === 'object') {
712
+ _fetchEventSource(res, callback);
713
+ return;
714
+ }
715
+ }
716
+
717
+ var events = source.events;
718
+
719
+ if (events) {
720
+ if ($.isFunction(events)) {
721
+ pushLoading();
722
+ events(cloneDate(rangeStart), cloneDate(rangeEnd), function (events) {
723
+ callback(events);
724
+ popLoading();
725
+ });
726
+ } else if ($.isArray(events)) {
727
+ callback(events);
728
+ } else {
729
+ callback();
730
+ }
731
+ } else {
732
+ var url = source.url;
733
+
734
+ if (url) {
735
+ var success = source.success;
736
+ var error = source.error;
737
+ var complete = source.complete;
738
+ var customData;
739
+
740
+ if ($.isFunction(source.data)) {
741
+ customData = source.data();
742
+ } else {
743
+ customData = source.data;
744
+ }
745
+
746
+ var data = $.extend({}, customData || {});
747
+ var startParam = firstDefined(source.startParam, options.startParam);
748
+ var endParam = firstDefined(source.endParam, options.endParam);
749
+
750
+ if (startParam) {
751
+ data[startParam] = Math.round(+rangeStart / 1000);
752
+ }
753
+ if (endParam) {
754
+ data[endParam] = Math.round(+rangeEnd / 1000);
755
+ }
756
+
757
+ pushLoading();
758
+
759
+ $.ajax($.extend({}, ajaxDefaults, source, {
760
+ data: data,
761
+ success: function (events) {
762
+ events = events || [];
763
+ var res = applyAll(success, this, arguments);
764
+
765
+ if ($.isArray(res)) {
766
+ events = res;
767
+ }
768
+
769
+ callback(events);
770
+ },
771
+ error: function () {
772
+ applyAll(error, this, arguments);
773
+ callback();
774
+ },
775
+ complete: function () {
776
+ applyAll(complete, this, arguments);
777
+ popLoading();
778
+ }
779
+ }));
780
+ } else {
781
+ callback();
782
+ }
783
+ }
784
+ }
785
+
786
+ function addEventSource(source) {
787
+ source = _addEventSource(source);
788
+
789
+ if (source) {
790
+ pendingSourceCnt++;
791
+
792
+ fetchEventSource(source, currentFetchID);
793
+ }
794
+ }
795
+
796
+ function _addEventSource(source) {
797
+ if ($.isFunction(source) || $.isArray(source)) {
798
+ source = { events: source };
799
+ } else if (typeof source === 'string') {
800
+ source = { url: source };
801
+ }
802
+
803
+ if (typeof source === 'object') {
804
+ normalizeSource(source);
805
+ sources.push(source);
806
+ return source;
807
+ }
808
+ }
809
+
810
+ function removeEventSource(source) {
811
+ sources = $.grep(sources, function (src) {
812
+ return !isSourcesEqual(src, source);
813
+ });
814
+ cache = $.grep(cache, function (e) {
815
+ return !isSourcesEqual(e.source, source);
816
+ });
817
+
818
+ reportEvents(cache);
819
+ }
820
+
821
+ function updateEvent(event) {
822
+ var len = cache.length;
823
+ var defaultEventEnd = getView().defaultEventEnd;
824
+ var startDelta = event.start - event._start;
825
+ var endDelta = event.end ? (event.end - (event._end || defaultEventEnd(event))) : 0;
826
+
827
+ for (var i = 0; i < len; i++) {
828
+ var e = cache[i];
829
+
830
+ if (e._id === event._id && e !== event) {
831
+ e.start = new Date(+e.start + startDelta);
832
+
833
+ if (event.end) {
834
+ if (e.end) {
835
+ e.end = new Date(+e.end + endDelta);
836
+ } else {
837
+ e.end = new Date(+defaultEventEnd(e) + endDelta);
838
+ }
839
+ } else {
840
+ e.end = null;
841
+ }
842
+
843
+ e.title = event.title;
844
+ e.url = event.url;
845
+ e.allDay = event.allDay;
846
+ e.className = event.className;
847
+ e.editable = event.editable;
848
+ e.color = event.color;
849
+ e.backgroundColor = event.backgroundColor;
850
+ e.borderColor = event.borderColor;
851
+ e.textColor = event.textColor;
852
+
853
+ normalizeEvent(e);
854
+ }
855
+ }
856
+
857
+ normalizeEvent(event);
858
+ reportEvents(cache);
859
+ }
860
+
861
+ function renderEvent(event, stick) {
862
+ normalizeEvent(event);
863
+
864
+ if (!event.source) {
865
+ if (stick) {
866
+ stickySource.events.push(event);
867
+ event.source = stickySource;
868
+ }
869
+
870
+ cache.push(event);
871
+ }
872
+
873
+ reportEvents(cache);
874
+ }
875
+
876
+ function removeEvents(filter) {
877
+ var i;
878
+
879
+ if (!filter) {
880
+ cache = [];
881
+
882
+ for (i = 0; i < sources.length; i++) {
883
+ if ($.isArray(sources[i].events)) {
884
+ sources[i].events = [];
885
+ }
886
+ }
887
+ } else {
888
+ if (!$.isFunction(filter)) {
889
+ var id = filter + '';
890
+
891
+ filter = function (e) {
892
+ return e._id === id;
893
+ };
894
+ }
895
+
896
+ cache = $.grep(cache, filter, true);
897
+
898
+ for (i = 0; i < sources.length; i++) {
899
+ if ($.isArray(sources[i].events)) {
900
+ sources[i].events = $.grep(sources[i].events, filter, true);
901
+ }
902
+ }
903
+ }
904
+
905
+ reportEvents(cache);
906
+ }
907
+
908
+ function clientEvents(filter) {
909
+ if ($.isFunction(filter)) {
910
+ return $.grep(cache, filter);
911
+ } else if (filter) {
912
+ filter += '';
913
+
914
+ return $.grep(cache, function (e) {
915
+ return e._id === filter;
916
+ });
917
+ }
918
+
919
+ return cache;
920
+ }
921
+
922
+ function pushLoading() {
923
+ if (!++loadingLevel) trigger('loading', null, true, getView());
924
+ }
925
+
926
+ function popLoading() {
927
+ if (!--loadingLevel) trigger('loading', null, false, getView());
928
+ }
929
+
930
+ function normalizeEvent(event) {
931
+ var source = event.source || {};
932
+ var ignoreTimezone = firstDefined(source.ignoreTimezone, options.ignoreTimezone);
933
+
934
+ event._id = event._id || (event.id === undefined ? '_fc' + eventGUID++ : event.id + '');
935
+
936
+ if (event.date) {
937
+ if (!event.start) {
938
+ event.start = event.date;
939
+ }
940
+
941
+ delete event.date;
942
+ }
943
+
944
+ event._start = cloneDate(event.start = parseDate(event.start, ignoreTimezone));
945
+ event.end = parseDate(event.end, ignoreTimezone);
946
+
947
+ if (event.end && event.end <= event.start) {
948
+ event.end = null;
949
+ }
950
+
951
+ event._end = event.end ? cloneDate(event.end) : null;
952
+
953
+ if (event.allDay === undefined) {
954
+ event.allDay = firstDefined(source.allDayDefault, options.allDayDefault);
955
+ }
956
+
957
+ if (event.className) {
958
+ if (typeof event.className === 'string') {
959
+ event.className = event.className.split(/\s+/);
960
+ }
961
+ } else {
962
+ event.className = [];
963
+ }
964
+ }
965
+
966
+ function normalizeSource(source) {
967
+ if (source.className) {
968
+ if (typeof source.className === 'string') {
969
+ source.className = source.className.split(/\s+/);
970
+ }
971
+ } else {
972
+ source.className = [];
973
+ }
974
+
975
+ var normalizers = fc.sourceNormalizers;
976
+
977
+ for (var i = 0; i < normalizers.length; i++) {
978
+ normalizers[i](source);
979
+ }
980
+ }
981
+
982
+ function isSourcesEqual(source1, source2) {
983
+ return source1 && source2 && getSourcePrimitive(source1) === getSourcePrimitive(source2);
984
+ }
985
+
986
+ function getSourcePrimitive(source) {
987
+ return ((typeof source === 'object') ? (source.googleCalendarId || source.events || source.url) : '') || source;
988
+ }
989
+ }
990
+
991
+ fc.addDays = addDays;
992
+ fc.cloneDate = cloneDate;
993
+ fc.parseDate = parseDate;
994
+ fc.parseISO8601 = parseISO8601;
995
+ fc.parseTime = parseTime;
996
+ fc.formatDate = formatDate;
997
+ fc.formatDates = formatDates;
998
+
999
+ var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
1000
+ var DAY_MS = 86400000;
1001
+ var HOUR_MS = 3600000;
1002
+ var MINUTE_MS = 60000;
1003
+
1004
+ function addYears(d, n, keepTime) {
1005
+ d.setFullYear(d.getFullYear() + n);
1006
+
1007
+ if (!keepTime) clearTime(d);
1008
+
1009
+ return d;
1010
+ }
1011
+
1012
+ function addMonths(d, n, keepTime) {
1013
+ if (+d) {
1014
+ var m = d.getMonth() + n;
1015
+ var check = cloneDate(d);
1016
+
1017
+ check.setDate(1);
1018
+ check.setMonth(m);
1019
+ d.setMonth(m);
1020
+
1021
+ if (!keepTime) clearTime(d);
1022
+
1023
+ while (d.getMonth() !== check.getMonth()) {
1024
+ d.setDate(d.getDate() + (d < check ? 1 : -1));
1025
+ }
1026
+ }
1027
+
1028
+ return d;
1029
+ }
1030
+
1031
+ function addDays(d, n, keepTime) {
1032
+ if (+d) {
1033
+ var dd = d.getDate() + n;
1034
+ var check = cloneDate(d);
1035
+
1036
+ check.setHours(9);
1037
+ check.setDate(dd);
1038
+ d.setDate(dd);
1039
+
1040
+ if (!keepTime) clearTime(d);
1041
+
1042
+ fixDate(d, check);
1043
+ }
1044
+
1045
+ return d;
1046
+ }
1047
+
1048
+ function fixDate(d, check) {
1049
+ if (+d) {
1050
+ while (d.getDate() !== check.getDate()) {
1051
+ d.setTime(+d + (d < check ? 1 : -1) * HOUR_MS);
1052
+ }
1053
+ }
1054
+ }
1055
+
1056
+ function addMinutes(d, n) {
1057
+ d.setMinutes(d.getMinutes() + n);
1058
+ return d;
1059
+ }
1060
+
1061
+ function clearTime(d) {
1062
+ d.setHours(0);
1063
+ d.setMinutes(0);
1064
+ d.setSeconds(0);
1065
+ d.setMilliseconds(0);
1066
+ return d;
1067
+ }
1068
+
1069
+ function cloneDate(d, dontKeepTime) {
1070
+ if (dontKeepTime) return clearTime(new Date(+d));
1071
+ return new Date(+d);
1072
+ }
1073
+
1074
+ function zeroDate() {
1075
+ var i = 0, d;
1076
+
1077
+ do {
1078
+ d = new Date(1970, i++, 1);
1079
+ } while (d.getHours());
1080
+
1081
+ return d;
1082
+ }
1083
+
1084
+ function dayDiff(d1, d2) {
1085
+ return Math.round((cloneDate(d1, true) - cloneDate(d2, true)) / DAY_MS);
1086
+ }
1087
+
1088
+ function setYMD(date, y, m, d) {
1089
+ if (y !== undefined && y !== date.getFullYear()) {
1090
+ date.setDate(1);
1091
+ date.setMonth(0);
1092
+ date.setFullYear(y);
1093
+ }
1094
+
1095
+ if (m !== undefined && m !== date.getMonth()) {
1096
+ date.setDate(1);
1097
+ date.setMonth(m);
1098
+ }
1099
+
1100
+ if (d !== undefined) date.setDate(d);
1101
+ }
1102
+
1103
+ function parseDate(s, ignoreTimezone) {
1104
+ if (typeof s === 'object') return s;
1105
+ if (typeof s === 'number') return new Date(s * 1000);
1106
+
1107
+ if (typeof s === 'string') {
1108
+ if (s.match(/^\d+(\.\d+)?$/)) return new Date(parseFloat(s) * 1000);
1109
+
1110
+ if (ignoreTimezone === undefined) {
1111
+ ignoreTimezone = true;
1112
+ }
1113
+
1114
+ return parseISO8601(s, ignoreTimezone) || (s ? new Date(s) : null);
1115
+ }
1116
+
1117
+ return null;
1118
+ }
1119
+
1120
+ function parseISO8601(s, ignoreTimezone) {
1121
+ var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);
1122
+
1123
+ if (!m) return null;
1124
+
1125
+ var date = new Date(m[1], 0, 1);
1126
+
1127
+ if (ignoreTimezone || !m[13]) {
1128
+ var check = new Date(m[1], 0, 1, 9, 0);
1129
+
1130
+ if (m[3]) {
1131
+ date.setMonth(m[3] - 1);
1132
+ check.setMonth(m[3] - 1);
1133
+ }
1134
+ if (m[5]) {
1135
+ date.setDate(m[5]);
1136
+ check.setDate(m[5]);
1137
+ }
1138
+
1139
+ fixDate(date, check);
1140
+
1141
+ if (m[7]) date.setHours(m[7]);
1142
+ if (m[8]) date.setMinutes(m[8]);
1143
+ if (m[10]) date.setSeconds(m[10]);
1144
+ if (m[12]) date.setMilliseconds(Number('0.' + m[12]) * 1000);
1145
+
1146
+ fixDate(date, check);
1147
+ } else {
1148
+ date.setUTCFullYear(
1149
+ m[1],
1150
+ m[3] ? m[3] - 1 : 0,
1151
+ m[5] || 1
1152
+ );
1153
+ date.setUTCHours(
1154
+ m[7] || 0,
1155
+ m[8] || 0,
1156
+ m[10] || 0,
1157
+ m[12] ? Number('0.' + m[12]) * 1000 : 0
1158
+ );
1159
+
1160
+ if (m[14]) {
1161
+ var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0);
1162
+
1163
+ offset *= m[15] === '-' ? 1 : -1;
1164
+ date = new Date(+date + (offset * 60 * 1000));
1165
+ }
1166
+ }
1167
+ return date;
1168
+ }
1169
+
1170
+ function parseTime(s) {
1171
+ if (typeof s === 'number') return s * 60;
1172
+ if (typeof s === 'object') return s.getHours() * 60 + s.getMinutes();
1173
+
1174
+ var m = s.match(/(\d+)(?::(\d+))?\s*(\w+)?/);
1175
+
1176
+ if (m) {
1177
+ var h = parseInt(m[1], 10);
1178
+
1179
+ if (m[3]) {
1180
+ h %= 12;
1181
+
1182
+ if (m[3].toLowerCase().charAt(0) === 'p') h += 12;
1183
+ }
1184
+
1185
+ return h * 60 + (m[2] ? parseInt(m[2], 10) : 0);
1186
+ }
1187
+ }
1188
+
1189
+ function formatDate(date, format, options) {
1190
+ return formatDates(date, null, format, options);
1191
+ }
1192
+
1193
+ function formatDates(date1, date2, format, options) {
1194
+ options = options || defaults;
1195
+
1196
+ var c, i, i2, formatter, subres;
1197
+ var date = date1;
1198
+ var otherDate = date2;
1199
+ var len = format.length;
1200
+ var res = '';
1201
+
1202
+ for (i = 0; i < len; i++) {
1203
+ c = format.charAt(i);
1204
+
1205
+ if (c === "'") {
1206
+ for (i2 = i + 1; i2 < len; i2++) {
1207
+ if (format.charAt(i2) === "'") {
1208
+ if (date) {
1209
+ if (i2 === i+1) {
1210
+ res += "'";
1211
+ } else {
1212
+ res += format.substring(i+1, i2);
1213
+ }
1214
+
1215
+ i = i2;
1216
+ }
1217
+
1218
+ break;
1219
+ }
1220
+ }
1221
+ } else if (c === '(') {
1222
+ for (i2 = i + 1; i2 < len; i2++) {
1223
+ if (format.charAt(i2) === ')') {
1224
+ subres = formatDate(date, format.substring(i + 1, i2), options);
1225
+
1226
+ if (parseInt(subres.replace(/\D/, ''), 10)) res += subres;
1227
+
1228
+ i = i2;
1229
+ break;
1230
+ }
1231
+ }
1232
+ } else if (c === '[') {
1233
+ for (i2 = i + 1; i2 < len; i2++) {
1234
+ if (format.charAt(i2) === ']') {
1235
+ var subformat = format.substring(i + 1, i2);
1236
+ subres = formatDate(date, subformat, options);
1237
+
1238
+ if (subres !== formatDate(otherDate, subformat, options)) res += subres;
1239
+
1240
+ i = i2;
1241
+ break;
1242
+ }
1243
+ }
1244
+ } else if (c === '{') {
1245
+ date = date2;
1246
+ otherDate = date1;
1247
+ } else if (c === '}') {
1248
+ date = date1;
1249
+ otherDate = date2;
1250
+ } else {
1251
+ for (i2 = len; i2 > i; i2--) {
1252
+ if (formatter = dateFormatters[format.substring(i, i2)]) {
1253
+ if (date) res += formatter(date, options);
1254
+
1255
+ i = i2 - 1;
1256
+ break;
1257
+ }
1258
+ }
1259
+
1260
+ if (i2 === i) {
1261
+ if (date) res += c;
1262
+ }
1263
+ }
1264
+ }
1265
+
1266
+ return res;
1267
+ }
1268
+
1269
+ var dateFormatters = {
1270
+ s: function (d) { return d.getSeconds(); },
1271
+ ss: function (d) { return zeroPad(d.getSeconds()); },
1272
+ m: function (d) { return d.getMinutes(); },
1273
+ mm: function (d) { return zeroPad(d.getMinutes()); },
1274
+ h: function (d) { return d.getHours() % 12 || 12; },
1275
+ hh: function (d) { return zeroPad(d.getHours() % 12 || 12); },
1276
+ H: function (d) { return d.getHours(); },
1277
+ HH: function (d) { return zeroPad(d.getHours()); },
1278
+ d: function (d) { return d.getDate(); },
1279
+ dd: function (d) { return zeroPad(d.getDate()); },
1280
+ ddd: function (d,o) { return o.dayNamesShort[d.getDay()]; },
1281
+ dddd: function (d,o) { return o.dayNames[d.getDay()]; },
1282
+ M: function (d) { return d.getMonth() + 1; },
1283
+ MM: function (d) { return zeroPad(d.getMonth() + 1); },
1284
+ MMM: function (d,o) { return o.monthNamesShort[d.getMonth()]; },
1285
+ MMMM: function (d,o) { return o.monthNames[d.getMonth()]; },
1286
+ yy: function (d) { return (d.getFullYear()+'').substring(2); },
1287
+ yyyy: function (d) { return d.getFullYear(); },
1288
+ t: function (d) { return d.getHours() < 12 ? 'a' : 'p'; },
1289
+ tt: function (d) { return d.getHours() < 12 ? 'am' : 'pm'; },
1290
+ T: function (d) { return d.getHours() < 12 ? 'A' : 'P'; },
1291
+ TT: function (d) { return d.getHours() < 12 ? 'AM' : 'PM'; },
1292
+ u: function (d) { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'"); },
1293
+ S: function (d) {
1294
+ var date = d.getDate();
1295
+
1296
+ if (date > 10 && date < 20) return 'th';
1297
+
1298
+ return ['st', 'nd', 'rd'][date%10-1] || 'th';
1299
+ },
1300
+ w: function (d, o) { return o.weekNumberCalculation(d); },
1301
+ W: function (d) { return iso8601Week(d); }
1302
+ };
1303
+
1304
+ fc.dateFormatters = dateFormatters;
1305
+
1306
+ function iso8601Week(date) {
1307
+ var checkDate = new Date(date.getTime());
1308
+
1309
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
1310
+
1311
+ var time = checkDate.getTime();
1312
+
1313
+ checkDate.setMonth(0);
1314
+ checkDate.setDate(1);
1315
+
1316
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
1317
+ }
1318
+
1319
+ fc.applyAll = applyAll;
1320
+
1321
+ function exclEndDay(event) {
1322
+ if (event.end) {
1323
+ return _exclEndDay(event.end, event.allDay);
1324
+ } else {
1325
+ return addDays(cloneDate(event.start), 1);
1326
+ }
1327
+ }
1328
+
1329
+ function _exclEndDay(end, allDay) {
1330
+ end = cloneDate(end);
1331
+ return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end);
1332
+ }
1333
+
1334
+ function lazySegBind(container, segs, bindHandlers) {
1335
+ container
1336
+ .unbind('mouseover')
1337
+ .mouseover(function (ev) {
1338
+ var e, i, seg;
1339
+ var parent = ev.target;
1340
+
1341
+ while (parent !== this) {
1342
+ e = parent;
1343
+ parent = parent.parentNode;
1344
+ }
1345
+
1346
+ if ((i = e._fci) !== undefined) {
1347
+ e._fci = undefined;
1348
+ seg = segs[i];
1349
+ bindHandlers(seg.event, seg.element, seg);
1350
+ $(ev.target).trigger(ev);
1351
+ }
1352
+
1353
+ ev.stopPropagation();
1354
+ });
1355
+ }
1356
+
1357
+ function setOuterWidth(element, width, includeMargins) {
1358
+ for (var i = 0, e; i < element.length; i++) {
1359
+ e = $(element[i]);
1360
+ e.width(Math.max(0, width - hsides(e, includeMargins)));
1361
+ }
1362
+ }
1363
+
1364
+ function setOuterHeight(element, height, includeMargins) {
1365
+ for (var i = 0, e; i < element.length; i++) {
1366
+ e = $(element[i]);
1367
+ e.height(Math.max(0, height - vsides(e, includeMargins)));
1368
+ }
1369
+ }
1370
+
1371
+ function hsides(element, includeMargins) {
1372
+ return hpadding(element) + hborders(element) + (includeMargins ? hmargins(element) : 0);
1373
+ }
1374
+
1375
+ function hpadding(element) {
1376
+ return (parseFloat($.css(element[0], 'paddingLeft', true)) || 0) +
1377
+ (parseFloat($.css(element[0], 'paddingRight', true)) || 0);
1378
+ }
1379
+
1380
+ function hmargins(element) {
1381
+ return (parseFloat($.css(element[0], 'marginLeft', true)) || 0) +
1382
+ (parseFloat($.css(element[0], 'marginRight', true)) || 0);
1383
+ }
1384
+
1385
+ function hborders(element) {
1386
+ return (parseFloat($.css(element[0], 'borderLeftWidth', true)) || 0) +
1387
+ (parseFloat($.css(element[0], 'borderRightWidth', true)) || 0);
1388
+ }
1389
+
1390
+ function vsides(element, includeMargins) {
1391
+ return vpadding(element) + vborders(element) + (includeMargins ? vmargins(element) : 0);
1392
+ }
1393
+
1394
+ function vpadding(element) {
1395
+ return (parseFloat($.css(element[0], 'paddingTop', true)) || 0) +
1396
+ (parseFloat($.css(element[0], 'paddingBottom', true)) || 0);
1397
+ }
1398
+
1399
+ function vmargins(element) {
1400
+ return (parseFloat($.css(element[0], 'marginTop', true)) || 0) +
1401
+ (parseFloat($.css(element[0], 'marginBottom', true)) || 0);
1402
+ }
1403
+
1404
+ function vborders(element) {
1405
+ return (parseFloat($.css(element[0], 'borderTopWidth', true)) || 0) +
1406
+ (parseFloat($.css(element[0], 'borderBottomWidth', true)) || 0);
1407
+ }
1408
+
1409
+ function noop() {}
1410
+
1411
+ function dateCompare(a, b) {
1412
+ return a - b;
1413
+ }
1414
+
1415
+ function arrayMax(a) {
1416
+ return Math.max.apply(Math, a);
1417
+ }
1418
+
1419
+ function zeroPad(n) {
1420
+ return (n < 10 ? '0' : '') + n;
1421
+ }
1422
+
1423
+ function smartProperty(obj, name) {
1424
+ if (obj[name] !== undefined) return obj[name];
1425
+
1426
+ var res;
1427
+ var parts = name.split(/(?=[A-Z])/);
1428
+
1429
+ for (var i = parts.length - 1; i >= 0; i--) {
1430
+ res = obj[parts[i].toLowerCase()];
1431
+ if (res !== undefined) return res;
1432
+ }
1433
+
1434
+ return obj[''];
1435
+ }
1436
+
1437
+ function htmlEscape(s) {
1438
+ return s.replace(/&/g, '&amp;')
1439
+ .replace(/</g, '&lt;')
1440
+ .replace(/>/g, '&gt;')
1441
+ .replace(/'/g, '&#039;')
1442
+ .replace(/"/g, '&quot;')
1443
+ .replace(/\n/g, '<br />');
1444
+ }
1445
+
1446
+ function disableTextSelection(element) {
1447
+ element
1448
+ .attr('unselectable', 'on')
1449
+ .css('MozUserSelect', 'none')
1450
+ .bind('selectstart.ui', function () { return false; });
1451
+ }
1452
+
1453
+ function markFirstLast(e) {
1454
+ e.children()
1455
+ .removeClass('calendar-first calendar-last')
1456
+ .filter(':first-child')
1457
+ .addClass('calendar-first')
1458
+ .end()
1459
+ .filter(':last-child')
1460
+ .addClass('calendar-last');
1461
+ }
1462
+
1463
+ function setDayID(cell, date) {
1464
+ cell.each(function (i, _cell) {
1465
+ _cell.className = _cell.className.replace(/^calendar-\w*/, 'calendar-' + dayIDs[date.getDay()]);
1466
+ });
1467
+ }
1468
+
1469
+ function getSkinCss(event, opt) {
1470
+ var source = event.source || {};
1471
+ var eventColor = event.color;
1472
+ var sourceColor = source.color;
1473
+ var optionColor = opt('eventColor');
1474
+ var statements = [];
1475
+ var backgroundColor =
1476
+ event.backgroundColor ||
1477
+ eventColor ||
1478
+ source.backgroundColor ||
1479
+ sourceColor ||
1480
+ opt('eventBackgroundColor') ||
1481
+ optionColor;
1482
+ var borderColor =
1483
+ event.borderColor ||
1484
+ eventColor ||
1485
+ source.borderColor ||
1486
+ sourceColor ||
1487
+ opt('eventBorderColor') ||
1488
+ optionColor;
1489
+ var textColor =
1490
+ event.textColor ||
1491
+ source.textColor ||
1492
+ opt('eventTextColor');
1493
+
1494
+ if (backgroundColor) statements.push('background-color:' + backgroundColor);
1495
+ if (borderColor) statements.push('border-color:' + borderColor);
1496
+ if (textColor) statements.push('color:' + textColor);
1497
+
1498
+ return statements.join(';');
1499
+ }
1500
+
1501
+ function applyAll(functions, thisObj, args) {
1502
+ if ($.isFunction(functions)) {
1503
+ functions = [ functions ];
1504
+ }
1505
+
1506
+ if (functions) {
1507
+ var ret;
1508
+
1509
+ for (var i = 0; i < functions.length; i++) {
1510
+ ret = functions[i].apply(thisObj, args) || ret;
1511
+ }
1512
+
1513
+ return ret;
1514
+ }
1515
+ }
1516
+
1517
+ function firstDefined() {
1518
+ for (var i = 0; i < arguments.length; i++) {
1519
+ if (arguments[i] !== undefined) return arguments[i];
1520
+ }
1521
+ }
1522
+
1523
+ fcViews.month = MonthView;
1524
+
1525
+ function MonthView(element, calendar) {
1526
+ var t = this;
1527
+
1528
+ t.render = render;
1529
+
1530
+ BasicView.call(t, element, calendar, 'month');
1531
+
1532
+ var opt = t.opt;
1533
+ var renderBasic = t.renderBasic;
1534
+ var skipHiddenDays = t.skipHiddenDays;
1535
+ var getCellsPerWeek = t.getCellsPerWeek;
1536
+ var formatDate = calendar.formatDate;
1537
+
1538
+ function render(date, delta) {
1539
+ if (delta) {
1540
+ addMonths(date, delta);
1541
+ date.setDate(1);
1542
+ }
1543
+
1544
+ var firstDay = opt('firstDay');
1545
+ var start = cloneDate(date, true);
1546
+
1547
+ start.setDate(1);
1548
+
1549
+ var end = addMonths(cloneDate(start), 1);
1550
+ var visStart = cloneDate(start);
1551
+
1552
+ addDays(visStart, -((visStart.getDay() - firstDay + 7) % 7));
1553
+ skipHiddenDays(visStart);
1554
+
1555
+ var visEnd = cloneDate(end);
1556
+
1557
+ addDays(visEnd, (7 - visEnd.getDay() + firstDay) % 7);
1558
+ skipHiddenDays(visEnd, -1, true);
1559
+
1560
+ var colCnt = getCellsPerWeek();
1561
+ var rowCnt = Math.round(dayDiff(visEnd, visStart) / 7);
1562
+
1563
+ if (opt('weekMode') === 'fixed') {
1564
+ addDays(visEnd, (6 - rowCnt) * 7);
1565
+ rowCnt = 6;
1566
+ }
1567
+
1568
+ t.title = formatDate(start, opt('titleFormat'));
1569
+ t.start = start;
1570
+ t.end = end;
1571
+ t.visStart = visStart;
1572
+ t.visEnd = visEnd;
1573
+
1574
+ renderBasic(rowCnt, colCnt, true);
1575
+ }
1576
+ }
1577
+
1578
+ fcViews.basicWeek = BasicWeekView;
1579
+
1580
+ function BasicWeekView(element, calendar) {
1581
+ var t = this;
1582
+
1583
+ t.render = render;
1584
+
1585
+ BasicView.call(t, element, calendar, 'basicWeek');
1586
+
1587
+ var opt = t.opt;
1588
+ var renderBasic = t.renderBasic;
1589
+ var skipHiddenDays = t.skipHiddenDays;
1590
+ var getCellsPerWeek = t.getCellsPerWeek;
1591
+ var formatDates = calendar.formatDates;
1592
+
1593
+ function render(date, delta) {
1594
+ if (delta) addDays(date, delta * 7);
1595
+
1596
+ var start = addDays(cloneDate(date), -((date.getDay() - opt('firstDay') + 7) % 7));
1597
+ var end = addDays(cloneDate(start), 7);
1598
+ var visStart = cloneDate(start);
1599
+
1600
+ skipHiddenDays(visStart);
1601
+
1602
+ var visEnd = cloneDate(end);
1603
+
1604
+ skipHiddenDays(visEnd, -1, true);
1605
+
1606
+ var colCnt = getCellsPerWeek();
1607
+
1608
+ t.start = start;
1609
+ t.end = end;
1610
+ t.visStart = visStart;
1611
+ t.visEnd = visEnd;
1612
+ t.title = formatDates(
1613
+ visStart,
1614
+ addDays(cloneDate(visEnd), -1),
1615
+ opt('titleFormat')
1616
+ );
1617
+
1618
+ renderBasic(1, colCnt, false);
1619
+ }
1620
+ }
1621
+
1622
+ fcViews.basicDay = BasicDayView;
1623
+
1624
+ function BasicDayView(element, calendar) {
1625
+ var t = this;
1626
+
1627
+ t.render = render;
1628
+
1629
+ BasicView.call(t, element, calendar, 'basicDay');
1630
+
1631
+ var opt = t.opt;
1632
+ var renderBasic = t.renderBasic;
1633
+ var skipHiddenDays = t.skipHiddenDays;
1634
+ var formatDate = calendar.formatDate;
1635
+
1636
+ function render(date, delta) {
1637
+ if (delta) addDays(date, delta);
1638
+
1639
+ skipHiddenDays(date, delta < 0 ? -1 : 1);
1640
+
1641
+ var start = cloneDate(date, true);
1642
+ var end = addDays(cloneDate(start), 1);
1643
+
1644
+ t.title = formatDate(date, opt('titleFormat'));
1645
+ t.start = t.visStart = start;
1646
+ t.end = t.visEnd = end;
1647
+
1648
+ renderBasic(1, 1, false);
1649
+ }
1650
+ }
1651
+
1652
+ setDefaults({ weekMode: 'fixed' });
1653
+
1654
+ function BasicView(element, calendar, viewName) {
1655
+ var t = this;
1656
+
1657
+ t.renderBasic = renderBasic;
1658
+ t.setHeight = setHeight;
1659
+ t.setWidth = setWidth;
1660
+ t.renderDayOverlay = renderDayOverlay;
1661
+ t.defaultSelectionEnd = defaultSelectionEnd;
1662
+ t.renderSelection = renderSelection;
1663
+ t.clearSelection = clearSelection;
1664
+ t.reportDayClick = reportDayClick;
1665
+ t.dragStart = dragStart;
1666
+ t.dragStop = dragStop;
1667
+ t.defaultEventEnd = defaultEventEnd;
1668
+ t.getHoverListener = function () { return hoverListener; };
1669
+ t.colLeft = colLeft;
1670
+ t.colRight = colRight;
1671
+ t.colContentLeft = colContentLeft;
1672
+ t.colContentRight = colContentRight;
1673
+ t.getIsCellAllDay = function () { return true; };
1674
+ t.allDayRow = allDayRow;
1675
+ t.getRowCnt = function () { return rowCnt; };
1676
+ t.getColCnt = function () { return colCnt; };
1677
+ t.getColWidth = function () { return colWidth; };
1678
+ t.getDaySegmentContainer = function () { return daySegmentContainer; };
1679
+
1680
+ View.call(t, element, calendar, viewName);
1681
+ OverlayManager.call(t);
1682
+ SelectionManager.call(t);
1683
+ BasicEventRenderer.call(t);
1684
+
1685
+ var opt = t.opt;
1686
+ var trigger = t.trigger;
1687
+ var renderOverlay = t.renderOverlay;
1688
+ var clearOverlays = t.clearOverlays;
1689
+ var daySelectionMousedown = t.daySelectionMousedown;
1690
+ var cellToDate = t.cellToDate;
1691
+ var dateToCell = t.dateToCell;
1692
+ var rangeToSegments = t.rangeToSegments;
1693
+ var formatDate = calendar.formatDate;
1694
+ var table, head, headCells, body, bodyRows, bodyCells, bodyFirstCells, firstRowCellInners,
1695
+ firstRowCellContentInners, daySegmentContainer, viewWidth, viewHeight, colWidth, weekNumberWidth, rowCnt, colCnt,
1696
+ showNumbers, coordinateGrid, hoverListener, colPositions, colContentPositions, colFormat, showWeekNumbers,
1697
+ weekNumberTitle, weekNumberFormat;
1698
+
1699
+ disableTextSelection(element.addClass('calendar-grid'));
1700
+
1701
+ function renderBasic(_rowCnt, _colCnt, _showNumbers) {
1702
+ rowCnt = _rowCnt;
1703
+ colCnt = _colCnt;
1704
+ showNumbers = _showNumbers;
1705
+
1706
+ updateOptions();
1707
+
1708
+ if (!body) buildEventContainer();
1709
+
1710
+ buildTable();
1711
+ }
1712
+
1713
+ function updateOptions() {
1714
+ colFormat = opt('columnFormat');
1715
+ showWeekNumbers = opt('weekNumbers');
1716
+ weekNumberTitle = opt('weekNumberTitle');
1717
+
1718
+ if (opt('weekNumberCalculation') !== 'iso') {
1719
+ weekNumberFormat = 'w';
1720
+ } else {
1721
+ weekNumberFormat = 'W';
1722
+ }
1723
+ }
1724
+
1725
+ function buildEventContainer() {
1726
+ daySegmentContainer =
1727
+ $('<div class="calendar-event-container" style="position: absolute; z-index: 8; top: 0; left: 0;"/>')
1728
+ .appendTo(element);
1729
+ }
1730
+
1731
+ function buildTable() {
1732
+ var html = buildTableHTML();
1733
+
1734
+ if (table) table.remove();
1735
+
1736
+ table = $(html).appendTo(element);
1737
+ head = table.find('thead');
1738
+ headCells = head.find('.calendar-day-header');
1739
+ body = table.find('tbody');
1740
+ bodyRows = body.find('tr');
1741
+ bodyCells = body.find('.calendar-day');
1742
+ bodyFirstCells = bodyRows.find('td:first-child');
1743
+ firstRowCellInners = bodyRows.eq(0).find('.calendar-day > div');
1744
+ firstRowCellContentInners = bodyRows.eq(0).find('.calendar-day-content > div');
1745
+
1746
+ markFirstLast(head.add(head.find('tr')));
1747
+ markFirstLast(bodyRows);
1748
+
1749
+ bodyRows.eq(0).addClass('calendar-first');
1750
+ bodyRows.filter(':last').addClass('calendar-last');
1751
+ bodyCells.each(function (i, _cell) {
1752
+ var date = cellToDate(
1753
+ Math.floor(i / colCnt),
1754
+ i % colCnt
1755
+ );
1756
+
1757
+ trigger('dayRender', t, date, $(_cell));
1758
+ });
1759
+
1760
+ dayBind(bodyCells);
1761
+ }
1762
+
1763
+ function buildTableHTML() {
1764
+ var html =
1765
+ '<table class="calendar-border-separate" style="width: 100%;" cellspacing="0">' +
1766
+ buildHeadHTML() +
1767
+ buildBodyHTML() +
1768
+ '</table>';
1769
+
1770
+ return html;
1771
+ }
1772
+
1773
+ function buildHeadHTML() {
1774
+ var col, date;
1775
+ var headerClass = 'calendar-widget-header';
1776
+ var html = '';
1777
+
1778
+ html += '<thead><tr>';
1779
+
1780
+ if (showWeekNumbers) {
1781
+ html +=
1782
+ '<th class="calendar-week-number ' + headerClass + '">' +
1783
+ htmlEscape(weekNumberTitle) +
1784
+ '</th>';
1785
+ }
1786
+
1787
+ for (col = 0; col < colCnt; col++) {
1788
+ date = cellToDate(0, col);
1789
+ html +=
1790
+ '<th class="calendar-day-header calendar-' + dayIDs[date.getDay()] + ' ' + headerClass + '">' +
1791
+ htmlEscape(formatDate(date, colFormat)) +
1792
+ '</th>';
1793
+ }
1794
+
1795
+ html += '</tr></thead>';
1796
+
1797
+ return html;
1798
+ }
1799
+
1800
+ function buildBodyHTML() {
1801
+ var row, col, date;
1802
+ var contentClass = 'calendar-widget-content';
1803
+ var html = '';
1804
+
1805
+ html += '<tbody>';
1806
+
1807
+ for (row = 0; row < rowCnt; row++) {
1808
+ html += '<tr class="calendar-week">';
1809
+
1810
+ if (showWeekNumbers) {
1811
+ date = cellToDate(row, 0);
1812
+ html +=
1813
+ '<td class="calendar-week-number ' + contentClass + '">' +
1814
+ '<div>' +
1815
+ htmlEscape(formatDate(date, weekNumberFormat)) +
1816
+ '</div>' +
1817
+ '</td>';
1818
+ }
1819
+
1820
+ for (col = 0; col < colCnt; col++) {
1821
+ date = cellToDate(row, col);
1822
+ html += buildCellHTML(date);
1823
+ }
1824
+
1825
+ html += '</tr>';
1826
+ }
1827
+
1828
+ html += '</tbody>';
1829
+
1830
+ return html;
1831
+ }
1832
+
1833
+ function buildCellHTML(date) {
1834
+ var html = '';
1835
+ var contentClass = 'calendar-widget-content';
1836
+ var month = t.start.getMonth();
1837
+ var today = clearTime(new Date());
1838
+ var classNames = [
1839
+ 'calendar-day',
1840
+ 'calendar-' + dayIDs[date.getDay()],
1841
+ contentClass
1842
+ ];
1843
+
1844
+ if (date.getMonth() !== month) classNames.push('calendar-other-month');
1845
+
1846
+ if (+date === +today) {
1847
+ classNames.push('calendar-today', 'calendar-state-highlight');
1848
+ } else if (date < today) {
1849
+ classNames.push('calendar-past');
1850
+ } else {
1851
+ classNames.push('calendar-future');
1852
+ }
1853
+
1854
+ html +=
1855
+ '<td class="' + classNames.join(' ') + '" data-date="' + formatDate(date, 'yyyy-MM-dd') + '"><div>';
1856
+
1857
+ if (showNumbers) html += '<div class="calendar-day-number">' + date.getDate() + '</div>';
1858
+
1859
+ html += '<div class="calendar-day-content">' +
1860
+ '<div style="position: relative;">&nbsp;</div>' +
1861
+ '</div>' +
1862
+ '</div>' +
1863
+ '</td>';
1864
+
1865
+ return html;
1866
+ }
1867
+
1868
+ function setHeight(height) {
1869
+ viewHeight = height;
1870
+
1871
+ var bodyHeight = viewHeight - head.height();
1872
+ var cell, rowHeight, rowHeightLast;
1873
+
1874
+ if (opt('weekMode') === 'variable') {
1875
+ rowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6));
1876
+ } else {
1877
+ rowHeight = Math.floor(bodyHeight / rowCnt);
1878
+ rowHeightLast = bodyHeight - rowHeight * (rowCnt-1);
1879
+ }
1880
+
1881
+ bodyFirstCells.each(function (i, _cell) {
1882
+ if (i < rowCnt) {
1883
+ cell = $(_cell);
1884
+ cell.find('> div')
1885
+ .css('min-height', (i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell));
1886
+ }
1887
+ });
1888
+ }
1889
+
1890
+ function setWidth(width) {
1891
+ viewWidth = width;
1892
+
1893
+ colPositions.clear();
1894
+ colContentPositions.clear();
1895
+
1896
+ weekNumberWidth = 0;
1897
+
1898
+ if (showWeekNumbers) {
1899
+ weekNumberWidth = head.find('th.calendar-week-number').outerWidth();
1900
+ }
1901
+
1902
+ colWidth = Math.floor((viewWidth - weekNumberWidth) / colCnt);
1903
+
1904
+ setOuterWidth(headCells.slice(0, -1), colWidth);
1905
+ }
1906
+
1907
+ function dayBind(days) {
1908
+ days.click(dayClick)
1909
+ .mousedown(daySelectionMousedown);
1910
+ }
1911
+
1912
+ function dayClick(ev) {
1913
+ if (!opt('selectable')) {
1914
+ var date = parseISO8601($(this).data('date'));
1915
+ trigger('dayClick', this, date, true, ev);
1916
+ }
1917
+ }
1918
+
1919
+ function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) {
1920
+ if (refreshCoordinateGrid) coordinateGrid.build();
1921
+
1922
+ var segments = rangeToSegments(overlayStart, overlayEnd);
1923
+
1924
+ for (var i = 0; i < segments.length; i++) {
1925
+ var segment = segments[i];
1926
+
1927
+ dayBind(renderCellOverlay(segment.row, segment.leftCol, segment.row, segment.rightCol));
1928
+ }
1929
+ }
1930
+
1931
+ function renderCellOverlay(row0, col0, row1, col1) {
1932
+ var rect = coordinateGrid.rect(row0, col0, row1, col1, element);
1933
+ return renderOverlay(rect, element);
1934
+ }
1935
+
1936
+ function defaultSelectionEnd(startDate, allDay) {
1937
+ return cloneDate(startDate);
1938
+ }
1939
+
1940
+ function renderSelection(startDate, endDate, allDay) {
1941
+ renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true);
1942
+ }
1943
+
1944
+ function clearSelection() {
1945
+ clearOverlays();
1946
+ }
1947
+
1948
+ function reportDayClick(date, allDay, ev) {
1949
+ var cell = dateToCell(date);
1950
+ var _element = bodyCells[cell.row*colCnt + cell.col];
1951
+
1952
+ trigger('dayClick', _element, date, allDay, ev);
1953
+ }
1954
+
1955
+ function dragStart(_dragElement, ev, ui) {
1956
+ hoverListener.start(function (cell) {
1957
+ clearOverlays();
1958
+
1959
+ if (cell) renderCellOverlay(cell.row, cell.col, cell.row, cell.col);
1960
+ }, ev);
1961
+ }
1962
+
1963
+ function dragStop(_dragElement, ev, ui) {
1964
+ var cell = hoverListener.stop();
1965
+
1966
+ clearOverlays();
1967
+
1968
+ if (cell) {
1969
+ var d = cellToDate(cell);
1970
+
1971
+ trigger('drop', _dragElement, d, true, ev, ui);
1972
+ }
1973
+ }
1974
+
1975
+ function defaultEventEnd(event) {
1976
+ return cloneDate(event.start);
1977
+ }
1978
+
1979
+ coordinateGrid = new CoordinateGrid(function (rows, cols) {
1980
+ var e, n, p;
1981
+
1982
+ headCells.each(function (i, _e) {
1983
+ e = $(_e);
1984
+ n = e.offset().left;
1985
+
1986
+ if (i) {
1987
+ p[1] = n;
1988
+ }
1989
+
1990
+ p = [n];
1991
+ cols[i] = p;
1992
+ });
1993
+
1994
+ p[1] = n + e.outerWidth();
1995
+
1996
+ bodyRows.each(function (i, _e) {
1997
+ if (i < rowCnt) {
1998
+ e = $(_e);
1999
+ n = e.offset().top;
2000
+
2001
+ if (i) {
2002
+ p[1] = n;
2003
+ }
2004
+
2005
+ p = [n];
2006
+ rows[i] = p;
2007
+ }
2008
+ });
2009
+
2010
+ p[1] = n + e.outerHeight();
2011
+ });
2012
+
2013
+ hoverListener = new HoverListener(coordinateGrid);
2014
+ colPositions = new HorizontalPositionCache(function (col) {
2015
+ return firstRowCellInners.eq(col);
2016
+ });
2017
+ colContentPositions = new HorizontalPositionCache(function (col) {
2018
+ return firstRowCellContentInners.eq(col);
2019
+ });
2020
+
2021
+ function colLeft(col) {
2022
+ return colPositions.left(col);
2023
+ }
2024
+
2025
+ function colRight(col) {
2026
+ return colPositions.right(col);
2027
+ }
2028
+
2029
+ function colContentLeft(col) {
2030
+ return colContentPositions.left(col);
2031
+ }
2032
+
2033
+ function colContentRight(col) {
2034
+ return colContentPositions.right(col);
2035
+ }
2036
+
2037
+ function allDayRow(i) {
2038
+ return bodyRows.eq(i);
2039
+ }
2040
+ }
2041
+
2042
+ function BasicEventRenderer() {
2043
+ var t = this;
2044
+
2045
+ t.renderEvents = renderEvents;
2046
+ t.clearEvents = clearEvents;
2047
+
2048
+ DayEventRenderer.call(t);
2049
+
2050
+ function renderEvents(events, modifiedEventId) {
2051
+ t.renderDayEvents(events, modifiedEventId);
2052
+ }
2053
+
2054
+ function clearEvents() {
2055
+ t.getDaySegmentContainer()
2056
+ .empty();
2057
+ }
2058
+ }
2059
+
2060
+ fcViews.agendaWeek = AgendaWeekView;
2061
+
2062
+ function AgendaWeekView(element, calendar) {
2063
+ var t = this;
2064
+
2065
+ t.render = render;
2066
+
2067
+ AgendaView.call(t, element, calendar, 'agendaWeek');
2068
+
2069
+ var opt = t.opt;
2070
+ var renderAgenda = t.renderAgenda;
2071
+ var skipHiddenDays = t.skipHiddenDays;
2072
+ var getCellsPerWeek = t.getCellsPerWeek;
2073
+ var formatDates = calendar.formatDates;
2074
+
2075
+ function render(date, delta) {
2076
+ if (delta) addDays(date, delta * 7);
2077
+
2078
+ var start = addDays(cloneDate(date), -((date.getDay() - opt('firstDay') + 7) % 7));
2079
+ var end = addDays(cloneDate(start), 7);
2080
+ var visStart = cloneDate(start);
2081
+
2082
+ skipHiddenDays(visStart);
2083
+
2084
+ var visEnd = cloneDate(end);
2085
+
2086
+ skipHiddenDays(visEnd, -1, true);
2087
+
2088
+ var colCnt = getCellsPerWeek();
2089
+
2090
+ t.title = formatDates(visStart, addDays(cloneDate(visEnd), -1), opt('titleFormat'));
2091
+ t.start = start;
2092
+ t.end = end;
2093
+ t.visStart = visStart;
2094
+ t.visEnd = visEnd;
2095
+
2096
+ renderAgenda(colCnt);
2097
+ }
2098
+ }
2099
+
2100
+ fcViews.agendaDay = AgendaDayView;
2101
+
2102
+ function AgendaDayView(element, calendar) {
2103
+ var t = this;
2104
+
2105
+ t.render = render;
2106
+
2107
+ AgendaView.call(t, element, calendar, 'agendaDay');
2108
+
2109
+ var opt = t.opt;
2110
+ var renderAgenda = t.renderAgenda;
2111
+ var skipHiddenDays = t.skipHiddenDays;
2112
+ var formatDate = calendar.formatDate;
2113
+
2114
+ function render(date, delta) {
2115
+ if (delta) addDays(date, delta);
2116
+
2117
+ skipHiddenDays(date, delta < 0 ? -1 : 1);
2118
+
2119
+ var start = cloneDate(date, true);
2120
+ var end = addDays(cloneDate(start), 1);
2121
+
2122
+ t.title = formatDate(date, opt('titleFormat'));
2123
+ t.start = t.visStart = start;
2124
+ t.end = t.visEnd = end;
2125
+
2126
+ renderAgenda(1);
2127
+ }
2128
+ }
2129
+
2130
+ setDefaults({
2131
+ allDaySlot: true,
2132
+ allDayText: 'All-Day',
2133
+ firstHour: 8,
2134
+ slotMinutes: 30,
2135
+ defaultEventMinutes: 120,
2136
+ axisFormat: 'h(:mm)tt',
2137
+ timeFormat: {
2138
+ agenda: 'h:mm{ - h:mm}'
2139
+ },
2140
+ dragOpacity: {
2141
+ agenda: 0.5
2142
+ },
2143
+ minTime: 0,
2144
+ maxTime: 24,
2145
+ slotEventOverlap: true
2146
+ });
2147
+
2148
+ function AgendaView(element, calendar, viewName) {
2149
+ var t = this;
2150
+
2151
+ t.renderAgenda = renderAgenda;
2152
+ t.setWidth = setWidth;
2153
+ t.setHeight = setHeight;
2154
+ t.afterRender = afterRender;
2155
+ t.defaultEventEnd = defaultEventEnd;
2156
+ t.timePosition = timePosition;
2157
+ t.getIsCellAllDay = getIsCellAllDay;
2158
+ t.allDayRow = getAllDayRow;
2159
+ t.getCoordinateGrid = function () { return coordinateGrid; };
2160
+ t.getHoverListener = function () { return hoverListener; };
2161
+ t.colLeft = colLeft;
2162
+ t.colRight = colRight;
2163
+ t.colContentLeft = colContentLeft;
2164
+ t.colContentRight = colContentRight;
2165
+ t.getDaySegmentContainer = function () { return daySegmentContainer; };
2166
+ t.getSlotSegmentContainer = function () { return slotSegmentContainer; };
2167
+ t.getMinMinute = function () { return minMinute; };
2168
+ t.getMaxMinute = function () { return maxMinute; };
2169
+ t.getSlotContainer = function () { return slotContainer; };
2170
+ t.getRowCnt = function () { return 1; };
2171
+ t.getColCnt = function () { return colCnt; };
2172
+ t.getColWidth = function () { return colWidth; };
2173
+ t.getSnapHeight = function () { return snapHeight; };
2174
+ t.getSnapMinutes = function () { return snapMinutes; };
2175
+ t.defaultSelectionEnd = defaultSelectionEnd;
2176
+ t.renderDayOverlay = renderDayOverlay;
2177
+ t.renderSelection = renderSelection;
2178
+ t.clearSelection = clearSelection;
2179
+ t.reportDayClick = reportDayClick;
2180
+ t.dragStart = dragStart;
2181
+ t.dragStop = dragStop;
2182
+
2183
+ View.call(t, element, calendar, viewName);
2184
+ OverlayManager.call(t);
2185
+ SelectionManager.call(t);
2186
+ AgendaEventRenderer.call(t);
2187
+
2188
+ var opt = t.opt;
2189
+ var trigger = t.trigger;
2190
+ var renderOverlay = t.renderOverlay;
2191
+ var clearOverlays = t.clearOverlays;
2192
+ var reportSelection = t.reportSelection;
2193
+ var unselect = t.unselect;
2194
+ var daySelectionMousedown = t.daySelectionMousedown;
2195
+ var slotSegHtml = t.slotSegHtml;
2196
+ var cellToDate = t.cellToDate;
2197
+ var dateToCell = t.dateToCell;
2198
+ var rangeToSegments = t.rangeToSegments;
2199
+ var formatDate = calendar.formatDate;
2200
+ var slotTopCache = {};
2201
+
2202
+ var dayTable, dayHead, dayHeadCells, dayBody, dayBodyCells, dayBodyCellInners, dayBodyCellContentInners,
2203
+ dayBodyFirstCell, dayBodyFirstCellStretcher, slotLayer, daySegmentContainer, allDayTable, allDayRow, slotScroller,
2204
+ slotContainer, slotSegmentContainer, slotTable, selectionHelper, viewWidth, viewHeight, axisWidth, colWidth,
2205
+ gutterWidth, slotHeight, snapMinutes, snapRatio, snapHeight, colCnt, slotCnt, coordinateGrid, hoverListener,
2206
+ colPositions, colContentPositions, minMinute, maxMinute, colFormat, showWeekNumbers, weekNumberTitle,
2207
+ weekNumberFormat;
2208
+
2209
+ disableTextSelection(element.addClass('calendar-agenda'));
2210
+
2211
+ function renderAgenda(c) {
2212
+ colCnt = c;
2213
+
2214
+ updateOptions();
2215
+
2216
+ if (!dayTable) {
2217
+ buildSkeleton();
2218
+ } else {
2219
+ buildDayTable();
2220
+ }
2221
+ }
2222
+
2223
+ function updateOptions() {
2224
+ minMinute = parseTime(opt('minTime'));
2225
+ maxMinute = parseTime(opt('maxTime'));
2226
+ colFormat = opt('columnFormat');
2227
+ showWeekNumbers = opt('weekNumbers');
2228
+ weekNumberTitle = opt('weekNumberTitle');
2229
+
2230
+ if (opt('weekNumberCalculation') !== 'iso') {
2231
+ weekNumberFormat = 'w';
2232
+ } else {
2233
+ weekNumberFormat = 'W';
2234
+ }
2235
+
2236
+ snapMinutes = opt('snapMinutes') || opt('slotMinutes');
2237
+ }
2238
+
2239
+ function buildSkeleton() {
2240
+ var s, d, i, maxd, minutes;
2241
+
2242
+ var headerClass = 'calendar-widget-header';
2243
+ var contentClass = 'calendar-widget-content';
2244
+ var slotNormal = opt('slotMinutes') % 15 === 0;
2245
+
2246
+ buildDayTable();
2247
+
2248
+ slotLayer =
2249
+ $('<div style="position: absolute; z-index: 2; left: 0; width: 100%;"/>')
2250
+ .appendTo(element);
2251
+
2252
+ if (opt('allDaySlot')) {
2253
+ daySegmentContainer =
2254
+ $('<div class="calendar-event-container" style="position: absolute; z-index: 8; top: 0; left: 0;"/>')
2255
+ .appendTo(slotLayer);
2256
+
2257
+ s = '<table style="width: 100%;" class="calendar-agenda-allday" cellspacing="0">' +
2258
+ '<tr>' +
2259
+ "<th class='" + headerClass + " calendar-agenda-axis'>" + opt('allDayText') + "</th>" +
2260
+ '<td>' +
2261
+ '<div class="calendar-day-content"><div style="position: relative"/></div>' +
2262
+ '</td>' +
2263
+ '<th class="' + headerClass + ' calendar-agenda-gutter">&nbsp;</th>' +
2264
+ '</tr>' +
2265
+ '</table>';
2266
+ allDayTable = $(s).appendTo(slotLayer);
2267
+ allDayRow = allDayTable.find('tr');
2268
+
2269
+ dayBind(allDayRow.find('td'));
2270
+
2271
+ slotLayer.append(
2272
+ '<div class="calendar-agenda-divider ' + headerClass + '">' +
2273
+ '<div class="calendar-agenda-divider-inner"></div>' +
2274
+ '</div>'
2275
+ );
2276
+ } else {
2277
+ daySegmentContainer = $([]);
2278
+ }
2279
+
2280
+ slotScroller =
2281
+ $('<div style="position: absolute; width: 100%; overflow-x: hidden; overflow-y: auto;"/>')
2282
+ .appendTo(slotLayer);
2283
+ slotContainer =
2284
+ $('<div style="position: relative; width: 100%; overflow: hidden;"/>')
2285
+ .appendTo(slotScroller);
2286
+ slotSegmentContainer =
2287
+ $('<div class="calendar-event-container" style="position: absolute; z-index: 8; top: 0; left: 0;"/>')
2288
+ .appendTo(slotContainer);
2289
+
2290
+ s = '<table class="calendar-agenda-slots" style="width: 100%;" cellspacing="0"> <tbody>';
2291
+ d = zeroDate();
2292
+ maxd = addMinutes(cloneDate(d), maxMinute);
2293
+ slotCnt = 0;
2294
+
2295
+ addMinutes(d, minMinute);
2296
+
2297
+ for (i = 0; d < maxd; i++) {
2298
+ minutes = d.getMinutes();
2299
+
2300
+ s += '<tr class="calendar-slot' + i + ' ' + (!minutes ? '' : 'calendar-minor') + '">' +
2301
+ '<th class="calendar-agenda-axis ' + headerClass + '">' +
2302
+ ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : '&nbsp;') +
2303
+ '</th>' +
2304
+ '<td class="' + contentClass + '">' +
2305
+ '<div style="position: relative;">&nbsp;</div>' +
2306
+ '</td>' +
2307
+ '</tr>';
2308
+
2309
+ addMinutes(d, opt('slotMinutes'));
2310
+
2311
+ slotCnt++;
2312
+ }
2313
+
2314
+ s += '</tbody></table>';
2315
+ slotTable = $(s).appendTo(slotContainer);
2316
+
2317
+ slotBind(slotTable.find('td'));
2318
+ }
2319
+
2320
+ function buildDayTable() {
2321
+ var html = buildDayTableHTML();
2322
+
2323
+ if (dayTable) dayTable.remove();
2324
+
2325
+ dayTable = $(html).appendTo(element);
2326
+ dayHead = dayTable.find('thead');
2327
+ dayHeadCells = dayHead.find('th').slice(1, -1);
2328
+ dayBody = dayTable.find('tbody');
2329
+ dayBodyCells = dayBody.find('td').slice(0, -1);
2330
+ dayBodyCellInners = dayBodyCells.find('> div');
2331
+ dayBodyCellContentInners = dayBodyCells.find('.calendar-day-content > div');
2332
+ dayBodyFirstCell = dayBodyCells.eq(0);
2333
+ dayBodyFirstCellStretcher = dayBodyCellInners.eq(0);
2334
+
2335
+ markFirstLast(dayHead.add(dayHead.find('tr')));
2336
+ markFirstLast(dayBody.add(dayBody.find('tr')));
2337
+ }
2338
+
2339
+ function buildDayTableHTML() {
2340
+ var html = '<table style="width: 100%;" class="calendar-agenda-days calendar-border-separate" cellspacing="0">' +
2341
+ buildDayTableHeadHTML() +
2342
+ buildDayTableBodyHTML() +
2343
+ '</table>';
2344
+
2345
+ return html;
2346
+ }
2347
+
2348
+ function buildDayTableHeadHTML() {
2349
+ var headerClass = 'calendar-widget-header';
2350
+ var html = '';
2351
+ var col, date, weekText;
2352
+
2353
+ html += '<thead><tr>';
2354
+
2355
+ if (showWeekNumbers) {
2356
+ date = cellToDate(0, 0);
2357
+ weekText = formatDate(date, weekNumberFormat);
2358
+ weekText = weekNumberTitle + weekText;
2359
+
2360
+ html += '<th class="calendar-agenda-axis calendar-week-number ' + headerClass + '">' +
2361
+ htmlEscape(weekText) +
2362
+ '</th>';
2363
+ }
2364
+ else {
2365
+ html += '<th class="calendar-agenda-axis ' + headerClass + '">&nbsp;</th>';
2366
+ }
2367
+
2368
+ for (col = 0; col < colCnt; col++) {
2369
+ date = cellToDate(0, col);
2370
+ html += '<th class="calendar-' + dayIDs[date.getDay()] + ' calendar-col' + col + ' ' + headerClass + '">' +
2371
+ htmlEscape(formatDate(date, colFormat)) +
2372
+ '</th>';
2373
+ }
2374
+
2375
+ html += '<th class="calendar-agenda-gutter ' + headerClass + '">&nbsp;</th></tr></thead>';
2376
+
2377
+ return html;
2378
+ }
2379
+
2380
+ function buildDayTableBodyHTML() {
2381
+ var headerClass = 'calendar-widget-header';
2382
+ var contentClass = 'calendar-widget-content';
2383
+ var today = clearTime(new Date());
2384
+ var html = '';
2385
+ var cellsHTML = '';
2386
+ var date, col, cellHTML, classNames;
2387
+
2388
+ html += '<tbody><tr><th class="calendar-agenda-axis ' + headerClass + '">&nbsp;</th>';
2389
+
2390
+ for (col = 0; col < colCnt; col++) {
2391
+ date = cellToDate(0, col);
2392
+ classNames = [
2393
+ 'calendar-col' + col,
2394
+ 'calendar-' + dayIDs[date.getDay()],
2395
+ contentClass
2396
+ ];
2397
+
2398
+ if (+date === +today) {
2399
+ classNames.push('calendar-state-highlight', 'calendar-today');
2400
+ } else if (date < today) {
2401
+ classNames.push('calendar-past');
2402
+ } else {
2403
+ classNames.push('calendar-future');
2404
+ }
2405
+
2406
+ cellHTML = '<td class="' + classNames.join(' ') + '"><div>' +
2407
+ '<div class="calendar-day-content">' +
2408
+ '<div style="position: relative;">&nbsp;</div>' +
2409
+ '</div>' +
2410
+ '</div></td>';
2411
+
2412
+ cellsHTML += cellHTML;
2413
+ }
2414
+
2415
+ html += cellsHTML;
2416
+ html += '<td class="calendar-agenda-gutter ' + contentClass + '">&nbsp;</td></tr></tbody>';
2417
+
2418
+ return html;
2419
+ }
2420
+
2421
+ function setHeight(height) {
2422
+ if (height === undefined) {
2423
+ height = viewHeight;
2424
+ }
2425
+
2426
+ viewHeight = height;
2427
+ slotTopCache = {};
2428
+
2429
+ var headHeight = dayBody.position().top;
2430
+ var allDayHeight = slotScroller.position().top;
2431
+ var bodyHeight = Math.min(height - headHeight, slotTable.height() + allDayHeight + 1);
2432
+
2433
+ dayBodyFirstCellStretcher.height(bodyHeight - vsides(dayBodyFirstCell));
2434
+ slotLayer.css('top', headHeight);
2435
+ slotScroller.height(bodyHeight - allDayHeight - 1);
2436
+
2437
+ slotHeight = slotTable.find('tr:first').height() + 1;
2438
+ snapRatio = opt('slotMinutes') / snapMinutes;
2439
+ snapHeight = slotHeight / snapRatio;
2440
+ }
2441
+
2442
+ function setWidth(width) {
2443
+ viewWidth = width;
2444
+
2445
+ colPositions.clear();
2446
+ colContentPositions.clear();
2447
+
2448
+ var axisFirstCells = dayHead.find('th:first');
2449
+
2450
+ if (allDayTable) {
2451
+ axisFirstCells = axisFirstCells.add(allDayTable.find('th:first'));
2452
+ }
2453
+
2454
+ axisFirstCells = axisFirstCells.add(slotTable.find('th:first'));
2455
+ axisWidth = 0;
2456
+
2457
+ setOuterWidth(
2458
+ axisFirstCells
2459
+ .width('')
2460
+ .each(function (i, _cell) {
2461
+ axisWidth = Math.max(axisWidth, $(_cell).outerWidth());
2462
+ }),
2463
+ axisWidth
2464
+ );
2465
+
2466
+ var gutterCells = dayTable.find('.calendar-agenda-gutter');
2467
+
2468
+ if (allDayTable) {
2469
+ gutterCells = gutterCells.add(allDayTable.find('th.calendar-agenda-gutter'));
2470
+ }
2471
+
2472
+ var slotTableWidth = slotScroller[0].clientWidth;
2473
+
2474
+ gutterWidth = slotScroller.width() - slotTableWidth;
2475
+
2476
+ if (gutterWidth) {
2477
+ setOuterWidth(gutterCells, gutterWidth);
2478
+
2479
+ gutterCells
2480
+ .show()
2481
+ .prev()
2482
+ .removeClass('calendar-last');
2483
+ } else {
2484
+ gutterCells
2485
+ .hide()
2486
+ .prev()
2487
+ .addClass('calendar-last');
2488
+ }
2489
+
2490
+ colWidth = Math.floor((slotTableWidth - axisWidth) / colCnt);
2491
+ setOuterWidth(dayHeadCells.slice(0, -1), colWidth);
2492
+ }
2493
+
2494
+ function resetScroll() {
2495
+ var d0 = zeroDate();
2496
+ var scrollDate = cloneDate(d0);
2497
+
2498
+ scrollDate.setHours(opt('firstHour'));
2499
+
2500
+ var top = timePosition(d0, scrollDate) + 1;
2501
+
2502
+ function scroll() {
2503
+ slotScroller.scrollTop(top);
2504
+ }
2505
+
2506
+ scroll();
2507
+ setTimeout(scroll, 0);
2508
+ }
2509
+
2510
+ function afterRender() {
2511
+ resetScroll();
2512
+ }
2513
+
2514
+ function dayBind(cells) {
2515
+ cells.click(slotClick)
2516
+ .mousedown(daySelectionMousedown);
2517
+ }
2518
+
2519
+ function slotBind(cells) {
2520
+ cells.click(slotClick)
2521
+ .mousedown(slotSelectionMousedown);
2522
+ }
2523
+
2524
+ function slotClick(ev) {
2525
+ if (!opt('selectable')) {
2526
+ var col = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth));
2527
+ var date = cellToDate(0, col);
2528
+ var rowMatch = this.parentNode.className.match(/calendar-slot(\d+)/);
2529
+
2530
+ if (rowMatch) {
2531
+ var mins = parseInt(rowMatch[1]) * opt('slotMinutes');
2532
+ var hours = Math.floor(mins / 60);
2533
+
2534
+ date.setHours(hours);
2535
+ date.setMinutes(mins % 60 + minMinute);
2536
+
2537
+ trigger('dayClick', dayBodyCells[col], date, false, ev);
2538
+ } else {
2539
+ trigger('dayClick', dayBodyCells[col], date, true, ev);
2540
+ }
2541
+ }
2542
+ }
2543
+
2544
+ function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) {
2545
+ if (refreshCoordinateGrid) coordinateGrid.build();
2546
+
2547
+ var segments = rangeToSegments(overlayStart, overlayEnd);
2548
+
2549
+ for (var i = 0; i < segments.length; i++) {
2550
+ var segment = segments[i];
2551
+
2552
+ dayBind(renderCellOverlay(segment.row, segment.leftCol, segment.row, segment.rightCol));
2553
+ }
2554
+ }
2555
+
2556
+ function renderCellOverlay(row0, col0, row1, col1) {
2557
+ var rect = coordinateGrid.rect(row0, col0, row1, col1, slotLayer);
2558
+ return renderOverlay(rect, slotLayer);
2559
+ }
2560
+
2561
+ function renderSlotOverlay(overlayStart, overlayEnd) {
2562
+ for (var i = 0; i < colCnt; i++) {
2563
+ var dayStart = cellToDate(0, i);
2564
+ var dayEnd = addDays(cloneDate(dayStart), 1);
2565
+ var stretchStart = new Date(Math.max(dayStart, overlayStart));
2566
+ var stretchEnd = new Date(Math.min(dayEnd, overlayEnd));
2567
+
2568
+ if (stretchStart < stretchEnd) {
2569
+ var rect = coordinateGrid.rect(0, i, 0, i, slotContainer);
2570
+ var top = timePosition(dayStart, stretchStart);
2571
+ var bottom = timePosition(dayStart, stretchEnd);
2572
+
2573
+ rect.top = top;
2574
+ rect.height = bottom - top;
2575
+
2576
+ slotBind(renderOverlay(rect, slotContainer));
2577
+ }
2578
+ }
2579
+ }
2580
+
2581
+ coordinateGrid = new CoordinateGrid(function (rows, cols) {
2582
+ var e, n, p;
2583
+
2584
+ dayHeadCells.each(function (i, _e) {
2585
+ e = $(_e);
2586
+ n = e.offset().left;
2587
+
2588
+ if (i) {
2589
+ p[1] = n;
2590
+ }
2591
+
2592
+ p = [n];
2593
+ cols[i] = p;
2594
+ });
2595
+
2596
+ p[1] = n + e.outerWidth();
2597
+
2598
+ if (opt('allDaySlot')) {
2599
+ e = allDayRow;
2600
+ n = e.offset().top;
2601
+ rows[0] = [n, n+e.outerHeight()];
2602
+ }
2603
+
2604
+ var slotTableTop = slotContainer.offset().top;
2605
+ var slotScrollerTop = slotScroller.offset().top;
2606
+ var slotScrollerBottom = slotScrollerTop + slotScroller.outerHeight();
2607
+
2608
+ function constrain(n) {
2609
+ return Math.max(slotScrollerTop, Math.min(slotScrollerBottom, n));
2610
+ }
2611
+
2612
+ for (var i = 0; i < slotCnt * snapRatio; i++) {
2613
+ rows.push([
2614
+ constrain(slotTableTop + snapHeight * i),
2615
+ constrain(slotTableTop + snapHeight * (i + 1))
2616
+ ]);
2617
+ }
2618
+ });
2619
+
2620
+ hoverListener = new HoverListener(coordinateGrid);
2621
+ colPositions = new HorizontalPositionCache(function (col) {
2622
+ return dayBodyCellInners.eq(col);
2623
+ });
2624
+ colContentPositions = new HorizontalPositionCache(function (col) {
2625
+ return dayBodyCellContentInners.eq(col);
2626
+ });
2627
+
2628
+ function colLeft(col) {
2629
+ return colPositions.left(col);
2630
+ }
2631
+
2632
+ function colContentLeft(col) {
2633
+ return colContentPositions.left(col);
2634
+ }
2635
+
2636
+ function colRight(col) {
2637
+ return colPositions.right(col);
2638
+ }
2639
+
2640
+ function colContentRight(col) {
2641
+ return colContentPositions.right(col);
2642
+ }
2643
+
2644
+ function getIsCellAllDay(cell) {
2645
+ return opt('allDaySlot') && !cell.row;
2646
+ }
2647
+
2648
+ function realCellToDate(cell) {
2649
+ var d = cellToDate(0, cell.col);
2650
+ var slotIndex = cell.row;
2651
+
2652
+ if (opt('allDaySlot')) slotIndex--;
2653
+ if (slotIndex >= 0) addMinutes(d, minMinute + slotIndex * snapMinutes);
2654
+
2655
+ return d;
2656
+ }
2657
+
2658
+ function timePosition(day, time) {
2659
+ day = cloneDate(day, true);
2660
+
2661
+ if (time < addMinutes(cloneDate(day), minMinute)) return 0;
2662
+ if (time >= addMinutes(cloneDate(day), maxMinute)) return slotTable.height();
2663
+
2664
+ var slotMinutes = opt('slotMinutes');
2665
+ var minutes = time.getHours()*60 + time.getMinutes() - minMinute;
2666
+ var slotI = Math.floor(minutes / slotMinutes);
2667
+ var slotTop = slotTopCache[slotI];
2668
+
2669
+ if (slotTop === undefined) {
2670
+ slotTop = slotTopCache[slotI] = slotTable.find('tr').eq(slotI).find('td div')[0].offsetTop;
2671
+ }
2672
+
2673
+ return Math.max(0, Math.round(
2674
+ slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
2675
+ ));
2676
+ }
2677
+
2678
+ function getAllDayRow(index) {
2679
+ return allDayRow;
2680
+ }
2681
+
2682
+ function defaultEventEnd(event) {
2683
+ var start = cloneDate(event.start);
2684
+
2685
+ if (event.allDay) return start;
2686
+
2687
+ return addMinutes(start, opt('defaultEventMinutes'));
2688
+ }
2689
+
2690
+ function defaultSelectionEnd(startDate, allDay) {
2691
+ if (allDay) return cloneDate(startDate);
2692
+
2693
+ return addMinutes(cloneDate(startDate), opt('slotMinutes'));
2694
+ }
2695
+
2696
+ function renderSelection(startDate, endDate, allDay) {
2697
+ if (allDay) {
2698
+ if (opt('allDaySlot')) renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true);
2699
+ } else {
2700
+ renderSlotSelection(startDate, endDate);
2701
+ }
2702
+ }
2703
+
2704
+ function renderSlotSelection(startDate, endDate) {
2705
+ var helperOption = opt('selectHelper');
2706
+
2707
+ coordinateGrid.build();
2708
+
2709
+ if (helperOption) {
2710
+ var col = dateToCell(startDate).col;
2711
+
2712
+ if (col >= 0 && col < colCnt) {
2713
+ var rect = coordinateGrid.rect(0, col, 0, col, slotContainer);
2714
+ var top = timePosition(startDate, startDate);
2715
+ var bottom = timePosition(startDate, endDate);
2716
+
2717
+ if (bottom > top) {
2718
+ rect.top = top;
2719
+ rect.height = bottom - top;
2720
+ rect.left += 2;
2721
+ rect.width -= 5;
2722
+
2723
+ if ($.isFunction(helperOption)) {
2724
+ var helperRes = helperOption(startDate, endDate);
2725
+
2726
+ if (helperRes) {
2727
+ rect.position = 'absolute';
2728
+ selectionHelper = $(helperRes)
2729
+ .css(rect)
2730
+ .appendTo(slotContainer);
2731
+ }
2732
+ } else {
2733
+ rect.isStart = true;
2734
+ rect.isEnd = true;
2735
+
2736
+ selectionHelper = $(slotSegHtml(
2737
+ {
2738
+ title: '',
2739
+ start: startDate,
2740
+ end: endDate,
2741
+ className: ['calendar-select-helper'],
2742
+ editable: false
2743
+ },
2744
+ rect
2745
+ ));
2746
+ selectionHelper.css('opacity', opt('dragOpacity'));
2747
+ }
2748
+
2749
+ if (selectionHelper) {
2750
+ slotBind(selectionHelper);
2751
+ slotContainer.append(selectionHelper);
2752
+ setOuterWidth(selectionHelper, rect.width, true);
2753
+ setOuterHeight(selectionHelper, rect.height, true);
2754
+ }
2755
+ }
2756
+ }
2757
+ } else {
2758
+ renderSlotOverlay(startDate, endDate);
2759
+ }
2760
+ }
2761
+
2762
+ function clearSelection() {
2763
+ clearOverlays();
2764
+
2765
+ if (selectionHelper) {
2766
+ selectionHelper.remove();
2767
+ selectionHelper = null;
2768
+ }
2769
+ }
2770
+
2771
+ function slotSelectionMousedown(ev) {
2772
+ if (ev.which === 1 && opt('selectable')) {
2773
+ var dates;
2774
+
2775
+ unselect(ev);
2776
+
2777
+ hoverListener.start(function (cell, origCell) {
2778
+ clearSelection();
2779
+
2780
+ if (cell && cell.col === origCell.col && !getIsCellAllDay(cell)) {
2781
+ var d1 = realCellToDate(origCell);
2782
+ var d2 = realCellToDate(cell);
2783
+
2784
+ dates = [
2785
+ d1,
2786
+ addMinutes(cloneDate(d1), snapMinutes),
2787
+ d2,
2788
+ addMinutes(cloneDate(d2), snapMinutes)
2789
+ ].sort(dateCompare);
2790
+
2791
+ renderSlotSelection(dates[0], dates[3]);
2792
+ } else {
2793
+ dates = null;
2794
+ }
2795
+ }, ev);
2796
+
2797
+ $(document).one('mouseup', function (ev) {
2798
+ hoverListener.stop();
2799
+
2800
+ if (dates) {
2801
+ if (+dates[0] === +dates[1]) reportDayClick(dates[0], false, ev);
2802
+
2803
+ reportSelection(dates[0], dates[3], false, ev);
2804
+ }
2805
+ });
2806
+ }
2807
+ }
2808
+
2809
+ function reportDayClick(date, allDay, ev) {
2810
+ trigger('dayClick', dayBodyCells[dateToCell(date).col], date, allDay, ev);
2811
+ }
2812
+
2813
+ function dragStart(_dragElement, ev, ui) {
2814
+ hoverListener.start(function (cell) {
2815
+ clearOverlays();
2816
+
2817
+ if (cell) {
2818
+ if (getIsCellAllDay(cell)) {
2819
+ renderCellOverlay(cell.row, cell.col, cell.row, cell.col);
2820
+ } else {
2821
+ var d1 = realCellToDate(cell);
2822
+ var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes'));
2823
+
2824
+ renderSlotOverlay(d1, d2);
2825
+ }
2826
+ }
2827
+ }, ev);
2828
+ }
2829
+
2830
+ function dragStop(_dragElement, ev, ui) {
2831
+ var cell = hoverListener.stop();
2832
+
2833
+ clearOverlays();
2834
+
2835
+ if (cell) trigger('drop', _dragElement, realCellToDate(cell), getIsCellAllDay(cell), ev, ui);
2836
+ }
2837
+ }
2838
+
2839
+ function AgendaEventRenderer() {
2840
+ var t = this;
2841
+
2842
+ t.renderEvents = renderEvents;
2843
+ t.clearEvents = clearEvents;
2844
+ t.slotSegHtml = slotSegHtml;
2845
+
2846
+ DayEventRenderer.call(t);
2847
+
2848
+ var opt = t.opt;
2849
+ var trigger = t.trigger;
2850
+ var isEventDraggable = t.isEventDraggable;
2851
+ var isEventResizable = t.isEventResizable;
2852
+ var eventEnd = t.eventEnd;
2853
+ var eventElementHandlers = t.eventElementHandlers;
2854
+ var setHeight = t.setHeight;
2855
+ var getDaySegmentContainer = t.getDaySegmentContainer;
2856
+ var getSlotSegmentContainer = t.getSlotSegmentContainer;
2857
+ var getHoverListener = t.getHoverListener;
2858
+ var getMaxMinute = t.getMaxMinute;
2859
+ var getMinMinute = t.getMinMinute;
2860
+ var timePosition = t.timePosition;
2861
+ var getIsCellAllDay = t.getIsCellAllDay;
2862
+ var colContentLeft = t.colContentLeft;
2863
+ var colContentRight = t.colContentRight;
2864
+ var cellToDate = t.cellToDate;
2865
+ var getColCnt = t.getColCnt;
2866
+ var getColWidth = t.getColWidth;
2867
+ var getSnapHeight = t.getSnapHeight;
2868
+ var getSnapMinutes = t.getSnapMinutes;
2869
+ var getSlotContainer = t.getSlotContainer;
2870
+ var reportEventElement = t.reportEventElement;
2871
+ var showEvents = t.showEvents;
2872
+ var hideEvents = t.hideEvents;
2873
+ var eventDrop = t.eventDrop;
2874
+ var eventResize = t.eventResize;
2875
+ var renderDayOverlay = t.renderDayOverlay;
2876
+ var clearOverlays = t.clearOverlays;
2877
+ var renderDayEvents = t.renderDayEvents;
2878
+ var calendar = t.calendar;
2879
+ var formatDate = calendar.formatDate;
2880
+ var formatDates = calendar.formatDates;
2881
+
2882
+ t.draggableDayEvent = draggableDayEvent;
2883
+
2884
+ function renderEvents(events, modifiedEventId) {
2885
+ var len = events.length;
2886
+ var dayEvents = [];
2887
+ var slotEvents = [];
2888
+
2889
+ for (var i = 0; i < len; i++) {
2890
+ if (events[i].allDay) {
2891
+ dayEvents.push(events[i]);
2892
+ } else {
2893
+ slotEvents.push(events[i]);
2894
+ }
2895
+ }
2896
+
2897
+ if (opt('allDaySlot')) {
2898
+ renderDayEvents(dayEvents, modifiedEventId);
2899
+ setHeight();
2900
+ }
2901
+
2902
+ renderSlotSegs(compileSlotSegs(slotEvents), modifiedEventId);
2903
+ }
2904
+
2905
+ function clearEvents() {
2906
+ getDaySegmentContainer().empty();
2907
+ getSlotSegmentContainer().empty();
2908
+ }
2909
+
2910
+ function compileSlotSegs(events) {
2911
+ var d, seg, colSegs;
2912
+ var colCnt = getColCnt();
2913
+ var minMinute = getMinMinute();
2914
+ var maxMinute = getMaxMinute();
2915
+ var visEventEnds = $.map(events, slotEventEnd);
2916
+ var segs = [];
2917
+
2918
+ for (var i = 0; i < colCnt; i++) {
2919
+ d = cellToDate(0, i);
2920
+
2921
+ addMinutes(d, minMinute);
2922
+
2923
+ colSegs = sliceSegs(events, visEventEnds, d, addMinutes(cloneDate(d), maxMinute-minMinute));
2924
+ colSegs = placeSlotSegs(colSegs);
2925
+
2926
+ for (var j = 0; j < colSegs.length; j++) {
2927
+ seg = colSegs[j];
2928
+ seg.col = i;
2929
+ segs.push(seg);
2930
+ }
2931
+ }
2932
+
2933
+ return segs;
2934
+ }
2935
+
2936
+ function sliceSegs(events, visEventEnds, start, end) {
2937
+ var segs = [];
2938
+ var len=events.length;
2939
+ var event, eventStart, eventEnd, segStart, segEnd, isStart, isEnd;
2940
+
2941
+ for (var i = 0; i < len; i++) {
2942
+ event = events[i];
2943
+ eventStart = event.start;
2944
+ eventEnd = visEventEnds[i];
2945
+
2946
+ if (eventEnd > start && eventStart < end) {
2947
+ if (eventStart < start) {
2948
+ segStart = cloneDate(start);
2949
+ isStart = false;
2950
+ } else {
2951
+ segStart = eventStart;
2952
+ isStart = true;
2953
+ }
2954
+
2955
+ if (eventEnd > end) {
2956
+ segEnd = cloneDate(end);
2957
+ isEnd = false;
2958
+ } else {
2959
+ segEnd = eventEnd;
2960
+ isEnd = true;
2961
+ }
2962
+
2963
+ segs.push({
2964
+ event: event,
2965
+ start: segStart,
2966
+ end: segEnd,
2967
+ isStart: isStart,
2968
+ isEnd: isEnd
2969
+ });
2970
+ }
2971
+ }
2972
+
2973
+ return segs.sort(compareSlotSegs);
2974
+ }
2975
+
2976
+ function slotEventEnd(event) {
2977
+ if (event.end) {
2978
+ return cloneDate(event.end);
2979
+ } else {
2980
+ return addMinutes(cloneDate(event.start), opt('defaultEventMinutes'));
2981
+ }
2982
+ }
2983
+
2984
+ function renderSlotSegs(segs, modifiedEventId) {
2985
+ var segCnt = segs.length;
2986
+ var html = '';
2987
+ var slotSegmentContainer = getSlotSegmentContainer();
2988
+ var seg, i, event, top, bottom, columnLeft, columnRight, columnWidth, width, left, right, eventElements,
2989
+ eventElement, triggerRes, titleElement, height;
2990
+
2991
+ for (i = 0; i < segCnt; i++) {
2992
+ seg = segs[i];
2993
+ event = seg.event;
2994
+ top = timePosition(seg.start, seg.start);
2995
+ bottom = timePosition(seg.start, seg.end);
2996
+ columnLeft = colContentLeft(seg.col);
2997
+ columnRight = colContentRight(seg.col);
2998
+ columnWidth = columnRight - columnLeft;
2999
+ columnRight -= columnWidth * 0.025;
3000
+ columnWidth = columnRight - columnLeft;
3001
+ width = columnWidth * (seg.forwardCoord - seg.backwardCoord);
3002
+
3003
+ if (opt('slotEventOverlap')) {
3004
+ width = Math.max((width - (20/2)) * 2, width);
3005
+ }
3006
+
3007
+ left = columnLeft + seg.backwardCoord * columnWidth;
3008
+ right = left + width;
3009
+ left = Math.max(left, columnLeft);
3010
+ right = Math.min(right, columnRight);
3011
+ width = right - left;
3012
+
3013
+ seg.top = top;
3014
+ seg.left = left;
3015
+ seg.outerWidth = width;
3016
+ seg.outerHeight = bottom - top;
3017
+
3018
+ html += slotSegHtml(event, seg);
3019
+ }
3020
+
3021
+ slotSegmentContainer[0].innerHTML = html;
3022
+ eventElements = slotSegmentContainer.children();
3023
+
3024
+ for (i = 0; i < segCnt; i++) {
3025
+ seg = segs[i];
3026
+ event = seg.event;
3027
+ eventElement = $(eventElements[i]);
3028
+ triggerRes = trigger('eventRender', event, event, eventElement);
3029
+
3030
+ if (triggerRes === false) {
3031
+ eventElement.remove();
3032
+ } else {
3033
+ if (triggerRes && triggerRes !== true) {
3034
+ eventElement.remove();
3035
+ eventElement = $(triggerRes)
3036
+ .css({
3037
+ position: 'absolute',
3038
+ top: seg.top,
3039
+ left: seg.left
3040
+ })
3041
+ .appendTo(slotSegmentContainer);
3042
+ }
3043
+
3044
+ seg.element = eventElement;
3045
+
3046
+ if (event._id === modifiedEventId) {
3047
+ bindSlotSeg(event, eventElement, seg);
3048
+ } else {
3049
+ eventElement[0]._fci = i;
3050
+ }
3051
+
3052
+ reportEventElement(event, eventElement);
3053
+ }
3054
+ }
3055
+
3056
+ lazySegBind(slotSegmentContainer, segs, bindSlotSeg);
3057
+
3058
+ for (i = 0; i < segCnt; i++) {
3059
+ seg = segs[i];
3060
+
3061
+ if (eventElement = seg.element) {
3062
+ seg.vsides = vsides(eventElement, true);
3063
+ seg.hsides = hsides(eventElement, true);
3064
+
3065
+ titleElement = eventElement.find('.calendar-event-title');
3066
+
3067
+ if (titleElement.length) {
3068
+ seg.contentTop = titleElement[0].offsetTop;
3069
+ }
3070
+ }
3071
+ }
3072
+
3073
+ for (i = 0; i < segCnt; i++) {
3074
+ seg = segs[i];
3075
+
3076
+ if (eventElement = seg.element) {
3077
+ eventElement[0].style.width = Math.max(0, seg.outerWidth - seg.hsides) + 'px';
3078
+ height = Math.max(0, seg.outerHeight - seg.vsides);
3079
+ eventElement[0].style.height = height + 'px';
3080
+ event = seg.event;
3081
+
3082
+ if (seg.contentTop !== undefined && height - seg.contentTop < 10) {
3083
+ eventElement.find('div.calendar-event-time')
3084
+ .text(formatDate(event.start, opt('timeFormat')) + ' - ' + event.title);
3085
+ eventElement.find('div.calendar-event-title')
3086
+ .remove();
3087
+ }
3088
+
3089
+ trigger('eventAfterRender', event, event, eventElement);
3090
+ }
3091
+ }
3092
+ }
3093
+
3094
+ function slotSegHtml(event, seg) {
3095
+ var html = '<';
3096
+ var url = event.url;
3097
+ var skinCss = getSkinCss(event, opt);
3098
+ var classes = ['calendar-event', 'calendar-event-vert'];
3099
+
3100
+ if (isEventDraggable(event)) classes.push('calendar-event-draggable');
3101
+ if (seg.isStart) classes.push('calendar-event-start');
3102
+ if (seg.isEnd) classes.push('calendar-event-end');
3103
+
3104
+ classes = classes.concat(event.className);
3105
+
3106
+ if (event.source) {
3107
+ classes = classes.concat(event.source.className || []);
3108
+ }
3109
+
3110
+ if (url) {
3111
+ html += 'a href="' + htmlEscape(event.url) + '"';
3112
+ } else {
3113
+ html += 'div';
3114
+ }
3115
+
3116
+ html += ' class="' + classes.join(' ') + '" style="position: absolute; ' +
3117
+ 'top:' + seg.top + 'px; ' +
3118
+ 'left:' + seg.left + 'px; ' +
3119
+ skinCss +
3120
+ "'>" +
3121
+ '<div class="calendar-event-inner">' +
3122
+ '<div class="calendar-event-time">' +
3123
+ htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +
3124
+ '</div>' +
3125
+ '<div class="calendar-event-title">' +
3126
+ htmlEscape(event.title || '') +
3127
+ '</div>' +
3128
+ '</div>' +
3129
+ '<div class="calendar-event-bg"></div>';
3130
+
3131
+ html += '</' + (url ? 'a' : 'div') + '>';
3132
+
3133
+ return html;
3134
+ }
3135
+
3136
+ function bindSlotSeg(event, eventElement, seg) {
3137
+ var timeElement = eventElement.find('div.calendar-event-time');
3138
+
3139
+ if (isEventDraggable(event)) draggableSlotEvent(event, eventElement, timeElement);
3140
+ if (seg.isEnd && isEventResizable(event)) resizableSlotEvent(event, eventElement, timeElement);
3141
+
3142
+ eventElementHandlers(event, eventElement);
3143
+ }
3144
+
3145
+ function draggableDayEvent(event, eventElement, seg) {
3146
+ var isStart = seg.isStart;
3147
+ var allDay = true;
3148
+ var hoverListener = getHoverListener();
3149
+ var colWidth = getColWidth();
3150
+ var snapHeight = getSnapHeight();
3151
+ var snapMinutes = getSnapMinutes();
3152
+ var minMinute = getMinMinute();
3153
+ var origWidth, revert, dayDelta;
3154
+
3155
+ eventElement.draggable({
3156
+ opacity: opt('dragOpacity', 'month'),
3157
+ revertDuration: opt('dragRevertDuration'),
3158
+ start: function (ev, ui) {
3159
+ trigger('eventDragStart', eventElement, event, ev, ui);
3160
+ hideEvents(event, eventElement);
3161
+
3162
+ origWidth = eventElement.width();
3163
+
3164
+ hoverListener.start(function (cell, origCell) {
3165
+ clearOverlays();
3166
+
3167
+ if (cell) {
3168
+ revert = false;
3169
+
3170
+ var origDate = cellToDate(0, origCell.col);
3171
+ var date = cellToDate(0, cell.col);
3172
+
3173
+ dayDelta = dayDiff(date, origDate);
3174
+
3175
+ if (!cell.row) {
3176
+ renderDayOverlay(addDays(cloneDate(event.start), dayDelta), addDays(exclEndDay(event), dayDelta));
3177
+ resetElement();
3178
+ } else {
3179
+ if (isStart) {
3180
+ if (allDay) {
3181
+ eventElement.width(colWidth - 10);
3182
+
3183
+ setOuterHeight(
3184
+ eventElement,
3185
+ snapHeight * Math.round(
3186
+ (event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes')) /
3187
+ snapMinutes
3188
+ )
3189
+ );
3190
+
3191
+ eventElement.draggable('option', 'grid', [colWidth, 1]);
3192
+
3193
+ allDay = false;
3194
+ }
3195
+ } else {
3196
+ revert = true;
3197
+ }
3198
+ }
3199
+
3200
+ revert = revert || (allDay && !dayDelta);
3201
+ } else {
3202
+ resetElement();
3203
+ revert = true;
3204
+ }
3205
+
3206
+ eventElement.draggable('option', 'revert', revert);
3207
+ }, ev, 'drag');
3208
+ },
3209
+ stop: function (ev, ui) {
3210
+ hoverListener.stop();
3211
+ clearOverlays();
3212
+ trigger('eventDragStop', eventElement, event, ev, ui);
3213
+
3214
+ if (revert) {
3215
+ resetElement();
3216
+ eventElement.css('filter', '');
3217
+ showEvents(event, eventElement);
3218
+ } else {
3219
+ var minuteDelta = 0;
3220
+
3221
+ if (!allDay) {
3222
+ minuteDelta = Math.round((eventElement.offset().top - getSlotContainer().offset().top) / snapHeight) *
3223
+ snapMinutes +
3224
+ minMinute -
3225
+ (event.start.getHours() * 60 + event.start.getMinutes());
3226
+ }
3227
+
3228
+ eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui);
3229
+ }
3230
+ }
3231
+ });
3232
+
3233
+ function resetElement() {
3234
+ if (!allDay) {
3235
+ eventElement
3236
+ .width(origWidth)
3237
+ .height('')
3238
+ .draggable('option', 'grid', null);
3239
+
3240
+ allDay = true;
3241
+ }
3242
+ }
3243
+ }
3244
+
3245
+ function draggableSlotEvent(event, eventElement, timeElement) {
3246
+ var coordinateGrid = t.getCoordinateGrid();
3247
+ var colCnt = getColCnt();
3248
+ var colWidth = getColWidth();
3249
+ var snapHeight = getSnapHeight();
3250
+ var snapMinutes = getSnapMinutes();
3251
+ var origPosition, origCell, isInBounds, prevIsInBounds, isAllDay, prevIsAllDay, colDelta, prevColDelta, dayDelta,
3252
+ minuteDelta, prevMinuteDelta;
3253
+
3254
+ eventElement.draggable({
3255
+ scroll: false,
3256
+ grid: [colWidth, snapHeight],
3257
+ axis: colCnt == 1 ? 'y' : false,
3258
+ opacity: opt('dragOpacity'),
3259
+ revertDuration: opt('dragRevertDuration'),
3260
+ start: function (ev, ui) {
3261
+ trigger('eventDragStart', eventElement, event, ev, ui);
3262
+ hideEvents(event, eventElement);
3263
+
3264
+ coordinateGrid.build();
3265
+
3266
+ origPosition = eventElement.position();
3267
+ origCell = coordinateGrid.cell(ev.pageX, ev.pageY);
3268
+ isInBounds = prevIsInBounds = true;
3269
+ isAllDay = prevIsAllDay = getIsCellAllDay(origCell);
3270
+ colDelta = prevColDelta = 0;
3271
+ dayDelta = 0;
3272
+ minuteDelta = prevMinuteDelta = 0;
3273
+ },
3274
+ drag: function (ev, ui) {
3275
+ var cell = coordinateGrid.cell(ev.pageX, ev.pageY);
3276
+
3277
+ isInBounds = !!cell;
3278
+
3279
+ if (isInBounds) {
3280
+ isAllDay = getIsCellAllDay(cell);
3281
+ colDelta = Math.round((ui.position.left - origPosition.left) / colWidth);
3282
+
3283
+ if (colDelta !== prevColDelta) {
3284
+ var origDate = cellToDate(0, origCell.col);
3285
+ var col = origCell.col + colDelta;
3286
+
3287
+ col = Math.max(0, col);
3288
+ col = Math.min(colCnt-1, col);
3289
+
3290
+ var date = cellToDate(0, col);
3291
+
3292
+ dayDelta = dayDiff(date, origDate);
3293
+ }
3294
+
3295
+ if (!isAllDay) {
3296
+ minuteDelta = Math.round((ui.position.top - origPosition.top) / snapHeight) * snapMinutes;
3297
+ }
3298
+ }
3299
+
3300
+ if (
3301
+ isInBounds !== prevIsInBounds ||
3302
+ isAllDay !== prevIsAllDay ||
3303
+ colDelta !== prevColDelta ||
3304
+ minuteDelta !== prevMinuteDelta
3305
+ ) {
3306
+ updateUI();
3307
+
3308
+ prevIsInBounds = isInBounds;
3309
+ prevIsAllDay = isAllDay;
3310
+ prevColDelta = colDelta;
3311
+ prevMinuteDelta = minuteDelta;
3312
+ }
3313
+
3314
+ eventElement.draggable('option', 'revert', !isInBounds);
3315
+ },
3316
+ stop: function (ev, ui) {
3317
+ clearOverlays();
3318
+ trigger('eventDragStop', eventElement, event, ev, ui);
3319
+
3320
+ if (isInBounds && (isAllDay || dayDelta || minuteDelta)) {
3321
+ eventDrop(this, event, dayDelta, isAllDay ? 0 : minuteDelta, isAllDay, ev, ui);
3322
+ } else {
3323
+ isInBounds = true;
3324
+ isAllDay = false;
3325
+ colDelta = 0;
3326
+ dayDelta = 0;
3327
+ minuteDelta = 0;
3328
+
3329
+ updateUI();
3330
+
3331
+ eventElement.css('filter', '');
3332
+ eventElement.css(origPosition);
3333
+
3334
+ showEvents(event, eventElement);
3335
+ }
3336
+ }
3337
+ });
3338
+
3339
+ function updateUI() {
3340
+ clearOverlays();
3341
+
3342
+ if (isInBounds) {
3343
+ if (isAllDay) {
3344
+ timeElement.hide();
3345
+ eventElement.draggable('option', 'grid', null);
3346
+ renderDayOverlay(addDays(cloneDate(event.start), dayDelta), addDays(exclEndDay(event), dayDelta));
3347
+ }
3348
+ else {
3349
+ updateTimeText(minuteDelta);
3350
+ timeElement.css('display', '');
3351
+ eventElement.draggable('option', 'grid', [colWidth, snapHeight]);
3352
+ }
3353
+ }
3354
+ }
3355
+
3356
+ function updateTimeText(minuteDelta) {
3357
+ var newStart = addMinutes(cloneDate(event.start), minuteDelta);
3358
+ var newEnd;
3359
+
3360
+ if (event.end) {
3361
+ newEnd = addMinutes(cloneDate(event.end), minuteDelta);
3362
+ }
3363
+
3364
+ timeElement.text(formatDates(newStart, newEnd, opt('timeFormat')));
3365
+ }
3366
+ }
3367
+
3368
+ function resizableSlotEvent(event, eventElement, timeElement) {
3369
+ var snapDelta, prevSnapDelta;
3370
+ var snapHeight = getSnapHeight();
3371
+ var snapMinutes = getSnapMinutes();
3372
+
3373
+ eventElement.resizable({
3374
+ handles: { s: '.ui-resizable-handle' },
3375
+ grid: snapHeight,
3376
+ start: function (ev, ui) {
3377
+ snapDelta = prevSnapDelta = 0;
3378
+
3379
+ hideEvents(event, eventElement);
3380
+ trigger('eventResizeStart', this, event, ev, ui);
3381
+ },
3382
+ resize: function (ev, ui) {
3383
+ snapDelta = Math.round((Math.max(snapHeight, eventElement.height()) - ui.originalSize.height) / snapHeight);
3384
+
3385
+ if (snapDelta !== prevSnapDelta) {
3386
+ timeElement.text(
3387
+ formatDates(
3388
+ event.start,
3389
+ (!snapDelta && !event.end) ? null : addMinutes(eventEnd(event), snapMinutes*snapDelta),
3390
+ opt('timeFormat')
3391
+ )
3392
+ );
3393
+
3394
+ prevSnapDelta = snapDelta;
3395
+ }
3396
+ },
3397
+ stop: function (ev, ui) {
3398
+ trigger('eventResizeStop', this, event, ev, ui);
3399
+
3400
+ if (snapDelta) {
3401
+ eventResize(this, event, 0, snapMinutes*snapDelta, ev, ui);
3402
+ } else {
3403
+ showEvents(event, eventElement);
3404
+ }
3405
+ }
3406
+ });
3407
+ }
3408
+ }
3409
+
3410
+ function placeSlotSegs(segs) {
3411
+ var levels = buildSlotSegLevels(segs);
3412
+ var level0 = levels[0];
3413
+ var i;
3414
+
3415
+ computeForwardSlotSegs(levels);
3416
+
3417
+ if (level0) {
3418
+ for (i = 0; i < level0.length; i++) {
3419
+ computeSlotSegPressures(level0[i]);
3420
+ }
3421
+ for (i = 0; i < level0.length; i++) {
3422
+ computeSlotSegCoords(level0[i], 0, 0);
3423
+ }
3424
+ }
3425
+
3426
+ return flattenSlotSegLevels(levels);
3427
+ }
3428
+
3429
+ function buildSlotSegLevels(segs) {
3430
+ var levels = [];
3431
+ var i, j, seg;
3432
+
3433
+ for (i = 0; i < segs.length; i++) {
3434
+ seg = segs[i];
3435
+
3436
+ for (j = 0; j < levels.length; j++) {
3437
+ if (!computeSlotSegCollisions(seg, levels[j]).length) break;
3438
+ }
3439
+
3440
+ (levels[j] || (levels[j] = [])).push(seg);
3441
+ }
3442
+
3443
+ return levels;
3444
+ }
3445
+
3446
+ function computeForwardSlotSegs(levels) {
3447
+ var level, seg;
3448
+
3449
+ for (var i = 0; i < levels.length; i++) {
3450
+ level = levels[i];
3451
+
3452
+ for (var j = 0; j < level.length; j++) {
3453
+ seg = level[j];
3454
+
3455
+ seg.forwardSegs = [];
3456
+
3457
+ for (var k = i + 1; k < levels.length; k++) {
3458
+ computeSlotSegCollisions(seg, levels[k], seg.forwardSegs);
3459
+ }
3460
+ }
3461
+ }
3462
+ }
3463
+
3464
+ function computeSlotSegPressures(seg) {
3465
+ var forwardSegs = seg.forwardSegs;
3466
+ var forwardPressure = 0;
3467
+ var forwardSeg;
3468
+
3469
+ if (seg.forwardPressure === undefined) {
3470
+
3471
+ for (var i = 0; i < forwardSegs.length; i++) {
3472
+ forwardSeg = forwardSegs[i];
3473
+
3474
+ computeSlotSegPressures(forwardSeg);
3475
+
3476
+ forwardPressure = Math.max(forwardPressure, 1 + forwardSeg.forwardPressure);
3477
+ }
3478
+
3479
+ seg.forwardPressure = forwardPressure;
3480
+ }
3481
+ }
3482
+
3483
+ function computeSlotSegCoords(seg, seriesBackwardPressure, seriesBackwardCoord) {
3484
+ var forwardSegs = seg.forwardSegs;
3485
+
3486
+ if (seg.forwardCoord === undefined) {
3487
+ if (!forwardSegs.length) {
3488
+ seg.forwardCoord = 1;
3489
+ } else {
3490
+ forwardSegs.sort(compareForwardSlotSegs);
3491
+
3492
+ computeSlotSegCoords(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord);
3493
+
3494
+ seg.forwardCoord = forwardSegs[0].backwardCoord;
3495
+ }
3496
+
3497
+ seg.backwardCoord = seg.forwardCoord -
3498
+ (seg.forwardCoord - seriesBackwardCoord) /
3499
+ (seriesBackwardPressure + 1);
3500
+
3501
+ for (var i = 0; i < forwardSegs.length; i++) {
3502
+ computeSlotSegCoords(forwardSegs[i], 0, seg.forwardCoord);
3503
+ }
3504
+ }
3505
+ }
3506
+
3507
+ function flattenSlotSegLevels(levels) {
3508
+ var segs = [];
3509
+ var level;
3510
+
3511
+ for (var i = 0; i < levels.length; i++) {
3512
+ level = levels[i];
3513
+
3514
+ for (var j = 0; j < level.length; j++) {
3515
+ segs.push(level[j]);
3516
+ }
3517
+ }
3518
+
3519
+ return segs;
3520
+ }
3521
+
3522
+ function computeSlotSegCollisions(seg, otherSegs, results) {
3523
+ results = results || [];
3524
+
3525
+ for (var i = 0; i < otherSegs.length; i++) {
3526
+ if (isSlotSegCollision(seg, otherSegs[i])) results.push(otherSegs[i]);
3527
+ }
3528
+
3529
+ return results;
3530
+ }
3531
+
3532
+ function isSlotSegCollision(seg1, seg2) {
3533
+ return seg1.end > seg2.start && seg1.start < seg2.end;
3534
+ }
3535
+
3536
+ function compareForwardSlotSegs(seg1, seg2) {
3537
+ return seg2.forwardPressure - seg1.forwardPressure ||
3538
+ (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) ||
3539
+ compareSlotSegs(seg1, seg2);
3540
+ }
3541
+
3542
+ function compareSlotSegs(seg1, seg2) {
3543
+ return seg1.start - seg2.start ||
3544
+ (seg2.end - seg2.start) - (seg1.end - seg1.start) ||
3545
+ (seg1.event.title || '').localeCompare(seg2.event.title);
3546
+ }
3547
+
3548
+ function View(element, calendar, viewName) {
3549
+ var t = this;
3550
+
3551
+ t.element = element;
3552
+ t.calendar = calendar;
3553
+ t.name = viewName;
3554
+ t.opt = opt;
3555
+ t.trigger = trigger;
3556
+ t.isEventDraggable = isEventDraggable;
3557
+ t.isEventResizable = isEventResizable;
3558
+ t.setEventData = setEventData;
3559
+ t.clearEventData = clearEventData;
3560
+ t.eventEnd = eventEnd;
3561
+ t.reportEventElement = reportEventElement;
3562
+ t.triggerEventDestroy = triggerEventDestroy;
3563
+ t.eventElementHandlers = eventElementHandlers;
3564
+ t.showEvents = showEvents;
3565
+ t.hideEvents = hideEvents;
3566
+ t.eventDrop = eventDrop;
3567
+ t.eventResize = eventResize;
3568
+
3569
+ var defaultEventEnd = t.defaultEventEnd;
3570
+ var normalizeEvent = calendar.normalizeEvent;
3571
+ var reportEventChange = calendar.reportEventChange;
3572
+ var eventsByID = {};
3573
+ var eventElementsByID = {};
3574
+ var eventElementCouples = [];
3575
+ var options = calendar.options;
3576
+
3577
+ function opt(name, viewNameOverride) {
3578
+ var v = options[name];
3579
+
3580
+ if ($.isPlainObject(v)) return smartProperty(v, viewNameOverride || viewName);
3581
+ return v;
3582
+ }
3583
+
3584
+ function trigger(name, thisObj) {
3585
+ return calendar.trigger.apply(
3586
+ calendar,
3587
+ [name, thisObj || t].concat(Array.prototype.slice.call(arguments, 2), [t])
3588
+ );
3589
+ }
3590
+
3591
+ function isEventDraggable(event) {
3592
+ var source = event.source || {};
3593
+
3594
+ return firstDefined(
3595
+ event.startEditable,
3596
+ source.startEditable,
3597
+ opt('eventStartEditable'),
3598
+ event.editable,
3599
+ source.editable,
3600
+ opt('editable')
3601
+ ) &&
3602
+ !opt('disableDragging');
3603
+ }
3604
+
3605
+ function isEventResizable(event) {
3606
+ var source = event.source || {};
3607
+
3608
+ return firstDefined(
3609
+ event.durationEditable,
3610
+ source.durationEditable,
3611
+ opt('eventDurationEditable'),
3612
+ event.editable,
3613
+ source.editable,
3614
+ opt('editable')
3615
+ ) &&
3616
+ !opt('disableResizing');
3617
+ }
3618
+
3619
+ function setEventData(events) {
3620
+ var len = events.length;
3621
+ var event;
3622
+
3623
+ eventsByID = {};
3624
+
3625
+ for (var i = 0; i < len; i++) {
3626
+ event = events[i];
3627
+
3628
+ if (eventsByID[event._id]) {
3629
+ eventsByID[event._id].push(event);
3630
+ } else {
3631
+ eventsByID[event._id] = [event];
3632
+ }
3633
+ }
3634
+ }
3635
+
3636
+ function clearEventData() {
3637
+ eventsByID = {};
3638
+ eventElementsByID = {};
3639
+ eventElementCouples = [];
3640
+ }
3641
+
3642
+ function eventEnd(event) {
3643
+ return event.end ? cloneDate(event.end) : defaultEventEnd(event);
3644
+ }
3645
+
3646
+ function reportEventElement(event, element) {
3647
+ eventElementCouples.push({ event: event, element: element });
3648
+
3649
+ if (eventElementsByID[event._id]) {
3650
+ eventElementsByID[event._id].push(element);
3651
+ } else {
3652
+ eventElementsByID[event._id] = [element];
3653
+ }
3654
+ }
3655
+
3656
+ function triggerEventDestroy() {
3657
+ $.each(eventElementCouples, function (i, couple) {
3658
+ t.trigger('eventDestroy', couple.event, couple.event, couple.element);
3659
+ });
3660
+ }
3661
+
3662
+ function eventElementHandlers(event, eventElement) {
3663
+ eventElement
3664
+ .click(function (ev) {
3665
+ if (!eventElement.hasClass('ui-draggable-dragging') && !eventElement.hasClass('ui-resizable-resizing')) {
3666
+ return trigger('eventClick', this, event, ev);
3667
+ }
3668
+ })
3669
+ .hover(
3670
+ function (ev) {
3671
+ trigger('eventMouseover', this, event, ev);
3672
+ },
3673
+ function (ev) {
3674
+ trigger('eventMouseout', this, event, ev);
3675
+ }
3676
+ );
3677
+ }
3678
+
3679
+ function showEvents(event, exceptElement) {
3680
+ eachEventElement(event, exceptElement, 'show');
3681
+ }
3682
+
3683
+ function hideEvents(event, exceptElement) {
3684
+ eachEventElement(event, exceptElement, 'hide');
3685
+ }
3686
+
3687
+ function eachEventElement(event, exceptElement, funcName) {
3688
+ var elements = eventElementsByID[event._id];
3689
+ var len = elements.length;
3690
+
3691
+ for (var i = 0; i < len; i++) {
3692
+ if (!exceptElement || elements[i][0] !== exceptElement[0]) elements[i][funcName]();
3693
+ }
3694
+ }
3695
+
3696
+ function eventDrop(e, event, dayDelta, minuteDelta, allDay, ev, ui) {
3697
+ var oldAllDay = event.allDay;
3698
+ var eventId = event._id;
3699
+
3700
+ moveEvents(eventsByID[eventId], dayDelta, minuteDelta, allDay);
3701
+ trigger(
3702
+ 'eventDrop',
3703
+ e,
3704
+ event,
3705
+ dayDelta,
3706
+ minuteDelta,
3707
+ allDay,
3708
+ function () {
3709
+ moveEvents(eventsByID[eventId], -dayDelta, -minuteDelta, oldAllDay);
3710
+ reportEventChange(eventId);
3711
+ },
3712
+ ev,
3713
+ ui
3714
+ );
3715
+ reportEventChange(eventId);
3716
+ }
3717
+
3718
+ function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
3719
+ var eventId = event._id;
3720
+
3721
+ elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
3722
+ trigger(
3723
+ 'eventResize',
3724
+ e,
3725
+ event,
3726
+ dayDelta,
3727
+ minuteDelta,
3728
+ function () {
3729
+ elongateEvents(eventsByID[eventId], -dayDelta, -minuteDelta);
3730
+ reportEventChange(eventId);
3731
+ },
3732
+ ev,
3733
+ ui
3734
+ );
3735
+ reportEventChange(eventId);
3736
+ }
3737
+
3738
+ function moveEvents(events, dayDelta, minuteDelta, allDay) {
3739
+ var len = events.length;
3740
+ var e;
3741
+
3742
+ minuteDelta = minuteDelta || 0;
3743
+
3744
+ for (var i = 0; i < len; i++) {
3745
+ e = events[i];
3746
+
3747
+ if (allDay !== undefined) {
3748
+ e.allDay = allDay;
3749
+ }
3750
+
3751
+ addMinutes(addDays(e.start, dayDelta, true), minuteDelta);
3752
+
3753
+ if (e.end) {
3754
+ e.end = addMinutes(addDays(e.end, dayDelta, true), minuteDelta);
3755
+ }
3756
+
3757
+ normalizeEvent(e, options);
3758
+ }
3759
+ }
3760
+
3761
+ function elongateEvents(events, dayDelta, minuteDelta) {
3762
+ var len = events.length;
3763
+ var e;
3764
+
3765
+ minuteDelta = minuteDelta || 0;
3766
+
3767
+ for (var i = 0; i < len; i++) {
3768
+ e = events[i];
3769
+ e.end = addMinutes(addDays(eventEnd(e), dayDelta, true), minuteDelta);
3770
+ normalizeEvent(e, options);
3771
+ }
3772
+ }
3773
+
3774
+ t.isHiddenDay = isHiddenDay;
3775
+ t.skipHiddenDays = skipHiddenDays;
3776
+ t.getCellsPerWeek = getCellsPerWeek;
3777
+ t.dateToCell = dateToCell;
3778
+ t.dateToDayOffset = dateToDayOffset;
3779
+ t.dayOffsetToCellOffset = dayOffsetToCellOffset;
3780
+ t.cellOffsetToCell = cellOffsetToCell;
3781
+ t.cellToDate = cellToDate;
3782
+ t.cellToCellOffset = cellToCellOffset;
3783
+ t.cellOffsetToDayOffset = cellOffsetToDayOffset;
3784
+ t.dayOffsetToDate = dayOffsetToDate;
3785
+ t.rangeToSegments = rangeToSegments;
3786
+
3787
+ var hiddenDays = opt('hiddenDays') || [];
3788
+ var isHiddenDayHash = [];
3789
+ var dayToCellMap = [];
3790
+ var cellToDayMap = [];
3791
+ var cellsPerWeek;
3792
+
3793
+ (function () {
3794
+ if (opt('weekends') === false) hiddenDays.push(0, 6);
3795
+
3796
+ for (var dayIndex=0, cellIndex=0; dayIndex<7; dayIndex++) {
3797
+ dayToCellMap[dayIndex] = cellIndex;
3798
+ isHiddenDayHash[dayIndex] = $.inArray(dayIndex, hiddenDays) !== -1;
3799
+
3800
+ if (!isHiddenDayHash[dayIndex]) {
3801
+ cellToDayMap[cellIndex] = dayIndex;
3802
+ cellIndex++;
3803
+ }
3804
+ }
3805
+
3806
+ cellsPerWeek = cellIndex;
3807
+
3808
+ if (!cellsPerWeek) throw 'invalid hiddenDays';
3809
+ })();
3810
+
3811
+ function isHiddenDay(day) {
3812
+ if (typeof day === 'object') {
3813
+ day = day.getDay();
3814
+ }
3815
+
3816
+ return isHiddenDayHash[day];
3817
+ }
3818
+
3819
+ function getCellsPerWeek() {
3820
+ return cellsPerWeek;
3821
+ }
3822
+
3823
+ function skipHiddenDays(date, inc, isExclusive) {
3824
+ inc = inc || 1;
3825
+
3826
+ while (isHiddenDayHash[(date.getDay() + (isExclusive ? inc : 0) + 7) % 7 ]) {
3827
+ addDays(date, inc);
3828
+ }
3829
+ }
3830
+
3831
+ function cellToDate() {
3832
+ var cellOffset = cellToCellOffset.apply(null, arguments);
3833
+ var dayOffset = cellOffsetToDayOffset(cellOffset);
3834
+ var date = dayOffsetToDate(dayOffset);
3835
+ return date;
3836
+ }
3837
+
3838
+ function cellToCellOffset(row, col) {
3839
+ var colCnt = t.getColCnt();
3840
+ var dis = 1;
3841
+ var dit = 0;
3842
+
3843
+ if (typeof row === 'object') {
3844
+ col = row.col;
3845
+ row = row.row;
3846
+ }
3847
+
3848
+ return row * colCnt + (col * dis + dit);
3849
+ }
3850
+
3851
+ function cellOffsetToDayOffset(cellOffset) {
3852
+ var day0 = t.visStart.getDay();
3853
+
3854
+ cellOffset += dayToCellMap[day0];
3855
+
3856
+ return Math.floor(cellOffset / cellsPerWeek) *
3857
+ 7 +
3858
+ cellToDayMap[(cellOffset % cellsPerWeek + cellsPerWeek) % cellsPerWeek] -
3859
+ day0;
3860
+ }
3861
+
3862
+ function dayOffsetToDate(dayOffset) {
3863
+ var date = cloneDate(t.visStart);
3864
+
3865
+ addDays(date, dayOffset);
3866
+ return date;
3867
+ }
3868
+
3869
+ function dateToCell(date) {
3870
+ var dayOffset = dateToDayOffset(date);
3871
+ var cellOffset = dayOffsetToCellOffset(dayOffset);
3872
+ var cell = cellOffsetToCell(cellOffset);
3873
+ return cell;
3874
+ }
3875
+
3876
+ function dateToDayOffset(date) {
3877
+ return dayDiff(date, t.visStart);
3878
+ }
3879
+
3880
+ function dayOffsetToCellOffset(dayOffset) {
3881
+ var day0 = t.visStart.getDay();
3882
+
3883
+ dayOffset += day0;
3884
+
3885
+ return Math.floor(dayOffset / 7) *
3886
+ cellsPerWeek +
3887
+ dayToCellMap[(dayOffset % 7 + 7) % 7] -
3888
+ dayToCellMap[day0];
3889
+ }
3890
+
3891
+ function cellOffsetToCell(cellOffset) {
3892
+ var colCnt = t.getColCnt();
3893
+ var dis = 1;
3894
+ var dit = 0;
3895
+ var row = Math.floor(cellOffset / colCnt);
3896
+ var col = ((cellOffset % colCnt + colCnt) % colCnt) * dis + dit;
3897
+
3898
+ return {
3899
+ row: row,
3900
+ col: col
3901
+ };
3902
+ }
3903
+
3904
+ function rangeToSegments(startDate, endDate) {
3905
+ var rowCnt = t.getRowCnt();
3906
+ var colCnt = t.getColCnt();
3907
+ var segments = [];
3908
+ var rangeDayOffsetStart = dateToDayOffset(startDate);
3909
+ var rangeDayOffsetEnd = dateToDayOffset(endDate);
3910
+ var rangeCellOffsetFirst = dayOffsetToCellOffset(rangeDayOffsetStart);
3911
+ var rangeCellOffsetLast = dayOffsetToCellOffset(rangeDayOffsetEnd) - 1;
3912
+
3913
+ for (var row = 0; row < rowCnt; row++) {
3914
+ var rowCellOffsetFirst = row * colCnt;
3915
+ var rowCellOffsetLast = rowCellOffsetFirst + colCnt - 1;
3916
+ var segmentCellOffsetFirst = Math.max(rangeCellOffsetFirst, rowCellOffsetFirst);
3917
+ var segmentCellOffsetLast = Math.min(rangeCellOffsetLast, rowCellOffsetLast);
3918
+
3919
+ if (segmentCellOffsetFirst <= segmentCellOffsetLast) {
3920
+ var segmentCellFirst = cellOffsetToCell(segmentCellOffsetFirst);
3921
+ var segmentCellLast = cellOffsetToCell(segmentCellOffsetLast);
3922
+ var cols = [ segmentCellFirst.col, segmentCellLast.col ].sort();
3923
+ var isStart = cellOffsetToDayOffset(segmentCellOffsetFirst) === rangeDayOffsetStart;
3924
+ var isEnd = cellOffsetToDayOffset(segmentCellOffsetLast) + 1 === rangeDayOffsetEnd;
3925
+
3926
+ segments.push({
3927
+ row: row,
3928
+ leftCol: cols[0],
3929
+ rightCol: cols[1],
3930
+ isStart: isStart,
3931
+ isEnd: isEnd
3932
+ });
3933
+ }
3934
+ }
3935
+
3936
+ return segments;
3937
+ }
3938
+ }
3939
+
3940
+ function DayEventRenderer() {
3941
+ var t = this;
3942
+
3943
+ t.renderDayEvents = renderDayEvents;
3944
+ t.draggableDayEvent = draggableDayEvent;
3945
+ t.resizableDayEvent = resizableDayEvent;
3946
+
3947
+ var opt = t.opt;
3948
+ var trigger = t.trigger;
3949
+ var isEventDraggable = t.isEventDraggable;
3950
+ var isEventResizable = t.isEventResizable;
3951
+ var eventEnd = t.eventEnd;
3952
+ var reportEventElement = t.reportEventElement;
3953
+ var eventElementHandlers = t.eventElementHandlers;
3954
+ var showEvents = t.showEvents;
3955
+ var hideEvents = t.hideEvents;
3956
+ var eventDrop = t.eventDrop;
3957
+ var eventResize = t.eventResize;
3958
+ var getRowCnt = t.getRowCnt;
3959
+ var getColCnt = t.getColCnt;
3960
+ var getColWidth = t.getColWidth;
3961
+ var allDayRow = t.allDayRow;
3962
+ var colLeft = t.colLeft;
3963
+ var colRight = t.colRight;
3964
+ var colContentLeft = t.colContentLeft;
3965
+ var colContentRight = t.colContentRight;
3966
+ var dateToCell = t.dateToCell;
3967
+ var getDaySegmentContainer = t.getDaySegmentContainer;
3968
+ var formatDates = t.calendar.formatDates;
3969
+ var renderDayOverlay = t.renderDayOverlay;
3970
+ var clearOverlays = t.clearOverlays;
3971
+ var clearSelection = t.clearSelection;
3972
+ var getHoverListener = t.getHoverListener;
3973
+ var rangeToSegments = t.rangeToSegments;
3974
+ var cellToDate = t.cellToDate;
3975
+ var cellToCellOffset = t.cellToCellOffset;
3976
+ var cellOffsetToDayOffset = t.cellOffsetToDayOffset;
3977
+ var dateToDayOffset = t.dateToDayOffset;
3978
+ var dayOffsetToCellOffset = t.dayOffsetToCellOffset;
3979
+
3980
+ function renderDayEvents(events, modifiedEventId) {
3981
+ var segments = _renderDayEvents(events, false, true);
3982
+
3983
+ segmentElementEach(segments, function (segment, element) {
3984
+ reportEventElement(segment.event, element);
3985
+ });
3986
+
3987
+ attachHandlers(segments, modifiedEventId);
3988
+
3989
+ segmentElementEach(segments, function (segment, element) {
3990
+ trigger('eventAfterRender', segment.event, segment.event, element);
3991
+ });
3992
+ }
3993
+
3994
+ function renderTempDayEvent(event, adjustRow, adjustTop) {
3995
+ var segments = _renderDayEvents( [event], true, false);
3996
+ var elements = [];
3997
+
3998
+ segmentElementEach(segments, function (segment, element) {
3999
+ if (segment.row === adjustRow) element.css('top', adjustTop);
4000
+
4001
+ elements.push(element[0]);
4002
+ });
4003
+
4004
+ return elements;
4005
+ }
4006
+
4007
+ function _renderDayEvents(events, doAppend, doRowHeights) {
4008
+ var finalContainer = getDaySegmentContainer();
4009
+ var renderContainer = doAppend ? $('<div/>') : finalContainer;
4010
+ var segments = buildSegments(events);
4011
+ var html, elements;
4012
+
4013
+ calculateHorizontals(segments);
4014
+
4015
+ html = buildHTML(segments);
4016
+
4017
+ renderContainer[0].innerHTML = html;
4018
+
4019
+ elements = renderContainer.children();
4020
+
4021
+ if (doAppend) finalContainer.append(elements);
4022
+
4023
+ resolveElements(segments, elements);
4024
+ segmentElementEach(segments, function (segment, element) {
4025
+ segment.hsides = hsides(element, true);
4026
+ });
4027
+ segmentElementEach(segments, function (segment, element) {
4028
+ element.width(Math.max(0, segment.outerWidth - segment.hsides));
4029
+ });
4030
+ segmentElementEach(segments, function (segment, element) {
4031
+ segment.outerHeight = element.outerHeight(true);
4032
+ });
4033
+ setVerticals(segments, doRowHeights);
4034
+
4035
+ return segments;
4036
+ }
4037
+
4038
+ function buildSegments(events) {
4039
+ var segments = [];
4040
+
4041
+ for (var i = 0; i < events.length; i++) {
4042
+ var eventSegments = buildSegmentsForEvent(events[i]);
4043
+
4044
+ segments.push.apply(segments, eventSegments);
4045
+ }
4046
+
4047
+ return segments;
4048
+ }
4049
+
4050
+ function buildSegmentsForEvent(event) {
4051
+ var startDate = event.start;
4052
+ var endDate = exclEndDay(event);
4053
+ var segments = rangeToSegments(startDate, endDate);
4054
+
4055
+ for (var i = 0; i < segments.length; i++) {
4056
+ segments[i].event = event;
4057
+ }
4058
+
4059
+ return segments;
4060
+ }
4061
+
4062
+ function calculateHorizontals(segments) {
4063
+ for (var i = 0; i < segments.length; i++) {
4064
+ var segment = segments[i];
4065
+ var leftFunc = segment.isStart ? colContentLeft : colLeft;
4066
+ var rightFunc = segment.isEnd ? colContentRight : colRight;
4067
+ var left = leftFunc(segment.leftCol);
4068
+ var right = rightFunc(segment.rightCol);
4069
+
4070
+ segment.left = left;
4071
+ segment.outerWidth = right - left;
4072
+ }
4073
+ }
4074
+
4075
+ function buildHTML(segments) {
4076
+ var html = '';
4077
+
4078
+ for (var i = 0; i < segments.length; i++) {
4079
+ html += buildHTMLForSegment(segments[i]);
4080
+ }
4081
+
4082
+ return html;
4083
+ }
4084
+
4085
+ function buildHTMLForSegment(segment) {
4086
+ var html = '';
4087
+ var event = segment.event;
4088
+ var url = event.url;
4089
+ var classNames = [ 'calendar-event', 'calendar-event-hori' ];
4090
+
4091
+ if (isEventDraggable(event)) classNames.push('calendar-event-draggable');
4092
+ if (segment.isStart) classNames.push('calendar-event-start');
4093
+ if (segment.isEnd) classNames.push('calendar-event-end');
4094
+
4095
+ classNames = classNames.concat(event.className);
4096
+
4097
+ if (event.source) {
4098
+ classNames = classNames.concat(event.source.className || []);
4099
+ }
4100
+
4101
+ var skinCss = getSkinCss(event, opt);
4102
+
4103
+ if (url) {
4104
+ html += '<a href="' + htmlEscape(url) + '"';
4105
+ } else {
4106
+ html += '<div';
4107
+ }
4108
+
4109
+ html +=' class="' + classNames.join(' ') + '"' +
4110
+ ' style="position: absolute;' +
4111
+ ' left:' + segment.left + 'px;' +
4112
+ skinCss +
4113
+ '">' +
4114
+ '<div class="calendar-event-inner">';
4115
+
4116
+ if (!event.allDay && segment.isStart) {
4117
+ html += '<span class="calendar-event-time">' +
4118
+ htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +
4119
+ '</span>';
4120
+ }
4121
+
4122
+ html += '<span class="calendar-event-title">' +
4123
+ htmlEscape(event.title || '') +
4124
+ '</span></div>';
4125
+
4126
+ html += '</' + (url ? 'a' : 'div') + '>';
4127
+
4128
+ return html;
4129
+ }
4130
+
4131
+ function resolveElements(segments, elements) {
4132
+ for (var i = 0; i < segments.length; i++) {
4133
+ var segment = segments[i];
4134
+ var event = segment.event;
4135
+ var element = elements.eq(i);
4136
+ var triggerRes = trigger('eventRender', event, event, element);
4137
+
4138
+ if (triggerRes === false) {
4139
+ element.remove();
4140
+ } else {
4141
+ if (triggerRes && triggerRes !== true) {
4142
+ triggerRes = $(triggerRes)
4143
+ .css({
4144
+ position: 'absolute',
4145
+ left: segment.left
4146
+ });
4147
+
4148
+ element.replaceWith(triggerRes);
4149
+ element = triggerRes;
4150
+ }
4151
+
4152
+ segment.element = element;
4153
+ }
4154
+ }
4155
+ }
4156
+
4157
+ function setVerticals(segments, doRowHeights) {
4158
+ var rowContentHeights = calculateVerticals(segments);
4159
+ var rowContentElements = getRowContentElements();
4160
+ var rowContentTops = [];
4161
+ var i;
4162
+
4163
+ if (doRowHeights) {
4164
+ for (i = 0; i < rowContentElements.length; i++) {
4165
+ rowContentElements[i].height(rowContentHeights[i]);
4166
+ }
4167
+ }
4168
+
4169
+ for (i = 0; i < rowContentElements.length; i++) {
4170
+ rowContentTops.push(rowContentElements[i].position().top);
4171
+ }
4172
+
4173
+ segmentElementEach(segments, function (segment, element) {
4174
+ element.css('top', rowContentTops[segment.row] + segment.top);
4175
+ });
4176
+ }
4177
+
4178
+ function calculateVerticals(segments) {
4179
+ var rowCnt = getRowCnt();
4180
+ var colCnt = getColCnt();
4181
+ var rowContentHeights = [];
4182
+ var segmentRows = buildSegmentRows(segments);
4183
+ var colI;
4184
+
4185
+ for (var rowI = 0; rowI < rowCnt; rowI++) {
4186
+ var segmentRow = segmentRows[rowI];
4187
+ var colHeights = [];
4188
+
4189
+ for (colI = 0; colI < colCnt; colI++) {
4190
+ colHeights.push(0);
4191
+ }
4192
+
4193
+ for (var segmentI = 0; segmentI < segmentRow.length; segmentI++) {
4194
+ var segment = segmentRow[segmentI];
4195
+
4196
+ segment.top = arrayMax(
4197
+ colHeights.slice(
4198
+ segment.leftCol,
4199
+ segment.rightCol + 1
4200
+ )
4201
+ );
4202
+
4203
+ for (colI = segment.leftCol; colI <= segment.rightCol; colI++) {
4204
+ colHeights[colI] = segment.top + segment.outerHeight;
4205
+ }
4206
+ }
4207
+
4208
+ rowContentHeights.push(arrayMax(colHeights));
4209
+ }
4210
+
4211
+ return rowContentHeights;
4212
+ }
4213
+
4214
+ function buildSegmentRows(segments) {
4215
+ var rowCnt = getRowCnt();
4216
+ var segmentRows = [];
4217
+ var rowI, segment, segmentI;
4218
+
4219
+ for (segmentI = 0; segmentI < segments.length; segmentI++) {
4220
+ segment = segments[segmentI];
4221
+ rowI = segment.row;
4222
+
4223
+ if (segment.element) {
4224
+ if (segmentRows[rowI]) {
4225
+ segmentRows[rowI].push(segment);
4226
+ } else {
4227
+ segmentRows[rowI] = [ segment ];
4228
+ }
4229
+ }
4230
+ }
4231
+
4232
+ for (rowI = 0; rowI < rowCnt; rowI++) {
4233
+ segmentRows[rowI] = sortSegmentRow(segmentRows[rowI] || []);
4234
+ }
4235
+
4236
+ return segmentRows;
4237
+ }
4238
+
4239
+ function sortSegmentRow(segments) {
4240
+ var sortedSegments = [];
4241
+ var subrows = buildSegmentSubrows(segments);
4242
+
4243
+ for (var i = 0; i < subrows.length; i++) {
4244
+ sortedSegments.push.apply(sortedSegments, subrows[i]);
4245
+ }
4246
+
4247
+ return sortedSegments;
4248
+ }
4249
+
4250
+ function buildSegmentSubrows(segments) {
4251
+ var subrows = [];
4252
+
4253
+ segments.sort(compareDaySegments);
4254
+
4255
+ for (var i = 0; i < segments.length; i++) {
4256
+ var segment = segments[i];
4257
+
4258
+ for (var j=0; j<subrows.length; j++) {
4259
+ if (!isDaySegmentCollision(segment, subrows[j])) break;
4260
+ }
4261
+
4262
+ if (subrows[j]) {
4263
+ subrows[j].push(segment);
4264
+ } else {
4265
+ subrows[j] = [ segment ];
4266
+ }
4267
+ }
4268
+
4269
+ return subrows;
4270
+ }
4271
+
4272
+ function getRowContentElements() {
4273
+ var rowCnt = getRowCnt();
4274
+ var rowDivs = [];
4275
+
4276
+ for (var i = 0; i < rowCnt; i++) {
4277
+ rowDivs[i] = allDayRow(i).find('div.calendar-day-content > div');
4278
+ }
4279
+
4280
+ return rowDivs;
4281
+ }
4282
+
4283
+ function attachHandlers(segments, modifiedEventId) {
4284
+ var segmentContainer = getDaySegmentContainer();
4285
+
4286
+ segmentElementEach(segments, function (segment, element, i) {
4287
+ var event = segment.event;
4288
+
4289
+ if (event._id === modifiedEventId) {
4290
+ bindDaySeg(event, element, segment);
4291
+ } else {
4292
+ element[0]._fci = i;
4293
+ }
4294
+ });
4295
+
4296
+ lazySegBind(segmentContainer, segments, bindDaySeg);
4297
+ }
4298
+
4299
+ function bindDaySeg(event, eventElement, segment) {
4300
+ if (isEventDraggable(event)) t.draggableDayEvent(event, eventElement, segment);
4301
+ if (segment.isEnd && isEventResizable(event)) t.resizableDayEvent(event, eventElement, segment);
4302
+
4303
+ eventElementHandlers(event, eventElement);
4304
+ }
4305
+
4306
+ function draggableDayEvent(event, eventElement) {
4307
+ var hoverListener = getHoverListener();
4308
+ var dayDelta;
4309
+
4310
+ eventElement.draggable({
4311
+ delay: 50,
4312
+ opacity: opt('dragOpacity'),
4313
+ revertDuration: opt('dragRevertDuration'),
4314
+ start: function (ev, ui) {
4315
+ trigger('eventDragStart', eventElement, event, ev, ui);
4316
+ hideEvents(event, eventElement);
4317
+
4318
+ hoverListener.start(function (cell, origCell, rowDelta, colDelta) {
4319
+ eventElement.draggable('option', 'revert', !cell || !rowDelta && !colDelta);
4320
+
4321
+ clearOverlays();
4322
+
4323
+ if (cell) {
4324
+ var origDate = cellToDate(origCell);
4325
+ var date = cellToDate(cell);
4326
+
4327
+ dayDelta = dayDiff(date, origDate);
4328
+
4329
+ renderDayOverlay(addDays(cloneDate(event.start), dayDelta), addDays(exclEndDay(event), dayDelta));
4330
+ } else {
4331
+ dayDelta = 0;
4332
+ }
4333
+ }, ev, 'drag');
4334
+ },
4335
+ stop: function (ev, ui) {
4336
+ hoverListener.stop();
4337
+
4338
+ clearOverlays();
4339
+ trigger('eventDragStop', eventElement, event, ev, ui);
4340
+
4341
+ if (dayDelta) {
4342
+ eventDrop(this, event, dayDelta, 0, event.allDay, ev, ui);
4343
+ } else {
4344
+ eventElement.css('filter', '');
4345
+ showEvents(event, eventElement);
4346
+ }
4347
+ }
4348
+ });
4349
+ }
4350
+
4351
+ function resizableDayEvent(event, element, segment) {
4352
+ var direction = 'e';
4353
+ var handle = element.find('.ui-resizable-' + direction);
4354
+ var isResizing = false;
4355
+
4356
+ disableTextSelection(element);
4357
+
4358
+ element
4359
+ .mousedown(function (ev) {
4360
+ ev.preventDefault();
4361
+ })
4362
+ .click(function (ev) {
4363
+ if (isResizing) {
4364
+ ev.preventDefault();
4365
+ ev.stopImmediatePropagation();
4366
+ }
4367
+ });
4368
+
4369
+ handle.mousedown(function (ev) {
4370
+ if (ev.which !== 1) return;
4371
+
4372
+ isResizing = true;
4373
+
4374
+ var hoverListener = getHoverListener();
4375
+ var rowCnt = getRowCnt();
4376
+ var colCnt = getColCnt();
4377
+ var elementTop = element.css('top');
4378
+ var dayDelta;
4379
+ var helpers;
4380
+ var eventCopy = $.extend({}, event);
4381
+ var minCellOffset = dayOffsetToCellOffset( dateToDayOffset(event.start) );
4382
+
4383
+ clearSelection();
4384
+
4385
+ $('body')
4386
+ .css('cursor', direction + '-resize')
4387
+ .one('mouseup', mouseup);
4388
+
4389
+ trigger('eventResizeStart', this, event, ev);
4390
+
4391
+ hoverListener.start(function (cell, origCell) {
4392
+ if (cell) {
4393
+ var origCellOffset = cellToCellOffset(origCell);
4394
+ var cellOffset = cellToCellOffset(cell);
4395
+
4396
+ cellOffset = Math.max(cellOffset, minCellOffset);
4397
+ dayDelta = cellOffsetToDayOffset(cellOffset) - cellOffsetToDayOffset(origCellOffset);
4398
+
4399
+ if (dayDelta) {
4400
+ eventCopy.end = addDays(eventEnd(event), dayDelta, true);
4401
+
4402
+ var oldHelpers = helpers;
4403
+
4404
+ helpers = renderTempDayEvent(eventCopy, segment.row, elementTop);
4405
+ helpers = $(helpers);
4406
+
4407
+ helpers.find('*').css('cursor', direction + '-resize');
4408
+
4409
+ if (oldHelpers) oldHelpers.remove();
4410
+
4411
+ hideEvents(event);
4412
+ } else {
4413
+ if (helpers) {
4414
+ showEvents(event);
4415
+ helpers.remove();
4416
+ helpers = null;
4417
+ }
4418
+ }
4419
+
4420
+ clearOverlays();
4421
+ renderDayOverlay(event.start, addDays(exclEndDay(event), dayDelta));
4422
+ }
4423
+ }, ev);
4424
+
4425
+ function mouseup(ev) {
4426
+ trigger('eventResizeStop', this, event, ev);
4427
+
4428
+ $('body').css('cursor', '');
4429
+
4430
+ hoverListener.stop();
4431
+
4432
+ clearOverlays();
4433
+
4434
+ if (dayDelta) eventResize(this, event, dayDelta, 0, ev);
4435
+
4436
+ setTimeout(function () {
4437
+ isResizing = false;
4438
+ }, 0);
4439
+ }
4440
+ });
4441
+ }
4442
+ }
4443
+
4444
+ function isDaySegmentCollision(segment, otherSegments) {
4445
+ for (var i = 0; i < otherSegments.length; i++) {
4446
+ var otherSegment = otherSegments[i];
4447
+
4448
+ if (otherSegment.leftCol <= segment.rightCol && otherSegment.rightCol >= segment.leftCol) return true;
4449
+ }
4450
+
4451
+ return false;
4452
+ }
4453
+
4454
+
4455
+ function segmentElementEach(segments, callback) {
4456
+ for (var i = 0; i < segments.length; i++) {
4457
+ var segment = segments[i];
4458
+ var element = segment.element;
4459
+
4460
+ if (element) callback(segment, element, i);
4461
+ }
4462
+ }
4463
+
4464
+
4465
+ function compareDaySegments(a, b) {
4466
+ return (b.rightCol - b.leftCol) - (a.rightCol - a.leftCol) ||
4467
+ b.event.allDay - a.event.allDay ||
4468
+ a.event.start - b.event.start ||
4469
+ (a.event.title || '').localeCompare(b.event.title);
4470
+ }
4471
+
4472
+ function SelectionManager() {
4473
+ var t = this;
4474
+
4475
+ t.select = select;
4476
+ t.unselect = unselect;
4477
+ t.reportSelection = reportSelection;
4478
+ t.daySelectionMousedown = daySelectionMousedown;
4479
+
4480
+ var opt = t.opt;
4481
+ var trigger = t.trigger;
4482
+ var defaultSelectionEnd = t.defaultSelectionEnd;
4483
+ var renderSelection = t.renderSelection;
4484
+ var clearSelection = t.clearSelection;
4485
+ var selected = false;
4486
+
4487
+ if (opt('selectable') && opt('unselectAuto')) {
4488
+ $(document).mousedown(function (ev) {
4489
+ var ignore = opt('unselectCancel');
4490
+
4491
+ if (ignore) {
4492
+ if ($(ev.target).parents(ignore).length) return;
4493
+ }
4494
+
4495
+ unselect(ev);
4496
+ });
4497
+ }
4498
+
4499
+ function select(startDate, endDate, allDay) {
4500
+ unselect();
4501
+
4502
+ if (!endDate) {
4503
+ endDate = defaultSelectionEnd(startDate, allDay);
4504
+ }
4505
+
4506
+ renderSelection(startDate, endDate, allDay);
4507
+ reportSelection(startDate, endDate, allDay);
4508
+ }
4509
+
4510
+ function unselect(ev) {
4511
+ if (selected) {
4512
+ selected = false;
4513
+ clearSelection();
4514
+ trigger('unselect', null, ev);
4515
+ }
4516
+ }
4517
+
4518
+ function reportSelection(startDate, endDate, allDay, ev) {
4519
+ selected = true;
4520
+ trigger('select', null, startDate, endDate, allDay, ev);
4521
+ }
4522
+
4523
+ function daySelectionMousedown(ev) {
4524
+ var cellToDate = t.cellToDate;
4525
+ var getIsCellAllDay = t.getIsCellAllDay;
4526
+ var hoverListener = t.getHoverListener();
4527
+ var reportDayClick = t.reportDayClick;
4528
+
4529
+ if (ev.which === 1 && opt('selectable')) {
4530
+ unselect(ev);
4531
+
4532
+ var _mousedownElement = this;
4533
+ var dates;
4534
+
4535
+ hoverListener.start(function (cell, origCell) {
4536
+ clearSelection();
4537
+
4538
+ if (cell && getIsCellAllDay(cell)) {
4539
+ dates = [ cellToDate(origCell), cellToDate(cell) ].sort(dateCompare);
4540
+
4541
+ renderSelection(dates[0], dates[1], true);
4542
+ } else {
4543
+ dates = null;
4544
+ }
4545
+ }, ev);
4546
+
4547
+ $(document).one('mouseup', function (ev) {
4548
+ hoverListener.stop();
4549
+
4550
+ if (dates) {
4551
+ if (+dates[0] === +dates[1]) reportDayClick(dates[0], true, ev);
4552
+
4553
+ reportSelection(dates[0], dates[1], true, ev);
4554
+ }
4555
+ });
4556
+ }
4557
+ }
4558
+ }
4559
+
4560
+ function OverlayManager() {
4561
+ var t = this;
4562
+
4563
+ t.renderOverlay = renderOverlay;
4564
+ t.clearOverlays = clearOverlays;
4565
+
4566
+ var usedOverlays = [];
4567
+ var unusedOverlays = [];
4568
+
4569
+ function renderOverlay(rect, parent) {
4570
+ var e = unusedOverlays.shift();
4571
+
4572
+ if (!e) {
4573
+ e = $("<div class='calendar-cell-overlay' style='position:absolute;z-index:3'/>");
4574
+ }
4575
+
4576
+ if (e[0].parentNode !== parent[0]) e.appendTo(parent);
4577
+
4578
+ usedOverlays.push(e.css(rect).show());
4579
+
4580
+ return e;
4581
+ }
4582
+
4583
+ function clearOverlays() {
4584
+ var e;
4585
+
4586
+ while (e = usedOverlays.shift()) {
4587
+ unusedOverlays.push(e.hide().unbind());
4588
+ }
4589
+ }
4590
+ }
4591
+
4592
+ function CoordinateGrid(buildFunc) {
4593
+ var t = this;
4594
+ var cols, rows;
4595
+
4596
+ t.build = function () {
4597
+ rows = [];
4598
+ cols = [];
4599
+
4600
+ buildFunc(rows, cols);
4601
+ };
4602
+
4603
+ t.cell = function (x, y) {
4604
+ var rowCnt = rows.length;
4605
+ var colCnt = cols.length;
4606
+ var i, r=-1, c=-1;
4607
+
4608
+ for (i = 0; i < rowCnt; i++) {
4609
+ if (y >= rows[i][0] && y < rows[i][1]) {
4610
+ r = i;
4611
+ break;
4612
+ }
4613
+ }
4614
+ for (i = 0; i < colCnt; i++) {
4615
+ if (x >= cols[i][0] && x < cols[i][1]) {
4616
+ c = i;
4617
+ break;
4618
+ }
4619
+ }
4620
+
4621
+ return (r >= 0 && c >= 0) ? { row: r, col: c } : null;
4622
+ };
4623
+
4624
+ t.rect = function (row0, col0, row1, col1, originElement) {
4625
+ var origin = originElement.offset();
4626
+
4627
+ return {
4628
+ top: rows[row0][0] - origin.top,
4629
+ left: cols[col0][0] - origin.left,
4630
+ width: cols[col1][1] - cols[col0][0],
4631
+ height: rows[row1][1] - rows[row0][0]
4632
+ };
4633
+ };
4634
+ }
4635
+
4636
+ function HoverListener(coordinateGrid) {
4637
+ var t = this;
4638
+ var bindType, change, firstCell, cell;
4639
+
4640
+ t.start = function (_change, ev, _bindType) {
4641
+ change = _change;
4642
+ firstCell = cell = null;
4643
+
4644
+ coordinateGrid.build();
4645
+
4646
+ mouse(ev);
4647
+
4648
+ bindType = _bindType || 'mousemove';
4649
+
4650
+ $(document).bind(bindType, mouse);
4651
+ };
4652
+
4653
+ function mouse(ev) {
4654
+ _fixUIEvent(ev);
4655
+
4656
+ var newCell = coordinateGrid.cell(ev.pageX, ev.pageY);
4657
+
4658
+ if (newCell !== cell || newCell && (newCell.row !== cell.row || newCell.col !== cell.col)) {
4659
+ if (newCell) {
4660
+ if (!firstCell) {
4661
+ firstCell = newCell;
4662
+ }
4663
+
4664
+ change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col);
4665
+ } else {
4666
+ change(newCell, firstCell);
4667
+ }
4668
+
4669
+ cell = newCell;
4670
+ }
4671
+ }
4672
+
4673
+ t.stop = function () {
4674
+ $(document).unbind(bindType, mouse);
4675
+ return cell;
4676
+ };
4677
+ }
4678
+
4679
+ function _fixUIEvent(event) {
4680
+ if (event.pageX === undefined) {
4681
+ event.pageX = event.originalEvent.pageX;
4682
+ event.pageY = event.originalEvent.pageY;
4683
+ }
4684
+ }
4685
+
4686
+ function HorizontalPositionCache(getElement) {
4687
+ var t = this;
4688
+ var elements = {};
4689
+ var lefts = {};
4690
+ var rights = {};
4691
+
4692
+ function e(i) {
4693
+ return elements[i] = elements[i] || getElement(i);
4694
+ }
4695
+
4696
+ t.left = function (i) {
4697
+ return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i];
4698
+ };
4699
+ t.right = function (i) {
4700
+ return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i];
4701
+ };
4702
+ t.clear = function () {
4703
+ elements = {};
4704
+ lefts = {};
4705
+ rights = {};
4706
+ };
4707
+ }
4708
+
4709
+ })(jQuery);