Commit 29f4630682371d7a32eff3d6a32c5106f5332584
1 parent
f6195010
Restored accidentaly removed richfaces.schedule.js
Showing
1 changed file
with
548 additions
and
0 deletions
1 | +window.RichFaces = window.RichFaces || {}; | |
2 | +//TODO test ajax reRender | |
3 | +RichFaces.Schedule = function(id, locale, options, dateRangeChangeEventName, itemSelectEventName, itemMoveEventName, itemResizeEventName, viewChangeEventName, dateSelectEventName, dateRangeSelectEventName, submitEventFunction) { | |
4 | + | |
5 | + var _this = this; | |
6 | + this.scheduleNode = document.getElementById(id); | |
7 | + this.scheduleNode.component = this; | |
8 | + if (!this.scheduleNode) { | |
9 | + throw "No element with id '" + id + "' found."; | |
10 | + } | |
11 | + | |
12 | + /** | |
13 | + * Message bundle setup. | |
14 | + */ | |
15 | + options = jQuery.extend({}, this.messages[locale], options); | |
16 | + | |
17 | + jQuery(document).ready(function() { | |
18 | + _this.delegate = jQuery(_this.scheduleNode).fullCalendar(options); | |
19 | + }); | |
20 | + | |
21 | + | |
22 | + // --- | |
23 | + /** | |
24 | + * Utility functions. | |
25 | + */ | |
26 | + // --- | |
27 | + /** | |
28 | + * Converts javascript date into integer that can be used as param | |
29 | + * for new Date(long) - milliseconds since epoch. | |
30 | + */ | |
31 | + var formatDateParam = function(date) { | |
32 | + return Math.round(date.getTime() / 1000); | |
33 | + }; | |
34 | + /** | |
35 | + * Compares two dates with with an accuracy of a day. | |
36 | + */ | |
37 | + var isSameDay = function(dateA, dateB) { | |
38 | + if (!dateA instanceof Date || !dateB instanceof Date) { | |
39 | + throw "Both params must be Date objects"; | |
40 | + } | |
41 | + return dateA.getYear() == dateB.getYear() | |
42 | + && dateA.getMonth() == dateB.getMonth() | |
43 | + && dateA.getDate() == dateB.getDate(); | |
44 | + }; | |
45 | + // --- | |
46 | + /** | |
47 | + * DELEGATE SETUP. | |
48 | + * Delegate (fullCalendar) needs callback methods | |
49 | + * for various events such as item clicking, dragging, resizing or loading | |
50 | + * items. | |
51 | + * Functions below can be overriden by ones declared in "options" parameter. | |
52 | + */ | |
53 | + // --- | |
54 | + /** | |
55 | + * Called by fullCalendar when it needs to load items - initial load, | |
56 | + * view type change, time navigation. | |
57 | + * If in ajax mode, then some initial items should be provided. | |
58 | + * If so then they are used for the first invocation of this function. | |
59 | + * This avoids creating additional ajax request on initial rendering. | |
60 | + * Custom users code cannot raise veto so any return statements there are | |
61 | + * ignored. | |
62 | + */ | |
63 | + var dateRangeChange = function(startDate, endDate, callback) { | |
64 | + var firstInvocation = options.initialItems != null; | |
65 | + if (firstInvocation) { | |
66 | + var startDateData = options.initialItems.startDate; | |
67 | + var endDateData = options.initialItems.endDate; | |
68 | + var initialStartDate = new Date(startDateData.year, startDateData.month, startDateData.date); | |
69 | + var initialEndDate = new Date(endDateData.year, endDateData.month, endDateData.date); | |
70 | + var items = options.initialItems.items; | |
71 | + /** | |
72 | + * After initial load this should be cleaned so items are not cached. | |
73 | + */ | |
74 | + options.initialItems = null; | |
75 | + /** | |
76 | + * In case the JSF component made a mistake in calculating initial | |
77 | + * date range we don't use initial items and just continue. | |
78 | + */ | |
79 | + if (isSameDay(startDate, initialStartDate) && isSameDay(endDate, initialEndDate)) { | |
80 | + callback(items); | |
81 | + return; | |
82 | + } | |
83 | + } | |
84 | + if (submitEventFunction != null) { | |
85 | + submitEventFunction({} /* stub event */, | |
86 | + null, | |
87 | + dateRangeChangeEventName, | |
88 | + null, | |
89 | + formatDateParam(startDate), | |
90 | + formatDateParam(endDate), | |
91 | + null, null, null, | |
92 | + function(request, event, data) { | |
93 | + var scheduleData = request.getJSON('_ajax:scheduleData') | |
94 | + if (scheduleData != undefined) { | |
95 | + callback(scheduleData); | |
96 | + } | |
97 | + if (options.ondaterangechange != null) { | |
98 | + RichFaces.Schedule.eval("(function(){" + options.ondaterangechange + "})()", { | |
99 | + 'startDate':startDate, | |
100 | + 'endDate':endDate, | |
101 | + 'data':data, | |
102 | + 'items':scheduleData | |
103 | + }); | |
104 | + } | |
105 | + } | |
106 | + ); | |
107 | + } else if (!firstInvocation && options.ondaterangechange != null) { | |
108 | + RichFaces.Schedule.eval("(function(){" + options.ondaterangechange + "})()", { | |
109 | + 'startDate':startDate, | |
110 | + 'endDate':endDate | |
111 | + }); | |
112 | + } | |
113 | + }; | |
114 | + /** | |
115 | + * Called by fullCalendar when item has started to be dragged. | |
116 | + */ | |
117 | + var itemDragStart = function(item, event, ui, view) { | |
118 | + if (options.onitemdragstart != null) { | |
119 | + RichFaces.Schedule.eval("(function(){" + options.onitemdragstart + "})()", { | |
120 | + 'item':item, | |
121 | + 'event':event, | |
122 | + 'ui':ui, | |
123 | + 'view':view | |
124 | + }); | |
125 | + } | |
126 | + }; | |
127 | + /** | |
128 | + * Called by fullCalendar when item has stopped to be dragged. | |
129 | + * This is invoked between itemDragStart and itemDrop. | |
130 | + */ | |
131 | + var itemDragStop = function(item, event, ui, view) { | |
132 | + if (options.onitemdragstop != null) { | |
133 | + RichFaces.Schedule.eval("(function(){" + options.onitemdragstop + "})()", { | |
134 | + 'item':item, | |
135 | + 'event':event, | |
136 | + 'ui':ui, | |
137 | + 'view':view | |
138 | + }); | |
139 | + } | |
140 | + }; | |
141 | + /** | |
142 | + * Called by fullCalendar when item was dropped (dragging finished). | |
143 | + * This is invoked after itemDragStop. | |
144 | + * Custom users code may raise veto by returning "false". In such case | |
145 | + * changes will be reverted and no event will be sent to server. | |
146 | + */ | |
147 | + var itemDrop = function(item, dayDelta, minuteDelta, allDay, revertFunc, event, ui, view) { | |
148 | + var result; | |
149 | + if (options.onbeforeitemdrop != null) { | |
150 | + result = RichFaces.Schedule.eval("(function(){" + options.onbeforeitemdrop + "})()", { | |
151 | + 'item':item, | |
152 | + 'dayDelta':dayDelta, | |
153 | + 'minuteDelta':minuteDelta, | |
154 | + 'allDay':allDay, | |
155 | + 'event':event, | |
156 | + 'ui':ui, | |
157 | + 'view':view | |
158 | + }); | |
159 | + if (result === false) { | |
160 | + revertFunc(); | |
161 | + return; | |
162 | + } | |
163 | + } | |
164 | + if (submitEventFunction != null) { | |
165 | + submitEventFunction(event, | |
166 | + null, | |
167 | + itemMoveEventName, | |
168 | + item.id, | |
169 | + null, | |
170 | + null, | |
171 | + dayDelta, minuteDelta, allDay, | |
172 | + function(request, event, data) { | |
173 | + var decision = request.getJSON('_ajax:scheduleData'); | |
174 | + var vetoed = false; | |
175 | + if (decision != undefined && decision !== true) { | |
176 | + revertFunc(); | |
177 | + vetoed = true; | |
178 | + } | |
179 | + if (options.onitemdrop != null) { | |
180 | + RichFaces.Schedule.eval("(function(){" + options.onitemdrop + "})()", { | |
181 | + 'item':item, | |
182 | + 'dayDelta':dayDelta, | |
183 | + 'minuteDelta':minuteDelta, | |
184 | + 'allDay':allDay, | |
185 | + 'event':event, | |
186 | + 'ui':ui, | |
187 | + 'view':view, | |
188 | + 'data':data, | |
189 | + 'vetoed':vetoed | |
190 | + }); | |
191 | + } | |
192 | + } | |
193 | + ); | |
194 | + } | |
195 | + }; | |
196 | + /** | |
197 | + * Called by fullCalendar when item has started to be resized. | |
198 | + */ | |
199 | + var itemResizeStart = function(item, event, ui, view) { | |
200 | + if (options.onitemresizestart != null) { | |
201 | + RichFaces.Schedule.eval("(function(){" + options.onitemresizestart + "})()", { | |
202 | + 'item':item, | |
203 | + 'event':event, | |
204 | + 'ui':ui, | |
205 | + 'view':view | |
206 | + }); | |
207 | + } | |
208 | + }; | |
209 | + /** | |
210 | + * Called by fullCalendar when item has stopped to be resized. | |
211 | + * This is invoked between itemResizeStart and itemResized. | |
212 | + */ | |
213 | + var itemResizeStop = function(item, event, ui, view) { | |
214 | + if (options.onitemresizestop != null) { | |
215 | + RichFaces.Schedule.eval("(function(){" + options.onitemresizestop + "})()", { | |
216 | + 'item':item, | |
217 | + 'event':event, | |
218 | + 'ui':ui, | |
219 | + 'view':view | |
220 | + }); | |
221 | + } | |
222 | + }; | |
223 | + /** | |
224 | + * Called by fullCalendar when item was resized. | |
225 | + * This is invoked after itemResizeStop. | |
226 | + * Custom users code may raise veto by returning "false". In such case | |
227 | + * changes will be reverted and no event will be sent to server. | |
228 | + */ | |
229 | + var itemResized = function(item, dayDelta, minuteDelta, revertFunc, event, ui, view) { | |
230 | + var result; | |
231 | + if (options.onbeforeitemresize != null) { | |
232 | + result = RichFaces.Schedule.eval("(function(){" + options.onbeforeitemresize + "})()", { | |
233 | + 'item':item, | |
234 | + 'dayDelta':dayDelta, | |
235 | + 'minuteDelta':minuteDelta, | |
236 | + 'event':event, | |
237 | + 'ui':ui, | |
238 | + 'view':view | |
239 | + }); | |
240 | + if (result === false) { | |
241 | + revertFunc(); | |
242 | + return; | |
243 | + } | |
244 | + } | |
245 | + if (submitEventFunction != null) { | |
246 | + submitEventFunction(event, | |
247 | + null, | |
248 | + itemResizeEventName, | |
249 | + item.id, | |
250 | + null, | |
251 | + null, | |
252 | + dayDelta, minuteDelta, null, | |
253 | + function(request, event, data) { | |
254 | + var decision = request.getJSON('_ajax:scheduleData'); | |
255 | + var vetoed = false; | |
256 | + if (decision != undefined && decision !== true) { | |
257 | + revertFunc(); | |
258 | + vetoed = true; | |
259 | + } | |
260 | + if (options.onitemresize != null) { | |
261 | + RichFaces.Schedule.eval("(function(){" + options.onitemresize + "})()", { | |
262 | + 'item':item, | |
263 | + 'dayDelta':dayDelta, | |
264 | + 'minuteDelta':minuteDelta, | |
265 | + 'event':event, | |
266 | + 'ui':ui, | |
267 | + 'view':view, | |
268 | + 'data':data, | |
269 | + 'vetoed':vetoed | |
270 | + }); | |
271 | + } | |
272 | + } | |
273 | + ); | |
274 | + } | |
275 | + }; | |
276 | + /** | |
277 | + * Called by fullCalendar when mouse moves over item. | |
278 | + */ | |
279 | + var itemMouseover = function(item, event, view) { | |
280 | + if (options.onitemmouseover != null) { | |
281 | + RichFaces.Schedule.eval("(function(){" + options.onitemmouseover + "})()", { | |
282 | + 'item':item, | |
283 | + 'event':event, | |
284 | + 'view':view | |
285 | + }); | |
286 | + } | |
287 | + }; | |
288 | + /** | |
289 | + * Called by fullCalendar when mouse leaves item. | |
290 | + */ | |
291 | + var itemMouseout = function(item, event, view) { | |
292 | + if (options.onitemmouseout != null) { | |
293 | + RichFaces.Schedule.eval("(function(){" + options.onitemmouseout + "})()", { | |
294 | + 'item':item, | |
295 | + 'event':event, | |
296 | + 'view':view | |
297 | + }); | |
298 | + } | |
299 | + }; | |
300 | + /** | |
301 | + * Called by fullCalendar when item is clicked. | |
302 | + * Custom users code may return "false". In such case | |
303 | + * changes no event will be sent to server and false will be returned | |
304 | + * to fullCalendar, which will prevent redirecting to URL associated | |
305 | + * with item (if such url was defined for the item). | |
306 | + */ | |
307 | + var itemClick = function(item, event, view) { | |
308 | + var result; | |
309 | + if (options.onbeforeitemselect != null) { | |
310 | + result = RichFaces.Schedule.eval("(function(){" + options.onbeforeitemselect + "})()", { | |
311 | + 'item':item, | |
312 | + 'event':event, | |
313 | + 'view':view | |
314 | + }); | |
315 | + } | |
316 | + if (result === false) { | |
317 | + return false; | |
318 | + } | |
319 | + if (submitEventFunction != null) { | |
320 | + submitEventFunction(event, | |
321 | + null, | |
322 | + itemSelectEventName, | |
323 | + item.id, | |
324 | + null, null, null, null, null, function(request, event, data) { | |
325 | + if (options.onitemselect != null) { | |
326 | + RichFaces.Schedule.eval("(function(){" + options.onitemselect + "})()", { | |
327 | + 'item':item, | |
328 | + 'event':event, | |
329 | + 'view':view, | |
330 | + 'data':data | |
331 | + }); | |
332 | + } | |
333 | + } | |
334 | + ); | |
335 | + } | |
336 | + return result; | |
337 | + }; | |
338 | + /** | |
339 | + * Called by fullCalendar when day is clicked. | |
340 | + * Custom users code may raise veto by returning "false". In such case | |
341 | + * changes will be reverted and no event will be sent to server. | |
342 | + */ | |
343 | + var dayClick = function(date, allDay, event, view) { | |
344 | + if (options.onbeforedateselect != null) { | |
345 | + var result = RichFaces.Schedule.eval("(function(){" + options.onbeforedateselect + "})()", { | |
346 | + 'date':date, | |
347 | + 'allDay':allDay, | |
348 | + 'event':event, | |
349 | + 'view':view | |
350 | + }); | |
351 | + if (result === false) { | |
352 | + return; | |
353 | + } | |
354 | + } | |
355 | + if (submitEventFunction != null) { | |
356 | + submitEventFunction(event, | |
357 | + null, | |
358 | + dateSelectEventName, | |
359 | + null, formatDateParam(date), null, null, null, allDay, function(request, event, data) { | |
360 | + if (options.ondateselect != null) { | |
361 | + RichFaces.Schedule.eval("(function(){" + options.ondateselect + "})()", { | |
362 | + 'date':date, | |
363 | + 'allDay':allDay, | |
364 | + 'event':event, | |
365 | + 'view':view, | |
366 | + 'data':data | |
367 | + }); | |
368 | + } | |
369 | + } | |
370 | + ); | |
371 | + } | |
372 | + }; | |
373 | + var selectedView; | |
374 | + /** | |
375 | + * Called by fullCalendar when view or dates change. | |
376 | + * We want to notify user only about view change, so we cache current view | |
377 | + * on private variable "selectedView" and compare it with value passed | |
378 | + * in parameter. | |
379 | + * Custom users code may not raise veto so any "return" statements are | |
380 | + * ignored. | |
381 | + */ | |
382 | + var viewChanged = function(view) { | |
383 | + if (selectedView != view && selectedView != undefined) { | |
384 | + if (submitEventFunction != null) { | |
385 | + submitEventFunction({}, | |
386 | + view.name, | |
387 | + viewChangeEventName, | |
388 | + null, null, null, null, null, null, function(request, event, data) { | |
389 | + if (options.onviewchange != null) { | |
390 | + RichFaces.Schedule.eval("(function(){" + options.onviewchange + "})()", { | |
391 | + 'view':view, | |
392 | + 'data':data | |
393 | + }); | |
394 | + } | |
395 | + } | |
396 | + ); | |
397 | + } else if (options.onviewchange != null) { | |
398 | + RichFaces.Schedule.eval("(function(){" + options.onviewchange + "})()", { | |
399 | + 'view':view | |
400 | + }); | |
401 | + } | |
402 | + } | |
403 | + selectedView = view; | |
404 | + }; | |
405 | + /** | |
406 | + * Called by fullCalendar when some date range is selected (user clicks | |
407 | + * and drags over empty time cells). | |
408 | + * Custom users code may raise veto by returning "false". In such case | |
409 | + * changes will be reverted and no event will be sent to server. | |
410 | + * What is more, selection will be cleared at the end of this function. | |
411 | + * (This is bad, i guess, but for now i don't see other way to | |
412 | + * hide selection marker after selection was made, event sent to server, | |
413 | + * and server side listeners have created new event for that selection. | |
414 | + * If no unselect would happen then we selection helper would still be there | |
415 | + * and mess the looks) | |
416 | + */ | |
417 | + var dateRangeSelected = function(startDate, endDate, allDay, view) { | |
418 | + if (!_this.delegate.fullCalendar('option', 'selectable')) { | |
419 | + return; | |
420 | + } | |
421 | + var result; | |
422 | + if (options.onbeforedaterangeselect != null) { | |
423 | + result = RichFaces.Schedule.eval("(function(){" + options.onbeforedaterangeselect + "})()", { | |
424 | + 'startDate':startDate, | |
425 | + 'endDate':endDate, | |
426 | + 'allDay':allDay, | |
427 | + 'view':view | |
428 | + }); | |
429 | + } | |
430 | + if (result === false) { | |
431 | + return; | |
432 | + } | |
433 | + if (submitEventFunction != null) { | |
434 | + submitEventFunction({}, | |
435 | + null, | |
436 | + dateRangeSelectEventName, | |
437 | + null, formatDateParam(startDate), formatDateParam(endDate), null, null, allDay, | |
438 | + function(request, event, data) { | |
439 | + _this.refetchItems(); | |
440 | + if (options.ondaterangeselect != null) { | |
441 | + RichFaces.Schedule.eval("(function(){" + options.ondaterangeselect + "})()", { | |
442 | + 'startDate':startDate, | |
443 | + 'endDate':endDate, | |
444 | + 'allDay':allDay, | |
445 | + 'view':view, | |
446 | + 'data':data | |
447 | + }); | |
448 | + } | |
449 | + } | |
450 | + ); | |
451 | + } | |
452 | + }; | |
453 | + options = jQuery.extend({ | |
454 | + events: dateRangeChange, | |
455 | + eventDragStart: itemDragStart, | |
456 | + eventDragStop: itemDragStop, | |
457 | + eventDrop: itemDrop, | |
458 | + eventResizeStart: itemResizeStart, | |
459 | + eventResizeStop: itemResizeStop, | |
460 | + eventResize: itemResized, | |
461 | + eventClick: itemClick, | |
462 | + eventMouseover: itemMouseover, | |
463 | + eventMouseout: itemMouseout, | |
464 | + viewDisplay: viewChanged, | |
465 | + dayClick: dayClick, | |
466 | + select: dateRangeSelected | |
467 | + }, options); | |
468 | + | |
469 | +}; | |
470 | +RichFaces.Schedule.prototype.messages = {}; | |
471 | +/** | |
472 | + * This function evaluates code in template with object in ScopeChain. | |
473 | + * This is usefull if you need to evaluate code that uses member names | |
474 | + * that colide with external names that the code refers to. | |
475 | + * There is almost exact method in utils.js called Richfaces.eval, | |
476 | + * but it swallows exception thrown during evaluation, which makes debugging | |
477 | + * hard. | |
478 | + */ | |
479 | +RichFaces.Schedule.eval = function(template, object) { | |
480 | + var value; | |
481 | + with (object) { | |
482 | + value = eval(template); | |
483 | + } | |
484 | + return value; | |
485 | +}; | |
486 | +RichFaces.Schedule.prototype.select = function(startDate, endDate, allDay) { | |
487 | + this.delegate.fullCalendar('select', startDate, endDate, allDay); | |
488 | +}; | |
489 | +RichFaces.Schedule.prototype.unselect = function() { | |
490 | + this.delegate.fullCalendar('unselect'); | |
491 | +}; | |
492 | +RichFaces.Schedule.prototype.render = function() { | |
493 | + this.delegate.fullCalendar('render'); | |
494 | +}; | |
495 | +RichFaces.Schedule.prototype.destroy = function() { | |
496 | + this.delegate.fullCalendar('destroy'); | |
497 | +}; | |
498 | +RichFaces.Schedule.prototype.getView = function() { | |
499 | + return this.delegate.fullCalendar('getView'); | |
500 | +}; | |
501 | +RichFaces.Schedule.prototype.changeView = function(viewName) { | |
502 | + this.delegate.fullCalendar('changeView', viewName); | |
503 | +}; | |
504 | +RichFaces.Schedule.prototype.prev = function() { | |
505 | + this.delegate.fullCalendar('prev'); | |
506 | +}; | |
507 | +RichFaces.Schedule.prototype.next = function() { | |
508 | + this.delegate.fullCalendar('next'); | |
509 | +}; | |
510 | +RichFaces.Schedule.prototype.prevYear = function() { | |
511 | + this.delegate.fullCalendar('prevYear'); | |
512 | +}; | |
513 | +RichFaces.Schedule.prototype.nextYear = function() { | |
514 | + this.delegate.fullCalendar('nextYear'); | |
515 | +}; | |
516 | +RichFaces.Schedule.prototype.today = function() { | |
517 | + this.delegate.fullCalendar('today'); | |
518 | +}; | |
519 | +RichFaces.Schedule.prototype.gotoDate = function(year, month, date) { | |
520 | + this.delegate.fullCalendar('gotoDate', year, month, date); | |
521 | +}; | |
522 | +RichFaces.Schedule.prototype.incrementDate = function(years, months, days) { | |
523 | + this.delegate.fullCalendar('incrementDate', years, months, days); | |
524 | +}; | |
525 | +RichFaces.Schedule.prototype.updateItem = function(item) { | |
526 | + this.delegate.fullCalendar('updateItem', item); | |
527 | +}; | |
528 | +RichFaces.Schedule.prototype.getItems = function(idOrFilter) { | |
529 | + return this.delegate.fullCalendar('clientEvents', idOrFilter); | |
530 | +}; | |
531 | +RichFaces.Schedule.prototype.removeItems = function(idOrFilter) { | |
532 | + this.delegate.fullCalendar('removeEvents', idOrFilter); | |
533 | +}; | |
534 | +RichFaces.Schedule.prototype.refetchItems = function() { | |
535 | + this.delegate.fullCalendar('refetchEvents'); | |
536 | +}; | |
537 | +RichFaces.Schedule.prototype.addItemsSource = function(source) { | |
538 | + this.delegate.fullCalendar('addEventSource', source); | |
539 | +}; | |
540 | +RichFaces.Schedule.prototype.removeItemsSource = function(source) { | |
541 | + this.delegate.fullCalendar('removeEventSource', source); | |
542 | +}; | |
543 | +RichFaces.Schedule.prototype.addItem = function(event, stick) { | |
544 | + this.delegate.fullCalendar('renderEvent', event, stick); | |
545 | +}; | |
546 | +RichFaces.Schedule.prototype.reRender = function() { | |
547 | + this.delegate.fullCalendar('rerenderEvents'); | |
548 | +}; | |
\ No newline at end of file | ... | ... |
Please
register
or
login
to post a comment