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