From fe47f049cd9ebf76bc39c11dde730170508648ea Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Fri, 3 Jun 2011 14:39:34 +0200 Subject: [PATCH] Little code re-arrangements: make rcube_calendar a global class --- plugins/calendar/calendar.js | 308 ++++++++++++++++++----------------- 1 file changed, 156 insertions(+), 152 deletions(-) diff --git a/plugins/calendar/calendar.js b/plugins/calendar/calendar.js index 1386a9d4..42643573 100644 --- a/plugins/calendar/calendar.js +++ b/plugins/calendar/calendar.js @@ -22,35 +22,59 @@ +-------------------------------------------------------------------------+ */ -/* calendar initialization */ -window.rcmail && rcmail.addEventListener('init', function(evt) { - - // quote html entities - function Q(str) - { - return String(str).replace(//g, '>').replace(/"/g, '"'); - } - // php equivalent - function nl2br(str) - { - return String(str).replace(/\n/g, "
"); - } - - // Roundcube calendar client class - function rcube_calendar(settings) - { - // member vars +// Roundcube calendar client class +function rcube_calendar(settings) +{ + /*** member vars ***/ this.settings = settings; this.alarm_ids = []; this.alarm_dialog = null; this.snooze_popup = null; this.dismiss_link = null - - // private vars + + + /*** private vars ***/ var me = this; var day_clicked = day_clicked_ts = 0; var ignore_click = false; + // general datepicker settings + var datepicker_settings = { + // translate from fullcalendar format to datepicker format + dateFormat: settings['date_format'].replace(/M/g, 'm').replace(/mmmmm/, 'MM').replace(/mmm/, 'M').replace(/dddd/, 'DD').replace(/ddd/, 'D').replace(/yy/g, 'y'), + firstDay : settings['first_day'], + dayNamesMin: settings['days_short'], + monthNames: settings['months'], + monthNamesShort: settings['months'], + changeMonth: false, + showOtherMonths: true, + selectOtherMonths: true, + }; + + + /*** private methods ***/ + + // quote html entities + var Q = function(str) + { + return String(str).replace(//g, '>').replace(/"/g, '"'); + }; + // php equivalent + var nl2br = function(str) + { + return String(str).replace(/\n/g, "
"); + }; + + // from time and date strings to a real date object + var parse_datetime = function(time, date) { + // we use the utility function from datepicker to parse dates + var date = $.datepicker.parseDate(datepicker_settings.dateFormat, date, datepicker_settings); + var time_arr = time.split(/[:.]/); + if (!isNaN(time_arr[0])) date.setHours(time_arr[0]); + if (!isNaN(time_arr[1])) date.setMinutes(time_arr[1]); + return date; + }; + // create a nice human-readable string for the date/time range var event_date_text = function(event) { @@ -262,8 +286,8 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { var buttons = {}; buttons[rcmail.gettext('save', 'calendar')] = function() { - var start = me.parse_datetime(starttime.val(), startdate.val()); - var end = me.parse_datetime(endtime.val(), enddate.val()); + var start = parse_datetime(starttime.val(), startdate.val()); + var end = parse_datetime(endtime.val(), enddate.val()); // basic input validatetion if (start.getTime() > end.getTime()) { @@ -293,7 +317,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { if (alarm) { var val, offset = $('select.edit-alarm-offset').val(); if (offset == '@') - data.alarms = '@' + (me.parse_datetime($('input.edit-alarm-time').val(), $('input.edit-alarm-date').val()).getTime()/1000) + ':' + alarm; + data.alarms = '@' + (parse_datetime($('input.edit-alarm-time').val(), $('input.edit-alarm-date').val()).getTime()/1000) + ':' + alarm; else if ((val = parseInt($('input.edit-alarm-value').val())) && !isNaN(val) && val >= 0) data.alarms = offset[0] + val + offset[1] + ':' + alarm; } @@ -310,7 +334,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { if (until == 'count') data.recurrence.COUNT = rrtimes.val(); else if (until == 'until') - data.recurrence.UNTIL = me.parse_datetime(endtime.val(), rrenddate.val()).getTime()/1000; + data.recurrence.UNTIL = parse_datetime(endtime.val(), rrenddate.val()).getTime()/1000; if (freq == 'WEEKLY') { var byday = []; @@ -383,7 +407,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { title.select(); }; - + // mouse-click handler to check if the show dialog is still open and prevent default action var dialog_check = function(e) { @@ -400,7 +424,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { } return true; }; - + // display confirm dialog when modifying/deleting a recurring event where the user needs to select the savemode var recurring_edit_confirm = function(event, action) { var $dialog = $('
').addClass('edit-recurring-warning'); @@ -442,30 +466,8 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { return true; }; - // general datepicker settings - this.datepicker_settings = { - // translate from fullcalendar format to datepicker format - dateFormat: settings['date_format'].replace(/M/g, 'm').replace(/mmmmm/, 'MM').replace(/mmm/, 'M').replace(/dddd/, 'DD').replace(/ddd/, 'D').replace(/yy/g, 'y'), - firstDay : settings['first_day'], - dayNamesMin: settings['days_short'], - monthNames: settings['months'], - monthNamesShort: settings['months'], - changeMonth: false, - showOtherMonths: true, - selectOtherMonths: true, - }; - - - // from time and date strings to a real date object - this.parse_datetime = function(time, date) { - // we use the utility function from datepicker to parse dates - var date = $.datepicker.parseDate(me.datepicker_settings.dateFormat, date, me.datepicker_settings); - var time_arr = time.split(/[:.]/); - if (!isNaN(time_arr[0])) date.setHours(time_arr[0]); - if (!isNaN(time_arr[1])) date.setMinutes(time_arr[1]); - return date; - }; + /*** public methods ***/ // public method to bring up the new event dialog this.add_event = function() { @@ -494,7 +496,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { return false; }; - + // display a notification for the given pending alarms this.display_alarms = function(alarms) { // clear old alert first @@ -552,7 +554,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { }); this.alarm_ids = event_ids; }; - + // show a drop-down menu with a selection of snooze times this.snooze_dropdown = function(link) { @@ -577,7 +579,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { this.dismiss_link = link; } }; - + // dismiss or snooze alarms for the given event this.dismiss_alarm = function(id, snooze) { @@ -765,7 +767,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { }; // initialize small calendar widget using jQuery UI datepicker - $('#datepicker').datepicker($.extend(this.datepicker_settings, { + $('#datepicker').datepicker($.extend(datepicker_settings, { inline: true, showWeek: true, changeMonth: false, // maybe enable? @@ -796,108 +798,78 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { $("#calendar .fc-button-prev").click(fullcalendar_update); $("#calendar .fc-button-next").click(fullcalendar_update); $("#calendar .fc-button-today").click(fullcalendar_update); - - // hide event dialog when clicking somewhere into document - $(document).bind('mousedown', dialog_check); - } // end rcube_calendar class + // format time string + var formattime = function(hour, minutes) { + return ((hour < 10) ? "0" : "") + hour + ((minutes < 10) ? ":0" : ":") + minutes; + }; + // if start date is changed, shift end date according to initial duration + var shift_enddate = function(dateText) { + var newstart = parse_datetime('0', dateText); + var newend = new Date(newstart.getTime() + $('#edit-startdate').data('duration') * 1000); + $('#edit-enddate').val($.fullCalendar.formatDate(newend, cal.settings['date_format'])); + }; - // configure toobar buttons - rcmail.register_command('plugin.addevent', function(){ cal.add_event(); }, true); + // init event dialog + $('#eventtabs').tabs(); + $('#edit-enddate, input.edit-alarm-date').datepicker(datepicker_settings); + $('#edit-startdate').datepicker(datepicker_settings).datepicker('option', 'onSelect', shift_enddate).change(function(){ shift_enddate(this.value); }); + $('#edit-allday').click(function(){ $('#edit-starttime, #edit-endtime')[(this.checked?'hide':'show')](); }); - // export events - rcmail.register_command('plugin.export', function(){ rcmail.goto_url('plugin.export_events', { source:cal.selected_calendar }); }, true); - rcmail.enable_command('plugin.export', true); - - // register callback commands - rcmail.addEventListener('plugin.display_alarms', function(alarms){ cal.display_alarms(alarms); }); - - // reload calendar - rcmail.addEventListener('plugin.reload_calendar', function() { $('#calendar').fullCalendar('refetchEvents'); }); - - - var formattime = function(hour, minutes) { - return ((hour < 10) ? "0" : "") + hour + ((minutes < 10) ? ":0" : ":") + minutes; - }; - - // if start date is changed, shift end date according to initial duration - var shift_enddate = function(dateText) { - var newstart = cal.parse_datetime('0', dateText); - var newend = new Date(newstart.getTime() + $('#edit-startdate').data('duration') * 1000); - $('#edit-enddate').val($.fullCalendar.formatDate(newend, cal.settings['date_format'])); - }; - - - // let's go - var cal = new rcube_calendar(rcmail.env.calendar_settings); - - $(window).resize(function() { - $('#calendar').fullCalendar('option', 'height', $(window).height() - 95); - }).resize(); - - // show toolbar - $('#toolbar').show(); - - // init event dialog - $('#eventtabs').tabs(); - $('#edit-enddate, input.edit-alarm-date').datepicker(cal.datepicker_settings); - $('#edit-startdate').datepicker(cal.datepicker_settings).datepicker('option', 'onSelect', shift_enddate).change(function(){ shift_enddate(this.value); }); - $('#edit-allday').click(function(){ $('#edit-starttime, #edit-endtime')[(this.checked?'hide':'show')](); }); - - // configure drop-down menu on time input fields based on jquery UI autocomplete - $('#edit-starttime, #edit-endtime, input.edit-alarm-time') - .attr('autocomplete', "off") - .autocomplete({ - delay: 100, - minLength: 1, - source: function(p, callback) { - /* Time completions */ - var result = []; - var now = new Date(); - var full = p.term - 1 > 0 || p.term.length > 1; - var hours = full? p.term - 0 : now.getHours(); - var step = 15; - var minutes = hours * 60 + (full ? 0 : now.getMinutes()); - var min = Math.ceil(minutes / step) * step % 60; - var hour = Math.floor(Math.ceil(minutes / step) * step / 60); - // list hours from 0:00 till now - for (var h = 0; h < hours; h++) - result.push(formattime(h, 0)); - // list 15min steps for the next two hours - for (; h < hour + 2; h++) { - while (min < 60) { - result.push(formattime(h, min)); - min += step; + // configure drop-down menu on time input fields based on jquery UI autocomplete + $('#edit-starttime, #edit-endtime, input.edit-alarm-time') + .attr('autocomplete', "off") + .autocomplete({ + delay: 100, + minLength: 1, + source: function(p, callback) { + /* Time completions */ + var result = []; + var now = new Date(); + var full = p.term - 1 > 0 || p.term.length > 1; + var hours = full? p.term - 0 : now.getHours(); + var step = 15; + var minutes = hours * 60 + (full ? 0 : now.getMinutes()); + var min = Math.ceil(minutes / step) * step % 60; + var hour = Math.floor(Math.ceil(minutes / step) * step / 60); + // list hours from 0:00 till now + for (var h = 0; h < hours; h++) + result.push(formattime(h, 0)); + // list 15min steps for the next two hours + for (; h < hour + 2; h++) { + while (min < 60) { + result.push(formattime(h, min)); + min += step; + } + min = 0; } - min = 0; + // list the remaining hours till 23:00 + while (h < 24) + result.push(formattime((h++), 0)); + return callback(result); + }, + open: function(event, ui) { + // scroll to current time + var widget = $(this).autocomplete('widget'); + var menu = $(this).data('autocomplete').menu; + var val = $(this).val(); + var li, html, offset = 0; + widget.children().each(function(){ + li = $(this); + html = li.children().first().html(); + if (html < val) + offset += li.height(); + if (html == val) + menu.activate($.Event({ type: 'mouseenter' }), li); + }); + widget.scrollTop(offset - 1); } - // list the remaining hours till 23:00 - while (h < 24) - result.push(formattime((h++), 0)); - return callback(result); - }, - open: function(event, ui) { - // scroll to current time - var widget = $(this).autocomplete('widget'); - var menu = $(this).data('autocomplete').menu; - var val = $(this).val(); - var li, html, offset = 0; - widget.children().each(function(){ - li = $(this); - html = li.children().first().html(); - if (html < val) - offset += li.height(); - if (html == val) - menu.activate($.Event({ type: 'mouseenter' }), li); - }); - widget.scrollTop(offset - 1); - } - }) - .click(function() { // show drop-down upon clicks - $(this).autocomplete('search', $(this).val() ? $(this).val().replace(/\D.*/, "") : " "); - }); - + }) + .click(function() { // show drop-down upon clicks + $(this).autocomplete('search', $(this).val() ? $(this).val().replace(/\D.*/, "") : " "); + }); + // register events on alarm fields $('select.edit-alarm-type').change(function(){ $(this).parent().find('span.edit-alarm-values')[(this.selectedIndex>0?'show':'hide')](); @@ -907,7 +879,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { $(this).parent().find('.edit-alarm-date, .edit-alarm-time')[mode](); $(this).parent().find('.edit-alarm-value').prop('disabled', mode == 'show'); }); - + // toggle recurrence frequency forms $('#edit-recurrence-frequency').change(function(e){ var freq = $(this).val().toLowerCase(); @@ -915,6 +887,38 @@ window.rcmail && rcmail.addEventListener('init', function(evt) { if (freq) $('#recurrence-form-'+freq+', #recurrence-form-until').show(); }); - $('#edit-recurrence-enddate').datepicker(cal.datepicker_settings).click(function(){ $("#edit-recurrence-repeat-until").prop('checked', true) }); - + $('#edit-recurrence-enddate').datepicker(datepicker_settings).click(function(){ $("#edit-recurrence-repeat-until").prop('checked', true) }); + + // hide event dialog when clicking somewhere into document + $(document).bind('mousedown', dialog_check); + +} // end rcube_calendar class + + +/* calendar plugin initialization */ +window.rcmail && rcmail.addEventListener('init', function(evt) { + + // configure toobar buttons + rcmail.register_command('plugin.addevent', function(){ cal.add_event(); }, true); + + // export events + rcmail.register_command('plugin.export', function(){ rcmail.goto_url('plugin.export_events', { source:cal.selected_calendar }); }, true); + rcmail.enable_command('plugin.export', true); + + // register callback commands + rcmail.addEventListener('plugin.display_alarms', function(alarms){ cal.display_alarms(alarms); }); + rcmail.addEventListener('plugin.reload_calendar', function(){ $('#calendar').fullCalendar('refetchEvents'); }); + + + // let's go + var cal = new rcube_calendar(rcmail.env.calendar_settings); + cal.init_ui(); + + $(window).resize(function() { + $('#calendar').fullCalendar('option', 'height', $(window).height() - 95); + }).resize(); + + // show toolbar + $('#toolbar').show(); + });