xref: /plugin/davcal/script.js (revision 80e1ddf76ff9879b01dd835b0e45e33631480f72)
1/* DOKUWIKI:include_once fullcalendar-2.4.0/moment.js */
2/* DOKUWIKI:include_once fullcalendar-2.4.0/fullcalendar.js */
3/* DOKUWIKI:include_once fullcalendar-2.4.0/lang/de.js */
4/* DOKUWIKI:include_once fullcalendar-2.4.0/lang/en.js */
5/* DOKUWIKI:include_once fullcalendar-2.4.0/lang/fr.js */
6/* DOKUWIKI:include_once fullcalendar-2.4.0/lang/nl.js */
7/* DOKUWIKI:include_once datetimepicker-2.4.5/jquery.datetimepicker.js */
8/* DOKUWIKI:include_once jstz.js */
9
10/**
11 * Initialize the DAVCal script, attaching some event handlers and triggering
12 * the initial load of the fullcalendar JS
13 */
14jQuery(function() {
15    // Redefine functions for using moment.js with datetimepicker
16
17    Date.parseDate = function( input, format ){
18      return moment(input,format).toDate();
19    };
20    Date.prototype.dateFormat = function( format ){
21      return moment(this).format(format);
22    };
23
24    // Attach to event links
25    var calendarpage = jQuery('#fullCalendar').data('calendarpage');
26    if(!calendarpage) return;
27    dw_davcal__modals.page = calendarpage;
28
29    jQuery('div.fullCalendarSettings a').each(function() {
30        var $link = jQuery(this);
31        var href = $link.attr('href');
32        if (!href) return;
33
34        $link.click(
35            function(e) {
36                dw_davcal__modals.showSettingsDialog();
37                e.preventDefault();
38                return '';
39            }
40        );
41        }
42    );
43
44    // First, retrieve the current settings.
45    // Upon success, initialize fullcalendar.
46    var postArray = { };
47    jQuery.post(
48        DOKU_BASE + 'lib/exe/ajax.php',
49        {
50            call: 'plugin_davcal',
51            id: dw_davcal__modals.page,
52            page: dw_davcal__modals.page,
53            action: 'getSettings',
54            params: postArray
55        },
56        function(data)
57        {
58            var result = data['result'];
59            if(result === true)
60            {
61                dw_davcal__modals.settings = data['settings'];
62                var tz = false;
63                if(data['settings']['timezone'] !== '')
64                    tz = data['settings']['timezone'];
65                // Force-overwrite thhe timezone setting if requested
66                if(data['settings']['meta']['forcetimezone'] !== 'no')
67                    tz = data['settings']['meta']['forcetimezone'];
68                var fcOptions = {
69                    dayClick: function(date, jsEvent, view) {
70                        dw_davcal__modals.showEditEventDialog(date, false);
71                    },
72                    eventClick: function(calEvent, jsEvent, view) {
73                        dw_davcal__modals.showEditEventDialog(calEvent, true);
74                    },
75                    events: {
76                        url: DOKU_BASE + 'lib/exe/ajax.php',
77                        type: 'POST',
78                        data: {
79                            call: 'plugin_davcal',
80                            action: 'getEvents',
81                            id: dw_davcal__modals.page,
82                            page: dw_davcal__modals.page
83                        },
84                        error: function() {
85                            dw_davcal__modals.msg = LANG.plugins.davcal['error_retrieving_data'];
86                            dw_davcal__modals.showDialog(false);
87                        }
88                    },
89                    header: {
90                        left: 'title',
91                        center: 'today prev,next',
92                        right: 'month,agendaWeek,agendaDay'
93                    },
94                    lang: JSINFO.plugin.davcal['language'],
95                    weekNumbers: (data['settings']['weeknumbers'] == 1) ? true : false,
96                    timezone: tz,
97                    weekends: (data['settings']['workweek'] == 1) ? false : true,
98                    firstDay: (data['settings']['monday'] == 1) ? 1 : 0,
99                    defaultView: data['settings']['meta']['view']
100                };
101                var timeformat = data['settings']['timeformat'];
102                // Force-overwrite the user's timezone setting if requested by the calendar
103                if(data['settings']['meta']['forcetimeformat'] !== 'no')
104                    timeformat = data['settings']['meta']['forcetimeformat'];
105                if(timeformat !== 'lang')
106                {
107                    // If the time format is language-based, we don't need to pass
108                    // the timeFormat option to fullCalendar
109                    if(timeformat == '24h')
110                    {
111                        fcOptions.timeFormat = 'H:mm';
112                    }
113                    if(timeformat == '12h')
114                    {
115                        fcOptions.timeFormat = 'h:mmt';
116                    }
117                }
118                var detectedTz = jstz.determine().name();
119                dw_davcal__modals.detectedTz = detectedTz;
120                // The current TZ value holds either the uers's selection or
121                // the force timezone value
122                dw_davcal__modals.currentTz = (tz === false) ? '' : tz;
123                // Initialize the davcal popup
124                var res = jQuery('#fullCalendar').fullCalendar(fcOptions);
125            }
126        }
127    );
128});
129
130/**
131 * This holds all modal windows that DAVCal uses.
132 */
133var dw_davcal__modals = {
134    $editEventDialog: null,
135    $dialog: null,
136    $settingsDialog: null,
137    $inputDialog: null,
138    msg: null,
139    completeCb: null,
140    action: null,
141    uid: null,
142    settings: null,
143    page: null,
144    detectedTz: null,
145    currentTz: null,
146
147    /**
148     * Show the settings dialog
149     */
150    // FIXME: Hide URLs for multi-calendar
151    showSettingsDialog : function() {
152        if(dw_davcal__modals.$settingsDialog)
153            return;
154
155        // Dialog buttons are language-dependent and defined here.
156        // Attach event handlers for save and cancel.
157        var dialogButtons = {};
158        if(!JSINFO.plugin.davcal['disable_settings'])
159        {
160            dialogButtons[LANG.plugins.davcal['save']] = function() {
161                var postArray = { };
162                jQuery("input[class=dw_davcal__settings], select[class=dw_davcal__settings]").each(function() {
163                  if(jQuery(this).attr('type') == 'checkbox')
164                  {
165                      postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
166                  }
167                  else
168                  {
169                      postArray[jQuery(this).prop('name')] = jQuery(this).val();
170                  }
171                });
172                jQuery('#dw_davcal__ajaxsettings').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
173                jQuery.post(
174                    DOKU_BASE + 'lib/exe/ajax.php',
175                    {
176                        call: 'plugin_davcal',
177                        id: dw_davcal__modals.page,
178                        page: dw_davcal__modals.page,
179                        action: 'saveSettings',
180                        params: postArray
181                    },
182                    function(data)
183                    {
184                        var result = data['result'];
185                        var html = data['html'];
186                        jQuery('#dw_davcal__ajaxsettings').html(html);
187                        if(result === true)
188                        {
189                            location.reload();
190                        }
191                    }
192                );
193            };
194        }
195        dialogButtons[LANG.plugins.davcal['cancel']] = function () {
196            dw_davcal__modals.hideSettingsDialog();
197        };
198
199        var settingsHtml = '<div><table>';
200
201        if(JSINFO.plugin.davcal['disable_settings'] && JSINFO.plugin.davcal['disable_sync'] && JSINFO.plugin.davcal['disable_ics'])
202        {
203            settingsHtml += LANG.plugins.davcal['nothing_to_show'];
204        }
205
206        if(!JSINFO.plugin.davcal['disable_settings'])
207        {
208            settingsHtml += '<tr><td>' + LANG.plugins.davcal['timezone'] + '</td><td><select name="timezone" id="dw_davcal__settings_timezone" class="dw_davcal__settings"></select></td></tr>' +
209            '<tr><td>' + LANG.plugins.davcal['timeformat'] + '</td><td><select name="timeformat" id="dw_davcal__settings_timeformat" class="dw_davcal__settings"></select></td></tr>' +
210            '<tr><td>' + LANG.plugins.davcal['weeknumbers'] + '</td><td><input type="checkbox" name="weeknumbers" id="dw_davcal__settings_weeknumbers" class="dw_davcal__settings"></td></tr>' +
211            '<tr><td>' + LANG.plugins.davcal['only_workweek'] + '</td><td><input type="checkbox" name="workweek" id="dw_davcal__settings_workweek" class="dw_davcal__settings"></td></tr>' +
212            '<tr><td>' + LANG.plugins.davcal['start_monday'] + '</td><td><input type="checkbox" name="monday" id="dw_davcal__settings_monday" class="dw_davcal__settings"></td></tr>';
213         }
214
215         if(!JSINFO.plugin.davcal['disable_sync'])
216         {
217             settingsHtml += '<tr id="dw_davcal__settings_syncurl"><td>' + LANG.plugins.davcal['sync_url'] + '</td><td><input type="text" name="syncurl" readonly="readonly" id="dw_davcal__settings_syncurl_edit" class="dw_davcal__text" value="' + dw_davcal__modals.settings['syncurl'] + '"></td></tr>';
218             settingsHtml += '<tr id="dw_davcal__settings_principalurl"><td>' + LANG.plugins.davcal['sync_ical'] + '</td><td><input type="text" name="principalurl" readonly="readonly" id="dw_davcal__settings_principalurl_edit" class="dw_davcal__text" value="' + dw_davcal__modals.settings['principalurl'] + '"></td></tr>';
219         }
220
221         if(!JSINFO.plugin.davcal['disable_ics'])
222         {
223             settingsHtml += '<tr id="dw_davcal__settings_privateurl"><td>' + LANG.plugins.davcal['private_url'] + '</td><td><input type="text" name="privateurl" readonly="readonly" id="dw_davcal__settings_privateurl_edit" class="dw_davcal__text" value="' + dw_davcal__modals.settings['privateurl'] + '"></td></tr>';
224         }
225
226         settingsHtml += '</table>' +
227            '</div>' +
228            '<div id="dw_davcal__ajaxsettings"></div>';
229
230        dw_davcal__modals.$settingsDialog = jQuery(document.createElement('div'))
231       .dialog({
232           autoOpen: false,
233           draggable: true,
234           title: LANG.plugins.davcal['settings'],
235           resizable: true,
236           buttons: dialogButtons,
237       })
238       .html(
239           settingsHtml
240            )
241       .parent()
242       .attr('id','dw_davcal__settings')
243       .show()
244       .appendTo('.dokuwiki:first');
245
246       jQuery('#dw_davcal__settings').position({
247           my: "center",
248           at: "center",
249           of: window
250       });
251
252       // Initialize current settings
253
254        if(!JSINFO.plugin.davcal['disable_settings'])
255        {
256            var $tzdropdown = jQuery('#dw_davcal__settings_timezone');
257            jQuery('#fullCalendarTimezoneList option').each(function() {
258                jQuery('<option />', {value: jQuery(this).val(),
259                        text: jQuery(this).text()}).appendTo($tzdropdown);
260            });
261
262            var $tfdropdown = jQuery('#dw_davcal__settings_timeformat');
263            jQuery('<option />', {value: 'lang', text: LANG.plugins.davcal['language_specific']}).appendTo($tfdropdown);
264            jQuery('<option />', {value: '24h', text: '24h'}).appendTo($tfdropdown);
265            jQuery('<option />', {value: '12h', text: '12h'}).appendTo($tfdropdown);
266
267            if(!JSINFO.plugin.davcal['disable_sync'])
268            {
269                jQuery('#dw_davcal__settings_syncurl_edit').on('click', function() {
270                    jQuery(this).select();
271                });
272                jQuery('#dw_davcal__settings_principalurl_edit').on('click', function() {
273                    jQuery(this).select();
274                });
275            }
276
277            if(!JSINFO.plugin.davcal['disable_ics'])
278            {
279                jQuery('#dw_davcal__settings_privateurl_edit').on('click', function() {
280                    jQuery(this).select();
281                });
282            }
283
284            if(dw_davcal__modals.settings)
285            {
286                if(dw_davcal__modals.settings['timeformat'] !== '')
287                    jQuery('#dw_davcal__settings_timeformat').val(dw_davcal__modals.settings['timeformat']);
288                if(dw_davcal__modals.settings['timezone'] !== '')
289                    jQuery('#dw_davcal__settings_timezone').val(dw_davcal__modals.settings['timezone']);
290                if(dw_davcal__modals.settings['weeknumbers'] == 1)
291                    jQuery('#dw_davcal__settings_weeknumbers').prop('checked', true);
292                else
293                    jQuery('#dw_davcal__settings_weeknumbers').prop('checked', false);
294
295                if(dw_davcal__modals.settings['workweek'] == 1)
296                    jQuery('#dw_davcal__settings_workweek').prop('checked', true);
297                else
298                    jQuery('#dw_davcal__settings_workweek').prop('checked', false);
299
300                if(dw_davcal__modals.settings['monday'] == 1)
301                    jQuery('#dw_davcal__settings_monday').prop('checked', true);
302                else
303                    jQuery('#dw_davcal__settings_monday').prop('checked', false);
304                if(dw_davcal__modals.settings['meta']['forcetimezone'] !== 'no')
305                    jQuery('#dw_davcal__settings_timezone').prop('disabled', true);
306                if(dw_davcal__modals.settings['meta']['forcetimeformat'] !== 'no')
307                    jQuery('#dw_davcal__settings_timeformat').prop('disabled', true);
308            }
309        }
310
311        // attach event handlers
312        jQuery('#dw_davcal__settings .ui-dialog-titlebar-close').click(function(){
313          dw_davcal__modals.hideSettingsDialog();
314        });
315    },
316
317    /**
318     * Sanity-check our events.
319     *
320     * @return boolean false on failure, otherwise true
321     */
322    checkEvents : function() {
323        // Retrieve dates
324        var allDay = jQuery('#dw_davcal__allday_edit').prop('checked');
325        var startDate = moment(jQuery('#dw_davcal__eventfrom_edit').val(), 'YYYY-MM-DD');
326        var endDate = moment(jQuery('#dw_davcal__eventto_edit').val(), 'YYYY-MM-DD');
327
328        // Do the checking
329        if(!allDay)
330        {
331            var startTime = moment.duration(jQuery('#dw_davcal__eventfromtime_edit').val());
332            var endTime = moment.duration(jQuery('#dw_davcal__eventtotime_edit').val());
333            startDate.add(startTime);
334            endDate.add(endTime);
335        }
336        if(!startDate.isValid())
337        {
338            dw_davcal__modals.msg = LANG.plugins.davcal['start_date_invalid'];
339            dw_davcal__modals.showDialog(false);
340            return false;
341        }
342        if(!endDate.isValid())
343        {
344            dw_davcal__modals.msg = LANG.plugins.davcal['end_date_invalid'];
345            dw_davcal__modals.showDialog(false);
346            return false;
347        }
348        if(endDate.isBefore(startDate))
349        {
350            dw_davcal__modals.msg = LANG.plugins.davcal['end_date_before_start_date'];
351            dw_davcal__modals.showDialog(false);
352            return false;
353        }
354        if(!allDay && endDate.isSame(startDate))
355        {
356            dw_davcal__modals.msg = LANG.plugins.davcal['end_date_is_same_as_start_date'];
357            dw_davcal__modals.showDialog(false);
358            return false;
359        }
360        return true;
361    },
362
363    /**
364     * Show the edit event dialog, which is also used to create new events
365     * @param {Object} event The event to create, that is the date or the calEvent
366     * @param {Object} edit  Whether we edit (true) or create a new event (false)
367     */
368    showEditEventDialog : function(event, edit) {
369        if(dw_davcal__modals.$editEventDialog)
370            return;
371
372        var readonly = dw_davcal__modals.settings['readonly'];
373        var title = '';
374        var dialogButtons = {};
375        var calEvent = [];
376        var recurringWarning = '';
377        // Buttons are dependent on edit or create
378        // Several possibilities:
379        //
380        // 1) Somebody tries to edit, it is not recurring and not readonly -> show
381        // 2) Somebody tries to edit, it is recurring and not readonly -> message
382        // 3) Somebody tries to edit, it is readonly -> message
383        // 4) Somebody tries to create and it is readonly -> message
384        // 5) Somebody tries to create -> show
385        if(edit && (event.recurring != true) && (readonly === false))
386        {
387            calEvent = event;
388            title = LANG.plugins.davcal['edit_event'];
389            dialogButtons[LANG.plugins.davcal['edit']] = function() {
390                if(!dw_davcal__modals.checkEvents())
391                  return;
392                var postArray = { };
393                var attachArr = new Array();
394                var pageid = dw_davcal__modals.page;
395                if(dw_davcal__modals.settings['multi'])
396                {
397                    pageid = jQuery("#dw_davcal__editevent_calendar option:selected").val();
398                }
399                jQuery('.dw_davcal__editevent_attachment_link').each(function() {
400                    var attachment = jQuery(this).attr('href');
401                    if(attachment != undefined)
402                    {
403                        attachArr.push(attachment);
404                    }
405                });
406                postArray['attachments'] = attachArr;
407                jQuery("input.dw_davcal__editevent, textarea.dw_davcal__editevent").each(function() {
408                  if(jQuery(this).attr('type') == 'checkbox')
409                  {
410                      postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
411                  }
412                  else
413                  {
414                      postArray[jQuery(this).prop('name')] = jQuery(this).val();
415                  }
416                });
417                jQuery('#dw_davcal__ajaxedit').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
418                jQuery.post(
419                    DOKU_BASE + 'lib/exe/ajax.php',
420                    {
421                        call: 'plugin_davcal',
422                        id: pageid,
423                        page: dw_davcal__modals.page,
424                        action: 'editEvent',
425                        params: postArray
426                    },
427                    function(data)
428                    {
429                        var result = data['result'];
430                        var html = data['html'];
431                        jQuery('#dw_davcal__ajaxedit').html(html);
432                        if(result === true)
433                        {
434                            jQuery('#fullCalendar').fullCalendar('refetchEvents');
435                            dw_davcal__modals.hideEditEventDialog();
436                        }
437                    }
438                );
439            };
440            dialogButtons[LANG.plugins.davcal['delete']] = function() {
441                dw_davcal__modals.action = 'deleteEvent';
442                dw_davcal__modals.msg = LANG.plugins.davcal['really_delete_this_event'];
443                dw_davcal__modals.completeCb = function(data) {
444                    var result = data['result'];
445                    var html = data['html'];
446                    jQuery('#dw_davcal__ajaxedit').html(html);
447                    if(result === true)
448                    {
449                        jQuery('#fullCalendar').fullCalendar('refetchEvents');
450                        dw_davcal__modals.hideEditEventDialog();
451                    }
452                };
453                dw_davcal__modals.showDialog(true);
454            };
455        }
456        else if(edit && (event.recurring == true) && (readonly === false))
457        {
458            calEvent = event;
459            title = LANG.plugins.davcal['edit_event'];
460            recurringWarning = LANG.plugins.davcal['recurring_cant_edit'];
461        }
462        else if(edit && (readonly === true))
463        {
464            calEvent = event;
465            title = LANG.plugins.davcal['edit_event'];
466            recurringWarning = LANG.plugins.davcal['no_permission'];
467        }
468        else if(readonly === true)
469        {
470            calEvent.start = event;
471            calEvent.end = moment(event);
472            calEvent.start.hour(12);
473            calEvent.start.minute(0);
474            calEvent.end.hour(13);
475            calEvent.end.minute(0);
476            calEvent.allDay = false;
477            calEvent.recurring = false;
478            calEvent.title = '';
479            calEvent.description = '';
480            calEvent.id = '0';
481            calEvent.page = dw_davcal__modals.page;
482            title = LANG.plugins.davcal['create_new_event'];
483            recurringWarning = LANG.plugins.davcal['no_permission'];
484        }
485        else
486        {
487            calEvent.start = event;
488            calEvent.end = moment(event);
489            calEvent.start.hour(12);
490            calEvent.start.minute(0);
491            calEvent.end.hour(13);
492            calEvent.end.minute(0);
493            calEvent.allDay = false;
494            calEvent.recurring = false;
495            calEvent.title = '';
496            calEvent.description = '';
497            calEvent.id = '0';
498            calEvent.page = dw_davcal__modals.settings['calids'][0]['page'];
499            title = LANG.plugins.davcal['create_new_event'];
500            dialogButtons[LANG.plugins.davcal['create']] = function() {
501                if(!dw_davcal__modals.checkEvents())
502                  return;
503
504                var postArray = { };
505                var pageid = dw_davcal__modals.page;
506                var attachArr = new Array();
507                if(dw_davcal__modals.settings['multi'])
508                {
509                    pageid = jQuery("#dw_davcal__editevent_calendar option:selected").val();
510                }
511                jQuery("input.dw_davcal__editevent, textarea.dw_davcal__editevent").each(function() {
512                  if(jQuery(this).attr('type') == 'checkbox')
513                  {
514                      postArray[jQuery(this).prop('name')] = jQuery(this).prop('checked') ? 1 : 0;
515                  }
516                  else
517                  {
518                      postArray[jQuery(this).prop('name')] = jQuery(this).val();
519                  }
520                });
521                jQuery('.dw_davcal__editevent_attachment_link').each(function() {
522                    var attachment = jQuery(this).attr('href');
523                    if(attachment != undefined)
524                    {
525                        attachArr.push(attachment);
526                    }
527                });
528                postArray['attachments'] = attachArr;
529                jQuery('#dw_davcal__ajaxedit').html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />');
530                jQuery.post(
531                    DOKU_BASE + 'lib/exe/ajax.php',
532                    {
533                        call: 'plugin_davcal',
534                        id: pageid,
535                        page: dw_davcal__modals.page,
536                        action: 'newEvent',
537                        params: postArray
538                    },
539                    function(data)
540                    {
541                        var result = data['result'];
542                        var html = data['html'];
543                        jQuery('#dw_davcal__ajaxedit').html(html);
544                        if(result === true)
545                        {
546                            jQuery('#fullCalendar').fullCalendar('refetchEvents');
547                            dw_davcal__modals.hideEditEventDialog();
548                        }
549                    }
550                );
551            };
552        }
553        dialogButtons[LANG.plugins.davcal['cancel']] = function() {
554            dw_davcal__modals.hideEditEventDialog();
555        };
556        dw_davcal__modals.uid = calEvent.id;
557        dw_davcal__modals.$editEventDialog = jQuery(document.createElement('div'))
558       .dialog({
559           autoOpen: false,
560           draggable: true,
561           title: title,
562           resizable: true,
563           buttons: dialogButtons,
564       })
565       .html(
566            '<div><table>' +
567            '<tr><td>' + LANG.plugins.davcal['calendar'] + '</td><td><select id="dw_davcal__editevent_calendar"></select></td></tr>' +
568            '<tr><td>' + LANG.plugins.davcal['title'] + '</td><td><input type="text" id="dw_davcal__eventname_edit" name="eventname" class="dw_davcal__editevent"></td></tr>' +
569            '<tr><td>' + LANG.plugins.davcal['description'] + '</td><td><textarea name="eventdescription" id="dw_davcal__eventdescription_edit" class="dw_davcal__editevent dw_davcal__text"></textarea></td></tr>' +
570            '<tr><td>' + LANG.plugins.davcal['from'] + '</td><td><input type="text" name="eventfrom" id="dw_davcal__eventfrom_edit" class="dw_davcal__editevent dw_davcal__date"><input type="text" name="eventfromtime" id="dw_davcal__eventfromtime_edit" class="dw_davcal__editevent dw_davcal__time"></td></tr>' +
571            '<tr><td>' + LANG.plugins.davcal['to'] + '</td><td><input type="text" name="eventto" id="dw_davcal__eventto_edit" class="dw_davcal__editevent dw_davcal__date"><input type="text" name="eventtotime" id="dw_davcal__eventtotime_edit" class="dw_davcal__editevent dw_davcal__time"></td></tr>' +
572            '<tr><td colspan="2"><input type="checkbox" name="allday" id="dw_davcal__allday_edit" class="dw_davcal__editevent">' + LANG.plugins.davcal['allday'] + '</td></tr>' +
573            '<tr><td>' + LANG.plugins.davcal['attachments'] + '</td><td><table id="dw_davcal__editevent_attachments"><tbody><tr><td><input type="text" id="dw_davcal__editevent_attachment" value="http://"></td><td><a href="#" id="dw_davcal__editevent_attach">' + LANG.plugins.davcal['add_attachment'] + '</a></td></tr></tbody></table></td></tr>' +
574            '</table>' +
575            recurringWarning +
576            '<input type="hidden" name="uid" id="dw_davcal__uid_edit" class="dw_davcal__editevent">' +
577            '<input type="hidden" name="detectedtz" id="dw_davcal__tz_edit" class="dw_davcal__editevent">' +
578            '<input type="hidden" name="currenttz" id="dw_davcal__currenttz_edit" class="dw_davcal__editevent">' +
579            '</div>' +
580            '<div id="dw_davcal__ajaxedit"></div>'
581            )
582       .parent()
583       .attr('id','dw_davcal__edit')
584       .show()
585       .appendTo('.dokuwiki:first');
586
587       jQuery('#dw_davcal__edit').position({
588           my: "center",
589           at: "center",
590           of: window
591       });
592
593       // Populate calendar dropdown
594       var $dropdown = jQuery("#dw_davcal__editevent_calendar");
595       for(var i=0; i<dw_davcal__modals.settings['calids'].length; i++)
596       {
597           var sel = '';
598           // When creating an event, do not show read-only calendars
599           if(!edit && (dw_davcal__modals.settings['calids'][i]['write'] === false))
600             continue;
601           if(calEvent.page == dw_davcal__modals.settings['calids'][i]['page'])
602             sel = ' selected="selected"';
603           $dropdown.append('<option value="' + dw_davcal__modals.settings['calids'][i]['page'] + '"' + sel + '>' + dw_davcal__modals.settings['calids'][i]['name'] + '</option>');
604       }
605       if(edit || (dw_davcal__modals.settings['calids'].length < 1))
606       {
607           $dropdown.prop('disabled', true);
608       }
609
610       // Set up existing/predefined values
611       jQuery('#dw_davcal__tz_edit').val(dw_davcal__modals.detectedTz);
612       jQuery('#dw_davcal__currenttz_edit').val(dw_davcal__modals.currentTz);
613       jQuery('#dw_davcal__uid_edit').val(calEvent.id);
614       jQuery('#dw_davcal__eventname_edit').val(calEvent.title);
615       jQuery('#dw_davcal__eventfrom_edit').val(calEvent.start.format('YYYY-MM-DD'));
616       jQuery('#dw_davcal__eventfromtime_edit').val(calEvent.start.format('HH:mm'));
617       jQuery('#dw_davcal__eventdescription_edit').val(calEvent.description);
618       if(calEvent.attachments && (calEvent.attachments !== null))
619       {
620           for(var i=0; i<calEvent.attachments.length; i++)
621           {
622               var url = calEvent.attachments[i];
623               var row = '<tr><td><a href="' + url + '" class="dw_davcal__editevent_attachment_link">' + url + '</a></td><td><a class="deleteLink" href="#">' + LANG.plugins.davcal['delete'] + '</a></td></tr>';
624               jQuery('#dw_davcal__editevent_attachments > tbody:last').append(row);
625
626           }
627       }
628       dw_davcal__modals.attachAttachmentDeleteHandlers();
629       jQuery('#dw_davcal__editevent_attach').on("click", function(e)
630       {
631           e.preventDefault();
632           var url = jQuery('#dw_davcal__editevent_attachment').val();
633           jQuery('#dw_davcal__editevent_attachment').val('http://');
634           var row = '<tr><td><a href="' + url + '" class="dw_davcal__editevent_attachment_link">' + url + '</a></td><td><a class="deleteLink" href="#">' + LANG.plugins.davcal['delete'] + '</a></td></tr>';
635           jQuery('#dw_davcal__editevent_attachments > tbody:last').append(row);
636           dw_davcal__modals.attachAttachmentDeleteHandlers();
637           return false;
638       });
639       if(calEvent.allDay && (calEvent.end === null))
640       {
641           jQuery('#dw_davcal__eventto_edit').val(calEvent.start.format('YYYY-MM-DD'));
642           jQuery('#dw_davcal__eventtotime_edit').val(calEvent.start.format('HH:mm'));
643       }
644       else if(calEvent.allDay)
645       {
646           endEvent = moment(calEvent.end);
647           endEvent.subtract(1, 'days');
648           jQuery('#dw_davcal__eventto_edit').val(endEvent.format('YYYY-MM-DD'));
649           jQuery('#dw_davcal__eventotime_edit').val(endEvent.format('HH:mm'));
650       }
651       else
652       {
653           jQuery('#dw_davcal__eventto_edit').val(calEvent.end.format('YYYY-MM-DD'));
654           jQuery('#dw_davcal__eventtotime_edit').val(calEvent.end.format('HH:mm'));
655       }
656       jQuery('#dw_davcal__allday_edit').prop('checked', calEvent.allDay);
657
658        // attach event handlers
659        jQuery('#dw_davcal__edit .ui-dialog-titlebar-close').click(function(){
660          dw_davcal__modals.hideEditEventDialog();
661        });
662        jQuery('#dw_davcal__eventfrom_edit').datetimepicker({format:'YYYY-MM-DD',
663                                                      formatDate:'YYYY-MM-DD',
664                                                      datepicker: true,
665                                                      timepicker: false,
666                                                      });
667        jQuery('#dw_davcal__eventfromtime_edit').datetimepicker({format:'HH:mm',
668                                                      formatTime:'HH:mm',
669                                                      datepicker: false,
670                                                      timepicker: true,
671                                                      step: 15});
672        jQuery('#dw_davcal__eventto_edit').datetimepicker({format:'YYYY-MM-DD',
673                                                      formatDate:'YYYY-MM-DD',
674                                                      datepicker: true,
675                                                      timepicker: false,
676                                                      });
677        jQuery('#dw_davcal__eventtotime_edit').datetimepicker({format:'HH:mm',
678                                                      formatTime:'HH:mm',
679                                                      datepicker: false,
680                                                      timepicker: true,
681                                                      step:15});
682        jQuery('#dw_davcal__allday_edit').change(function() {
683            if(jQuery(this).is(":checked"))
684            {
685                jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', true);
686                jQuery('#dw_davcal__eventtotime_edit').prop('readonly', true);
687            }
688            else
689            {
690                jQuery('#dw_davcal__eventfromtime_edit').prop('readonly', false);
691                jQuery('#dw_davcal__eventtotime_edit').prop('readonly', false);
692            }
693        });
694        jQuery('#dw_davcal__allday_edit').change();
695    },
696
697    /**
698     * Attach handles to delete the attachments to all 'delete' links
699     */
700    attachAttachmentDeleteHandlers: function()
701    {
702       jQuery("#dw_davcal__editevent_attachments .deleteLink").on("click", function(e)
703       {
704            e.preventDefault();
705            var tr = jQuery(this).closest('tr');
706            tr.css("background-color", "#FF3700");
707            tr.fadeOut(400, function()
708            {
709                tr.remove();
710            });
711            return false;
712       });
713    },
714
715    /**
716     * Show an info/confirmation dialog
717     * @param {Object} confirm Whether a confirmation dialog (true) or an info dialog (false) is requested
718     */
719    showDialog : function(confirm)
720    {
721        if(dw_davcal__modals.$confirmDialog)
722            return;
723        var dialogButtons = {};
724        var title = '';
725        if(confirm)
726        {
727            title = LANG.plugins.davcal['confirmation'];
728            var pageid = dw_davcal__modals.page;
729            if(dw_davcal__modals.settings['multi'])
730            {
731                pageid = jQuery("#dw_davcal__editevent_calendar option:selected").val();
732            }
733            dialogButtons[LANG.plugins.davcal['yes']] =  function() {
734                            jQuery.post(
735                                DOKU_BASE + 'lib/exe/ajax.php',
736                                {
737                                    call: 'plugin_davcal',
738                                    id: pageid,
739                                    page: dw_davcal__modals.page,
740                                    action: dw_davcal__modals.action,
741                                    params: {
742                                        uid: dw_davcal__modals.uid
743                                    }
744                                },
745                                function(data)
746                                {
747                                    dw_davcal__modals.completeCb(data);
748                                }
749                            );
750                            dw_davcal__modals.hideDialog();
751                    };
752            dialogButtons[LANG.plugins.davcal['cancel']] = function() {
753                            dw_davcal__modals.hideDialog();
754                    };
755        }
756        else
757        {
758            title = LANG.plugins.davcal['info'];
759            dialogButtons[LANG.plugins.davcal['ok']] = function() {
760                 dw_davcal__modals.hideDialog();
761            };
762        }
763        dw_davcal__modals.$dialog = jQuery(document.createElement('div'))
764            .dialog({
765                autoOpen: false,
766                draggable: true,
767                title: title,
768                resizable: true,
769                buttons: dialogButtons,
770            })
771            .html(
772                '<div>' + dw_davcal__modals.msg + '</div>'
773            )
774            .parent()
775            .attr('id','dw_davcal__confirm')
776            .show()
777            .appendTo('.dokuwiki:first');
778
779            jQuery('#dw_davcal__confirm').position({
780                my: "center",
781                at: "center",
782                of: window
783            });
784                 // attach event handlers
785            jQuery('#dw_davcal__confirm .ui-dialog-titlebar-close').click(function(){
786                dw_davcal__modals.hideDialog();
787            });
788    },
789
790    /**
791     * Hide the edit event dialog
792     */
793    hideEditEventDialog : function() {
794        dw_davcal__modals.$editEventDialog.empty();
795        dw_davcal__modals.$editEventDialog.remove();
796        dw_davcal__modals.$editEventDialog = null;
797    },
798
799    /**
800     * Hide the confirm/info dialog
801     */
802    hideDialog: function() {
803        dw_davcal__modals.$dialog.empty();
804        dw_davcal__modals.$dialog.remove();
805        dw_davcal__modals.$dialog = null;
806    },
807
808    /**
809     * Hide the settings dialog
810     */
811    hideSettingsDialog: function() {
812        dw_davcal__modals.$settingsDialog.empty();
813        dw_davcal__modals.$settingsDialog.remove();
814        dw_davcal__modals.$settingsDialog = null;
815    }
816};
817