From 2d78686db75c390cec4db191ddea45fce0cef629 Mon Sep 17 00:00:00 2001 From: "ajay javiya (OpenERP)" Date: Mon, 21 Oct 2013 19:20:04 +0530 Subject: [PATCH 01/25] [REF]: Refector many2many_tags bzr revid: aja@tinyerp.com-20131021135004-rmxft7jrvbixhekx --- addons/web/static/src/js/view_form.js | 52 ++++++++++++++++++--------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 7a0890bdcfa..8bff844a540 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -4216,6 +4216,7 @@ var lazy_build_o2m_kanban_view = function() { instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(instance.web.form.CompletionFieldMixin, instance.web.form.ReinitializeFieldMixin, { template: "FieldMany2ManyTags", + tag_template: "FieldMany2ManyTag", init: function() { this._super.apply(this, arguments); instance.web.form.CompletionFieldMixin.init.call(this); @@ -4223,13 +4224,9 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in this._display_orderer = new instance.web.DropMisordered(); this._drop_shown = false; }, - initialize_content: function() { - if (this.get("effective_readonly")) - return; + initialize_texttext: function(){ var self = this; - var ignore_blur = false; - self.$text = this.$("textarea"); - self.$text.textext({ + return { plugins : 'tags arrow autocomplete', autocomplete: { render: function(suggestion) { @@ -4280,7 +4277,15 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in }, }, }, - }).bind('getSuggestions', function(e, data) { + } + }, + initialize_content: function() { + if (this.get("effective_readonly")) + return; + var self = this; + var ignore_blur = false; + self.$text = this.$("textarea"); + self.$text.textext(self.initialize_texttext()).bind('getSuggestions', function(e, data) { var _this = this; var str = !!data ? data.query || '' : ''; self.get_search_result(str).done(function(result) { @@ -4328,6 +4333,24 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in get_search_blacklist: function() { return this.get("value"); }, + map_tag: function(data){ + return _.map(data, function(el) {return {name: el[1], id:el[0]};}) + }, + get_render_data: function(ids){ + var self = this; + var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.build_context()); + return dataset.name_get(ids); + }, + render_tag: function(data) { + var self = this; + if (! self.get("effective_readonly")) { + self.tags.containerElement().children().remove(); + self.$('textarea').css("padding-left", "3px"); + self.tags.addTags(self.map_tag(data)); + } else { + self.$el.html(QWeb.render(self.tag_template, {elements: data})); + } + }, render_value: function() { var self = this; var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.build_context()); @@ -4340,17 +4363,12 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in indexed[el[0]] = el; }); data = _.map(values, function(el) { return indexed[el]; }); - if (! self.get("effective_readonly")) { - self.tags.containerElement().children().remove(); - self.$('textarea').css("padding-left", "3px"); - self.tags.addTags(_.map(data, function(el) {return {name: el[1], id:el[0]};})); - } else { - self.$el.html(QWeb.render("FieldMany2ManyTag", {elements: data})); - } - }; + self.render_tag(data); + } if (! values || values.length > 0) { - this._display_orderer.add(dataset.name_get(values)).done(handle_names); - } else { + this._display_orderer.add(self.get_render_data(values)).done(handle_names); + } + else{ handle_names([]); } }, From e6baeb0ff1ef3e9b36acc2657b1b3eb6ad3bf53b Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Thu, 7 Nov 2013 12:19:57 +0100 Subject: [PATCH 02/25] [IMP] Replace from web_calendar dx Calendar by jQ fullCalendar. Add lib for touchscreen (to test) in web bzr revid: jke@openerp.com-20131107111957-139ny2sz899xx3tl --- addons/web/__openerp__.py | 1 + .../js/jquery.ui.touch-punch.js | 160 + addons/web_calendar/__openerp__.py | 14 +- .../codebase/dhtmlxscheduler.css | 5 - .../codebase/dhtmlxscheduler_dhx_terrace.css | 5 - .../codebase/dhtmlxscheduler_glossy.css | 5 - .../codebase/imgs/but_repeat.gif | Bin 1149 -> 0 bytes .../dhtmlxScheduler/codebase/imgs/buttons.png | Bin 159 -> 0 bytes .../codebase/imgs/calendar.gif | Bin 622 -> 0 bytes .../codebase/imgs/clock_big.gif | Bin 1321 -> 0 bytes .../codebase/imgs/clock_small.gif | Bin 388 -> 0 bytes .../codebase/imgs/collapse_expand_icon.gif | Bin 452 -> 0 bytes .../codebase/imgs/controls.gif | Bin 2496 -> 0 bytes .../dhtmlxScheduler/codebase/imgs/databg.png | Bin 97 -> 0 bytes .../codebase/imgs/databg_now.png | Bin 97 -> 0 bytes .../dhtmlxScheduler/codebase/imgs/icon.png | Bin 209 -> 0 bytes .../dhtmlxScheduler/codebase/imgs/images.png | Bin 899 -> 0 bytes .../dhtmlxScheduler/codebase/imgs/loading.gif | Bin 3951 -> 0 bytes .../codebase/imgs/resize_dots.png | Bin 81 -> 0 bytes .../codebase/imgs_dhx_terrace/arrow_left.png | Bin 177 -> 0 bytes .../codebase/imgs_dhx_terrace/arrow_right.png | Bin 168 -> 0 bytes .../codebase/imgs_dhx_terrace/but_repeat.gif | Bin 1472 -> 0 bytes .../codebase/imgs_dhx_terrace/calendar.gif | Bin 1018 -> 0 bytes .../codebase/imgs_dhx_terrace/clock_big.gif | Bin 1958 -> 0 bytes .../codebase/imgs_dhx_terrace/clock_small.gif | Bin 588 -> 0 bytes .../codebase/imgs_dhx_terrace/close_icon.png | Bin 141 -> 0 bytes .../imgs_dhx_terrace/collapse_expand_icon.gif | Bin 1192 -> 0 bytes .../codebase/imgs_dhx_terrace/controls.png | Bin 706 -> 0 bytes .../codebase/imgs_dhx_terrace/databg.png | Bin 82 -> 0 bytes .../codebase/imgs_dhx_terrace/databg_now.png | Bin 82 -> 0 bytes .../codebase/imgs_dhx_terrace/resize_dots.png | Bin 78 -> 0 bytes .../codebase/imgs_dhx_terrace/resizing.png | Bin 78 -> 0 bytes .../codebase/imgs_glossy/blue_tab.png | Bin 212 -> 0 bytes .../codebase/imgs_glossy/blue_tab_wide.png | Bin 231 -> 0 bytes .../codebase/imgs_glossy/but_repeat.gif | Bin 1149 -> 0 bytes .../codebase/imgs_glossy/buttons.gif | Bin 616 -> 0 bytes .../codebase/imgs_glossy/calendar.gif | Bin 622 -> 0 bytes .../codebase/imgs_glossy/clock_big.png | Bin 998 -> 0 bytes .../codebase/imgs_glossy/clock_small.png | Bin 401 -> 0 bytes .../imgs_glossy/collapse_expand_icon.gif | Bin 452 -> 0 bytes .../codebase/imgs_glossy/controlls5.png | Bin 1874 -> 0 bytes .../codebase/imgs_glossy/databg.png | Bin 89 -> 0 bytes .../codebase/imgs_glossy/databg_now.png | Bin 89 -> 0 bytes .../codebase/imgs_glossy/event-bg.png | Bin 127 -> 0 bytes .../codebase/imgs_glossy/icon.png | Bin 209 -> 0 bytes .../codebase/imgs_glossy/left-separator.png | Bin 190 -> 0 bytes .../codebase/imgs_glossy/left-time-bg.png | Bin 119 -> 0 bytes .../codebase/imgs_glossy/lightbox.png | Bin 177 -> 0 bytes .../codebase/imgs_glossy/loading.gif | Bin 3951 -> 0 bytes .../codebase/imgs_glossy/move.png | Bin 123 -> 0 bytes .../codebase/imgs_glossy/multi-days-bg.png | Bin 276 -> 0 bytes .../imgs_glossy/second-top-days-bg.png | Bin 117 -> 0 bytes .../codebase/imgs_glossy/top-days-bg.png | Bin 154 -> 0 bytes .../codebase/imgs_glossy/top-separator.gif | Bin 259 -> 0 bytes .../codebase/imgs_glossy/white_tab.png | Bin 241 -> 0 bytes .../codebase/imgs_glossy/white_tab_wide.png | Bin 266 -> 0 bytes .../static/lib/dhtmlxScheduler/license.txt | 228 - .../static/lib/dhtmlxScheduler/readme.txt | 6 - .../sources/dhtmlxscheduler.css | 1419 ----- .../sources/dhtmlxscheduler.js | 4806 --------------- .../sources/dhtmlxscheduler_dhx_terrace.css | 2018 ------- .../sources/dhtmlxscheduler_glossy.css | 1715 ------ .../ext/dhtmlxscheduler_active_links.js | 28 - .../ext/dhtmlxscheduler_agenda_view.js | 120 - .../sources/ext/dhtmlxscheduler_all_timed.js | 133 - .../sources/ext/dhtmlxscheduler_collision.js | 119 - .../sources/ext/dhtmlxscheduler_cookie.js | 42 - .../ext/dhtmlxscheduler_dhx_terrace.js | 90 - .../sources/ext/dhtmlxscheduler_editors.js | 142 - .../sources/ext/dhtmlxscheduler_expand.js | 74 - .../sources/ext/dhtmlxscheduler_grid_view.js | 470 -- .../ext/dhtmlxscheduler_html_templates.js | 19 - .../sources/ext/dhtmlxscheduler_key_nav.js | 79 - .../sources/ext/dhtmlxscheduler_limit.js | 831 --- .../sources/ext/dhtmlxscheduler_map_view.js | 490 -- .../sources/ext/dhtmlxscheduler_minical.js | 435 -- .../ext/dhtmlxscheduler_multiselect.js | 66 - .../ext/dhtmlxscheduler_multisource.js | 26 - .../sources/ext/dhtmlxscheduler_offline.js | 79 - .../sources/ext/dhtmlxscheduler_outerdrag.js | 51 - .../sources/ext/dhtmlxscheduler_pdf.js | 276 - .../sources/ext/dhtmlxscheduler_readonly.js | 144 - .../sources/ext/dhtmlxscheduler_recurring.js | 750 --- .../sources/ext/dhtmlxscheduler_serialize.js | 77 - .../sources/ext/dhtmlxscheduler_timeline.js | 963 --- .../sources/ext/dhtmlxscheduler_tooltip.js | 172 - .../ext/dhtmlxscheduler_treetimeline.js | 292 - .../sources/ext/dhtmlxscheduler_units.js | 226 - .../sources/ext/dhtmlxscheduler_url.js | 34 - .../ext/dhtmlxscheduler_week_agenda.js | 256 - .../sources/ext/dhtmlxscheduler_year_view.js | 276 - .../static/lib/dhtmlxScheduler/whatsnew.txt | 48 - .../lib/fullcalendar/css/fullcalendar.css | 579 ++ .../lib/fullcalendar/js/fullcalendar.js | 5377 +++++++++++++++++ .../static/lib/fullcalendar/js/gcal.js | 107 + .../static/lib/fullcalendar/license.txt | 20 + .../static/src/css/web_calendar.css | 26 - .../static/src/css/web_calendar.sass | 35 - .../static/src/css/web_fullcalendar.css | 30 + .../static/src/css/web_fullcalendar.sass | 36 + .../web_calendar/static/src/img/cal_left.png | Bin 183 -> 0 bytes .../web_calendar/static/src/img/cal_right.png | Bin 188 -> 0 bytes .../static/src/img/minical_left.png | Bin 190 -> 0 bytes .../static/src/img/minical_right.png | Bin 190 -> 0 bytes addons/web_calendar/static/src/js/calendar.js | 596 -- .../static/src/js/fullcalendar.js | 1078 ++++ .../static/src/xml/web_calendar.xml | 40 - .../static/src/xml/web_fullcalendar.xml | 33 + 108 files changed, 7427 insertions(+), 17720 deletions(-) create mode 100644 addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_dhx_terrace.css delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_glossy.css delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/but_repeat.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/buttons.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/calendar.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/clock_big.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/clock_small.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/collapse_expand_icon.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg_now.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/icon.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/images.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/loading.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/resize_dots.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/arrow_left.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/arrow_right.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/but_repeat.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/calendar.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/clock_big.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/clock_small.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/close_icon.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/collapse_expand_icon.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/controls.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/databg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/databg_now.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/resize_dots.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/resizing.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/blue_tab.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/blue_tab_wide.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/but_repeat.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/buttons.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/calendar.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/clock_big.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/clock_small.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/collapse_expand_icon.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/controlls5.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/databg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/databg_now.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/event-bg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/icon.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/left-separator.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/left-time-bg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/lightbox.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/loading.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/move.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/multi-days-bg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/second-top-days-bg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/top-days-bg.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/top-separator.gif delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/white_tab.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/white_tab_wide.png delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/license.txt delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/readme.txt delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.css delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler_dhx_terrace.css delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler_glossy.css delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_active_links.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_agenda_view.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_all_timed.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_collision.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_cookie.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_dhx_terrace.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_editors.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_expand.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_grid_view.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_html_templates.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_key_nav.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_limit.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_map_view.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_minical.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multiselect.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multisource.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_offline.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_outerdrag.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_pdf.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_readonly.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_recurring.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_serialize.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_timeline.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_tooltip.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_treetimeline.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_units.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_url.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_week_agenda.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_year_view.js delete mode 100644 addons/web_calendar/static/lib/dhtmlxScheduler/whatsnew.txt create mode 100644 addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css create mode 100644 addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js create mode 100644 addons/web_calendar/static/lib/fullcalendar/js/gcal.js create mode 100644 addons/web_calendar/static/lib/fullcalendar/license.txt delete mode 100644 addons/web_calendar/static/src/css/web_calendar.css delete mode 100644 addons/web_calendar/static/src/css/web_calendar.sass create mode 100644 addons/web_calendar/static/src/css/web_fullcalendar.css create mode 100644 addons/web_calendar/static/src/css/web_fullcalendar.sass delete mode 100644 addons/web_calendar/static/src/img/cal_left.png delete mode 100644 addons/web_calendar/static/src/img/cal_right.png delete mode 100644 addons/web_calendar/static/src/img/minical_left.png delete mode 100644 addons/web_calendar/static/src/img/minical_right.png delete mode 100644 addons/web_calendar/static/src/js/calendar.js create mode 100644 addons/web_calendar/static/src/js/fullcalendar.js delete mode 100644 addons/web_calendar/static/src/xml/web_calendar.xml create mode 100644 addons/web_calendar/static/src/xml/web_fullcalendar.xml diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index bb9fcaa0dbd..afd207b13d3 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -32,6 +32,7 @@ This module provides the core of the OpenERP Web Client. "static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js", "static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js", "static/lib/jquery.ui.notify/js/jquery.notify.js", + "static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js", "static/lib/jquery.deferred-queue/jquery.deferred-queue.js", "static/lib/jquery.scrollTo/jquery.scrollTo-min.js", "static/lib/jquery.tipsy/jquery.tipsy.js", diff --git a/addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js b/addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js new file mode 100644 index 00000000000..2766f4184d6 --- /dev/null +++ b/addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js @@ -0,0 +1,160 @@ +/*! + * jQuery UI Touch Punch 0.2.2 + * + * Copyright 2011, Dave Furfero + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Depends: + * jquery.ui.widget.js + * jquery.ui.mouse.js + */ +(function ($) { + + // Detect touch support + $.support.touch = 'ontouchend' in document; + + // Ignore browsers without touch support + if (!$.support.touch) { + return; + } + + var mouseProto = $.ui.mouse.prototype, + _mouseInit = mouseProto._mouseInit, + touchHandled; + + /** + * Simulate a mouse event based on a corresponding touch event + * @param {Object} event A touch event + * @param {String} simulatedType The corresponding mouse event + */ + function simulateMouseEvent (event, simulatedType) { + + // Ignore multi-touch events + if (event.originalEvent.touches.length > 1) { + return; + } + + event.preventDefault(); + + var touch = event.originalEvent.changedTouches[0], + simulatedEvent = document.createEvent('MouseEvents'); + + // Initialize the simulated mouse event using the touch event's coordinates + simulatedEvent.initMouseEvent( + simulatedType, // type + true, // bubbles + true, // cancelable + window, // view + 1, // detail + touch.screenX, // screenX + touch.screenY, // screenY + touch.clientX, // clientX + touch.clientY, // clientY + false, // ctrlKey + false, // altKey + false, // shiftKey + false, // metaKey + 0, // button + null // relatedTarget + ); + + // Dispatch the simulated event to the target element + event.target.dispatchEvent(simulatedEvent); + } + + /** + * Handle the jQuery UI widget's touchstart events + * @param {Object} event The widget element's touchstart event + */ + mouseProto._touchStart = function (event) { + + var self = this; + + // Ignore the event if another widget is already being handled + if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) { + return; + } + + // Set the flag to prevent other widgets from inheriting the touch event + touchHandled = true; + + // Track movement to determine if interaction was a click + self._touchMoved = false; + + // Simulate the mouseover event + simulateMouseEvent(event, 'mouseover'); + + // Simulate the mousemove event + simulateMouseEvent(event, 'mousemove'); + + // Simulate the mousedown event + simulateMouseEvent(event, 'mousedown'); + }; + + /** + * Handle the jQuery UI widget's touchmove events + * @param {Object} event The document's touchmove event + */ + mouseProto._touchMove = function (event) { + + // Ignore event if not handled + if (!touchHandled) { + return; + } + + // Interaction was not a click + this._touchMoved = true; + + // Simulate the mousemove event + simulateMouseEvent(event, 'mousemove'); + }; + + /** + * Handle the jQuery UI widget's touchend events + * @param {Object} event The document's touchend event + */ + mouseProto._touchEnd = function (event) { + + // Ignore event if not handled + if (!touchHandled) { + return; + } + + // Simulate the mouseup event + simulateMouseEvent(event, 'mouseup'); + + // Simulate the mouseout event + simulateMouseEvent(event, 'mouseout'); + + // If the touch interaction did not move, it should trigger a click + if (!this._touchMoved) { + + // Simulate the click event + simulateMouseEvent(event, 'click'); + } + + // Unset the flag to allow other widgets to inherit the touch event + touchHandled = false; + }; + + /** + * A duck punch of the $.ui.mouse _mouseInit method to support touch events. + * This method extends the widget with bound touch event handlers that + * translate touch events to mouse events and pass them to the widget's + * original mouse event handling methods. + */ + mouseProto._mouseInit = function () { + + var self = this; + + // Delegate the touch handlers to the widget's element + self.element + .bind('touchstart', $.proxy(self, '_touchStart')) + .bind('touchmove', $.proxy(self, '_touchMove')) + .bind('touchend', $.proxy(self, '_touchEnd')); + + // Call the original $.ui.mouse init method + _mouseInit.call(self); + }; + +})(jQuery); \ No newline at end of file diff --git a/addons/web_calendar/__openerp__.py b/addons/web_calendar/__openerp__.py index d4b348bd17f..183d56787cb 100644 --- a/addons/web_calendar/__openerp__.py +++ b/addons/web_calendar/__openerp__.py @@ -9,17 +9,15 @@ OpenERP Web Calendar view. 'version': '2.0', 'depends': ['web'], 'js': [ - 'static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.js', - 'static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_minical.js', - 'static/src/js/calendar.js' + 'static/lib/fullcalendar/js/fullcalendar.js', + 'static/lib/fullcalendar/js/gcal.js', + 'static/src/js/*.js' ], 'css': [ - #'static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css', - #'static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_dhx_terrace.css', - 'static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_glossy.css', - 'static/src/css/web_calendar.css' + 'static/lib/fullcalendar/css/*.css', + 'static/src/css/*.css' ], - 'qweb' : [ + 'qweb': [ 'static/src/xml/*.xml', ], 'auto_install': True diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css deleted file mode 100644 index 2e4cae2bdbf..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css +++ /dev/null @@ -1,5 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -.dhtmlx_message_area{position:fixed;right:5px;width:250px;z-index:1000;}.dhtmlx-info{min-width:120px;padding:4px 4px 4px 20px;font-family:Tahoma;z-index:10000;margin:5px;margin-bottom:10px;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease;}.dhtmlx-info.hidden{height:0;padding:0;border-width:0;margin:0;overflow:hidden;}.dhtmlx_modal_box{overflow:hidden;display:inline-block;min-width:300px;width:300px;text-align:center;position:fixed;background-color:#fff;background:-webkit-linear-gradient(top,#fff 1%,#d0d0d0 99%);background:-moz-linear-gradient(top,#fff 1%,#d0d0d0 99%);box-shadow:0 0 14px #888;font-family:Tahoma;z-index:20000;border-radius:6px;border:1px solid #fff;}.dhtmlx_popup_title{border-top-left-radius:5px;border-top-right-radius:5px;border-width:0;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAoCAMAAAAIaGBFAAAAhFBMVEVwcHBubm5sbGxqampoaGhmZmZlZWVjY2NhYWFfX19dXV1bW1taWlpYWFhWVlZUVFRSUlJRUVFPT09NTU1LS0tJSUlHR0dGRkZERERCQkJAQEA+Pj49PT09PT0+Pj5AQEBBQUFDQ0NERERGRkZHR0dJSUlKSkpMTExMTEw5OTk5OTk5OTkny8YEAAAAQklEQVQImQXBCRJCAAAAwKVSQqdyjSPXNP7/QLsIhA6OTiJnF7GrRCpzc/fw9PKW+/gqlCq1RqvTG/yMJrPF6m/bAVEhAxxnHG0oAAAAAElFTkSuQmCC);background-image:-webkit-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%);background-image:-moz-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%);}.dhtmlx-info,.dhtmlx_popup_button,.dhtmlx_button{user-select:none;-webkit-user-select:none;-moz-user-select:-moz-none;cursor:pointer;}.dhtmlx_popup_text{overflow:hidden;}.dhtmlx_popup_controls{border-radius:6px;padding:5px;}.dhtmlx_popup_button,.dhtmlx_button{height:30px;line-height:30px;display:inline-block;margin:0 5px;border-radius:6px;color:#FFF;}.dhtmlx_popup_button{min-width:120px;}div.dhx_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity = 20);opacity:.2;position:fixed;z-index:19999;left:0;top:0;width:100%;height:100%;border:none;zoom:1;}.dhtmlx-info img,.dhtmlx_modal_box img{float:left;margin-right:20px;}.dhtmlx-alert-error .dhtmlx_popup_title,.dhtmlx-confirm-error .dhtmlx_popup_title{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAIAAAArRUU2AAAATklEQVR4nIWLuw2AMBBDjVuQiBT2oWbRDATrnB0KQOJoqPzRe3BrHI6dcBASYREKovtK6/6DsDOX+stN+3H1YX9ciRgnYq5EWYhS2dftBIuLT4JyIrPCAAAAAElFTkSuQmCC);}.dhtmlx-alert-error,.dhtmlx-confirm-error{border:1px solid #f00;}.dhtmlx_button,.dhtmlx_popup_button{box-shadow:0 0 4px #888;border:1px solid #838383;}.dhtmlx_button input,.dhtmlx_popup_button div{border:1px solid #FFF;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAYFBMVEVwcHBtbW1ra2toaGhmZmZjY2NhYWFeXl5cXFxaWlpXV1dVVVVSUlJQUFBNTU1LS0tJSUlGRkZERERBQUE/Pz88PDw9PT0+Pj5AQEBCQkJDQ0NFRUVHR0dISEhKSkpMTEzqthaMAAAAMklEQVQImQXBhQ2AMAAAsOIMlwWH/8+kRSKVyRVKlVrQaHV6g9FktlhFm93hdLk9Xt8PIfgBvdUqyskAAAAASUVORK5CYII=);background-image:-webkit-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 99%);background-image:-moz-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 99%);border-radius:6px;font-size:15px;font-weight:normal;-moz-box-sizing:content-box;box-sizing:content-box;color:#fff;padding:0;margin:0;vertical-align:top;height:28px;line-height:28px;}.dhtmlx_button input:focus,.dhtmlx_button input:active,.dhtmlx_popup_button div:active,.dhtmlx_popup_button div:focus{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAXVBMVEVwcHBubm5tbW1sbGxra2tpaWloaGhnZ2dmZmZlZWVjY2NiYmJhYWFgYGBfX19dXV1cXFxbW1taWlpZWVlXV1dWVlZVVVVUVFRTU1NRUVFQUFBPT09OTk5NTU1LS0tT9SY0AAAAMUlEQVQImQXBhQGAMAAAIGxnx2z9/00BiVQmVyhVakGj1ekNRpPZYhVtdofT5fZ4fT8hpwG05JjexgAAAABJRU5ErkJggg==);background-image:-webkit-linear-gradient(top,#707070 1%,#4c4c4c 99%);background-image:-moz-linear-gradient(top,#707070 1%,#4c4c4c 99%);}.dhtmlx_popup_title{color:#fff;text-shadow:1px 1px #000;height:40px;line-height:40px;font-size:20px;}.dhtmlx_popup_text{margin:15px 15px 5px 15px;font-size:14px;color:#000;min-height:30px;border-radius:6px;}.dhtmlx-info,.dhtmlx-error{font-size:14px;color:#000;box-shadow:0 0 10px #888;padding:0;background-color:#FFF;border-radius:3px;border:1px solid #fff;}.dhtmlx-info div{padding:5px 10px 5px 10px;background-color:#fff;border-radius:3px;border:1px solid #B8B8B8;}.dhtmlx-error{background-color:#d81b1b;border:1px solid #ff3c3c;box-shadow:0 0 10px #000;}.dhtmlx-error div{background-color:#d81b1b;border:1px solid #940000;color:#FFF;}.dhx_cal_container{background-color:#C2D5FC;font-family:Tahoma;font-size:8pt;position:relative;overflow:hidden;}.dhx_cal_container div{-moz-user-select:none;-moz-user-select:-moz-none;}.dhx_cal_navline{height:20px;position:absolute;z-index:3;width:750px;color:#2F3A48;}.dhx_cal_navline div{position:absolute;top:2px;white-space:nowrap;}.dhx_cal_navline .dhx_cal_date{font-weight:600;left:210px;padding-top:1px;}.dhx_cal_button .dhx_left_bg{width:1px;overflow:hidden;height:17px;z-index:20;top:0;}.dhx_cal_prev_button{background-image:url(imgs/buttons.png);background-position:0 0;width:29px;height:17px;left:50px;cursor:pointer;}.dhx_cal_next_button{background-image:url(imgs/buttons.png);background-position:-30px 0;width:29px;height:17px;left:80px;cursor:pointer;}.dhx_cal_today_button{background-image:url(imgs/buttons.png);background-position:-60px 0;width:75px;height:17px;left:112px;cursor:pointer;text-align:center;text-decoration:underline;}.dhx_cal_tab{width:59px;height:19px;text-align:center;text-decoration:underline;padding-top:2px;cursor:pointer;background-color:#D8E1EA;-webkit-border-top-left-radius:4px;-webkit-border-top-right-radius:4px;-moz-border-radius-topleft:4px;-moz-border-radius-topright:4px;border-top-left-radius:4px;border-top-right-radius:4px;}.dhx_cal_tab.active{text-decoration:none;cursor:default;font-weight:bold;border:1px dotted #586A7E;border-bottom:0;background-color:#C2D5FC;}.dhx_cal_header{position:absolute;left:10px;top:23px;width:750px;border-top:1px dotted #8894A3;border-right:1px dotted #8894A3;z-index:2;overflow:hidden;color:#2F3A48;}.dhx_cal_data{border-top:1px dotted #8894A3;position:absolute;top:44px;width:600px;overflow-y:auto;overflow-x:hidden;}.dhx_scale_bar{position:absolute;text-align:center;background-color:#C2D5FC;padding-top:3px;border-left:1px dotted #586A7E;}.dhx_scale_holder{position:absolute;border-right:1px dotted #586A7E;background-image:url(imgs/databg.png);}.dhx_scale_holder_now{position:absolute;border-right:1px dotted #586A7E;background-image:url(imgs/databg_now.png);}.dhx_scale_hour{height:41px;width:50px;border-bottom:1px dotted #8894A3;background-color:#C2D5FC;text-align:center;line-height:40px;color:#586A7E;overflow:hidden;}.dhx_month_head{background-color:#EBEFF4;color:#2F3A48;border-right:1px dotted #586A7E;height:18px;padding-right:5px;padding-top:3px;text-align:right;}.dhx_month_body{border-right:1px dotted #586A7E;border-bottom:1px dotted #586A7E;background-color:#FFF;}.dhx_now .dhx_month_body{background-color:#E2EDFF;}.dhx_after .dhx_month_body,.dhx_before .dhx_month_body{background-color:#ECECEC;}.dhx_after .dhx_month_head,.dhx_before .dhx_month_head{background-color:#E2E3E6;color:#94A6BB;}.dhx_now .dhx_month_head{background-color:#D1DEF4;font-weight:bold;}.dhx_cal_drag{position:absolute;z-index:9999;background-color:#FFE763;border:1px solid #B7A543;opacity:.5;filter:alpha(opacity=50);}.dhx_loading{position:absolute;width:128px;height:15px;background-image:url(imgs/loading.gif);z-index:9999;}.dhx_multi_day_icon,.dhx_multi_day{background-color:#E1E6FF;background-repeat:no-repeat;border-right:1px dotted #8894A3;}.dhx_multi_day{position:absolute;border-top:1px dotted #8894A3;}.dhx_multi_day_icon,.dhx_multi_day_icon_small{background-position:center center;background-color:#E1E6FF;background-repeat:no-repeat;border-bottom:1px dotted #8894A3;border-right:1px dotted #8894A3;}.dhx_multi_day_icon{background-image:url(imgs/clock_big.gif);}.dhx_multi_day_icon_small{background-image:url(imgs/clock_small.gif);}.dhtmlxLayoutPolyContainer_dhx_skyblue .dhx_cal_container{background-color:#d0e5ff;}.dhx_cal_event .dhx_header,.dhx_cal_event .dhx_title,.dhx_cal_event .dhx_body,.dhx_cal_event .dhx_footer{background-color:#FFE763;border:1px solid #B7A543;color:#887A2E;overflow:hidden;width:100%;font-family:Tahoma;font-size:8pt;}.dhx_move_denied .dhx_cal_event .dhx_header,.dhx_move_denied .dhx_cal_event .dhx_title{cursor:default;}.dhx_cal_event .dhx_header{height:1px;margin-left:1px;border-width:1px 1px 0 1px;cursor:pointer;}.dhx_cal_event .dhx_title{height:12px;border-width:0 1px 1px 1px;border-bottom-style:dotted;font-size:7pt;font-weight:bold;text-align:center;background-position:right;background-repeat:no-repeat;cursor:pointer;}.dhx_cal_event .dhx_body,.dhx_cal_event.dhx_cal_select_menu .dhx_body{border-width:0 1px 1px 1px;padding:5px;}.dhx_resize_denied{cursor:default!important;}.dhx_cal_event .dhx_event_resize{cursor:s-resize;}.dhx_cal_event .dhx_footer,.dhx_cal_event .dhx_select_menu_footer{height:1px;margin-left:2px;border-width:0 1px 1px 1px;}.dhx_cal_event_line{background-color:#FFE763;border:1px solid #B7A543;border-radius:3px;font-family:Tahoma;font-size:8pt;height:13px;padding-left:10px;color:#887A2E;cursor:pointer;overflow:hidden;}.dhx_cal_event_clear{font-family:Tahoma;font-size:8pt;height:13px;padding-left:2px;color:#887A2E;white-space:nowrap;overflow:hidden;cursor:pointer;}.dhx_in_move{background-color:#FFFF80;}div.dhx_cal_editor{background-color:#FFE763;border:1px solid #B7A543;border-top-style:dotted;z-index:999;position:absolute;overflow:hidden;}textarea.dhx_cal_editor{width:100%;height:100%;border:0 solid black;margin:none;padding:none;overflow:auto;}div.dhx_menu_head{background-image:url(imgs/controls.gif);background-position:0 -43px;width:10px;height:10px;margin-left:5px;margin-top:1px;border:none;cursor:default;}div.dhx_menu_icon{background-image:url(imgs/controls.gif);width:20px;height:20px;margin-left:-5px;margin-top:0;border:none;cursor:pointer;}div.icon_details{background-position:0 0;}div.icon_edit{background-position:-22px 0;}div.icon_save{background-position:-84px -1px;}div.icon_cancel{background-position:-62px 0;}div.icon_delete{background-position:-42px 0;}.dhx_unselectable,.dhx_unselectable div{-webkit-user-select:none;-moz-user-select:none;-moz-user-select:-moz-none;}.dhx_cal_light{background-color:#FFE763;border-radius:5px;font-family:Tahoma;font-size:8pt;border:1px solid #B7A64B;color:#887A2E;position:absolute;z-index:10001;width:580px;height:300px;box-shadow:5px 5px 5px #888;}.dhx_cal_light_wide{width:650px;}.dhx_mark{position:relative;top:3px;background-image:url('./imgs/controls.gif');background-position:0 -43px;padding-left:10px;}.dhx_ie6 .dhx_mark{background-position:6px -41px;}.dhx_cal_light select{font-family:Tahoma;font-size:8pt;color:#887A2E;padding:2px;margin:0;}.dhx_cal_ltitle{padding:2px 0 2px 5px;overflow:hidden;white-space:nowrap;}.dhx_cal_ltitle span{white-space:nowrap;}.dhx_cal_lsection{background-color:#DBCF8C;color:#FFF4B5;font-weight:bold;padding:5px 0 3px 10px;}.dhx_section_time{background-color:#DBCF8C;white-space:nowrap;}.dhx_cal_lsection .dhx_fullday{float:right;margin-right:5px;color:#887A2E;font-size:12px;font-weight:normal;line-height:20px;vertical-align:top;cursor:pointer;}.dhx_cal_lsection{font-size:18px;font-family:Arial;}.dhx_cal_ltext{padding:2px 0 2px 10px;overflow:hidden;}.dhx_cal_ltext textarea{background-color:#FFF4B5;overflow:auto;border:none;color:#887A2E;height:100%;width:100%;outline:none!important;resize:none;}.dhx_time{font-weight:bold;}.dhx_cal_light .dhx_title{padding-left:10px;}.dhx_cal_larea{border:1px solid #DCC43E;background-color:#FFF4B5;overflow:hidden;margin-left:3px;width:572px;height:1px;}.dhx_btn_set{padding:5px 10px 0 10px;float:left;}.dhx_btn_set div{float:left;height:21px;line-height:21px;vertical-align:middle;cursor:pointer;}.dhx_save_btn{background-image:url('./imgs/controls.gif');background-position:-84px 0;width:21px;}.dhx_cancel_btn{background-image:url('./imgs/controls.gif');background-position:-63px 0;width:20px;}.dhx_delete_btn{background-image:url('./imgs/controls.gif');background-position:-42px 0;width:20px;}.dhx_cal_cover{width:100%;height:100%;position:absolute;z-index:10000;top:0;left:0;background-color:black;opacity:.1;filter:alpha(opacity=10);}.dhx_custom_button{padding:0 3px 0 3px;color:#887A2E;font-family:Tahoma;font-size:8pt;background-color:#FFE763;font-weight:normal;margin-right:5px;margin-top:0;cursor:pointer;}.dhx_custom_button div{cursor:pointer;float:left;height:21px;line-height:21px;vertical-align:middle;}.dhx_cal_light_wide .dhx_cal_larea{border-top-width:0;}.dhx_cal_light_wide .dhx_cal_lsection{border:0;float:left;text-align:right;width:100px;height:20px;font-size:16px;padding:5px 0 0 10px;}.dhx_cal_light_wide .dhx_wrap_section{border-top:1px solid #DBCF8C;position:relative;background-color:#DBCF8C;overflow:hidden;}.dhx_cal_light_wide .dhx_section_time{padding-top:2px!important;height:20px!important;}.dhx_section_time{text-align:center;}.dhx_cal_light_wide .dhx_cal_larea{width:730px;}.dhx_cal_light_wide{width:738px;}.dhx_cal_light_wide .dhx_section_time{background:transparent;}.dhx_cal_light_wide .dhx_cal_checkbox label{padding-left:0;}.dhx_cal_wide_checkbox input{margin-top:8px;margin-left:14px;}.dhx_cal_light input{font-family:Tahoma;font-size:8pt;color:#887A2E;}.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday{float:none;margin-right:0;color:#FFF4B5;font-weight:bold;font-size:16px;font-family:Arial;cursor:pointer;}.dhx_custom_button{float:right;height:21px;width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;}.dhx_cal_light_wide .dhx_custom_button{position:absolute;top:0;right:0;margin-top:2px;}.dhx_cal_light_wide .dhx_repeat_right{margin-right:55px;}.dhx_minical_popup{position:absolute;z-index:10100;width:251px;height:175px;}.dhx_scale_bar_header{position:absolute;border-bottom:1px dotted #8894A3;width:100%;}.dhx_expand_icon{position:absolute;top:0;right:0;background-image:url(./imgs/collapse_expand_icon.gif);width:18px;height:18px;cursor:pointer;background-position:0 18px;z-index:16;}.dhx_scheduler_agenda .dhx_cal_data{background-image:url(./imgs/databg.png);}.dhx_agenda_area{width:100%;overflow-y:auto;background-image:url(./imgs/databg.png);}.dhx_agenda_line{height:21px;clear:both;overflow:hidden;}.dhx_agenda_line div{float:left;width:188px;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_agenda_area .dhx_agenda_line div{border-right:0 dotted #8894A3;}.dhx_v_border{position:absolute;left:187px;top:0;border-right:1px dotted #8894A3;width:1px;height:100%;}.dhx_agenda_line .dhx_event_icon{width:20px;border-width:0;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_agenda_line span{padding-left:5px;line-height:21px;}.dhx_year_body{border-left:1px dotted #586A7E;}.dhx_year_week{position:relative;}.dhx_scale_bar_last{border-right:1px dotted #586A7E;}.dhx_year_month{height:18px;padding-top:3px;border:1px dotted #586A7E;text-align:center;vertical-align:middle;}.dhx_year_body .dhx_before .dhx_month_head,.dhx_year_body .dhx_after .dhx_month_head,.dhx_year_body .dhx_before .dhx_month_head a,.dhx_year_body .dhx_after .dhx_month_head a{color:#E2E3E6!important;}.dhx_year_body .dhx_month_body{height:0;overflow:hidden;}.dhx_month_head.dhx_year_event{background-color:#FFE763;}.dhx_year_body .dhx_before .dhx_month_head,.dhx_year_body .dhx_after .dhx_month_head{cursor:default;}.dhx_tooltip{border:1px solid #BBB;background-image:url(./imgs/databg.png);position:absolute;z-index:9998;width:300px;height:auto;font-family:Tahoma;font-size:8pt;overflow:hidden;}.dhx_tooltip_line{line-height:20px;height:20px;overflow:hidden;}.dhx_tooltip_line .dhx_event_icon{width:20px;height:20px;padding-right:10px;float:left;border-width:0;position:relative;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_tooltip_date{float:left;width:auto;padding-left:5px;text-align:center;}.dhx_text_disabled{color:#887A2E;font-family:Tahoma;font-size:8pt;}.dhx_mini_calendar{-moz-box-shadow:5px 5px 5px #888;-khtml-box-shadow:5px 5px 5px #888;}.dhx_mini_calendar .dhx_month_head{cursor:pointer;}.dhx_mini_calendar .dhx_calendar_click{background-color:#C2D5FC;}.dhx_cal_navline div.dhx_minical_icon{width:18px;height:18px;left:190px;top:1px;cursor:pointer;background-image:url(./imgs/calendar.gif);}.dhx_matrix_scell{height:100%;}.dhx_matrix_cell,.dhx_matrix_scell{overflow:hidden;text-align:center;vertical-align:middle;border-bottom:1px dotted #8894A3;border-right:1px dotted #8894A3;}.dhx_matrix_cell{background-color:white;}.dhx_matrix_line{overflow:hidden;}.dhx_matrix_cell div,.dhx_matrix_scell div{overflow:hidden;text-align:center;height:auto;}.dhx_cal_lsection .dhx_readonly{font-size:9pt;font-size:8pt;padding:2px;color:#887A2E;}.dhx_cal_event_line .dhx_event_resize{cursor:w-resize;background:url(./imgs/resize_dots.png) repeat-y;position:absolute;top:0;width:4px;}.dhx_event_resize_start{left:0;}.dhx_event_resize_end{right:0;}.dhx_matrix_scell.folder,.dhx_data_table.folder .dhx_matrix_cell{background-color:#969394;cursor:pointer;}.dhx_matrix_scell .dhx_scell_level0{padding-left:5px;}.dhx_matrix_scell .dhx_scell_level1{padding-left:20px;}.dhx_matrix_scell .dhx_scell_level2{padding-left:35px;}.dhx_matrix_scell .dhx_scell_level3{padding-left:50px;}.dhx_matrix_scell .dhx_scell_level4{padding-left:65px;}.dhx_matrix_scell.folder{font-weight:bold;text-align:left;}.dhx_matrix_scell.folder .dhx_scell_expand{float:left;width:10px;padding-right:3px;}.dhx_matrix_scell.folder .dhx_scell_name{float:left;width:auto;}.dhx_matrix_scell.item .dhx_scell_name{padding-left:15px;text-align:left;}.dhx_data_table.folder .dhx_matrix_cell{border-right:0;}.dhx_section_timeline{overflow:hidden;padding:4px 0 2px 10px;}.dhx_section_timeline select{width:552px;}.dhx_map_area{width:100%;height:100%;overflow-y:auto;overflow-x:hidden;background-image:url(./imgs/databg.png);}.dhx_map_line .dhx_event_icon{width:20px;border-width:0;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_map_line{height:21px;clear:both;overflow:hidden;}.dhx_map{position:absolute;}.dhx_map_line div{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .headline_description{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .dhx_map_description{float:left;border-right:0 dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .headline_date,.dhx_map_line .headline_description{border-left:0;}.dhx_map_line .line_description{float:left;border-right:1px dotted #8894A3;text-align:left;padding-left:5px;line-height:21px;overflow:hidden;}.dhx_map_line.highlight{background-color:#C4C5CC;}.dhx_map_area .dhx_map_line div{border-right:0 dotted #8894A3;}.dhtmlXTooltip.tooltip{-moz-box-shadow:3px 3px 3px #888;-webkit-box-shadow:3px 3px 3px #888;-o-box-shadow:3px 3px 3px #888;box-shadow:3px 3px 3px #888;filter:progid:DXImageTransform.Microsoft.Shadow(color='#888888',Direction=135,Strength=5);background-color:white;border-left:1px dotted #887A2E;border-top:1px dotted #887A2E;color:#887A2E;cursor:default;padding:10px;position:absolute;z-index:500;}.dhx_cal_checkbox label{padding-left:5px;}.dhx_cal_light .radio{padding:2px 0 2px 10px;}.dhx_cal_light .radio input,.dhx_cal_light .radio label{line-height:15px;}.dhx_cal_light .radio input{vertical-align:middle;margin:0;padding:0;}.dhx_cal_light .radio label{vertical-align:middle;padding-right:10px;}.dhx_cal_light .combo{padding:4px;}.dhx_cal_light_wide .dhx_combo_box{width:608px!important;left:10px;}.dhx_wa_column{float:left;}.dhx_wa_column_last .dhx_wa_day_cont{border-left:1px dotted #8894A3;}.dhx_wa_scale_bar{font-family:Tahoma;padding-left:10px;font-size:11px;border-top:1px dotted #8894A3;border-bottom:1px dotted #8894A3;}.dhx_wa_day_data{background-color:#FCFEFC;overflow-y:auto;}.dhx_wa_ev_body{border-bottom:1px dotted #789;font-size:12px;padding:5px 0 5px 7px;}.dhx_wa_dnd{font-family:Tahoma;position:absolute;padding-right:7px;color:#887AE2!important;background-color:#FFE763!important;border:1px solid #B7A543;}.dhx_cal_event_selected{background-color:#9cc1db;color:white;}.dhx_second_scale_bar{border-bottom:1px dotted #586A7E;padding-top:2px;}.dhx_cal_header div div{border-left:1px dotted #8894A3;}.dhx_grid_area{width:100%;height:100%;overflow-y:auto;background-color:#FCFEFC;}.dhx_grid_area table{border-collapse:collapse;border-spacing:0;width:100%;table-layout:fixed;}.dhx_grid_area td{table-layout:fixed;text-align:center;}.dhx_grid_line{height:21px;clear:both;overflow:hidden;}.dhx_grid_line div{float:left;cursor:default;padding-top:0;padding-bottom:0;text-align:center;line-height:21px;overflow:hidden;}.dhx_grid_area td,.dhx_grid_line div{padding-left:8px;padding-right:8px;}.dhx_grid_area tr.dhx_grid_event{height:21px;overflow:hidden;margin:0 0 1px 0;}.dhx_grid_area tr.dhx_grid_event td{border-bottom:1px solid #ECEEF4;}.dhx_grid_area tr.dhx_grid_event:nth-child(2n+1) td,.dhx_grid_area tr.dhx_grid_event:nth-child(2n) td{border-bottom-width:0;border-bottom-style:none;}.dhx_grid_area tr.dhx_grid_event:nth-child(2n){background-color:#ECEEF4;;}.dhx_grid_area .dhx_grid_dummy{table-layout:auto;margin:0!important;padding:0!important;}.dhx_grid_v_border{position:absolute;border-right:1px solid #A4BED4;width:1px;height:100%;}.dhx_grid_event_selected{background-color:#9cc1db!important;color:white!important;}.dhx_grid_sort_desc .dhx_grid_view_sort{background-position:0 -55px;}.dhx_grid_sort_asc .dhx_grid_view_sort{background-position:0 -66px;}.dhx_grid_view_sort{width:10px;height:10px;position:absolute;border:none!important;top:5px;background-repeat:no-repeat;background-image:url(./imgs/images.png);}.dhx_marked_timespan{position:absolute;width:100%;}.dhx_time_block{position:absolute;width:100%;background:silver;opacity:.4;filter:alpha(opacity=40);z-index:1;}.dhx_time_block_reset{opacity:1;filter:alpha(opacity=100);}.dhx_scheduler_month .dhx_marked_timespan{display:none;}.dhx_mini_calendar .dhx_marked_timespan{display:none;}.dhx_now_time{width:100%;border-bottom:2px dotted red;z-index:1;}.dhx_scheduler_month .dhx_now_time{border-bottom:0;border-left:2px dotted red;}.dhx_matrix_now_time{border-left:2px dotted red;z-index:1;}div.dhx_form_repeat input.radio{margin:-4px 0 0 -4px!ie;}div.dhx_form_repeat input.checkbox{margin:0 0 0 -4px!ie;}.dhx_form_repeat,.dhx_form_repeat input{padding:0;margin:0;padding-left:5px;font-family:Tahoma,Verdana;font-size:11px;line-height:24px;}.dhx_form_repeat{overflow:hidden;height:0;background-color:#FFF4B5;}.dhx_cal_light_wide .dhx_form_repeat{background-color:transparent;}.dhx_repeat_center,.dhx_repeat_left{height:115px;padding:10px 0 10px 10px;float:left;}.dhx_repeat_left{width:95px;}.dhx_repeat_center{width:335px;margin-top:12px;}.dhx_repeat_divider{float:left;height:115px;border-left:1px dotted #DCC43E;width:1px;}.dhx_repeat_right{float:right;height:115px;width:160px;padding:10px 3px 10px 10px;margin-top:7px;}input.dhx_repeat_text{height:16px;width:27px;margin:0 4px 0 4px;line-height:18px;padding:0 0 0 2px;}.dhx_form_repeat select{height:20px;width:87px;padding:0 0 0 2px;margin:0 4px 0 4px;}input.dhx_repeat_date{height:18px;width:80px;padding:0 0 0 2px;margin:0 4px 0 4px;background-repeat:no-repeat;background-position:64px 0;border:1px #7f9db9 solid;line-height:18px;}input.dhx_repeat_radio{margin-right:4px;}input.dhx_repeat_checkbox{margin:4px 4px 0 0;}.dhx_repeat_days td{padding-right:5px;}.dhx_repeat_days label{font-size:10px;}.dhx_custom_button{width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;}.dhx_custom_button_recurring{background-image:url(./imgs/but_repeat.gif);background-position:-5px 20px;width:20px;margin-right:10px;}.dhx_cal_light_rec{width:640px;}.dhx_cal_light_rec .dhx_cal_larea{width:632px;}.dhx_cal_light_rec.dhx_cal_light_wide{width:816px;}.dhx_cal_light_rec.dhx_cal_light_wide .dhx_cal_larea{width:808px;} \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_dhx_terrace.css b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_dhx_terrace.css deleted file mode 100644 index 48230ffe08f..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_dhx_terrace.css +++ /dev/null @@ -1,5 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -.dhtmlx_message_area{position:fixed;right:5px;width:250px;z-index:1000;}.dhtmlx-info{min-width:120px;padding:4px 4px 4px 20px;font-family:Tahoma;z-index:10000;margin:5px;margin-bottom:10px;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease;}.dhtmlx-info.hidden{height:0;padding:0;border-width:0;margin:0;overflow:hidden;}.dhtmlx_modal_box{overflow:hidden;display:inline-block;min-width:300px;width:300px;text-align:center;position:fixed;background-color:#fff;background:-webkit-linear-gradient(top,#fff 1%,#d0d0d0 99%);background:-moz-linear-gradient(top,#fff 1%,#d0d0d0 99%);box-shadow:0 0 14px #888;font-family:Tahoma;z-index:20000;border-radius:6px;border:1px solid #fff;}.dhtmlx_popup_title{border-top-left-radius:5px;border-top-right-radius:5px;border-width:0;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAoCAMAAAAIaGBFAAAAhFBMVEVwcHBubm5sbGxqampoaGhmZmZlZWVjY2NhYWFfX19dXV1bW1taWlpYWFhWVlZUVFRSUlJRUVFPT09NTU1LS0tJSUlHR0dGRkZERERCQkJAQEA+Pj49PT09PT0+Pj5AQEBBQUFDQ0NERERGRkZHR0dJSUlKSkpMTExMTEw5OTk5OTk5OTkny8YEAAAAQklEQVQImQXBCRJCAAAAwKVSQqdyjSPXNP7/QLsIhA6OTiJnF7GrRCpzc/fw9PKW+/gqlCq1RqvTG/yMJrPF6m/bAVEhAxxnHG0oAAAAAElFTkSuQmCC);background-image:-webkit-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%);background-image:-moz-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%);}.dhtmlx-info,.dhtmlx_popup_button,.dhtmlx_button{user-select:none;-webkit-user-select:none;-moz-user-select:-moz-none;cursor:pointer;}.dhtmlx_popup_text{overflow:hidden;}.dhtmlx_popup_controls{border-radius:6px;padding:5px;}.dhtmlx_popup_button,.dhtmlx_button{height:30px;line-height:30px;display:inline-block;margin:0 5px;border-radius:6px;color:#FFF;}.dhtmlx_popup_button{min-width:120px;}div.dhx_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity = 20);opacity:.2;position:fixed;z-index:19999;left:0;top:0;width:100%;height:100%;border:none;zoom:1;}.dhtmlx-info img,.dhtmlx_modal_box img{float:left;margin-right:20px;}.dhtmlx-alert-error .dhtmlx_popup_title,.dhtmlx-confirm-error .dhtmlx_popup_title{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAIAAAArRUU2AAAATklEQVR4nIWLuw2AMBBDjVuQiBT2oWbRDATrnB0KQOJoqPzRe3BrHI6dcBASYREKovtK6/6DsDOX+stN+3H1YX9ciRgnYq5EWYhS2dftBIuLT4JyIrPCAAAAAElFTkSuQmCC);}.dhtmlx-alert-error,.dhtmlx-confirm-error{border:1px solid #f00;}.dhtmlx_button,.dhtmlx_popup_button{box-shadow:0 0 4px #888;border:1px solid #838383;}.dhtmlx_button input,.dhtmlx_popup_button div{border:1px solid #FFF;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAYFBMVEVwcHBtbW1ra2toaGhmZmZjY2NhYWFeXl5cXFxaWlpXV1dVVVVSUlJQUFBNTU1LS0tJSUlGRkZERERBQUE/Pz88PDw9PT0+Pj5AQEBCQkJDQ0NFRUVHR0dISEhKSkpMTEzqthaMAAAAMklEQVQImQXBhQ2AMAAAsOIMlwWH/8+kRSKVyRVKlVrQaHV6g9FktlhFm93hdLk9Xt8PIfgBvdUqyskAAAAASUVORK5CYII=);background-image:-webkit-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 99%);background-image:-moz-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 99%);border-radius:6px;font-size:15px;font-weight:normal;-moz-box-sizing:content-box;box-sizing:content-box;color:#fff;padding:0;margin:0;vertical-align:top;height:28px;line-height:28px;}.dhtmlx_button input:focus,.dhtmlx_button input:active,.dhtmlx_popup_button div:active,.dhtmlx_popup_button div:focus{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAXVBMVEVwcHBubm5tbW1sbGxra2tpaWloaGhnZ2dmZmZlZWVjY2NiYmJhYWFgYGBfX19dXV1cXFxbW1taWlpZWVlXV1dWVlZVVVVUVFRTU1NRUVFQUFBPT09OTk5NTU1LS0tT9SY0AAAAMUlEQVQImQXBhQGAMAAAIGxnx2z9/00BiVQmVyhVakGj1ekNRpPZYhVtdofT5fZ4fT8hpwG05JjexgAAAABJRU5ErkJggg==);background-image:-webkit-linear-gradient(top,#707070 1%,#4c4c4c 99%);background-image:-moz-linear-gradient(top,#707070 1%,#4c4c4c 99%);}.dhtmlx_popup_title{color:#fff;text-shadow:1px 1px #000;height:40px;line-height:40px;font-size:20px;}.dhtmlx_popup_text{margin:15px 15px 5px 15px;font-size:14px;color:#000;min-height:30px;border-radius:6px;}.dhtmlx-info,.dhtmlx-error{font-size:14px;color:#000;box-shadow:0 0 10px #888;padding:0;background-color:#FFF;border-radius:3px;border:1px solid #fff;}.dhtmlx-info div{padding:5px 10px 5px 10px;background-color:#fff;border-radius:3px;border:1px solid #B8B8B8;}.dhtmlx-error{background-color:#d81b1b;border:1px solid #ff3c3c;box-shadow:0 0 10px #000;}.dhtmlx-error div{background-color:#d81b1b;border:1px solid #940000;color:#FFF;}.dhx_cal_container{background-color:#C2D5FC;font-family:Tahoma;font-size:8pt;position:relative;overflow:hidden;}.dhx_cal_container div{-moz-user-select:none;-moz-user-select:-moz-none;}.dhx_cal_navline{height:20px;position:absolute;z-index:3;width:750px;color:#2F3A48;}.dhx_cal_navline div{position:absolute;top:2px;white-space:nowrap;}.dhx_cal_navline .dhx_cal_date{font-weight:600;left:210px;padding-top:1px;}.dhx_cal_button .dhx_left_bg{width:1px;overflow:hidden;height:17px;z-index:20;top:0;}.dhx_cal_prev_button{background-image:url(imgs/buttons.png);background-position:0 0;width:29px;height:17px;left:50px;cursor:pointer;}.dhx_cal_next_button{background-image:url(imgs/buttons.png);background-position:-30px 0;width:29px;height:17px;left:80px;cursor:pointer;}.dhx_cal_today_button{background-image:url(imgs/buttons.png);background-position:-60px 0;width:75px;height:17px;left:112px;cursor:pointer;text-align:center;text-decoration:underline;}.dhx_cal_tab{width:59px;height:19px;text-align:center;text-decoration:underline;padding-top:2px;cursor:pointer;background-color:#D8E1EA;-webkit-border-top-left-radius:4px;-webkit-border-top-right-radius:4px;-moz-border-radius-topleft:4px;-moz-border-radius-topright:4px;border-top-left-radius:4px;border-top-right-radius:4px;}.dhx_cal_tab.active{text-decoration:none;cursor:default;font-weight:bold;border:1px dotted #586A7E;border-bottom:0;background-color:#C2D5FC;}.dhx_cal_header{position:absolute;left:10px;top:23px;width:750px;border-top:1px dotted #8894A3;border-right:1px dotted #8894A3;z-index:2;overflow:hidden;color:#2F3A48;}.dhx_cal_data{border-top:1px dotted #8894A3;position:absolute;top:44px;width:600px;overflow-y:auto;overflow-x:hidden;}.dhx_scale_bar{position:absolute;text-align:center;background-color:#C2D5FC;padding-top:3px;border-left:1px dotted #586A7E;}.dhx_scale_holder{position:absolute;border-right:1px dotted #586A7E;background-image:url(imgs/databg.png);}.dhx_scale_holder_now{position:absolute;border-right:1px dotted #586A7E;background-image:url(imgs/databg_now.png);}.dhx_scale_hour{height:41px;width:50px;border-bottom:1px dotted #8894A3;background-color:#C2D5FC;text-align:center;line-height:40px;color:#586A7E;overflow:hidden;}.dhx_month_head{background-color:#EBEFF4;color:#2F3A48;border-right:1px dotted #586A7E;height:18px;padding-right:5px;padding-top:3px;text-align:right;}.dhx_month_body{border-right:1px dotted #586A7E;border-bottom:1px dotted #586A7E;background-color:#FFF;}.dhx_now .dhx_month_body{background-color:#E2EDFF;}.dhx_after .dhx_month_body,.dhx_before .dhx_month_body{background-color:#ECECEC;}.dhx_after .dhx_month_head,.dhx_before .dhx_month_head{background-color:#E2E3E6;color:#94A6BB;}.dhx_now .dhx_month_head{background-color:#D1DEF4;font-weight:bold;}.dhx_cal_drag{position:absolute;z-index:9999;background-color:#FFE763;border:1px solid #B7A543;opacity:.5;filter:alpha(opacity=50);}.dhx_loading{position:absolute;width:128px;height:15px;background-image:url(imgs/loading.gif);z-index:9999;}.dhx_multi_day_icon,.dhx_multi_day{background-color:#E1E6FF;background-repeat:no-repeat;border-right:1px dotted #8894A3;}.dhx_multi_day{position:absolute;border-top:1px dotted #8894A3;}.dhx_multi_day_icon,.dhx_multi_day_icon_small{background-position:center center;background-color:#E1E6FF;background-repeat:no-repeat;border-bottom:1px dotted #8894A3;border-right:1px dotted #8894A3;}.dhx_multi_day_icon{background-image:url(imgs/clock_big.gif);}.dhx_multi_day_icon_small{background-image:url(imgs/clock_small.gif);}.dhtmlxLayoutPolyContainer_dhx_skyblue .dhx_cal_container{background-color:#d0e5ff;}.dhx_cal_event .dhx_header,.dhx_cal_event .dhx_title,.dhx_cal_event .dhx_body,.dhx_cal_event .dhx_footer{background-color:#FFE763;border:1px solid #B7A543;color:#887A2E;overflow:hidden;width:100%;font-family:Tahoma;font-size:8pt;}.dhx_move_denied .dhx_cal_event .dhx_header,.dhx_move_denied .dhx_cal_event .dhx_title{cursor:default;}.dhx_cal_event .dhx_header{height:1px;margin-left:1px;border-width:1px 1px 0 1px;cursor:pointer;}.dhx_cal_event .dhx_title{height:12px;border-width:0 1px 1px 1px;border-bottom-style:dotted;font-size:7pt;font-weight:bold;text-align:center;background-position:right;background-repeat:no-repeat;cursor:pointer;}.dhx_cal_event .dhx_body,.dhx_cal_event.dhx_cal_select_menu .dhx_body{border-width:0 1px 1px 1px;padding:5px;}.dhx_resize_denied{cursor:default!important;}.dhx_cal_event .dhx_event_resize{cursor:s-resize;}.dhx_cal_event .dhx_footer,.dhx_cal_event .dhx_select_menu_footer{height:1px;margin-left:2px;border-width:0 1px 1px 1px;}.dhx_cal_event_line{background-color:#FFE763;border:1px solid #B7A543;border-radius:3px;font-family:Tahoma;font-size:8pt;height:13px;padding-left:10px;color:#887A2E;cursor:pointer;overflow:hidden;}.dhx_cal_event_clear{font-family:Tahoma;font-size:8pt;height:13px;padding-left:2px;color:#887A2E;white-space:nowrap;overflow:hidden;cursor:pointer;}.dhx_in_move{background-color:#FFFF80;}div.dhx_cal_editor{background-color:#FFE763;border:1px solid #B7A543;border-top-style:dotted;z-index:999;position:absolute;overflow:hidden;}textarea.dhx_cal_editor{width:100%;height:100%;border:0 solid black;margin:none;padding:none;overflow:auto;}div.dhx_menu_head{background-image:url(imgs/controls.gif);background-position:0 -43px;width:10px;height:10px;margin-left:5px;margin-top:1px;border:none;cursor:default;}div.dhx_menu_icon{background-image:url(imgs/controls.gif);width:20px;height:20px;margin-left:-5px;margin-top:0;border:none;cursor:pointer;}div.icon_details{background-position:0 0;}div.icon_edit{background-position:-22px 0;}div.icon_save{background-position:-84px -1px;}div.icon_cancel{background-position:-62px 0;}div.icon_delete{background-position:-42px 0;}.dhx_unselectable,.dhx_unselectable div{-webkit-user-select:none;-moz-user-select:none;-moz-user-select:-moz-none;}.dhx_cal_light{background-color:#FFE763;border-radius:5px;font-family:Tahoma;font-size:8pt;border:1px solid #B7A64B;color:#887A2E;position:absolute;z-index:10001;width:580px;height:300px;box-shadow:5px 5px 5px #888;}.dhx_cal_light_wide{width:650px;}.dhx_mark{position:relative;top:3px;background-image:url('./imgs/controls.gif');background-position:0 -43px;padding-left:10px;}.dhx_ie6 .dhx_mark{background-position:6px -41px;}.dhx_cal_light select{font-family:Tahoma;font-size:8pt;color:#887A2E;padding:2px;margin:0;}.dhx_cal_ltitle{padding:2px 0 2px 5px;overflow:hidden;white-space:nowrap;}.dhx_cal_ltitle span{white-space:nowrap;}.dhx_cal_lsection{background-color:#DBCF8C;color:#FFF4B5;font-weight:bold;padding:5px 0 3px 10px;}.dhx_section_time{background-color:#DBCF8C;white-space:nowrap;}.dhx_cal_lsection .dhx_fullday{float:right;margin-right:5px;color:#887A2E;font-size:12px;font-weight:normal;line-height:20px;vertical-align:top;cursor:pointer;}.dhx_cal_lsection{font-size:18px;font-family:Arial;}.dhx_cal_ltext{padding:2px 0 2px 10px;overflow:hidden;}.dhx_cal_ltext textarea{background-color:#FFF4B5;overflow:auto;border:none;color:#887A2E;height:100%;width:100%;outline:none!important;resize:none;}.dhx_time{font-weight:bold;}.dhx_cal_light .dhx_title{padding-left:10px;}.dhx_cal_larea{border:1px solid #DCC43E;background-color:#FFF4B5;overflow:hidden;margin-left:3px;width:572px;height:1px;}.dhx_btn_set{padding:5px 10px 0 10px;float:left;}.dhx_btn_set div{float:left;height:21px;line-height:21px;vertical-align:middle;cursor:pointer;}.dhx_save_btn{background-image:url('./imgs/controls.gif');background-position:-84px 0;width:21px;}.dhx_cancel_btn{background-image:url('./imgs/controls.gif');background-position:-63px 0;width:20px;}.dhx_delete_btn{background-image:url('./imgs/controls.gif');background-position:-42px 0;width:20px;}.dhx_cal_cover{width:100%;height:100%;position:absolute;z-index:10000;top:0;left:0;background-color:black;opacity:.1;filter:alpha(opacity=10);}.dhx_custom_button{padding:0 3px 0 3px;color:#887A2E;font-family:Tahoma;font-size:8pt;background-color:#FFE763;font-weight:normal;margin-right:5px;margin-top:0;cursor:pointer;}.dhx_custom_button div{cursor:pointer;float:left;height:21px;line-height:21px;vertical-align:middle;}.dhx_cal_light_wide .dhx_cal_larea{border-top-width:0;}.dhx_cal_light_wide .dhx_cal_lsection{border:0;float:left;text-align:right;width:100px;height:20px;font-size:16px;padding:5px 0 0 10px;}.dhx_cal_light_wide .dhx_wrap_section{border-top:1px solid #DBCF8C;position:relative;background-color:#DBCF8C;overflow:hidden;}.dhx_cal_light_wide .dhx_section_time{padding-top:2px!important;height:20px!important;}.dhx_section_time{text-align:center;}.dhx_cal_light_wide .dhx_cal_larea{width:730px;}.dhx_cal_light_wide{width:738px;}.dhx_cal_light_wide .dhx_section_time{background:transparent;}.dhx_cal_light_wide .dhx_cal_checkbox label{padding-left:0;}.dhx_cal_wide_checkbox input{margin-top:8px;margin-left:14px;}.dhx_cal_light input{font-family:Tahoma;font-size:8pt;color:#887A2E;}.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday{float:none;margin-right:0;color:#FFF4B5;font-weight:bold;font-size:16px;font-family:Arial;cursor:pointer;}.dhx_custom_button{float:right;height:21px;width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;}.dhx_cal_light_wide .dhx_custom_button{position:absolute;top:0;right:0;margin-top:2px;}.dhx_cal_light_wide .dhx_repeat_right{margin-right:55px;}.dhx_minical_popup{position:absolute;z-index:10100;width:251px;height:175px;}.dhx_scale_bar_header{position:absolute;border-bottom:1px dotted #8894A3;width:100%;}.dhx_expand_icon{position:absolute;top:0;right:0;background-image:url(./imgs/collapse_expand_icon.gif);width:18px;height:18px;cursor:pointer;background-position:0 18px;z-index:16;}.dhx_scheduler_agenda .dhx_cal_data{background-image:url(./imgs/databg.png);}.dhx_agenda_area{width:100%;overflow-y:auto;background-image:url(./imgs/databg.png);}.dhx_agenda_line{height:21px;clear:both;overflow:hidden;}.dhx_agenda_line div{float:left;width:188px;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_agenda_area .dhx_agenda_line div{border-right:0 dotted #8894A3;}.dhx_v_border{position:absolute;left:187px;top:0;border-right:1px dotted #8894A3;width:1px;height:100%;}.dhx_agenda_line .dhx_event_icon{width:20px;border-width:0;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_agenda_line span{padding-left:5px;line-height:21px;}.dhx_year_body{border-left:1px dotted #586A7E;}.dhx_year_week{position:relative;}.dhx_scale_bar_last{border-right:1px dotted #586A7E;}.dhx_year_month{height:18px;padding-top:3px;border:1px dotted #586A7E;text-align:center;vertical-align:middle;}.dhx_year_body .dhx_before .dhx_month_head,.dhx_year_body .dhx_after .dhx_month_head,.dhx_year_body .dhx_before .dhx_month_head a,.dhx_year_body .dhx_after .dhx_month_head a{color:#E2E3E6!important;}.dhx_year_body .dhx_month_body{height:0;overflow:hidden;}.dhx_month_head.dhx_year_event{background-color:#FFE763;}.dhx_year_body .dhx_before .dhx_month_head,.dhx_year_body .dhx_after .dhx_month_head{cursor:default;}.dhx_tooltip{border:1px solid #BBB;background-image:url(./imgs/databg.png);position:absolute;z-index:9998;width:300px;height:auto;font-family:Tahoma;font-size:8pt;overflow:hidden;}.dhx_tooltip_line{line-height:20px;height:20px;overflow:hidden;}.dhx_tooltip_line .dhx_event_icon{width:20px;height:20px;padding-right:10px;float:left;border-width:0;position:relative;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_tooltip_date{float:left;width:auto;padding-left:5px;text-align:center;}.dhx_text_disabled{color:#887A2E;font-family:Tahoma;font-size:8pt;}.dhx_mini_calendar{-moz-box-shadow:5px 5px 5px #888;-khtml-box-shadow:5px 5px 5px #888;}.dhx_mini_calendar .dhx_month_head{cursor:pointer;}.dhx_mini_calendar .dhx_calendar_click{background-color:#C2D5FC;}.dhx_cal_navline div.dhx_minical_icon{width:18px;height:18px;left:190px;top:1px;cursor:pointer;background-image:url(./imgs/calendar.gif);}.dhx_matrix_scell{height:100%;}.dhx_matrix_cell,.dhx_matrix_scell{overflow:hidden;text-align:center;vertical-align:middle;border-bottom:1px dotted #8894A3;border-right:1px dotted #8894A3;}.dhx_matrix_cell{background-color:white;}.dhx_matrix_line{overflow:hidden;}.dhx_matrix_cell div,.dhx_matrix_scell div{overflow:hidden;text-align:center;height:auto;}.dhx_cal_lsection .dhx_readonly{font-size:9pt;font-size:8pt;padding:2px;color:#887A2E;}.dhx_cal_event_line .dhx_event_resize{cursor:w-resize;background:url(./imgs/resize_dots.png) repeat-y;position:absolute;top:0;width:4px;}.dhx_event_resize_start{left:0;}.dhx_event_resize_end{right:0;}.dhx_matrix_scell.folder,.dhx_data_table.folder .dhx_matrix_cell{background-color:#969394;cursor:pointer;}.dhx_matrix_scell .dhx_scell_level0{padding-left:5px;}.dhx_matrix_scell .dhx_scell_level1{padding-left:20px;}.dhx_matrix_scell .dhx_scell_level2{padding-left:35px;}.dhx_matrix_scell .dhx_scell_level3{padding-left:50px;}.dhx_matrix_scell .dhx_scell_level4{padding-left:65px;}.dhx_matrix_scell.folder{font-weight:bold;text-align:left;}.dhx_matrix_scell.folder .dhx_scell_expand{float:left;width:10px;padding-right:3px;}.dhx_matrix_scell.folder .dhx_scell_name{float:left;width:auto;}.dhx_matrix_scell.item .dhx_scell_name{padding-left:15px;text-align:left;}.dhx_data_table.folder .dhx_matrix_cell{border-right:0;}.dhx_section_timeline{overflow:hidden;padding:4px 0 2px 10px;}.dhx_section_timeline select{width:552px;}.dhx_map_area{width:100%;height:100%;overflow-y:auto;overflow-x:hidden;background-image:url(./imgs/databg.png);}.dhx_map_line .dhx_event_icon{width:20px;border-width:0;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_map_line{height:21px;clear:both;overflow:hidden;}.dhx_map{position:absolute;}.dhx_map_line div{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .headline_description{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .dhx_map_description{float:left;border-right:0 dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .headline_date,.dhx_map_line .headline_description{border-left:0;}.dhx_map_line .line_description{float:left;border-right:1px dotted #8894A3;text-align:left;padding-left:5px;line-height:21px;overflow:hidden;}.dhx_map_line.highlight{background-color:#C4C5CC;}.dhx_map_area .dhx_map_line div{border-right:0 dotted #8894A3;}.dhtmlXTooltip.tooltip{-moz-box-shadow:3px 3px 3px #888;-webkit-box-shadow:3px 3px 3px #888;-o-box-shadow:3px 3px 3px #888;box-shadow:3px 3px 3px #888;filter:progid:DXImageTransform.Microsoft.Shadow(color='#888888',Direction=135,Strength=5);background-color:white;border-left:1px dotted #887A2E;border-top:1px dotted #887A2E;color:#887A2E;cursor:default;padding:10px;position:absolute;z-index:500;}.dhx_cal_checkbox label{padding-left:5px;}.dhx_cal_light .radio{padding:2px 0 2px 10px;}.dhx_cal_light .radio input,.dhx_cal_light .radio label{line-height:15px;}.dhx_cal_light .radio input{vertical-align:middle;margin:0;padding:0;}.dhx_cal_light .radio label{vertical-align:middle;padding-right:10px;}.dhx_cal_light .combo{padding:4px;}.dhx_cal_light_wide .dhx_combo_box{width:608px!important;left:10px;}.dhx_wa_column{float:left;}.dhx_wa_column_last .dhx_wa_day_cont{border-left:1px dotted #8894A3;}.dhx_wa_scale_bar{font-family:Tahoma;padding-left:10px;font-size:11px;border-top:1px dotted #8894A3;border-bottom:1px dotted #8894A3;}.dhx_wa_day_data{background-color:#FCFEFC;overflow-y:auto;}.dhx_wa_ev_body{border-bottom:1px dotted #789;font-size:12px;padding:5px 0 5px 7px;}.dhx_wa_dnd{font-family:Tahoma;position:absolute;padding-right:7px;color:#887AE2!important;background-color:#FFE763!important;border:1px solid #B7A543;}.dhx_cal_event_selected{background-color:#9cc1db;color:white;}.dhx_second_scale_bar{border-bottom:1px dotted #586A7E;padding-top:2px;}.dhx_cal_header div div{border-left:1px dotted #8894A3;}.dhx_grid_area{width:100%;height:100%;overflow-y:auto;background-color:#FCFEFC;}.dhx_grid_area table{border-collapse:collapse;border-spacing:0;width:100%;table-layout:fixed;}.dhx_grid_area td{table-layout:fixed;text-align:center;}.dhx_grid_line{height:21px;clear:both;overflow:hidden;}.dhx_grid_line div{float:left;cursor:default;padding-top:0;padding-bottom:0;text-align:center;line-height:21px;overflow:hidden;}.dhx_grid_area td,.dhx_grid_line div{padding-left:8px;padding-right:8px;}.dhx_grid_area tr.dhx_grid_event{height:21px;overflow:hidden;margin:0 0 1px 0;}.dhx_grid_area tr.dhx_grid_event td{border-bottom:1px solid #ECEEF4;}.dhx_grid_area tr.dhx_grid_event:nth-child(2n+1) td,.dhx_grid_area tr.dhx_grid_event:nth-child(2n) td{border-bottom-width:0;border-bottom-style:none;}.dhx_grid_area tr.dhx_grid_event:nth-child(2n){background-color:#ECEEF4;;}.dhx_grid_area .dhx_grid_dummy{table-layout:auto;margin:0!important;padding:0!important;}.dhx_grid_v_border{position:absolute;border-right:1px solid #A4BED4;width:1px;height:100%;}.dhx_grid_event_selected{background-color:#9cc1db!important;color:white!important;}.dhx_grid_sort_desc .dhx_grid_view_sort{background-position:0 -55px;}.dhx_grid_sort_asc .dhx_grid_view_sort{background-position:0 -66px;}.dhx_grid_view_sort{width:10px;height:10px;position:absolute;border:none!important;top:5px;background-repeat:no-repeat;background-image:url(./imgs/images.png);}.dhx_marked_timespan{position:absolute;width:100%;}.dhx_time_block{position:absolute;width:100%;background:silver;opacity:.4;filter:alpha(opacity=40);z-index:1;}.dhx_time_block_reset{opacity:1;filter:alpha(opacity=100);}.dhx_scheduler_month .dhx_marked_timespan{display:none;}.dhx_mini_calendar .dhx_marked_timespan{display:none;}.dhx_now_time{width:100%;border-bottom:2px dotted red;z-index:1;}.dhx_scheduler_month .dhx_now_time{border-bottom:0;border-left:2px dotted red;}.dhx_matrix_now_time{border-left:2px dotted red;z-index:1;}div.dhx_form_repeat input.radio{margin:-4px 0 0 -4px!ie;}div.dhx_form_repeat input.checkbox{margin:0 0 0 -4px!ie;}.dhx_form_repeat,.dhx_form_repeat input{padding:0;margin:0;padding-left:5px;font-family:Tahoma,Verdana;font-size:11px;line-height:24px;}.dhx_form_repeat{overflow:hidden;height:0;background-color:#FFF4B5;}.dhx_cal_light_wide .dhx_form_repeat{background-color:transparent;}.dhx_repeat_center,.dhx_repeat_left{height:115px;padding:10px 0 10px 10px;float:left;}.dhx_repeat_left{width:95px;}.dhx_repeat_center{width:335px;margin-top:12px;}.dhx_repeat_divider{float:left;height:115px;border-left:1px dotted #DCC43E;width:1px;}.dhx_repeat_right{float:right;height:115px;width:160px;padding:10px 3px 10px 10px;margin-top:7px;}input.dhx_repeat_text{height:16px;width:27px;margin:0 4px 0 4px;line-height:18px;padding:0 0 0 2px;}.dhx_form_repeat select{height:20px;width:87px;padding:0 0 0 2px;margin:0 4px 0 4px;}input.dhx_repeat_date{height:18px;width:80px;padding:0 0 0 2px;margin:0 4px 0 4px;background-repeat:no-repeat;background-position:64px 0;border:1px #7f9db9 solid;line-height:18px;}input.dhx_repeat_radio{margin-right:4px;}input.dhx_repeat_checkbox{margin:4px 4px 0 0;}.dhx_repeat_days td{padding-right:5px;}.dhx_repeat_days label{font-size:10px;}.dhx_custom_button{width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;}.dhx_custom_button_recurring{background-image:url(./imgs/but_repeat.gif);background-position:-5px 20px;width:20px;margin-right:10px;}.dhx_cal_light_rec{width:640px;}.dhx_cal_light_rec .dhx_cal_larea{width:632px;}.dhx_cal_light_rec.dhx_cal_light_wide{width:816px;}.dhx_cal_light_rec.dhx_cal_light_wide .dhx_cal_larea{width:808px;}.dhx_cal_event .dhx_title{border-width:1px 1px 0 1px;padding-top:1px;-webkit-border-top-left-radius:4px;-webkit-border-top-right-radius:4px;-moz-border-radius-topleft:4px;-moz-border-radius-topright:4px;border-top-left-radius:4px;border-top-right-radius:4px;font-family:arial;font-weight:bold;font-size:12px;}.dhx_cal_event .dhx_body,.dhx_cal_event.dhx_cal_select_menu .dhx_body{padding-bottom:8px;-webkit-border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;}.dhx_cal_event .dhx_header,.dhx_cal_event.dhx_cal_select_menu .dhx_footer{display:none;}.dhx_cal_event .dhx_footer{height:5px;border:0;margin-top:-6px;background:url(imgs_dhx_terrace/resizing.png) no-repeat center center;}.dhx_cal_event .dhx_header,.dhx_cal_event .dhx_footer,.dhx_cal_event .dhx_body,.dhx_cal_event .dhx_title{background-color:#1796b0;border-color:transparent;color:white;}div.dhx_cal_editor{border:1px solid transparent;background-color:#1796b0;}.dhx_cal_editor{font-size:12px;font-family:Arial,sans-serif;}div.dhx_menu_head,div.dhx_menu_icon{background-image:url(imgs_dhx_terrace/controls.png);}.dhx_cal_event_line{border:1px solid #1796b0;background-color:#1796b0;color:white;height:17px;line-height:17px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;}.dhx_cal_event_line_start{-webkit-border-top-left-radius:9px;-webkit-border-bottom-left-radius:9px;-moz-border-radius-topleft:9px;-moz-border-radius-bottomleft:9px;border-top-left-radius:9px;border-bottom-left-radius:9px;}.dhx_cal_event_line_end{-webkit-border-top-right-radius:9px;-webkit-border-bottom-right-radius:9px;-moz-border-radius-topright:9px;-moz-border-radius-bottomright:9px;border-top-right-radius:9px;border-bottom-right-radius:9px;}.dhx_cal_event .dhx_body,.dhx_cal_event_line{font-size:12px;font-family:Arial,sans-serif;}.dhx_cal_container{background-color:white;}.dhx_cal_data{border-top:1px solid #CECECE;}.dhx_scale_holder{background-image:url(imgs_dhx_terrace/databg.png);border-right:1px solid #CECECE;}.dhx_scale_holder_now{background-image:url(imgs_dhx_terrace/databg_now.png);border-right:1px solid #CECECE;}.dhx_scale_hour{border-bottom:1px solid #CECECE;background-color:white;font:11px/44px Arial;color:#767676;}.dhx_cal_header{border:1px solid #CECECE;border-left:0;border-bottom:0;}.dhx_scale_bar{border-left:1px solid #CECECE;}.dhx_scale_bar{font:11px/16px Arial;color:#767676;padding-top:2px;background-color:white;}.dhx_cal_navline div{top:14px;}.dhx_cal_tab,.dhx_cal_date,.dhx_cal_today_button,.dhx_cal_prev_button,.dhx_cal_next_button{color:#454544;height:30px;line-height:30px;background:none;border:1px solid #CECECE;}.dhx_cal_navline .dhx_cal_date{border:0;font-size:18px;font-weight:normal;font-family:arial;width:100%;top:14px;text-align:center;position:absolute;left:0;z-index:-1;}.dhx_cal_today_button{color:#747473;left:auto;right:123px;background:none;text-decoration:none;width:80px;font-size:12px;font-weight:bold;font-family:arial;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}.dhx_cal_prev_button,.dhx_cal_next_button{left:auto;width:46px;}.dhx_cal_prev_button{right:61px;background:url(imgs_dhx_terrace/arrow_left.png) no-repeat center center;-webkit-border-top-left-radius:5px;-webkit-border-bottom-left-radius:5px;-moz-border-radius-topleft:5px;-moz-border-radius-bottomleft:5px;border-top-left-radius:5px;border-bottom-left-radius:5px;}.dhx_cal_next_button{right:14px;background:url(imgs_dhx_terrace/arrow_right.png) no-repeat center center;-webkit-border-top-right-radius:5px;-webkit-border-bottom-right-radius:5px;-moz-border-radius-topright:5px;-moz-border-radius-bottomright:5px;border-top-right-radius:5px;border-bottom-right-radius:5px;}.dhx_cal_tab{color:#747473;width:60px;padding-top:0;text-decoration:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;font-weight:bold;font-family:arial;font-size:12px;}.dhx_cal_tab.active{background-color:#F0EDE7;color:#454544;border:1px solid #CECECE;text-shadow:0 1px 0 white;}.dhx_cal_tab_first{-webkit-border-top-left-radius:5px;-webkit-border-bottom-left-radius:5px;-moz-border-radius-topleft:5px;-moz-border-radius-bottomleft:5px;border-top-left-radius:5px;border-bottom-left-radius:5px;}.dhx_cal_tab_last{-webkit-border-top-right-radius:5px;-webkit-border-bottom-right-radius:5px;-moz-border-radius-topright:5px;-moz-border-radius-bottomright:5px;border-top-right-radius:5px;border-bottom-right-radius:5px;}.dhx_cal_tab_standalone{-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;padding:0 5px;}.dhx_multi_day,.dhx_multi_day_icon_small,.dhx_multi_day_icon{background-color:white;}.dhx_multi_day{border-top:1px solid #CECECE;}.dhx_multi_day_icon,.dhx_multi_day_icon_small{border-bottom:1px solid #CECECE;border-right:1px solid #CECECE;}.dhx_multi_day_icon_small{background-image:url(imgs_dhx_terrace/clock_small.gif);}.dhx_multi_day_icon{background-image:url(imgs_dhx_terrace/clock_big.gif);}.dhx_month_head,.dhx_after .dhx_month_head,.dhx_before .dhx_month_head,.dhx_after .dhx_month_body,.dhx_before .dhx_month_body{background-color:white;}.dhx_month_head{height:21px;padding-top:0;font:12px/21px Arial;color:#362d26;border-right:1px solid #CECECE;}.dhx_after .dhx_month_head,.dhx_before .dhx_month_head,.dhx_after .dhx_month_head,.dhx_before .dhx_month_head{color:#bbb;}.dhx_month_body{border-right:1px solid #CECECE;border-bottom:1px solid #CECECE;}.dhx_now .dhx_month_head,.dhx_now .dhx_month_body{background-color:#FFF3A1;font-weight:normal;}.dhx_cal_event_clear{color:#0E64A0;}.dhx_cal_larea{margin-left:0;}.dhx_cal_light_wide .dhx_cal_larea{margin-left:3px;}.dhx_cal_light_wide .dhx_wrap_section{padding:5px 0;}.dhx_cal_light,.dhx_cal_larea,.dhx_cal_lsection,.dhx_wrap_section,.dhx_cal_light_wide .dhx_wrap_section,.dhx_cal_ltext textarea{background-color:white;}.dhx_cal_lsection,.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday,.dhx_cal_lsection .dhx_fullday,.dhx_cal_light input{color:#747473;}.dhx_cal_light_wide .dhx_wrap_section{border-top:0;border-bottom:1px solid #CECECE;}.dhx_cal_larea{border:1px solid transparent;}.dhx_cal_ltext textarea,.dhx_cal_light select,.dhx_cal_light{color:#2E2E2E;}.dhx_cal_light{border:1px solid #CECECE;}.dhx_cal_light_wide .dhx_cal_lsection,.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday{font-size:13px;}.dhx_section_time{background-color:transparent;}.dhx_save_btn,.dhx_cancel_btn,.dhx_delete_btn{display:none;}.dhx_btn_set,.dhx_btn_set div{height:30px;padding:0 20px;line-height:30px;}.dhx_btn_set{margin:12px 0 0 0;padding:0;font-size:12px;color:#454544;font-weight:bold;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}.dhx_left_btn_set{margin-left:20px;}.dhx_right_btn_set{margin-right:20px;}.dhx_save_btn_set{border:1px solid #22A1BC;color:white;text-shadow:0 -1px 0 #6F6F6F;background-color:#22A1BC;}.dhx_cancel_btn_set{border:1px solid #CECECE;}.dhx_delete_btn_set{border:1px solid #FF8831;background-color:#FF8831;color:white;text-shadow:0 -1px 0 #93755F;}.dhx_cal_ltitle{height:30px;line-height:30px;border-bottom:1px solid #CECECE;}.dhx_mark{display:none;}.dhx_time{padding-left:10px;}.dhx_close_icon{float:right;width:9px;height:9px;background:url(imgs_dhx_terrace/close_icon.png) no-repeat center center;padding:10px;margin-top:1px;}.dhx_cal_light_wide .dhx_cal_ltext.dhx_cal_template{line-height:22px;}.dhx_cal_ltext textarea{line-height:20px;box-sizing:border-box;-moz-box-sizing:border-box;border:1px solid #CECECE;background-color:#F9F9F9;}.dhtmlx_modal_box{background:white;width:330px;}.dhtmlx_popup_controls{padding-bottom:9px;}.dhtmlx_popup_button,.dhtmlx_popup_button:active,.dhtmlx_popup_button div,.dhtmlx_popup_button div:active{color:#444;background:white;box-shadow:none;}.dhtmlx_popup_button.dhtmlx_ok_button{border:1px solid #22A1BC;background-color:#22A1BC;}.dhtmlx_popup_button.dhtmlx_ok_button div{background:#22A1BC;border:1px solid #22A1BC;color:white;text-shadow:0 -1px 0 #6F6F6F;}.dhx_cal_container.dhx_mini_calendar{box-sizing:border-box;border:1px solid #CECECE;box-shadow:2px 2px 5px #888;}.dhx_mini_calendar .dhx_year_month{border:1px solid #CECECE;font-family:Arial;}.dhx_mini_calendar .dhx_month_head,.dhx_mini_calendar .dhx_year_month,.dhx_mini_calendar .dhx_month_body,.dhx_mini_calendar .dhx_scale_bar,.dhx_mini_calendar .dhx_year_body{border-color:transparent;}.dhx_mini_calendar .dhx_year_body{padding-top:1px;}.dhx_mini_calendar .dhx_scale_bar{border-width:0;}.dhx_mini_calendar .dhx_year_week{border-bottom:1px solid #CECECE;padding-top:1px;}.dhx_mini_calendar .dhx_month_head{padding-right:0;margin-right:1px;text-align:center;}.dhx_mini_calendar .dhx_cal_prev_button,.dhx_mini_calendar .dhx_cal_next_button{border:0;height:20px;}.dhx_cal_navline div.dhx_minical_icon{left:210px;top:14px;width:30px;height:30px;background:url(./imgs_dhx_terrace/calendar.gif) no-repeat;background-position:3px 5px;}.dhx_cal_event_line .dhx_event_resize{background:url(./imgs_dhx_terrace/resize_dots.png) repeat-y;}.dhx_matrix_scell,.dhx_matrix_cell{border-bottom:1px solid #CECECE;border-right:1px solid #CECECE;}.dhx_cal_header div div{border-left:1px solid #CECECE;}.dhx_matrix_scell.folder{border-right:0;}.dhx_second_scale_bar{border-bottom:1px solid #CECECE;}.dhx_repeat_divider{border-left:1px solid #CECECE;}.dhx_custom_button{background-color:white;border:1px solid #CECECE;color:#747473;}.dhx_cal_light_wide .dhx_custom_button{margin-top:6px;}.dhx_custom_button_recurring{background-image:url(./imgs_dhx_terrace/but_repeat.gif);}.dhx_v_border,.dhx_agenda_line div{border-right:1px solid #CECECE;}.dhx_year_month{border:1px solid #CECECE;}.dhx_scale_bar_last{border-right:1px solid #CECECE;}.dhx_year_body{border-left:1px solid #CECECE;}.dhx_expand_icon{top:-3px;}.dhx_scale_bar .dhx_cal_next_button,.dhx_scale_bar .dhx_cal_prev_button{width:20px;height:20px;top:0!important;border:0;}.dhx_scale_bar .dhx_cal_next_button{right:1px!important;border-left:1px solid #CECECE;}.dhx_scale_bar .dhx_cal_prev_button{left:1px!important;border-right:1px solid #CECECE;}.dhx_map_line .headline_date,.dhx_map_line .headline_description{border:0;}.dhx_map_line .headline_date{border-right:1px solid #CECECE;}.dhtmlXTooltip.tooltip{border-left:1px solid #CECECE;border-top:1px solid #CECECE;color:#747473;font-size:12px;line-height:16px;}.dhx_wa_scale_bar{border-top:1px solid #CECECE;border-bottom:1px solid #CECECE;}.dhx_wa_column_last .dhx_wa_day_cont{border-left:1px solid #CECECE;}.dhx_wa_ev_body{border-bottom:1px solid #CECECE;}.dhx_wa_scale_bar{background-color:#f0ede7;}.dhx_wa_ev_body.dhx_cal_event_selected{background-color:#fff3a1;color:#362d26;}.dhx_wa_dnd{background-color:#fddb93!important;color:#747473!important;border:1px solid #ccb177;}.dhx_text_disabled{color:#2E2E2E;}.dhx_cal_ltext .dhx_text_disabled{line-height:22px;}.dhx_grid_v_border{border-right-color:#CECECE;} \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_glossy.css b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_glossy.css deleted file mode 100644 index 7831ca4028c..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler_glossy.css +++ /dev/null @@ -1,5 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -.dhtmlx_message_area{position:fixed;right:5px;width:250px;z-index:1000;}.dhtmlx-info{min-width:120px;padding:4px 4px 4px 20px;font-family:Tahoma;z-index:10000;margin:5px;margin-bottom:10px;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease;}.dhtmlx-info.hidden{height:0;padding:0;border-width:0;margin:0;overflow:hidden;}.dhtmlx_modal_box{overflow:hidden;display:inline-block;min-width:300px;width:300px;text-align:center;position:fixed;background-color:#fff;background:-webkit-linear-gradient(top,#fff 1%,#d0d0d0 99%);background:-moz-linear-gradient(top,#fff 1%,#d0d0d0 99%);box-shadow:0 0 14px #888;font-family:Tahoma;z-index:20000;border-radius:6px;border:1px solid #fff;}.dhtmlx_popup_title{border-top-left-radius:5px;border-top-right-radius:5px;border-width:0;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAoCAMAAAAIaGBFAAAAhFBMVEVwcHBubm5sbGxqampoaGhmZmZlZWVjY2NhYWFfX19dXV1bW1taWlpYWFhWVlZUVFRSUlJRUVFPT09NTU1LS0tJSUlHR0dGRkZERERCQkJAQEA+Pj49PT09PT0+Pj5AQEBBQUFDQ0NERERGRkZHR0dJSUlKSkpMTExMTEw5OTk5OTk5OTkny8YEAAAAQklEQVQImQXBCRJCAAAAwKVSQqdyjSPXNP7/QLsIhA6OTiJnF7GrRCpzc/fw9PKW+/gqlCq1RqvTG/yMJrPF6m/bAVEhAxxnHG0oAAAAAElFTkSuQmCC);background-image:-webkit-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%);background-image:-moz-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 97%,#393939 97%);}.dhtmlx-info,.dhtmlx_popup_button,.dhtmlx_button{user-select:none;-webkit-user-select:none;-moz-user-select:-moz-none;cursor:pointer;}.dhtmlx_popup_text{overflow:hidden;}.dhtmlx_popup_controls{border-radius:6px;padding:5px;}.dhtmlx_popup_button,.dhtmlx_button{height:30px;line-height:30px;display:inline-block;margin:0 5px;border-radius:6px;color:#FFF;}.dhtmlx_popup_button{min-width:120px;}div.dhx_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity = 20);opacity:.2;position:fixed;z-index:19999;left:0;top:0;width:100%;height:100%;border:none;zoom:1;}.dhtmlx-info img,.dhtmlx_modal_box img{float:left;margin-right:20px;}.dhtmlx-alert-error .dhtmlx_popup_title,.dhtmlx-confirm-error .dhtmlx_popup_title{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAIAAAArRUU2AAAATklEQVR4nIWLuw2AMBBDjVuQiBT2oWbRDATrnB0KQOJoqPzRe3BrHI6dcBASYREKovtK6/6DsDOX+stN+3H1YX9ciRgnYq5EWYhS2dftBIuLT4JyIrPCAAAAAElFTkSuQmCC);}.dhtmlx-alert-error,.dhtmlx-confirm-error{border:1px solid #f00;}.dhtmlx_button,.dhtmlx_popup_button{box-shadow:0 0 4px #888;border:1px solid #838383;}.dhtmlx_button input,.dhtmlx_popup_button div{border:1px solid #FFF;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAYFBMVEVwcHBtbW1ra2toaGhmZmZjY2NhYWFeXl5cXFxaWlpXV1dVVVVSUlJQUFBNTU1LS0tJSUlGRkZERERBQUE/Pz88PDw9PT0+Pj5AQEBCQkJDQ0NFRUVHR0dISEhKSkpMTEzqthaMAAAAMklEQVQImQXBhQ2AMAAAsOIMlwWH/8+kRSKVyRVKlVrQaHV6g9FktlhFm93hdLk9Xt8PIfgBvdUqyskAAAAASUVORK5CYII=);background-image:-webkit-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 99%);background-image:-moz-linear-gradient(top,#707070 1%,#3d3d3d 70%,#4c4c4c 99%);border-radius:6px;font-size:15px;font-weight:normal;-moz-box-sizing:content-box;box-sizing:content-box;color:#fff;padding:0;margin:0;vertical-align:top;height:28px;line-height:28px;}.dhtmlx_button input:focus,.dhtmlx_button input:active,.dhtmlx_popup_button div:active,.dhtmlx_popup_button div:focus{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAXVBMVEVwcHBubm5tbW1sbGxra2tpaWloaGhnZ2dmZmZlZWVjY2NiYmJhYWFgYGBfX19dXV1cXFxbW1taWlpZWVlXV1dWVlZVVVVUVFRTU1NRUVFQUFBPT09OTk5NTU1LS0tT9SY0AAAAMUlEQVQImQXBhQGAMAAAIGxnx2z9/00BiVQmVyhVakGj1ekNRpPZYhVtdofT5fZ4fT8hpwG05JjexgAAAABJRU5ErkJggg==);background-image:-webkit-linear-gradient(top,#707070 1%,#4c4c4c 99%);background-image:-moz-linear-gradient(top,#707070 1%,#4c4c4c 99%);}.dhtmlx_popup_title{color:#fff;text-shadow:1px 1px #000;height:40px;line-height:40px;font-size:20px;}.dhtmlx_popup_text{margin:15px 15px 5px 15px;font-size:14px;color:#000;min-height:30px;border-radius:6px;}.dhtmlx-info,.dhtmlx-error{font-size:14px;color:#000;box-shadow:0 0 10px #888;padding:0;background-color:#FFF;border-radius:3px;border:1px solid #fff;}.dhtmlx-info div{padding:5px 10px 5px 10px;background-color:#fff;border-radius:3px;border:1px solid #B8B8B8;}.dhtmlx-error{background-color:#d81b1b;border:1px solid #ff3c3c;box-shadow:0 0 10px #000;}.dhtmlx-error div{background-color:#d81b1b;border:1px solid #940000;color:#FFF;}.dhx_cal_container{background-color:#C2D5FC;font-family:Tahoma;font-size:8pt;position:relative;overflow:hidden;}.dhx_cal_container div{-moz-user-select:none;-moz-user-select:-moz-none;}.dhx_cal_navline{height:20px;position:absolute;z-index:3;width:750px;color:#2F3A48;}.dhx_cal_navline div{position:absolute;top:2px;white-space:nowrap;}.dhx_cal_navline .dhx_cal_date{font-weight:600;left:210px;padding-top:1px;}.dhx_cal_button .dhx_left_bg{width:1px;overflow:hidden;height:17px;z-index:20;top:0;}.dhx_cal_prev_button{background-image:url(imgs/buttons.png);background-position:0 0;width:29px;height:17px;left:50px;cursor:pointer;}.dhx_cal_next_button{background-image:url(imgs/buttons.png);background-position:-30px 0;width:29px;height:17px;left:80px;cursor:pointer;}.dhx_cal_today_button{background-image:url(imgs/buttons.png);background-position:-60px 0;width:75px;height:17px;left:112px;cursor:pointer;text-align:center;text-decoration:underline;}.dhx_cal_tab{width:59px;height:19px;text-align:center;text-decoration:underline;padding-top:2px;cursor:pointer;background-color:#D8E1EA;-webkit-border-top-left-radius:4px;-webkit-border-top-right-radius:4px;-moz-border-radius-topleft:4px;-moz-border-radius-topright:4px;border-top-left-radius:4px;border-top-right-radius:4px;}.dhx_cal_tab.active{text-decoration:none;cursor:default;font-weight:bold;border:1px dotted #586A7E;border-bottom:0;background-color:#C2D5FC;}.dhx_cal_header{position:absolute;left:10px;top:23px;width:750px;border-top:1px dotted #8894A3;border-right:1px dotted #8894A3;z-index:2;overflow:hidden;color:#2F3A48;}.dhx_cal_data{border-top:1px dotted #8894A3;position:absolute;top:44px;width:600px;overflow-y:auto;overflow-x:hidden;}.dhx_scale_bar{position:absolute;text-align:center;background-color:#C2D5FC;padding-top:3px;border-left:1px dotted #586A7E;}.dhx_scale_holder{position:absolute;border-right:1px dotted #586A7E;background-image:url(imgs/databg.png);}.dhx_scale_holder_now{position:absolute;border-right:1px dotted #586A7E;background-image:url(imgs/databg_now.png);}.dhx_scale_hour{height:41px;width:50px;border-bottom:1px dotted #8894A3;background-color:#C2D5FC;text-align:center;line-height:40px;color:#586A7E;overflow:hidden;}.dhx_month_head{background-color:#EBEFF4;color:#2F3A48;border-right:1px dotted #586A7E;height:18px;padding-right:5px;padding-top:3px;text-align:right;}.dhx_month_body{border-right:1px dotted #586A7E;border-bottom:1px dotted #586A7E;background-color:#FFF;}.dhx_now .dhx_month_body{background-color:#E2EDFF;}.dhx_after .dhx_month_body,.dhx_before .dhx_month_body{background-color:#ECECEC;}.dhx_after .dhx_month_head,.dhx_before .dhx_month_head{background-color:#E2E3E6;color:#94A6BB;}.dhx_now .dhx_month_head{background-color:#D1DEF4;font-weight:bold;}.dhx_cal_drag{position:absolute;z-index:9999;background-color:#FFE763;border:1px solid #B7A543;opacity:.5;filter:alpha(opacity=50);}.dhx_loading{position:absolute;width:128px;height:15px;background-image:url(imgs/loading.gif);z-index:9999;}.dhx_multi_day_icon,.dhx_multi_day{background-color:#E1E6FF;background-repeat:no-repeat;border-right:1px dotted #8894A3;}.dhx_multi_day{position:absolute;border-top:1px dotted #8894A3;}.dhx_multi_day_icon,.dhx_multi_day_icon_small{background-position:center center;background-color:#E1E6FF;background-repeat:no-repeat;border-bottom:1px dotted #8894A3;border-right:1px dotted #8894A3;}.dhx_multi_day_icon{background-image:url(imgs/clock_big.gif);}.dhx_multi_day_icon_small{background-image:url(imgs/clock_small.gif);}.dhtmlxLayoutPolyContainer_dhx_skyblue .dhx_cal_container{background-color:#d0e5ff;}.dhx_cal_event .dhx_header,.dhx_cal_event .dhx_title,.dhx_cal_event .dhx_body,.dhx_cal_event .dhx_footer{background-color:#FFE763;border:1px solid #B7A543;color:#887A2E;overflow:hidden;width:100%;font-family:Tahoma;font-size:8pt;}.dhx_move_denied .dhx_cal_event .dhx_header,.dhx_move_denied .dhx_cal_event .dhx_title{cursor:default;}.dhx_cal_event .dhx_header{height:1px;margin-left:1px;border-width:1px 1px 0 1px;cursor:pointer;}.dhx_cal_event .dhx_title{height:12px;border-width:0 1px 1px 1px;border-bottom-style:dotted;font-size:7pt;font-weight:bold;text-align:center;background-position:right;background-repeat:no-repeat;cursor:pointer;}.dhx_cal_event .dhx_body,.dhx_cal_event.dhx_cal_select_menu .dhx_body{border-width:0 1px 1px 1px;padding:5px;}.dhx_resize_denied{cursor:default!important;}.dhx_cal_event .dhx_event_resize{cursor:s-resize;}.dhx_cal_event .dhx_footer,.dhx_cal_event .dhx_select_menu_footer{height:1px;margin-left:2px;border-width:0 1px 1px 1px;}.dhx_cal_event_line{background-color:#FFE763;border:1px solid #B7A543;border-radius:3px;font-family:Tahoma;font-size:8pt;height:13px;padding-left:10px;color:#887A2E;cursor:pointer;overflow:hidden;}.dhx_cal_event_clear{font-family:Tahoma;font-size:8pt;height:13px;padding-left:2px;color:#887A2E;white-space:nowrap;overflow:hidden;cursor:pointer;}.dhx_in_move{background-color:#FFFF80;}div.dhx_cal_editor{background-color:#FFE763;border:1px solid #B7A543;border-top-style:dotted;z-index:999;position:absolute;overflow:hidden;}textarea.dhx_cal_editor{width:100%;height:100%;border:0 solid black;margin:none;padding:none;overflow:auto;}div.dhx_menu_head{background-image:url(imgs/controls.gif);background-position:0 -43px;width:10px;height:10px;margin-left:5px;margin-top:1px;border:none;cursor:default;}div.dhx_menu_icon{background-image:url(imgs/controls.gif);width:20px;height:20px;margin-left:-5px;margin-top:0;border:none;cursor:pointer;}div.icon_details{background-position:0 0;}div.icon_edit{background-position:-22px 0;}div.icon_save{background-position:-84px -1px;}div.icon_cancel{background-position:-62px 0;}div.icon_delete{background-position:-42px 0;}.dhx_unselectable,.dhx_unselectable div{-webkit-user-select:none;-moz-user-select:none;-moz-user-select:-moz-none;}.dhx_cal_light{background-color:#FFE763;border-radius:5px;font-family:Tahoma;font-size:8pt;border:1px solid #B7A64B;color:#887A2E;position:absolute;z-index:10001;width:580px;height:300px;box-shadow:5px 5px 5px #888;}.dhx_cal_light_wide{width:650px;}.dhx_mark{position:relative;top:3px;background-image:url('./imgs/controls.gif');background-position:0 -43px;padding-left:10px;}.dhx_ie6 .dhx_mark{background-position:6px -41px;}.dhx_cal_light select{font-family:Tahoma;font-size:8pt;color:#887A2E;padding:2px;margin:0;}.dhx_cal_ltitle{padding:2px 0 2px 5px;overflow:hidden;white-space:nowrap;}.dhx_cal_ltitle span{white-space:nowrap;}.dhx_cal_lsection{background-color:#DBCF8C;color:#FFF4B5;font-weight:bold;padding:5px 0 3px 10px;}.dhx_section_time{background-color:#DBCF8C;white-space:nowrap;}.dhx_cal_lsection .dhx_fullday{float:right;margin-right:5px;color:#887A2E;font-size:12px;font-weight:normal;line-height:20px;vertical-align:top;cursor:pointer;}.dhx_cal_lsection{font-size:18px;font-family:Arial;}.dhx_cal_ltext{padding:2px 0 2px 10px;overflow:hidden;}.dhx_cal_ltext textarea{background-color:#FFF4B5;overflow:auto;border:none;color:#887A2E;height:100%;width:100%;outline:none!important;resize:none;}.dhx_time{font-weight:bold;}.dhx_cal_light .dhx_title{padding-left:10px;}.dhx_cal_larea{border:1px solid #DCC43E;background-color:#FFF4B5;overflow:hidden;margin-left:3px;width:572px;height:1px;}.dhx_btn_set{padding:5px 10px 0 10px;float:left;}.dhx_btn_set div{float:left;height:21px;line-height:21px;vertical-align:middle;cursor:pointer;}.dhx_save_btn{background-image:url('./imgs/controls.gif');background-position:-84px 0;width:21px;}.dhx_cancel_btn{background-image:url('./imgs/controls.gif');background-position:-63px 0;width:20px;}.dhx_delete_btn{background-image:url('./imgs/controls.gif');background-position:-42px 0;width:20px;}.dhx_cal_cover{width:100%;height:100%;position:absolute;z-index:10000;top:0;left:0;background-color:black;opacity:.1;filter:alpha(opacity=10);}.dhx_custom_button{padding:0 3px 0 3px;color:#887A2E;font-family:Tahoma;font-size:8pt;background-color:#FFE763;font-weight:normal;margin-right:5px;margin-top:0;cursor:pointer;}.dhx_custom_button div{cursor:pointer;float:left;height:21px;line-height:21px;vertical-align:middle;}.dhx_cal_light_wide .dhx_cal_larea{border-top-width:0;}.dhx_cal_light_wide .dhx_cal_lsection{border:0;float:left;text-align:right;width:100px;height:20px;font-size:16px;padding:5px 0 0 10px;}.dhx_cal_light_wide .dhx_wrap_section{border-top:1px solid #DBCF8C;position:relative;background-color:#DBCF8C;overflow:hidden;}.dhx_cal_light_wide .dhx_section_time{padding-top:2px!important;height:20px!important;}.dhx_section_time{text-align:center;}.dhx_cal_light_wide .dhx_cal_larea{width:730px;}.dhx_cal_light_wide{width:738px;}.dhx_cal_light_wide .dhx_section_time{background:transparent;}.dhx_cal_light_wide .dhx_cal_checkbox label{padding-left:0;}.dhx_cal_wide_checkbox input{margin-top:8px;margin-left:14px;}.dhx_cal_light input{font-family:Tahoma;font-size:8pt;color:#887A2E;}.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday{float:none;margin-right:0;color:#FFF4B5;font-weight:bold;font-size:16px;font-family:Arial;cursor:pointer;}.dhx_custom_button{float:right;height:21px;width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;}.dhx_cal_light_wide .dhx_custom_button{position:absolute;top:0;right:0;margin-top:2px;}.dhx_cal_light_wide .dhx_repeat_right{margin-right:55px;}.dhx_minical_popup{position:absolute;z-index:10100;width:251px;height:175px;}.dhx_scale_bar_header{position:absolute;border-bottom:1px dotted #8894A3;width:100%;}.dhx_expand_icon{position:absolute;top:0;right:0;background-image:url(./imgs/collapse_expand_icon.gif);width:18px;height:18px;cursor:pointer;background-position:0 18px;z-index:16;}.dhx_scheduler_agenda .dhx_cal_data{background-image:url(./imgs/databg.png);}.dhx_agenda_area{width:100%;overflow-y:auto;background-image:url(./imgs/databg.png);}.dhx_agenda_line{height:21px;clear:both;overflow:hidden;}.dhx_agenda_line div{float:left;width:188px;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_agenda_area .dhx_agenda_line div{border-right:0 dotted #8894A3;}.dhx_v_border{position:absolute;left:187px;top:0;border-right:1px dotted #8894A3;width:1px;height:100%;}.dhx_agenda_line .dhx_event_icon{width:20px;border-width:0;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_agenda_line span{padding-left:5px;line-height:21px;}.dhx_year_body{border-left:1px dotted #586A7E;}.dhx_year_week{position:relative;}.dhx_scale_bar_last{border-right:1px dotted #586A7E;}.dhx_year_month{height:18px;padding-top:3px;border:1px dotted #586A7E;text-align:center;vertical-align:middle;}.dhx_year_body .dhx_before .dhx_month_head,.dhx_year_body .dhx_after .dhx_month_head,.dhx_year_body .dhx_before .dhx_month_head a,.dhx_year_body .dhx_after .dhx_month_head a{color:#E2E3E6!important;}.dhx_year_body .dhx_month_body{height:0;overflow:hidden;}.dhx_month_head.dhx_year_event{background-color:#FFE763;}.dhx_year_body .dhx_before .dhx_month_head,.dhx_year_body .dhx_after .dhx_month_head{cursor:default;}.dhx_tooltip{border:1px solid #BBB;background-image:url(./imgs/databg.png);position:absolute;z-index:9998;width:300px;height:auto;font-family:Tahoma;font-size:8pt;overflow:hidden;}.dhx_tooltip_line{line-height:20px;height:20px;overflow:hidden;}.dhx_tooltip_line .dhx_event_icon{width:20px;height:20px;padding-right:10px;float:left;border-width:0;position:relative;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_tooltip_date{float:left;width:auto;padding-left:5px;text-align:center;}.dhx_text_disabled{color:#887A2E;font-family:Tahoma;font-size:8pt;}.dhx_mini_calendar{-moz-box-shadow:5px 5px 5px #888;-khtml-box-shadow:5px 5px 5px #888;}.dhx_mini_calendar .dhx_month_head{cursor:pointer;}.dhx_mini_calendar .dhx_calendar_click{background-color:#C2D5FC;}.dhx_cal_navline div.dhx_minical_icon{width:18px;height:18px;left:190px;top:1px;cursor:pointer;background-image:url(./imgs/calendar.gif);}.dhx_matrix_scell{height:100%;}.dhx_matrix_cell,.dhx_matrix_scell{overflow:hidden;text-align:center;vertical-align:middle;border-bottom:1px dotted #8894A3;border-right:1px dotted #8894A3;}.dhx_matrix_cell{background-color:white;}.dhx_matrix_line{overflow:hidden;}.dhx_matrix_cell div,.dhx_matrix_scell div{overflow:hidden;text-align:center;height:auto;}.dhx_cal_lsection .dhx_readonly{font-size:9pt;font-size:8pt;padding:2px;color:#887A2E;}.dhx_cal_event_line .dhx_event_resize{cursor:w-resize;background:url(./imgs/resize_dots.png) repeat-y;position:absolute;top:0;width:4px;}.dhx_event_resize_start{left:0;}.dhx_event_resize_end{right:0;}.dhx_matrix_scell.folder,.dhx_data_table.folder .dhx_matrix_cell{background-color:#969394;cursor:pointer;}.dhx_matrix_scell .dhx_scell_level0{padding-left:5px;}.dhx_matrix_scell .dhx_scell_level1{padding-left:20px;}.dhx_matrix_scell .dhx_scell_level2{padding-left:35px;}.dhx_matrix_scell .dhx_scell_level3{padding-left:50px;}.dhx_matrix_scell .dhx_scell_level4{padding-left:65px;}.dhx_matrix_scell.folder{font-weight:bold;text-align:left;}.dhx_matrix_scell.folder .dhx_scell_expand{float:left;width:10px;padding-right:3px;}.dhx_matrix_scell.folder .dhx_scell_name{float:left;width:auto;}.dhx_matrix_scell.item .dhx_scell_name{padding-left:15px;text-align:left;}.dhx_data_table.folder .dhx_matrix_cell{border-right:0;}.dhx_section_timeline{overflow:hidden;padding:4px 0 2px 10px;}.dhx_section_timeline select{width:552px;}.dhx_map_area{width:100%;height:100%;overflow-y:auto;overflow-x:hidden;background-image:url(./imgs/databg.png);}.dhx_map_line .dhx_event_icon{width:20px;border-width:0;background:url(./imgs/icon.png) no-repeat;background-position:5px 4px;cursor:pointer;}.dhx_map_line{height:21px;clear:both;overflow:hidden;}.dhx_map{position:absolute;}.dhx_map_line div{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .headline_description{float:left;border-right:1px dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .dhx_map_description{float:left;border-right:0 dotted #8894A3;text-align:center;line-height:21px;overflow:hidden;}.dhx_map_line .headline_date,.dhx_map_line .headline_description{border-left:0;}.dhx_map_line .line_description{float:left;border-right:1px dotted #8894A3;text-align:left;padding-left:5px;line-height:21px;overflow:hidden;}.dhx_map_line.highlight{background-color:#C4C5CC;}.dhx_map_area .dhx_map_line div{border-right:0 dotted #8894A3;}.dhtmlXTooltip.tooltip{-moz-box-shadow:3px 3px 3px #888;-webkit-box-shadow:3px 3px 3px #888;-o-box-shadow:3px 3px 3px #888;box-shadow:3px 3px 3px #888;filter:progid:DXImageTransform.Microsoft.Shadow(color='#888888',Direction=135,Strength=5);background-color:white;border-left:1px dotted #887A2E;border-top:1px dotted #887A2E;color:#887A2E;cursor:default;padding:10px;position:absolute;z-index:500;}.dhx_cal_checkbox label{padding-left:5px;}.dhx_cal_light .radio{padding:2px 0 2px 10px;}.dhx_cal_light .radio input,.dhx_cal_light .radio label{line-height:15px;}.dhx_cal_light .radio input{vertical-align:middle;margin:0;padding:0;}.dhx_cal_light .radio label{vertical-align:middle;padding-right:10px;}.dhx_cal_light .combo{padding:4px;}.dhx_cal_light_wide .dhx_combo_box{width:608px!important;left:10px;}.dhx_wa_column{float:left;}.dhx_wa_column_last .dhx_wa_day_cont{border-left:1px dotted #8894A3;}.dhx_wa_scale_bar{font-family:Tahoma;padding-left:10px;font-size:11px;border-top:1px dotted #8894A3;border-bottom:1px dotted #8894A3;}.dhx_wa_day_data{background-color:#FCFEFC;overflow-y:auto;}.dhx_wa_ev_body{border-bottom:1px dotted #789;font-size:12px;padding:5px 0 5px 7px;}.dhx_wa_dnd{font-family:Tahoma;position:absolute;padding-right:7px;color:#887AE2!important;background-color:#FFE763!important;border:1px solid #B7A543;}.dhx_cal_event_selected{background-color:#9cc1db;color:white;}.dhx_second_scale_bar{border-bottom:1px dotted #586A7E;padding-top:2px;}.dhx_cal_header div div{border-left:1px dotted #8894A3;}.dhx_grid_area{width:100%;height:100%;overflow-y:auto;background-color:#FCFEFC;}.dhx_grid_area table{border-collapse:collapse;border-spacing:0;width:100%;table-layout:fixed;}.dhx_grid_area td{table-layout:fixed;text-align:center;}.dhx_grid_line{height:21px;clear:both;overflow:hidden;}.dhx_grid_line div{float:left;cursor:default;padding-top:0;padding-bottom:0;text-align:center;line-height:21px;overflow:hidden;}.dhx_grid_area td,.dhx_grid_line div{padding-left:8px;padding-right:8px;}.dhx_grid_area tr.dhx_grid_event{height:21px;overflow:hidden;margin:0 0 1px 0;}.dhx_grid_area tr.dhx_grid_event td{border-bottom:1px solid #ECEEF4;}.dhx_grid_area tr.dhx_grid_event:nth-child(2n+1) td,.dhx_grid_area tr.dhx_grid_event:nth-child(2n) td{border-bottom-width:0;border-bottom-style:none;}.dhx_grid_area tr.dhx_grid_event:nth-child(2n){background-color:#ECEEF4;;}.dhx_grid_area .dhx_grid_dummy{table-layout:auto;margin:0!important;padding:0!important;}.dhx_grid_v_border{position:absolute;border-right:1px solid #A4BED4;width:1px;height:100%;}.dhx_grid_event_selected{background-color:#9cc1db!important;color:white!important;}.dhx_grid_sort_desc .dhx_grid_view_sort{background-position:0 -55px;}.dhx_grid_sort_asc .dhx_grid_view_sort{background-position:0 -66px;}.dhx_grid_view_sort{width:10px;height:10px;position:absolute;border:none!important;top:5px;background-repeat:no-repeat;background-image:url(./imgs/images.png);}.dhx_marked_timespan{position:absolute;width:100%;}.dhx_time_block{position:absolute;width:100%;background:silver;opacity:.4;filter:alpha(opacity=40);z-index:1;}.dhx_time_block_reset{opacity:1;filter:alpha(opacity=100);}.dhx_scheduler_month .dhx_marked_timespan{display:none;}.dhx_mini_calendar .dhx_marked_timespan{display:none;}.dhx_now_time{width:100%;border-bottom:2px dotted red;z-index:1;}.dhx_scheduler_month .dhx_now_time{border-bottom:0;border-left:2px dotted red;}.dhx_matrix_now_time{border-left:2px dotted red;z-index:1;}div.dhx_form_repeat input.radio{margin:-4px 0 0 -4px!ie;}div.dhx_form_repeat input.checkbox{margin:0 0 0 -4px!ie;}.dhx_form_repeat,.dhx_form_repeat input{padding:0;margin:0;padding-left:5px;font-family:Tahoma,Verdana;font-size:11px;line-height:24px;}.dhx_form_repeat{overflow:hidden;height:0;background-color:#FFF4B5;}.dhx_cal_light_wide .dhx_form_repeat{background-color:transparent;}.dhx_repeat_center,.dhx_repeat_left{height:115px;padding:10px 0 10px 10px;float:left;}.dhx_repeat_left{width:95px;}.dhx_repeat_center{width:335px;margin-top:12px;}.dhx_repeat_divider{float:left;height:115px;border-left:1px dotted #DCC43E;width:1px;}.dhx_repeat_right{float:right;height:115px;width:160px;padding:10px 3px 10px 10px;margin-top:7px;}input.dhx_repeat_text{height:16px;width:27px;margin:0 4px 0 4px;line-height:18px;padding:0 0 0 2px;}.dhx_form_repeat select{height:20px;width:87px;padding:0 0 0 2px;margin:0 4px 0 4px;}input.dhx_repeat_date{height:18px;width:80px;padding:0 0 0 2px;margin:0 4px 0 4px;background-repeat:no-repeat;background-position:64px 0;border:1px #7f9db9 solid;line-height:18px;}input.dhx_repeat_radio{margin-right:4px;}input.dhx_repeat_checkbox{margin:4px 4px 0 0;}.dhx_repeat_days td{padding-right:5px;}.dhx_repeat_days label{font-size:10px;}.dhx_custom_button{width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px;}.dhx_custom_button_recurring{background-image:url(./imgs/but_repeat.gif);background-position:-5px 20px;width:20px;margin-right:10px;}.dhx_cal_light_rec{width:640px;}.dhx_cal_light_rec .dhx_cal_larea{width:632px;}.dhx_cal_light_rec.dhx_cal_light_wide{width:816px;}.dhx_cal_light_rec.dhx_cal_light_wide .dhx_cal_larea{width:808px;}.dhx_cal_tab.active{border:none;}.dhx_multi_day{border:none;border-top:1px solid #A4BED4;}.dhx_multi_day_icon,.dhx_multi_day_icon_small{border-right:none;}.dhx_cal_container{background-image:url(imgs_glossy/top-days-bg.png);background-position:0 24px;background-repeat:repeat-x;background-color:#EBEBEB;}.dhx_cal_navline{background-color:#EBEBEB;height:23px!important;}.dhx_cal_prev_button{background-image:url(imgs_glossy/buttons.gif);width:30px;height:20px;}.dhx_cal_next_button{background-image:url(imgs_glossy/buttons.gif);width:30px;height:20px;}.dhx_cal_today_button{padding-top:3px;background-image:url(imgs_glossy/buttons.gif);width:67px;left:110px;text-decoration:none;}.dhx_cal_navline .dhx_cal_date{padding-top:4px;left:230px;}.dhx_cal_tab{background-image:url(imgs_glossy/white_tab.png);width:60px;height:15px;text-decoration:none;padding-top:4px;margin-top:4px;}.dhx_cal_tab.active{background-image:url(imgs_glossy/blue_tab.png);height:18px;width:60px;padding-top:4px;margin-top:2px;}.dhx_cal_data{border-top:1px solid #A4BED4;}.dhx_cal_header{background-image:url(imgs_glossy/top-days-bg.png);background-repeat:repeat-x;border-top:0;border-right:0;}.dhx_scale_bar{background-image:url(imgs_glossy/top-separator.gif);background-position:0 0;background-repeat:no-repeat;background-color:transparent;padding-top:3px;border-left:0;}.dhx_scale_holder{border-right:1px solid #A4BED4;}.dhx_scale_holder_now{border-right:1px solid #A4BED4;}.dhx_scale_hour{background-image:url(imgs_glossy/left-time-bg.png);border-bottom:1px solid #A4BED4;color:#2F3A48;}.dhx_multi_day{background-image:url(imgs_glossy/multi-days-bg.png);background-repeat:repeat;border-bottom:1px solid #A4BED4;border-left:0;}.dhx_multi_day_icon,.dhx_multi_day_icon_small{background-image:url(imgs_glossy/clock_big.png);border-bottom:1px solid #A4BED4;border-left:1px solid #fff;background-color:transparent;background-repeat:no-repeat;}.dhx_multi_day_icon_small{background-image:url(imgs_glossy/clock_small.png);}.dhx_month_head{background-color:#FFF;}.dhx_after .dhx_month_head,.dhx_before .dhx_month_head{background-color:#EFEDE2;}.dhx_now .dhx_month_head{background-color:#E4EFFF;}.dhx_after .dhx_month_body,.dhx_before .dhx_month_body{background-color:#EFEDE2;}.dhx_cal_event div{border:1px solid #FFBD51;background-color:#FFE4AB;color:#000;}.dhx_cal_event_clear{color:#000;}.dhx_cal_event_line{background-image:url(imgs_glossy/event-bg.png);border:1px solid #FFBD51;color:#000;}.dhx_in_move{background-image:url(imgs_glossy/move.png);}.dhx_cal_event .dhx_body{background-color:#FFE4AB;}.dhx_cal_event .dhx_title{background-color:#FFE4AB;}.dhx_cal_light{-moz-box-shadow:5px 5px 5px #888;-khtml-box-shadow:5px 5px 5px #888;background-color:#EBEBEB;border:2px solid #A4BED4;color:#000;}.dhx_cal_larea{border:1px solid #A4BED4;border-width:0 1px 1px;background-color:#FFF;}.dhx_cal_lsection{background-image:url(imgs_glossy/lightbox.png);font-size:14px;padding:5px 0 5px 10px;color:#000;}.dhx_cal_light_wide .dhx_cal_lsection{background-image:url(imgs_glossy/multi-days-bg.png);}.dhx_cal_ltext textarea{background-color:#fff;color:#000;}.dhx_cal_light select,.dhx_cal_light input{color:#000;}.dhx_save_btn{background-image:url(imgs_glossy/controlls5.png);}.dhx_cancel_btn{background-image:url(imgs_glossy/controlls5.png);}.dhx_delete_btn{background-image:url(imgs_glossy/controlls5.png);}div.dhx_menu_head{background-image:url(imgs_glossy/controlls5.png);border:1px solid #FFE4AB;}div.dhx_menu_icon{background-image:url(imgs_glossy/controlls5.png);border:medium none;}.dhx_section_time{height:20px!important;padding:7px 0!important;text-align:center;background:white;}div.dhx_cal_editor{background-color:#FFE4AB;}.dhx_year_month{background-image:url(imgs_glossy/top-days-bg.png);border:0;}.dhx_year_week{background-image:url(imgs_glossy/top-days-bg.png);}.dhx_month_head{border-right:1px solid #A4BED4;}.dhx_month_body,.dhx_matrix_cell,.dhx_matrix_scell{border-right:1px solid #A4BED4;border-bottom:1px solid #A4BED4;}.dhx_year_body{border-left:1px solid #A4BED4;}.dhx_scale_bar_last{border-right:none;}.dhx_month_head.dhx_year_event{background-color:#FFE4AB;}.dhx_year_body .dhx_before .dhx_month_head,.dhx_year_body .dhx_after .dhx_month_head,.dhx_year_body .dhx_before .dhx_month_head a,.dhx_year_body .dhx_after .dhx_month_head a{color:#EFEDE2!important;}.dhx_cal_lsection .dhx_readonly{color:#000;}.dhx_tooltip{-moz-box-shadow:2px 2px 2px #888;-khtml-box-shadow:2px 2px 2px #888;}.dhx_custom_button{margin-top:-2px;}.dhx_cal_lsection .dhx_fullday{color:#000;}.dhx_cal_lsection.dhx_cal_checkbox{height:16px;line-height:18px;}.dhx_cal_light_wide .dhx_cal_lsection.dhx_cal_checkbox{height:20px;}.dhx_cal_checkbox label{vertical-align:top;}.dhx_cal_light_wide .dhx_cal_lsection{color:black;}.dhx_cal_light_wide .dhx_wrap_section{border-top:1px solid #A4BED4;background-image:url(imgs_glossy/multi-days-bg.png);}.dhx_cal_light_wide .dhx_cal_ltext{border-left:1px solid #A4BED4;}.dhx_cal_light_wide .dhx_cal_ltext{background-color:white;}.dhx_custom_button{background:white;color:black;}.dhx_form_repeat{background:white;}.dhx_repeat_divider{border-left:1px solid #A4BED4;}.dhx_cal_header.dhx_second_cal_header{background-image:url("imgs_glossy/second-top-days-bg.png");padding-right:20px;}.dhx_cal_header div div{border-left:0;}.dhx_scale_bar{padding-top:4px;}.dhx_second_scale_bar{border-bottom:0;padding-top:4px;}.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday,.dhx_cal_lsection .dhx_fullday{color:#000;font-size:14px;}.dhx_cal_light_wide .dhx_cal_lsection{font-size:14px;padding-right:10px;} \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/but_repeat.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/but_repeat.gif deleted file mode 100644 index dd6595e5d9ef43bd03c486ff87079f398267e085..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1149 zcmZ?wbhEHblw#0e_|Cu(?klqTfBEyoYklCmVoqenVS|Pe!)>e59cFWsU9>AW zZP8U{yyh;8RlNr303RUE2#_d#_^)>0%x$Xs10t-?UO*$CP9jc$w;rijn>#HZ* ziuOA9HrlOUoN#1EY26vWko7W`kGGuIQyH^LXXo0ihgT<^dANV+jn?#K4u`fCUwwP* z-M5!ZXNH}5yl>s2_-m)ym(2>l`}us|%dq{M3y$q7@2KifR>Y}Mw6)3c8m-~M#w=7-a1 z2lYB02kd$=@8hpG|NsAI7zM*O1QdU=FfuSCFzA512+9-e9RC>(a>#gWSa7hJLs%<@ z!>y62jYpg%f??u==`spD872Y>4UJt1VGkBu+W4e}lTpRt$^pd#JWK}3LKB3T9*Ht> z{5N>MH5zv}sFyVmL)JDz@z9|n~A2ze=aoMTfc#?RCTa!a?fk(jUuvRNSo+m#7 zABgF&Eo)ezv2bzAcA+K}&I`<}M+6xCroGv*gqxjLp!QVD$^#6OloTdwc^t4{g{)f>K6CCawk>Cl{7Cw?#BK3K$BV zSs5kRIOOdXxUhBTvni|)Xl*QJN-QjLPzCavSUfPI0sfDy@jpkeH{?dy!N3 zhQbX7(}VJFMYr8B{IE5rQKCY`;NikW%s2R0UNrDKaC~s&6i8KY$lHF<>prLT)%o*dfGgj$`HW)Az6cjY9_^@!{!iEJG{{Q%I;E^z4 z!G;SD{sW1G2@e`(9Qfam@FBrq!iozH0SOHY9(?%lzo28ogbn{4Djqzr5a{jgov`A= zh65M&@85s>_U->O8UiXVBt#?>EcoD1aG_wvg9k7EH#9UXSaD#%jt2)U1ZK{h8PM>c zVZn$0|NmdSa?Qab;lPOt4J-aPEI9Dt$A5={2S5dnpFCc$;lTAP*C%YaV3lz(dCI*9 z4g$qf)-Kp_;lhmv7j9e#Xtg?cw=gYN-LX^L zkc~}ezmnDRmHU*|uGiL?1^(|-fE8lblbd4od4L*O>-Nnixo_MTBMAhPt^YXsC%yN=J0u$6;9q86(1O;^YnlA`!OMrv9(1`BVyeag@*_CuyPgcJ8^Pz`Z*T|W<~~U06^u> AiU0rr diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/clock_big.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/clock_big.gif deleted file mode 100644 index 61f7dc2e5ac32fc064ffb4e231f344df03d07baf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1321 zcmeH``!m}I0KmVIhu6+xXQh>06V%F?qh)EkZW3)hs&#ZarWvxNoo;QVXEiO_5K$#2 z#3Qb$#AB(~2ueM&NkRnmh*v}-2#b)=1sRIUu7ARQ-{<$wFQ2=Qf1ux~)A*ynQDB=1 z7>!1;SX|9t2@eksi-{YQYbGWpD%+Ooy0mdgS<1zCJfSY5{B?FQxA1qBY<91EWb?-a zY8rbwzjh9PJ6SZWBoGLOt+$f#1qQo*dVaraXydP?75Us=W`#mAuhFjQXBQ7zgwj7H zW17`X{rYA`ei^f}d1T@>wM?E_P*GGfRK%{yd9KW5)d%C^N}J`67;V{XQ8rguRaM1p z=*(bL)_3$%*i-#7jbe7Os&koL+aZu@cm^7wXN@X-Xe8PN?$>z29$mX=EIjrQ&;<*L&i(WN_EhjyG@vvlM zVrG|C$maLSMy7XEnzc#gZu(Qn+TR;gmL!W=PhrdQN*g*QvP4=#R@q>yX!J>8Wo_F) zgFwd@_T@dRlT5CZ)^lYoT|sVFFT;WtZ~AVk=f!jOFMXfDCf7J;?tQP z5%C`}U?5*ByZ}z^p*jFrIHdJ;4H9K?#)Xs)cZ{N1@4aZ2nl#MPhsy56Hr+^JoodF;gB)*blVN`(U9opG zg#^RL$q+kY!O!_tBK$bY7vcjlyJm!XVe*uEfFDFU_%yX* zBpYUP0@)s#hIx?ggB9V?0Qis;U5pAiJBn~N^+G`r2k&g>aq$78=Sj?4a6hoO*D{Cv z^`sPI*MctxtcXOw_a`=p`S@ET5d*XO*gT#5!C_1p3doCqUVxp5`J8S`X!C$rpo6I* zxI0Y+y%=3Z&#dh{Q3Xy-~T6X|NCUj z-+AKAj$^O4oc%v(-P4P=e*FLcf6~g^o6r1jUwo^5;nm*dx0CC)-F@*tt7XTEoe$67 z_;%s`|Hp6s*U!GR{=kbx`@T+Hb}p-J@5KlIx1IZ+(X#u*#rLa^|4XUcG-vJAQ(#*m&j9|EU{aOxyJG*p2@MJ%=AY`_F&_DE?$& zWMD97&;iMV{KUYv@WAW>k3F_F6aCa5Rf^0Hc(f>KmxF?MaH`;2K1nUfB%f(3CGM?g zQ?lBT⋙T<>He0Gy4HbLMc( zohvreNymVB`EtG$%mzA(%{BB`HgDnEqNlN5Q-YUm-~N5P5}NDHbrpp;Pn{N0)II8? euP&@CBcm*=u7ANSnAsUe&p%Yv$JM$_W8+`K+vL zQy1@KV`DF|zZPaRp-Va7Es`fWH{!n_taqfi)L%}l+!NRT_gf~c5vTfPAO=yP@zY`zB-u?Ry@*U>$I(GcT$y28*)fmoQIDhHFx$tYDF7dZ+ zoj;d(|GrD{K0OuZ-`~Uy| diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/controls.gif deleted file mode 100644 index 9732e2da748c79c35fc5569d09df73dec52d741c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2496 zcmdVZ`y-PJ1Hkd;nM*U&Ow;5xrKPNM)T~Idx!>}-blloGZ4puA7Q>vjxhwaQJ9Ai) zG532W(aLxy3Q49zB&XN4aMJU>=g)XQf5G>cueGg}p%Kj=AOhcnz|??iQVe#i%MjXp z1}*x}zOaNgd;b3O^2)?TXuTQw6tpOIfR>Xsr#+$1v0*eIFIj(i%t_RwKPR%O&N1re z9fMZ64FxKBED%~LU(}z-i3OqW%h3OP8-~{T&`Qy_nMf9MS~g4qg6SE<>>@rvt4E8 z>A4zUu*+|5cK~0}uML^qcT1(aD$MagsjdoWm9x%b( zVdSg6ps|6NlDns7hc1^S!aj`tUU3&*atGH}M|QQ9N{f=KNJBMNdhxmbpJzD3Z6Jo^!O|?Nmg*bTg;w`in4X7+x!F23xoUwFFe_GJdL*YXNj2IJ?5e;fMI9O% z;D`jiHDy<7@{Tuhonx-S8|vD+)0Cd1?_HhzB|aFOdEuBGiMf6I_R1VL(g*CW4@->J ze!{<6lY6AD%>Gr6mqch$kZPHme1=zI>+9>A5)P(D?#s{5ug?3|qkCo|K}1@NIyB<@ zr|4pS8lkOBy`6XS!c}_;h#K$e`k4Zo~64z7HhBII-Wl8}e(ifro3 z`|n@~0pT8I?B^&o;*U=jEViPWQRq95PtwVirb_a&0lGBmg~SY)hREeOr|6XLhWf}W zn?WTL-2ePP+R!opOXVhX(J7)?kcEiZq-fs0R(@PUaZF$Mr#Sd+1f%^`+BeQ<=idBWJ^p zEt5K$KJ7&$NF-!Axl=kp^fsmJ;FlPswy*_F!hD&c56G6+(gai&5=zK}UUc%^EQ6Cv z&z#KdLtT7UkQXtfU_> zNG+S~*N`u+?^n~&slv+Lyb&@$HUg~GLxfEa#W6_+6>Q+BWPuj@{Y1POLbC#pF*l)O z`(*JgZ7c=N4S;5jqip5xRSl@R{QEXbC`O|%imhcdDfLK2GVYO2rh$5RT)Z+O$srA% z66(#^8#tkzv6GPOq;^bNI|1hsKbdG|+9Zal;`y1+3Vo`!`^b(47vGT^)s^Jak%1mF zu_lNzwpmmrydNiIu*_u0b6H6BpKb_bHR*=bV`^$`z;iN*q z#w-beg4Z5?yv^5cH~%8O`PFZF#QIXw?yX6~(p}=H9K$TzR`=1fZ2M9jK?IDxz>9?S zNJH7*rlajMTO~14C8O`@>lCpZ$Crgd{_tfcxK(edz)!N=8Djq?-3uQ^~pDD%7 zt+g+B$#Ku_ffc2%FL>WacgS3OG~Y2;+KL|k5;mRgAWN6IIgZfLFYa9x9@R_dR4%f!eF ztWK|$!?`Pf!rO@fq6+W}1?H>~Vr6|gy~@IA@sESs9?bnbp(UQ}yl+C+>J-8y6Njl7 z+`+I8Et{ohH2qQP^19N*F*}`vLS@y8txvkaZ0)^JikOr}xp!2UuYy3@K_BE^kmM>? zStzMsttmSVxxB6;nx%A*@)q@gic-!O%?)~U{VxPYyP`gfv9;c1`^yJEg|)mG3JN6v z@&eo$PYGxg-B|d6BEW%_TIgUxal)E_qf(}8H9uQyIEAawv4oB(Ua@nX^6`>pB3T|P z1~6C}Nt!BQp0^=$kZHPRA+jU1>Ht&Zg(|d*m>odA=ho7|HdC(F`)&KU$J0Y^Y(f$N zELKvfpLWcllL>Hpn-K96Oozw-R|~AbvxtIr2ux-A|6cnoYxa=9JTodBqyM7F_3vpj$0d@4mYEXvx?18-fb6 z2hSWTT9G;I=!}FLj)zMM9}MsxT# kS)Gq(ey|_(Dh|N$ZnKC4C&P}}A%3#8!v~bN4i+%}FOLpJjQ{`u diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg.png deleted file mode 100644 index cbe2e940f646f97e094f7ac98a9fe59c6669fd3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^j6kf#$P6SsHY~OWQfvV}A+B%Uefjh6&yCkfCx9Yi so-U3d6>+@>89|C26fXOgJ3idUI`tD*W2f7$UqCSiPgg&ebxsLQ0L$1NlmGw# diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg_now.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/databg_now.png deleted file mode 100644 index 8cb8a8106ad82589a65e7d179c0179761851acf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^j6kf#$P6SsHY~OWQfvV}A+C3xefjh6&zpyOOMoI` so-U3d6>+@>89|C26fXOgJ3idUI`tD*W2f7$UqCSiPgg&ebxsLQ0JuUOE&u=k diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/icon.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/icon.png deleted file mode 100644 index 5e13a09f6f63027579d34b9fd548dae4d3169562..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^{2(?5GmvyVaHJSWIR*HHxTaSwO|M**QMoj;W?5G4 zik$k@`OWJJ+cy<=ZY}BBR@$?pymLc&|E`J&dnzaGt)I59VbYeixrf_l?VGvm$o>SE*JaxG$M9=w_iB5*Xc}O>LTA|)irJt`H!jG zSRJx#<~HwjvYJURYfsDcHY&{exZ(Nw-b~nBPQk(@Ik;OpT1B~5HX4^3^FiHjZ zgt!6)5)%{u|NoCkLIkmj1Eo?@QZS`5GBV&sWo2an*-1%BzkmPE&d&b(_b-tB`SWL> zU}|bAkPQS+o;(2>^5x4Hh)N(EXaZ1UPEJmFd3kMZZC_tse}DhHdGmJc*s*WlzKa(x zUb=MY;lqcIA3uKi@+DB0NA13ZzEdSYPzr=4r9cu0DoRTi-mIvosI084udi=f_iW1c z=krfJU$tu0=F=~Co`19N((4;PnB?v55NTxQNci?rb*blNp}9L33Oki3T%RUmz3I)V zEjoFRL^E`olLC0U91T|lM*fN4W4x|=w^Xgt7wcKfbA%j&n~ha7j(uQjOD*l6n|SyC zopT#Zt#;-95&PhM@IA+Vqbu_}SUq-GGJEh}Tb2^EOPp;aU@ zEm_05<{TAG&#zbV|IGP+LD-X*k2IC8_SqkM8rJ0Qxc>JXcCI-rDeo@DdM4g$vyO_N zWc;#thgRQ)tn6nIA8zbhHKX>=4AVJl&aRR0)A*d@s%Empe(}v3@rxNIAyZ9$2d#Lr z_x`rW-^DlFeK*}gGJDgsA69erUQ@91UUD(p@VW8L)|=}TjoK!g^340OVRP2^=9%*) zo951czusTl;_4(x{jdq1PK`mYCaqdOYssnEI!j|FhlHIGI+ZBxvXOz5mxuuAMWm3;;j? za{$1`W{CCHKeepSG1muPZmt1;g!YEYZQ}>`uNd7m{^^V^aLeYV_PWLuS6fRrTN^D; zd$(6wmJXI)PR^D#XYAkDIRms;w(eBkJay{p^{d4ahOC7h>j}W4MdA!TRX4TF37~VV5toY{8&jyL>s7Khd zXWlB|uVA z!Ra58vf^`+(^7I{3o`)esQhd!x*{*LpsI*aQid<5R?={o(i$e4!l~smcy-luVk5ah z$SUq2bvAdmwQyVOSt8khbV$%QGB`Ti-=mO^H%TVPraz+Dbd6=xX&U^RpXar9X~l3JCkRd2i=$ z=N)M8>FWN*B`Q4nTSP#7P)L|Z1Uys&l#vPA1I$4KvvYIu3yN|}(4~ctf^u+WUPUFg z8dr(RB-Ij%85mX>rwV|lQL~+v~d(}VP_k@B}+ac>*^mJ=onY@ z_EB3V#2;tICYKf@i(lqy)+l4|6y>nmpwD2LQkb?x4+16|^)6Ou8;7fb%xpkfTekdL zDy0{WIb^mgt1j>k?h8sYk55iTKjN5T6Qk!X%9lQQ`K+%%W#w#@IjgPa^*4_Ef-p_L zuPohL)`Wo+yBWW|@3J>6-+_H$!KHNMaa8pZ&I`w%?8ngU-MwAmfu24Zettn= z!O|!n9XcHgj3Mf-rCtwCvO;R8g6Nmc1d_evM~jHcDlcBU~y=9 zWEC^fBc5*uX$tPZjC_{*_bw;`It{eg*$E;kmnkj+|U5wL& zZffd(tLBf)*;I|t?XW^+p%%qJ)wGCozc zN>d}VXb`847<5?-$2BhTWGk-ocj@6p4g)jH+GJG|EK;J5RixGhE5I(ChDWB|`ZvUNdi z()1;HfSK=AS3`Fnn=rcwPdF^tImj>8KR)DLly_)o;M3$RRE~p5N_u`uW-c0$U4lIT zs;mM*aaGj>JcLXE1L+JPl*wRoSP;ITme1ofGMgDSBti$SizsZ6G)Y_fxN>^y&|n=v z)J`RfE2n56dKlo}Nc1IIPDZq;?krvJXN`|wl2^mC@iM5!@{cNcaca!Gfj zjf6aDP4_-{=;odsaYHwd%KOa>i>h=)2}k>$1(?L5fBt6Qth~Nx{_^eU^N~9LjbDi` zVyS1lhn0DJRx0|1j%CNt z;E_NYbsYTuO2cnQ9!7Umk*7}96gr{CtseW0uMuc({eE|JJ?QnyIyAyE=zSnEATBss zDbhCCGb%PA-9ID#aEkpqkK8byMBgjUG1+j`VNewg1jXYB#A*nI3Z_AUEH;qIVe$Av z&Ss$!K=>?14TVhX!iz~Qtxa61NM1kKINS_w1-8>WJG!TPW_!nEivCXnD?@7|Uq%7# zl|bE!Y^ul1x?JVe9XT;{srEb58#6DABY+)7Zt9h%k6cGUhqd>3$Jy{gR6pep5nG@C z8lZ9HH_b6eR7k3h<6>L3s{(;K?OoNI`rip+)U=inEcLVjES!~*Cr1NuGVnQ+EaC#C?f=#wC&Ns?Zwmg z7E(`1_bM(ry9EXMyDNF!_xAO%wu=b~Hj1}!Nel>!MB0Yir#ZysIHBK|WEDmfqxAEV z%i!f&ARHb9t;Q2c1PHYTTuUKAfm|Mt!{-V`_54O&GnYxDvZ}kt9c)QAL{!(;-zper z7-<^iwKF=UJ(In&viTW6|1fxY=<`SUYJc~ZT{oJa(JaKfR_i>Sds%*fCSyahyRu90 zeW%Uxy6);(@!g=g7c{?f)!;=h-aTQsJf16vS6zy8TR|TEDe}|L{q>}|%-b>AXT4N? zEQ@~4Y1;i4I4*wBis-o!VwZ{@+-6l?$Hdi}CSC1AiWe_3zdycpHH4V~if5lq{V`u} z)ooYY^+AyaCoQj8!>bUN#2?Yor^=MDJ z-}zZ|Ao8L|#LJNI)X0Q4?=xJpVy-5oeMoljvP?&n#zqDFS;?ECW#InIkxnJEh;7U+ zwz#vl{SS`Ka&W(3K-4Pjp6HqC1&q(hW-5n9M+V25KJ%96l{#~~V*1a+XGb#G{O0Ed z0L50dM6XyYR-np(5jg42ndf@ZYSXWw_T~F7#~-_OVnQ&R%lG@+hW*u|9IcwP?ar_Y zllh=u{Wbh}s;j5|Q-9qj{O82A^ZVkY5rpzFN}&4Z2tB=rznKoI1tU*(9y#u|EAXUj zQjzdO`uT#!ZTTAT8(q7ow{AKbxHxP0#q$U9C%QXekHql?&rbU*me)Rf@c=IS8+qUM z2@bgzY8L47TIcN#?_CjLi4pK5567o*v5|gPKO`rh!&6gU1r(>FbU@g05VWGa3Rejs z5W(bX9Ib+mhX6TTAe6@y2>I;#O{Pq28wJozZEdNQFdBt*{e3(+ue+;9-1|{B!J2B9 zPLGZQ>KnjI!=gd1VqbDZ&T{!>_)K*hH{^LPI$DQ*(T8A|qlj%ih zK|-R=xmwYp4sz`uq{ctJ;Hd%I9c8d<1eE%d1=fjl2T1z&6WiCm`%iX(2`|!m!eJ#9 zapmfI*0x3--$?Wc3S_59+YN*;%sdsoX7J(Cp*?1&c9xwkNbJn;AwMx8=|evVJFHbO zt*E4aPyH$E^47|qhZ#^OT0;D>@p%s=4 z-#NzKBj;XN{v&cj^F+HKcK@@haHvkJ^@rO)q32O)QjJSh{!M`PxP3~>Uy3(^~ z@sfN89m^p#s@hQU{A)#xupr@3M2OzEp4SeX5?k-dyis)J_zq>{uf=5l86CM?25s~;9 z{_-E7>>Lmjos*ZJ3n?lFV+!-j(Uk=yMYwDzkU|BLYbe<23RV>dUq;}OM5O?xfZfam z(-*uuPgg)*6^6g_UGatCWjc-K2{h$!!``~ayT$mNq4V0D+f@Y+nvN9p)TyTC) zR&fR`2uVUjV%o;(hh*3=<@BuAtta?r-ucNi6T_}+? zHTMq6q;-9Yk%o_5qYZNM(AeDg!sLW_co9FdjN9M>te~S)vf7<9z4kLaCpkG}pZbZY pWf!ZHp$(dbz}SD8G>Wgb=uaa1zqEv)*f`MtlO;U=)dv3&{{wX{9B%*s diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/resize_dots.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs/resize_dots.png deleted file mode 100644 index 011bfafbe12b7ba0e8d525e48147943ef1500206..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^EI`c6!3HF^d|7u4NJ)6QIEHXUCnr4cKjU&x;nDxk fDQp7Av=|uDjQHR7uZU>}s$uYS^>bP0l+XkK{Ztlh diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/arrow_left.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/arrow_left.png deleted file mode 100644 index f0fc5d0e3ba5584c8e042b3dffe22e10fdffc11c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^+(693!3HF^taP6Tq$)gJ978lFCja>V-=5iyhvkjK z8}1`}T0~|U8X8_|*@UwlN~cW!-$B8yGxY{an^LB{Ts5*~dA^ diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/arrow_right.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/arrow_right.png deleted file mode 100644 index 14167035058aa1f5026e8111d955aef84f2aa1d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^+(693!3HF^taP6Tr1Cvo978lFCMP5$JYY@YS4jK+ z|Gz!69S;+ej}MQnLkxe)Y{AtMJ&k{C{QTG~7l|A;FgA8J3Fw=zaWvr0sY8bzFohiU z>PeDVmzbJrpb%vkFjrCW=v#;M9l|ASSDKkxY$8}hCNK9|(y-|E^cgSM7*aSkMr>;h RO$1ua;OXk;vd$@?2>|-HH&Flp diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/but_repeat.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/but_repeat.gif deleted file mode 100644 index 93066671bd916122294b9bafd3fb0fa062eeca5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1472 zcmZ?wbhEHblw#0exT?tT^XJcv8#k_Ay?V*wMK`WrTeWiewk?~E9zOKx)2Ep;XRKel zX4b4(`}glXa^&!vH*YqsU$<}HzUR-Lo<4p0@}-OS?%n(K>({(_^S*xlx@^hfqeqYK z+q37^t()`b&wKm!?Y+Bqr%#{0asAr=|Nk@43@HBRj_?goa7ipl1kyJ46$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J=B$SufC zElE_U$j!+swyLmIN=(U5O0@#ALBje<3ScEA*|tiKAPEJKozD41sS2ig2D-@xW(Epo zhI)p^Cg$emItoSxh6efuM*4YxcX2i_H!?JIHFPw!FmrJ< zGIldIH+D5KHiPMP$xklLP0cHT=}kfCb;YR{ln`aDv3%K5U{SGf!Tfo1=ggip zbH?;(Q>RRxG;umQ)5GYU2RQuRb@qaS!qdeQDH%TUT#iyR%S+e zT53viQer}UTx?8qRAfYWSZGLaP+)++pRbR%m#2rjo2!enlcR&Zovn?vm8FHbnW>4f z5impP>FQ`}X=3_75)2UOZIupK@yp}<2&s{h22qLV&MO!HTmNHLf=H@Yw$d0Qmudt|wTfzXcY ztQ?jR@x2U=Q?x6@W%<`VJaopPPnt_X&__gGLe8C6*oQ+*MuAPX%!P@&NkJ-XigSj0 zV7R_CV2fu-_3o6 PJHM`8a8SvSfx#L8Aj1`Q diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/calendar.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/calendar.gif deleted file mode 100644 index 8c12c947abc061840e77609603b73982074582c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1018 zcmZ?wbhEHb6lV}+_|Cx4)7A6m-=8J(=B!z@X34T8b7sw%GO1_Dq9tqAty!{Y&YERQ zrc9c$W!)NvQ7{?;!!ZODf3kqRr2`^Cd4iqeI)k``0EdD@11pmtA4|Z81x^esYytua z2NoP*6ju-95eQUfX5(NJ(QtUM*pr3FWfIFthl5O06qFauIcfBSVHS(n29uMUm-|oW z5Rov^D9H$14zON=7IJQ2H|5NM*)0~8jUNdL8?w+BWyp=2F*w*X`?*dM< z6&qdEo@#t`X@@iWGp$=2UT*BVx=41%w69qwESrToY#zM5eQUGmgF5LFM+XLL02DBF A$N&HU diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/clock_big.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/clock_big.gif deleted file mode 100644 index 26b331cf05e6419f9cb1bec5a6dc77ea833490d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1958 zcmbVMX;>3i6rBLFD4^m>-GHxk2i0*_nv#-yXR~V;`q?G zYoImI&+(Az%H_1Qw86nav)P=Qnp#q2zabf0ULKD-?>%%#4im^m{+uRbDF0%*-4a85tWJtFP1KWM_|$kJr}L z*3{G}mC6D|p2=joTvVu1sTvy_3knL#OI1~s<+-`J#mb_q>dHH}zkm4fVNUj!%}x5Q zuC9rRiJPrACMPGeva&7}=0AG$DDUEhg8V#T6d!Iy#z~^rNGud_`VcYs-b)^A%+(yMo6QD;;cnND>FH@HDJj#_(+~u?P0!mC90IesGA{UU-6j`vd6B3L4oCM3L=5~u zbsZiS@EQ2slweY@n1x0N0uM{jU58%|;~kFV(fIgnzVKE#T`m+0Q5hGO3!_9*x}1UM z^09D~4(66^A|9SGkwr4_{+0vSg2}=pC`=)cJa{B338o?h#M8^$+uI!`lMoV-L?$9+ z55$}9Nv4xX@LwMuph@`q=%H-RUszzpz(>erVmgr+6B9#-@g!i9{X~RDqgi5*$sWMM zLwZOgKD`83PY8eNuu@931>Kut-XnDTu(sghV-4 zOhgDIqEKk5YsOkC3q}7<$7>Y`+@>P@ClnN(�D>SiD#eqHuxN-UiALoxDYG%2>Fe*q zB2m0pOpZ4NK>`pOiA-hs_#j>!e<}#+KkFMLlFGOu9y*IFu;4!NW&W!#oh3oJGE5SN zVNtUk5E6mOFlhuPhFQBP@NR*KkHttWkMpEfHYyPuMEM*ECWL2hmo9h~I{CkD zRV7!7FDr{?)B$J_keci-vobT%(^6Bu`25^wXV08I_30-cfArzW6UUDwCw-8Za5O$H z_Q?B(56NQ=M$4p<_r#b;7!`Ry5V3zB%IAf1_rCki+i$)3#_M}_zxHa_uF#z!ue=<* ztJtZJIBV_3J26>+y;#CkULNsp!aJa$Zq;*eBuX5$;XbL zIOc4J-yFLc|3=8kb5?G#xYY|>-63~ZU#6SYx#ab@W!?_U=Prs{GTb2)vR(zPI=}8t^>Ta2Hp$NYNPEgD_^g$q?HTxVLPqVupDseMo54BTT?;Qgq7ZGz zElYG>j4;I)eC_Dr_Do#&i_Ou*IdZd`fpgOJg(lNbXsJHgK5+s*s%SrT%u6~rI z3x<3gj2ll|J8Cz@ZcwsG_wRcx2{tYKjWyDi;KHhzKkrTBjYCJ4seMhE!MT?6}rm^)&LY5QHR6cFNbe`8D`EsoCmfuBnMoSm453>!U5*)m=%k z1vyFj^Bz66`BVGwJ5FsmaT6-Z-CIe*T@T$6Sf1bn*@*bPD`0I)@={E!J0Eh-*51`g zY}U5>>7AW$5+5xk(9aQ?!>KRv%bAaxN8-G-Zkr*?9i9(ug&Ov@SxrDaF80utKLKO$ BRLKAU diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/clock_small.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/clock_small.gif deleted file mode 100644 index 9646dab0d163279a6702e2c2a2654315d7f2eb27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 588 zcmZ?wbhEHblxN^)c*el+_wV1ibLYN#^=jtKnHx85{PpYCg9i`JpFe;7`t^ki7k>Eg z;n>k53l=PR_U!4)moFbbe*Ev>zcZ&#&!0DM^{SPRA3ys2`}f0#5C8o6bMoZL*|TOn zdGh%E`*&y0o?W|U^_I<>pFe*#efsn(moMMBb9?jV&2#3=UbAM+jqBI%-@pI!=g*Dn z*B&}};N81-mo8meylBy;4eNm5#PMU-uU%WQV#V_1%lGfyvv~31bLY<8x^?TxlP9}& z?b^C!)4H{5jvhVy<;$0^U%%eGaee*zb?eu!-?44$qeqYK+_`h>*3C^D)?d7E9;pAs z@#D8{-n@P5*5ykVXV0F!XV=avSFZg3|DRzn0mYvzj0_Bc3_2i3f#QULePu&nQ*%q8 zsF@?Pf~tf@YyX56K4X1XZD|oLYv+k`oB5gj0|Jy52k^R?&zs1~Be;xlS%8R<~e?=m(XzD-<0rO#_4s^1MF|jBpOgM1pkfV6g Sg$zd~j&>$-XD%)l25SK4FZx~p diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/close_icon.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/close_icon.png deleted file mode 100644 index 23b826f113cba48080ae7535443c654bd37af059..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VA)YRdAr-fJCmiHrP~dQ08hrd* zZA$z_)fe;6igR8%nXu!m;;a>`ZoF>eDqrwXzkQ0*Wdj=z*TXQWZ>qU9_|>i}_OdHoeQ&;;(~DO|DS<@LGeF#gl~X?OJYePkhZa}C`e4sPAySL zN=?tqvsHS(d%u!GW{Ry+xT&v!Z-H}aMy5wqQEG6NUr2IQcCuxPlD(aRO@&oOZb5Ep zNuokUZcbjYRfVlmVoH8esuhq864qBz04piUwpDTjNhpBqbj~kIRWQ{v&`mZlGf*%y z)H5_TF*i5YQ7|$vG|)FN(l<2HH8i&}HnK7>P=Ep@plwAdX;wilZcw{`JX@uVl9B=| zef{$Ca=mh6z5JqdeM3u2OOP2xM!G;1y2X`wC5aWfdBw^w6I@b@lZ!G7N;32F6hI~> zCgqow*eU^C3h_d20o>TUVm+{T^pf*)^(zt!^bPe4Kwg3=^!3HBG&dKny0|1L72#g2 z1{a4^7NqJ2r55Lx7A2F<7;)ua#$BaY0ZFv$KJ@xuKz}p_7rBv7@7f zk&%n5v#FV*1x&9?esXDUYF-IUZwf-M3r@YDgpgYRwAm%KD6=dz#jPkmR{`u{t4!Q( zal~mJRBsAyw>aU{s}FRHJ}6p|q8TOxOgkVZJkbI<@MNEw2Tbclz(mdX|KHy~zkmJw z@%`J^FP}es{P6zW+c&RYy?pWf+0!SFA3c0<|K8m@w{P9NasArWE0-@_ym0>9*)yk4 zojh^;*wG`04;?(Pf8X9cyLau}v3=XtEt@xO+^~M#+BK_Jtz5Bu+0rG87cE>cf8N|V zvuDkmF@4(9DU&BnoY3Fb+tc0E+0owC+S1(A*ic_rTT@+CSy5hAT2fq8SdgEWo0FZD znUS8Bnv$H9m=GTq8xtKB84(^98WJ277~t>c>*MX^>EZ6?>f-F==wNSWYh!I?X<=?= zYGP~z%usr|I@(&A8tQ7QD#}WV3i5KYGSX6#65?W_BEmv~0{ncuJltHI9PDhYEX+)d zz>?u73y@@D&;gbb44{&Ofhm4U|H{*E85Yku5R&e+!T-uz+XtnF4PtFqS1F|y9Q#l+ zVR_r*cN4#BJm2}#!Qr4m_-2mU-8~<7c6u3HS@pGR>85SELEm2e4a=Rf^3e)rrwcAD Wvon(Q@10!mhv#g5#G@QW25SH;i?#Ov diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/controls.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/controls.png deleted file mode 100644 index c336f88d60f7a2b4c085c9888174be650a5e6c6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 706 zcmV;z0zLhSP)DIARpb#h&0v%ftNK2Q1A;I7W=;XCv z2n0+Gr)T)!2H~4?uN3!)>igh_E$K*@`}2{m{HG8R(sKqs0F*=qE@^od5CI{Py8lAb zRN7~14r(0KA?-vp_md8iD&>`OrEI_z)>XceIwnt&-3bQC$&^1Wn}xcA`mrK1p5>b4$u{~A?UM&9OYb-iX74<*@E08 zg@Lah5Oj^@36|%EB+;yuIziBh_rxJdkh7#U>h>NI1op9RWgPR+>Z64GR-SuK!Oi1Gy3P4?7Z(H$&C^|=mXJH;n;^~8 ztA8f}OAv6KI2eLP%AzrGusD%MjQzbjDQq_d*^*GxMv^@RM{Xj5KD3yES6gn7FO;%h zlH%7NA4&Gj>;kj6eK6^GGdor`*mtSy`F?iSo!vq(909o}Xh`QfnzGown2M oW7(d!IkiI{eBR7b68V?>1-$6^MFVmnqyPW_07*qoM6N<$f?=jV6aWAK diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/databg.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_dhx_terrace/databg.png deleted file mode 100644 index 5d5836930f8bab386ab297f459e65f34cbae6680..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfz!2~3=U0uz9l%%JNV+hCf8rINb3` c^R6L-YTj#Qx2cx@fC?BqUHx3vIVCg!0H9G6&j0`b diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/blue_tab.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/blue_tab.png deleted file mode 100644 index 7f7a5dd3642ab03ddbfa2788bbb544e4d91ec015..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212 zcmV;_04x8AP)P)t-s0001_ zzSOP7*uv81#MR@))ac08>C4&c&fDzJ-R;xg?$+V&+2ios^Wy6C=dOcgOV5K)uu(z_a5m9~;{}Y4QXYm)aFc4A>kMNeb^|L#k z%VvKn>+Jy=BBydI$6gQ1+1OT#DKtb*YmohNz1e&+vS*he0J)W8zdyRS^^^+)ppj#@ z&!m(gfI45%q%SPdKcaJg3GE@#|4KAc5RGU+^ngXvdFjzS9e`*=vx2iOvw~CafOoYklCmVoqenVS|Pe!)>e59cFWsU9>AW zZP8U{yyh;8RlNr303RUE2#_d#_^)>0%x$Xs10t-?UO*$CP9jc$w;rijn>#HZ* ziuOA9HrlOUoN#1EY26vWko7W`kGGuIQyH^LXXo0ihgT<^dANV+jn?#K4u`fCUwwP* z-M5!ZXNH}5yl>s2_-m)ym(2>l`}us|%dq{M3y$q7@2KifR>Y}Mw6)3c8m-~M#w=7-a1 z2lYB02kd$=@8hpG|NsAI7zM*O1QdU=FfuSCFzA512+9-e9RC>(a>#gWSa7hJLs%<@ z!>y62jYpg%f??u==`spD872Y>4UJt1VGkBu+W4e}lTpRt$^pd#JWK}3LKB3T9*Ht> z{5N>MH5zv}sFyVmL)JDz@z9|n~A2ze=aoMTfc#?RCTa!a?fk(jUuvRNSo+m#7 zABgF&Eo)ezv2bzAcA+K}&I`<}M+6xCroGv*gqxjLp!QVD$^#6OloTdwc^t4{g{)f>K6CCawk>Cl{7Cw?#BK3K$BV zSs5kRIOOdXxUhBTvni|)Xl*QJN-QjLPzCavSUfPI0sfDy@jpkeH{?dy!N3 zhQbX7(}VJFMYr8B{IE5rQKCY`;NikW%s2R0UNrDKaC~s&6i8KY$lHF<>b{ktD z&gisyeO}}wWwu=IPQcysynfG5*AoY441ID30dRqYbB2hDj*oeU0SAKw43?OemjIca zmy8XQ2$l?`rlkO-{A0vp~mdytYTbG?msW^U zr#j6lvq09dT+^yuJJf1X0dM0fC;-4L+`9_kQoUzXuU`e6%*y?X_HW+7hz~0^%s6r5 zqF(Vz#(P-uVW*ZU-_3lP;(^MbIg1WWdbDW)xdf)NP2)85Uy zx9{J;VH*OpAUN;?ZyFFc{+kM-;>@E-IQ3E2UV#jV2dz}|K7IbH;;QNrz*VAWT z&%M2R_w3)xkI!-mk0eEOoX77&KNJ1{1{YYw5-_xof)G1|V4wyF7P#Pp5RRZj1OPka Cm_4ij diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/calendar.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/calendar.gif deleted file mode 100644 index 67257083540f7ea06881718da65d749f7284e165..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 622 zcmZ?wbhEHb6k-r!c*ek>prLT)%o*dfGgj$`HW)Az6cjY9_^@!{!iEJG{{Q%I;E^z4 z!G;SD{sW1G2@e`(9Qfam@FBrq!iozH0SOHY9(?%lzo28ogbn{4Djqzr5a{jgov`A= zh65M&@85s>_U->O8UiXVBt#?>EcoD1aG_wvg9k7EH#9UXSaD#%jt2)U1ZK{h8PM>c zVZn$0|NmdSa?Qab;lPOt4J-aPEI9Dt$A5={2S5dnpFCc$;lTAP*C%YaV3lz(dCI*9 z4g$qf)-Kp_;lhmv7j9e#Xtg?cw=gYN-LX^L zkc~}ezmnDRmHU*|uGiL?1^(|-fE8lblbd4od4L*O>-Nnixo_MTBMAhPt^YXsC%yN=J0u$6;9q86(1O;^YnlA`!OMrv9(1`BVyeag@*_CuyPgcJ8^Pz`Z*T|W<~~U06^u> AiU0rr diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/clock_big.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/clock_big.png deleted file mode 100644 index 1cf5dbbedddaef045ebc5636e491ef942c3a39cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 998 zcmV7=;kZ+nVYS68gR>h$*c$J63!c7=kU*_Ex~*53QwqS}+6 zuH@$Fu)*uY&-0S2-;1W*sHmu>ue*kmq^`QjgP+%soU5z9;rROejGnxAkGgn-lbf>N z$=2uF-s7md=%1^)*x&oW(C4tZ#b$Y#r?bL;oYR@G+`h-s=j`+F@$-g~p_rtz&(zw5 zq1cF&qn4`8mY=GPr`?a7u1;KUp0n70lemkY!o|hKh@;!v;OFY?@ZRJ8wZYKT)YRGF z{K(DIRAhV7+vb6jvVMt}dWfH}xy07r>Vb`%e2ACd;^nl)<%6HtaEG*hna|YR`izyI zyvWwi+4$k-?bY4-gqz3h@A8G5$BLM)gP+!sp0B&d)_9DsilNN5!qJJ9q^r2fufXfP z!N`%FtjE>qo~ygR&GO9H=jrS2=jZ2!qT9jF@}jrqV{n1{{QOj4Z^z8j=j-rreUD#X zUvPbn^!4_`(BbIn?Oa@3NmXQ4VsoOm+r`V$lB(9t(%I(d>%!0BTyBie-0NOmUZ$p| z_V@Vr_xSPi^yuvIRbg@E<>jKb+so0|uE6SDZ;fMbfRn1$V`F1sYNB5N0004WQchC< zK<3zH0005WNkl(Z) z0uixnM3Nqski2aD&1&rzfzk>TvEOQaMtU-yG;Pc+0HCKV%xyFg)Xo=O+jrm$UOPW; zcl~yrX=C+npdCwjY|1tYykho& zUV_iOqW-@rxNh&z28Rh(Xw+d}52hDQXt58&IlcmA*xn*ADvN6kp(?mYRj6TYQJeo# z%}xpjtevTynk6TrL7K+~d(oxo9UN;W43bASIj+u;@s2u<+ss~2BZ=LxSZ4Rf%b|RH zf7W986(dF_o4x76r?-$Vh0{M!AoDrJQ$PC}pEUNpnJUhi|IhpLC?3Oge1DhWFGfFC UkyCm;RR91007*qoM6N<$f+ny*b^rhX diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/clock_small.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/clock_small.png deleted file mode 100644 index bdd7e6fc320b06e6fc6c09644eabacf69b34b445..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 401 zcmV;C0dD?@P)Rd@+J~Xlji=jVf41G| z|7wJ|sJY?K*!Ixh|Ksfcf1A>;!04jB^_8a1YKFbh;QzMH|7e7}$kFes$Npq~vYf5e z%G2?Uso;Z~%y*B#r?uL{*8gdMvHt%5$_#js00001bW%=J06^y0W&i*Hmq|oHRCr#M$wiJsF%(2me`aQ83{&_1 zcNW{qAky_{fgMyVwa@7XweVes-+TN|MSWe00000NkvXXu0mjf{fy$? diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/collapse_expand_icon.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/collapse_expand_icon.gif deleted file mode 100644 index 64da9483ea6a8bf40eac57f64afddb28638c1c47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 452 zcmZ?wbhEHb6kSnAsUe&p%Yv$JM$_W8+`K+vL zQy1@KV`DF|zZPaRp-Va7Es`fWH{!n_taqfi)L%}l+!NRT_gf~c5vTfPAO=yP@zY`zB-u?Ry@*U>$I(GcT$y28*)fmoQIDhHFx$tYDF7dZ+ zoj;d(|GrD{K0OuZ-`~Uy| diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/controlls5.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/controlls5.png deleted file mode 100644 index a6c5388c45dc47ed036e4545fdc372b05d41a6e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1874 zcmV-Y2d(&tP)+9>Z zw6y>K|D?Xui0+8x<>kyG0RLu0h=_=$rl#TH;o$H8;Nalt^#9Dv%;V$Z0002#>FL?o z*}S~G$H&L#=jXk>z2D#8&d$!Z(6-j-|K{=kWXfc!yUfhp?q0-R#MS0>bael!h?tm| zD2^y1h$64R(QDCby41QenKOBLc@cLJe}8||)6*@JEx5S2)YR0%!ou9#+}GFF%F4>s z)zzx1s?E*KLPA1vrP#H`*KcocM5;tMo;ZKyf9-5hki+)J*y-YqeA+S)w9d5A(b3}K z;{Tauetv##q11A6a^Rhh^GYbb*uHppcMR?w*bCa!~(XJpW@sbeh26TtR%V;&-au=tm`G zj<-B*p0>)`R)Vhl{{O7K&W(+Y=H}+T*1hib|GU+@`*c>;*4AB+!|3Sf6nYfq%Ea4+ zbKc(GioNjL+uNk1r02}W^0lbX&(GxKgzALYWKHq7tmW|iNJvQa zsFyf6IR1uY00DGTPE!Ct=GbNc00ag} zL_t(|UhS82tSeg-hu5gKk8Rt$wr$(CZQHhOKijr#CU55K?%}&9@7*;0tKZHvD=Tfk zS<^K8x52*zFl)71GdvQl+x2c#v}JRjKAX1`HR|22HOTn>6A)8^E-{lPPgSd@PM-7- z!8@-4qE*Y2vn%KJn?Jwb+{)P}TebozG4FrJtB4XUzX-sbJ=lFjbo7Ys2haYysI(Li zhov(emWxc9JGj9bgoT@ZJ9WO=MWyO;wR5MwpycHqbPquEBqj6&F>SuMq4^ScUJ$^o z{sXQ({`Q*yPphM^4d@SYUKvh5H5?ElcZH85Bgq+L@kMfX*shT>QJc>}AgX!8uQhu# zKcqH~!mYKV*M0UQ!1L;8)wV3a5pJwA6M*4q9;ydOGMXh;bc|hx8yYPVmukvt!phJXiT(aJrdK_S@V$S zb(lA6EAFP#=?4G~q|*Zjas^`0ehGtQBAKaBZW=Olm{$bDh7Q5q*aSK@F)@}-NQg}Y z%qU~{IAf%7#>Jbv{i+>HwjrQ_o0(9pO)fM?1}5~cv6 z0TRhg_;+fITh%RAAkl++D_T_JZqS^F2%3(Fm=gp79rWS)sz^OMlRjP_rtbiVUdxwb zk#eTC!c1otFL_b*9>6mnJh^1?8Q@i`K4e)X7Qxt0C5#2cTfG{9f+(d4F4tMKeuG-Q zVf~^ymq8%t=(1%;B_f!8^=tTFlOVnoin#j2N6nBp~3`B7A$N!cyQB&3z~qK zx+y7j;gKPd(Lc9gG64d|j;~ayRvteFekMSGKw=3bmOx?we!VQmNej~ z&nA{DnwZnSxN;9+6Jrx476aCUkXU%Tv%dQjmss+ypD;7bUewQ&Czf1v1AqPfQ)&$1 zNV6IEr^h%%iN&-RjmezP#)&1*ZRYRElc7yXIsIF{-IQr_qqpizcH$C|VYj>NE|;Ci zCv3oR-t%jgDF=NLV|AqRi6!}h)jMaJo=tRNn|+c<=C>_I$=A-j2btpO;uyjqn;eiJ bbbybMw}|1V(Ns?{pag@btDnm{r-UW|>Wn(o diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/icon.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/icon.png deleted file mode 100644 index 5e13a09f6f63027579d34b9fd548dae4d3169562..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^{2(?5GmvyVaHJSWIR*HHxTaSwO|M**QMoj;W?5G4 zik$k@`OWJJ+cy<=ZY}BBR@$?pymLc&|E`J&dnzaGt)I59VbYeixrf_l?VGvm$o>SE*JaxG$M9=w_iB5*Xc}O>LTA|)irJt`H!jG zSRJx#<~HwjvYJURYfsDcHY&{exZ(Nw-YY3>`>nlC)n^X%Ur%&mKAJm(qEK@6U*elF{r5}E*x=T8X$ diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/left-time-bg.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/left-time-bg.png deleted file mode 100644 index cd47de7e0cddcee0d7a07365e2f4ffab0d746871..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^#z4%-!2~4#6f)ihQg)s$jv*Y;$#?2r88S=!`G1~) z+2C2d1>^L_;{VEtDvBbp28=4EI%j-z&h!Wfok&efYEep4vxts%EO_~EHN)>fF^jEj SF|&atF?hQAxvXf?N^}pM%{@r@@@5al2*I)d*`uyLO=l?E0`*-o_ zzY9Oz5mxuuAMWm3;;j? za{$1`W{CCHKeepSG1muPZmt1;g!YEYZQ}>`uNd7m{^^V^aLeYV_PWLuS6fRrTN^D; zd$(6wmJXI)PR^D#XYAkDIRms;w(eBkJay{p^{d4ahOC7h>j}W4MdA!TRX4TF37~VV5toY{8&jyL>s7Khd zXWlB|uVA z!Ra58vf^`+(^7I{3o`)esQhd!x*{*LpsI*aQid<5R?={o(i$e4!l~smcy-luVk5ah z$SUq2bvAdmwQyVOSt8khbV$%QGB`Ti-=mO^H%TVPraz+Dbd6=xX&U^RpXar9X~l3JCkRd2i=$ z=N)M8>FWN*B`Q4nTSP#7P)L|Z1Uys&l#vPA1I$4KvvYIu3yN|}(4~ctf^u+WUPUFg z8dr(RB-Ij%85mX>rwV|lQL~+v~d(}VP_k@B}+ac>*^mJ=onY@ z_EB3V#2;tICYKf@i(lqy)+l4|6y>nmpwD2LQkb?x4+16|^)6Ou8;7fb%xpkfTekdL zDy0{WIb^mgt1j>k?h8sYk55iTKjN5T6Qk!X%9lQQ`K+%%W#w#@IjgPa^*4_Ef-p_L zuPohL)`Wo+yBWW|@3J>6-+_H$!KHNMaa8pZ&I`w%?8ngU-MwAmfu24Zettn= z!O|!n9XcHgj3Mf-rCtwCvO;R8g6Nmc1d_evM~jHcDlcBU~y=9 zWEC^fBc5*uX$tPZjC_{*_bw;`It{eg*$E;kmnkj+|U5wL& zZffd(tLBf)*;I|t?XW^+p%%qJ)wGCozc zN>d}VXb`847<5?-$2BhTWGk-ocj@6p4g)jH+GJG|EK;J5RixGhE5I(ChDWB|`ZvUNdi z()1;HfSK=AS3`Fnn=rcwPdF^tImj>8KR)DLly_)o;M3$RRE~p5N_u`uW-c0$U4lIT zs;mM*aaGj>JcLXE1L+JPl*wRoSP;ITme1ofGMgDSBti$SizsZ6G)Y_fxN>^y&|n=v z)J`RfE2n56dKlo}Nc1IIPDZq;?krvJXN`|wl2^mC@iM5!@{cNcaca!Gfj zjf6aDP4_-{=;odsaYHwd%KOa>i>h=)2}k>$1(?L5fBt6Qth~Nx{_^eU^N~9LjbDi` zVyS1lhn0DJRx0|1j%CNt z;E_NYbsYTuO2cnQ9!7Umk*7}96gr{CtseW0uMuc({eE|JJ?QnyIyAyE=zSnEATBss zDbhCCGb%PA-9ID#aEkpqkK8byMBgjUG1+j`VNewg1jXYB#A*nI3Z_AUEH;qIVe$Av z&Ss$!K=>?14TVhX!iz~Qtxa61NM1kKINS_w1-8>WJG!TPW_!nEivCXnD?@7|Uq%7# zl|bE!Y^ul1x?JVe9XT;{srEb58#6DABY+)7Zt9h%k6cGUhqd>3$Jy{gR6pep5nG@C z8lZ9HH_b6eR7k3h<6>L3s{(;K?OoNI`rip+)U=inEcLVjES!~*Cr1NuGVnQ+EaC#C?f=#wC&Ns?Zwmg z7E(`1_bM(ry9EXMyDNF!_xAO%wu=b~Hj1}!Nel>!MB0Yir#ZysIHBK|WEDmfqxAEV z%i!f&ARHb9t;Q2c1PHYTTuUKAfm|Mt!{-V`_54O&GnYxDvZ}kt9c)QAL{!(;-zper z7-<^iwKF=UJ(In&viTW6|1fxY=<`SUYJc~ZT{oJa(JaKfR_i>Sds%*fCSyahyRu90 zeW%Uxy6);(@!g=g7c{?f)!;=h-aTQsJf16vS6zy8TR|TEDe}|L{q>}|%-b>AXT4N? zEQ@~4Y1;i4I4*wBis-o!VwZ{@+-6l?$Hdi}CSC1AiWe_3zdycpHH4V~if5lq{V`u} z)ooYY^+AyaCoQj8!>bUN#2?Yor^=MDJ z-}zZ|Ao8L|#LJNI)X0Q4?=xJpVy-5oeMoljvP?&n#zqDFS;?ECW#InIkxnJEh;7U+ zwz#vl{SS`Ka&W(3K-4Pjp6HqC1&q(hW-5n9M+V25KJ%96l{#~~V*1a+XGb#G{O0Ed z0L50dM6XyYR-np(5jg42ndf@ZYSXWw_T~F7#~-_OVnQ&R%lG@+hW*u|9IcwP?ar_Y zllh=u{Wbh}s;j5|Q-9qj{O82A^ZVkY5rpzFN}&4Z2tB=rznKoI1tU*(9y#u|EAXUj zQjzdO`uT#!ZTTAT8(q7ow{AKbxHxP0#q$U9C%QXekHql?&rbU*me)Rf@c=IS8+qUM z2@bgzY8L47TIcN#?_CjLi4pK5567o*v5|gPKO`rh!&6gU1r(>FbU@g05VWGa3Rejs z5W(bX9Ib+mhX6TTAe6@y2>I;#O{Pq28wJozZEdNQFdBt*{e3(+ue+;9-1|{B!J2B9 zPLGZQ>KnjI!=gd1VqbDZ&T{!>_)K*hH{^LPI$DQ*(T8A|qlj%ih zK|-R=xmwYp4sz`uq{ctJ;Hd%I9c8d<1eE%d1=fjl2T1z&6WiCm`%iX(2`|!m!eJ#9 zapmfI*0x3--$?Wc3S_59+YN*;%sdsoX7J(Cp*?1&c9xwkNbJn;AwMx8=|evVJFHbO zt*E4aPyH$E^47|qhZ#^OT0;D>@p%s=4 z-#NzKBj;XN{v&cj^F+HKcK@@haHvkJ^@rO)q32O)QjJSh{!M`PxP3~>Uy3(^~ z@sfN89m^p#s@hQU{A)#xupr@3M2OzEp4SeX5?k-dyis)J_zq>{uf=5l86CM?25s~;9 z{_-E7>>Lmjos*ZJ3n?lFV+!-j(Uk=yMYwDzkU|BLYbe<23RV>dUq;}OM5O?xfZfam z(-*uuPgg)*6^6g_UGatCWjc-K2{h$!!``~ayT$mNq4V0D+f@Y+nvN9p)TyTC) zR&fR`2uVUjV%o;(hh*3=<@BuAtta?r-ucNi6T_}+? zHTMq6q;-9Yk%o_5qYZNM(AeDg!sLW_co9FdjN9M>te~S)vf7<9z4kLaCpkG}pZbZY pWf!ZHp$(dbz}SD8G>Wgb=uaa1zqEv)*f`MtlO;U=)dv3&{{wX{9B%*s diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/move.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/move.png deleted file mode 100644 index bd61e3fbd1ca00315adcf10f40be7f51f8523478..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^j371(GmxD1Q}Q5?(hBeias3Yj{~rDSclZCloB#h^ z`TzIA|G%gI|2_Wy@1g&H_x}I8^Z%bM|Nm_G|7SJho#WC#T|AyHjv*Yf$pQ(77#X=A WF}zGud#L~vXYh3Ob6Mw<&;$VJxj3W% diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/multi-days-bg.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/multi-days-bg.png deleted file mode 100644 index af75532c8f877ad3739f46ec216679b367178101..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 276 zcmXxfy-vb#6b10VaWPGpj1EkWOvYEx6s3tFM0o%b-F*i)pTWh&)lm~SHxm^>MWa!o zwoq(ok=hCsIL8asW~+}w}7LVhi!r8T8g%E;*(l2am_nU?CpJUNs&Evy%_B+U-$ zZ9F-s*{C*f`Tpn1geXs3TS!zaR2t*9#7z_8cH+)PLgv(3xc~R?fk$UN|JlV$8+8w_ zKHhxDUh5OhF6;oU0L~ZOkX}STV&|LP9)mu^m{H8$5BmegLk>n9jtI!roOjEM^2MB? mFBdbLTcz#v!ugW6dX_nuRchZ;$JL#jD-FuX=JlhM((W&9bj42q diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/second-top-days-bg.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/second-top-days-bg.png deleted file mode 100644 index 5bee85bbb9877afcabcf2e0b92b074f21c0f20ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^j6kf#!3HFY>I`dul#Qp0V+coda>SmdKI;Vst0MS(^2mk;8 diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/top-days-bg.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/top-days-bg.png deleted file mode 100644 index 1606c6d50ca07c33b56cf84da8719c1677899303..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{L!3-qLB-myEDW?FR5ZC|z|1a5h<@M{=`!77( zd;aO}vrl)Pd9wY~Eal|A)B0#l8}&)mZZWXDZ$99$zXHd@$z(_G=rzBpUXO@geCy}J4gNi diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/top-separator.gif b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/top-separator.gif deleted file mode 100644 index 18b4bfa95b0b62a3f145bc91c6cc65f87c8acf7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 259 zcmZ?wbh9u|WMU9wSjxb#WZ#wl|NmdP{|<=G-g`1px&CF4n_O8yr)Fq>iQ?Oe~R- ZJN}%psYOZYWQNhg04>pOR|ysdYXG(YZ0G<0 diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/white_tab.png b/addons/web_calendar/static/lib/dhtmlxScheduler/codebase/imgs_glossy/white_tab.png deleted file mode 100644 index b47770cfa2b4e57855624e89a29299f74d50e89c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241 zcmVP)t-s0001_ zzSOP7*uT)`!qVr&)#Js~=*ZUT&fDzJ-R;xg?$+V&+2ios^Wy6C0s_NHX4`To0W58vN>{Nc{ikN01E ze)Q_g(>GsVy!-b0!}oWeeth`y^Ygb~-+uo2`TOtx|Nlc+j++CGV=M{s3ubV5b|VeQ ziSTrB4DmSr_JSc-gMom{#r-OoZ(LNq+s|vgal35oVPsg>7NqqWp%Y~ zHC6pma?QorJ

qhFR{dFYYfnCaite&N9#Z>GiqM%HK6Cp5HlN#n8+k-FBV9{5{YP N22WQ%mvv4FO#loDfCK;l diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/license.txt b/addons/web_calendar/static/lib/dhtmlxScheduler/license.txt deleted file mode 100644 index f695d8ecb2c..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/license.txt +++ /dev/null @@ -1,228 +0,0 @@ - - GNU GENERAL PUBLIC LICENSE - -Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. - -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Everyone is permitted to copy and distribute verbatim copies - -of this license document, but changing it is not allowed. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a -notice placed by the copyright holder saying it may be distributed under -the terms of this General Public License. The "Program", below, refers -to any such program or work, and a "work based on the Program" means -either the Program or any derivative work under copyright law: that is -to say, a work containing the Program or a portion of it, either -verbatim or with modifications and/or translated into another language. -(Hereinafter, translation is included without limitation in the term -"modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of running -the Program is not restricted, and the output from the Program is -covered only if its contents constitute a work based on the Program -(independent of having been made by running the Program). Whether that -is true depends on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source -code as you receive it, in any medium, provided that you conspicuously -and appropriately publish on each copy an appropriate copyright notice -and disclaimer of warranty; keep intact all the notices that refer to -this License and to the absence of any warranty; and give any other -recipients of the Program a copy of this License along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of -it, thus forming a work based on the Program, and copy and distribute -such modifications or work under the terms of Section 1 above, provided -that you also meet all of these conditions: - -a) You must cause the modified files to carry prominent notices stating -that you changed the files and the date of any change. - -b) You must cause any work that you distribute or publish, that in whole -or in part contains or is derived from the Program or any part thereof, -to be licensed as a whole at no charge to all third parties under the -terms of this License. - -c) If the modified program normally reads commands interactively when -run, you must cause it, when started running for such interactive use in -the most ordinary way, to print or display an announcement including an -appropriate copyright notice and a notice that there is no warranty (or -else, saying that you provide a warranty) and that users may -redistribute the program under these conditions, and telling the user -how to view a copy of this License. (Exception: if the Program itself is -interactive but does not normally print such an announcement, your work -based on the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, and -can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based on -the Program, the distribution of the whole must be on the terms of this -License, whose permissions for other licensees extend to the entire -whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of a -storage or distribution medium does not bring the other work under the -scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under -Section 2) in object code or executable form under the terms of Sections -1 and 2 above provided that you also do one of the following: - -a) Accompany it with the complete corresponding machine-readable source -code, which must be distributed under the terms of Sections 1 and 2 -above on a medium customarily used for software interchange; or, - -b) Accompany it with a written offer, valid for at least three years, to -give any third party, for a charge no more than your cost of physically -performing source distribution, a complete machine-readable copy of the -corresponding source code, to be distributed under the terms of Sections -1 and 2 above on a medium customarily used for software interchange; or, - -c) Accompany it with the information you received as to the offer to -distribute corresponding source code. (This alternative is allowed only -for noncommercial distribution and only if you received the program in -object code or executable form with such an offer, in accord with -Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source code -means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to control -compilation and installation of the executable. However, as a special -exception, the source code distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies the -executable. - -If distribution of executable or object code is made by offering access -to copy from a designated place, then offering equivalent access to copy -the source code from the same place counts as distribution of the source -code, even though third parties are not compelled to copy the source -along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt otherwise -to copy, modify, sublicense or distribute the Program is void, and will -automatically terminate your rights under this License. However, parties -who have received copies, or rights, from you under this License will -not have their licenses terminated so long as such parties remain in -full compliance. - -5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and all -its terms and conditions for copying, distributing or modifying the -Program or works based on it. - -6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further restrictions -on the recipients' exercise of the rights granted herein. You are not -responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot distribute -so as to satisfy simultaneously your obligations under this License and -any other pertinent obligations, then as a consequence you may not -distribute the Program at all. For example, if a patent license would -not permit royalty-free redistribution of the Program by all those who -receive copies directly or indirectly through you, then the only way you -could satisfy both it and this License would be to refrain entirely from -distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is implemented -by public license practices. Many people have made generous -contributions to the wide range of software distributed through that -system in reliance on consistent application of that system; it is up to -the author/donor to decide if he or she is willing to distribute -software through any other system and a licensee cannot impose that choice. - -This section is intended to make thoroughly clear what is believed to be -a consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License may -add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among countries -not thus excluded. In such case, this License incorporates the -limitation as if written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Program does not specify a version -number of this License, you may choose any version ever published by the -Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the -author to ask for permission. For software which is copyrighted by the -Free Software Foundation, write to the Free Software Foundation; we -sometimes make exceptions for this. Our decision will be guided by the -two goals of preserving the free status of all derivatives of our free -software and of promoting the sharing and reuse of software generally. - -NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE -ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH -YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL -NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR -DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL -DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM -(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED -INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF -THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR -OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/readme.txt b/addons/web_calendar/static/lib/dhtmlxScheduler/readme.txt deleted file mode 100644 index 0bc2f8df50d..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -dhtmlxScheduler v.3.5 build 120823 - -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details - -(c) DHTMLX Ltd. \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.css b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.css deleted file mode 100644 index e2b512bc030..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.css +++ /dev/null @@ -1,1419 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ - -.dhtmlx_message_area{ - position:fixed; - right:5px; - width:250px; - z-index:1000; -} - -.dhtmlx-info{ - min-width: 120px; - padding:4px 4px 4px 20px; - font-family:Tahoma; - z-index: 10000; - - margin:5px; - margin-bottom:10px; - - -webkit-transition: all .5s ease; - -moz-transition: all .5s ease; - -o-transition: all .5s ease; - transition: all .5s ease; -} -.dhtmlx-info.hidden{ - height:0px; - padding:0px; - border-width:0px; - margin:0px; - overflow:hidden; -} - -.dhtmlx_modal_box{ - overflow:hidden; - display: inline-block; - min-width: 300px; - width: 300px; - text-align: center; - position:fixed; - - background-color: #fff; - background:-webkit-linear-gradient(top, #ffffff 1%, #d0d0d0 99%); - background:-moz-linear-gradient(top, #ffffff 1%, #d0d0d0 99%); - box-shadow: 0px 0px 14px #888; - - font-family: Tahoma; - - z-index:20000; - - border-radius:6px; - border: 1px solid #ffffff; -} - -.dhtmlx_popup_title{ - border-top-left-radius:5px; - border-top-right-radius:5px; - - border-width:0px; - - background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAoCAMAAAAIaGBFAAAAhFBMVEVwcHBubm5sbGxqampoaGhmZmZlZWVjY2NhYWFfX19dXV1bW1taWlpYWFhWVlZUVFRSUlJRUVFPT09NTU1LS0tJSUlHR0dGRkZERERCQkJAQEA+Pj49PT09PT0+Pj5AQEBBQUFDQ0NERERGRkZHR0dJSUlKSkpMTExMTEw5OTk5OTk5OTkny8YEAAAAQklEQVQImQXBCRJCAAAAwKVSQqdyjSPXNP7/QLsIhA6OTiJnF7GrRCpzc/fw9PKW+/gqlCq1RqvTG/yMJrPF6m/bAVEhAxxnHG0oAAAAAElFTkSuQmCC); - background-image: -webkit-linear-gradient(top, #707070 1%, #3d3d3d 70%, #4c4c4c 97%, #393939 97%); - background-image: -moz-linear-gradient(top, #707070 1%, #3d3d3d 70%, #4c4c4c 97%, #393939 97%); -} - -.dhtmlx-info, .dhtmlx_popup_button, .dhtmlx_button{ - user-select: none; - -webkit-user-select: none; - -moz-user-select:-moz-none; - - cursor:pointer; -} - -.dhtmlx_popup_text{ - overflow:hidden; -} - -.dhtmlx_popup_controls{ - border-radius:6px; - padding:5px; -} - -.dhtmlx_popup_button, .dhtmlx_button{ - height: 30px; - line-height:30px; - - display: inline-block; - margin: 0 5px; - border-radius: 6px; - - color:#FFF; -} -.dhtmlx_popup_button{ - min-width: 120px; -} - -div.dhx_modal_cover { - background-color:#000; - cursor:default; - - filter:alpha(opacity = 20); - opacity: 0.2; - - position: fixed; - z-index:19999; - left: 0px; top: 0px; - width: 100%; height: 100%; - - border: none; - zoom: 1; -} - -.dhtmlx-info img, .dhtmlx_modal_box img{ - float:left; - margin-right:20px; -} - -.dhtmlx-alert-error .dhtmlx_popup_title, .dhtmlx-confirm-error .dhtmlx_popup_title{ - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAsCAIAAAArRUU2AAAATklEQVR4nIWLuw2AMBBDjVuQiBT2oWbRDATrnB0KQOJoqPzRe3BrHI6dcBASYREKovtK6/6DsDOX+stN+3H1YX9ciRgnYq5EWYhS2dftBIuLT4JyIrPCAAAAAElFTkSuQmCC); -} -.dhtmlx-alert-error, .dhtmlx-confirm-error { - border: 1px solid #ff0000; -} - -/*Skin section*/ -.dhtmlx_button, .dhtmlx_popup_button{ - box-shadow: 0px 0px 4px #888; - border:1px solid #838383; -} -.dhtmlx_button input, .dhtmlx_popup_button div{ - border:1px solid #FFF; - background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAYFBMVEVwcHBtbW1ra2toaGhmZmZjY2NhYWFeXl5cXFxaWlpXV1dVVVVSUlJQUFBNTU1LS0tJSUlGRkZERERBQUE/Pz88PDw9PT0+Pj5AQEBCQkJDQ0NFRUVHR0dISEhKSkpMTEzqthaMAAAAMklEQVQImQXBhQ2AMAAAsOIMlwWH/8+kRSKVyRVKlVrQaHV6g9FktlhFm93hdLk9Xt8PIfgBvdUqyskAAAAASUVORK5CYII=); - background-image: -webkit-linear-gradient(top, #707070 1%, #3d3d3d 70%, #4c4c4c 99%); - background-image: -moz-linear-gradient(top, #707070 1%, #3d3d3d 70%, #4c4c4c 99%); - - border-radius:6px; - font-size:15px; - font-weight:normal; - -moz-box-sizing:content-box; - box-sizing:content-box; - - color:#fff; padding:0px; margin:0px; - vertical-align:top; - - height:28px; - line-height:28px; -} - -.dhtmlx_button input:focus, .dhtmlx_button input:active, .dhtmlx_popup_button div:active, .dhtmlx_popup_button div:focus{ - - background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAMAAADaS4T1AAAAXVBMVEVwcHBubm5tbW1sbGxra2tpaWloaGhnZ2dmZmZlZWVjY2NiYmJhYWFgYGBfX19dXV1cXFxbW1taWlpZWVlXV1dWVlZVVVVUVFRTU1NRUVFQUFBPT09OTk5NTU1LS0tT9SY0AAAAMUlEQVQImQXBhQGAMAAAIGxnx2z9/00BiVQmVyhVakGj1ekNRpPZYhVtdofT5fZ4fT8hpwG05JjexgAAAABJRU5ErkJggg==); - background-image: -webkit-linear-gradient(top, #707070 1%, #4c4c4c 99%); - background-image: -moz-linear-gradient(top, #707070 1%, #4c4c4c 99%); -} -.dhtmlx_popup_title{ - color:#fff; - text-shadow: 1px 1px #000; - height:40px; line-height:40px; - font-size:20px; -} -.dhtmlx_popup_text{ - margin:15px 15px 5px 15px; - font-size:14px; - color:#000; - min-height:30px; - border-radius:6px; -} - - -.dhtmlx-info, .dhtmlx-error{ - font-size:14px; - color:#000; - box-shadow: 0px 0px 10px #888; - - padding:0px; - - background-color:#FFF; - border-radius:3px; - border:1px solid #ffffff; -} -.dhtmlx-info div{ - padding:5px 10px 5px 10px; - background-color: #fff; - - border-radius:3px; - border:1px solid #B8B8B8; -} -.dhtmlx-error{ - background-color: #d81b1b; - border:1px solid #ff3c3c; - box-shadow: 0px 0px 10px #000; -} -.dhtmlx-error div{ - background-color: #d81b1b; - border:1px solid #940000; - color:#FFF; -} - - -.dhx_cal_container{ - background-color:#C2D5FC; - font-family:Tahoma; - font-size:8pt; - position:relative; - overflow:hidden; -} -.dhx_cal_container div{ - -moz-user-select:none; - -moz-user-select:-moz-none; -} -.dhx_cal_navline{ - height:20px; - position:absolute; - z-index:3; - width:750px; - color:#2F3A48; -} -.dhx_cal_navline div{ - position:absolute; - top:2px; - white-space:nowrap; -} -.dhx_cal_navline .dhx_cal_date { - font-weight:600; - left:210px; - padding-top: 1px; -} -.dhx_cal_button .dhx_left_bg{ - width:1px; overflow:hidden; - height:17px; - z-index:20; - top:0px; -} -.dhx_cal_prev_button{ - background-image:url(imgs/buttons.png); - background-position:0px 0px; - width:29px; height:17px; - left:50px; cursor:pointer; -} -.dhx_cal_next_button{ - background-image:url(imgs/buttons.png); - background-position: -30px 0px; - width:29px; height:17px; - left:80px; cursor:pointer; -} -.dhx_cal_today_button{ - background-image:url(imgs/buttons.png); - background-position: -60px 0px; - width:75px; height:17px; - left:112px; cursor:pointer; - text-align:center; - text-decoration:underline; -} -.dhx_cal_tab{ - width:59px; height:19px; - text-align:center; - text-decoration:underline; - padding-top:2px; - cursor:pointer; - background-color: #D8E1EA; - - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} -.dhx_cal_tab.active{ - text-decoration:none; - - cursor:default; - font-weight:bold; - border: 1px dotted #586A7E; - border-bottom: 0; - background-color: #C2D5FC; -} -.dhx_cal_header{ - position:absolute; - left:10px; top:23px; - width:750px; - border-top:1px dotted #8894A3; - border-right:1px dotted #8894A3; - z-index:2; - overflow:hidden; - color:#2F3A48; -} -.dhx_cal_data{ - border-top:1px dotted #8894A3; - position:absolute; - top:44px; - width:600px; - overflow-y:auto; - overflow-x:hidden; -} -.dhx_scale_bar{ - position:absolute; - text-align:center; - background-color:#C2D5FC; - padding-top:3px; - border-left:1px dotted #586A7E; -} -.dhx_scale_holder{ - position:absolute; - border-right:1px dotted #586A7E; - background-image:url(imgs/databg.png); -} -.dhx_scale_holder_now{ - position:absolute; - border-right:1px dotted #586A7E; - background-image:url(imgs/databg_now.png); -} -.dhx_scale_hour{ - height:41px; - width:50px; - border-bottom:1px dotted #8894A3; - background-color:#C2D5FC; - text-align:center; - line-height:40px; - color:#586A7E; - overflow:hidden; -} -.dhx_month_head{ - background-color:#EBEFF4; - color:#2F3A48; - border-right:1px dotted #586A7E; - height:18px; - padding-right:5px; - padding-top:3px; - text-align:right; -} -.dhx_month_body{ - border-right:1px dotted #586A7E; - border-bottom:1px dotted #586A7E; - background-color:#FFFFFF; -} -.dhx_now .dhx_month_body{ - background-color:#E2EDFF; -} -.dhx_after .dhx_month_body, .dhx_before .dhx_month_body{ - background-color:#ECECEC; -} -.dhx_after .dhx_month_head, .dhx_before .dhx_month_head{ - background-color:#E2E3E6; - color:#94A6BB; -} -.dhx_now .dhx_month_head{ - background-color:#D1DEF4; - font-weight:bold; -} -.dhx_cal_drag{ - position:absolute; - z-index:9999; - background-color:#FFE763; - border:1px solid #B7A543; - opacity:0.5; - filter:alpha(opacity=50); -} -.dhx_loading{ - position:absolute; - width:128px; - height:15px; - background-image:url(imgs/loading.gif); - z-index:9999; -} -.dhx_multi_day_icon, .dhx_multi_day{ - background-color:#E1E6FF; - background-repeat:no-repeat; - border-right:1px dotted #8894A3; -} -.dhx_multi_day{ - position: absolute; - border-top:1px dotted #8894A3; -} -.dhx_multi_day_icon, .dhx_multi_day_icon_small{ - background-position: center center; - background-color:#E1E6FF; - background-repeat:no-repeat; - border-bottom:1px dotted #8894A3; - border-right:1px dotted #8894A3; -} -.dhx_multi_day_icon{ - background-image:url(imgs/clock_big.gif); -} -.dhx_multi_day_icon_small{ - background-image:url(imgs/clock_small.gif); - -} -.dhtmlxLayoutPolyContainer_dhx_skyblue .dhx_cal_container { - background-color: #d0e5ff; -} -.dhx_cal_event .dhx_header, .dhx_cal_event .dhx_title, .dhx_cal_event .dhx_body, .dhx_cal_event .dhx_footer { - background-color:#FFE763; - border:1px solid #B7A543; - color:#887A2E; - overflow:hidden; - width:100%; - - font-family:Tahoma; - font-size:8pt; -} -.dhx_move_denied .dhx_cal_event .dhx_header, .dhx_move_denied .dhx_cal_event .dhx_title{ - cursor:default; -} -.dhx_cal_event .dhx_header{ - height:1px; - margin-left:1px; - border-width:1px 1px 0px 1px; - cursor:pointer; -} -.dhx_cal_event .dhx_title { - height:12px; - border-width:0px 1px 1px 1px; - border-bottom-style:dotted; - - font-size:7pt; - font-weight:bold; - text-align:center; - - background-position:right; - background-repeat:no-repeat; - cursor:pointer; -} -.dhx_cal_event .dhx_body, .dhx_cal_event.dhx_cal_select_menu .dhx_body{ - border-width:0 1px 1px 1px; - padding:5px; -} -.dhx_resize_denied { - cursor:default !important; -} -.dhx_cal_event .dhx_event_resize { - cursor:s-resize; -} -.dhx_cal_event .dhx_footer, .dhx_cal_event .dhx_select_menu_footer{ - height:1px; - margin-left:2px; - border-width:0px 1px 1px 1px; -} -.dhx_cal_event_line{ - background-color:#FFE763; - border:1px solid #B7A543; - border-radius:3px; - font-family:Tahoma; - font-size:8pt; - height:13px; - padding-left:10px; - color:#887A2E; - cursor:pointer; - overflow:hidden; -} -.dhx_cal_event_clear{ - font-family:Tahoma; - font-size:8pt; - height:13px; - padding-left:2px; - color:#887A2E; - white-space:nowrap; - overflow:hidden; - cursor:pointer; -} -.dhx_in_move{ - background-color:#FFFF80; -} -div.dhx_cal_editor{ - background-color:#FFE763; - border:1px solid #B7A543; - border-top-style:dotted; - z-index:999; - position:absolute; - overflow:hidden; -} -textarea.dhx_cal_editor{ - width:100%; - height:100%; - border:0px solid black; - margin:none; - padding:none; - overflow:auto; -} -div.dhx_menu_head{ - background-image:url(imgs/controls.gif); - background-position: 0px -43px; - width:10px; height:10px; - margin-left:5px; margin-top:1px; - border:none; - cursor:default; -} -div.dhx_menu_icon{ - background-image:url(imgs/controls.gif); - width:20px; height:20px; - margin-left:-5px; margin-top:0px; - border:none; - cursor:pointer; -} -div.icon_details{ - background-position: 0px 0px; -} -div.icon_edit{ - background-position: -22px 0px; -} -div.icon_save{ - background-position: -84px -1px; -} -div.icon_cancel{ - background-position: -62px 0px; -} -div.icon_delete{ - background-position: -42px 0px; -} -.dhx_unselectable, .dhx_unselectable div{ - -webkit-user-select:none; - -moz-user-select:none; - -moz-user-select:-moz-none; -} -.dhx_cal_light{ - background-color:#FFE763; - border-radius:5px; - font-family:Tahoma; - font-size:8pt; - border:1px solid #B7A64B; - color:#887A2E; - - position:absolute; - z-index:10001; - - width:580px; - height:300px; - - box-shadow:5px 5px 5px #888; -} -.dhx_cal_light_wide{ - width:650px; -} -.dhx_mark{ - position:relative; top:3px; - background-image:url('./imgs/controls.gif'); - background-position: 0px -43px; - padding-left:10px; -} -.dhx_ie6 .dhx_mark{ - background-position: 6px -41px; -} - -.dhx_cal_light select{ - font-family:Tahoma; - font-size:8pt; - color:#887A2E; - padding:2px; - margin:0px; -} -.dhx_cal_ltitle{ - padding:2px 0px 2px 5px; - overflow:hidden; - white-space:nowrap; -} -.dhx_cal_ltitle span{ - white-space:nowrap; -} -.dhx_cal_lsection{ - background-color:#DBCF8C; - color:#FFF4B5; - font-weight:bold; - padding:5px 0px 3px 10px; -} -.dhx_section_time{ - background-color:#DBCF8C; - white-space:nowrap; -} -.dhx_cal_lsection .dhx_fullday{ - float:right; - margin-right:5px; - color:#887A2E; - font-size:12px; - font-weight:normal; - line-height:20px; - vertical-align:top; - cursor:pointer; -} -.dhx_cal_lsection{ - font-size:18px; - font-family:Arial; -} -.dhx_cal_ltext{ - padding:2px 0px 2px 10px; - overflow:hidden; -} -.dhx_cal_ltext textarea{ - background-color: #FFF4B5; /* #FFF4B5; should be the same for dhx_cal_larea, was transperent */ - overflow:auto; - border:none; - color:#887A2E; - height:100%; - width:100%; - outline:none !important; - resize: none; -} -.dhx_time{ - font-weight:bold; -} -.dhx_cal_light .dhx_title{ - padding-left:10px; -} -.dhx_cal_larea{ - border:1px solid #DCC43E; - background-color:#FFF4B5; - overflow:hidden; - - margin-left:3px; - - width:572px; - height:1px; -} -.dhx_btn_set{ - padding:5px 10px 0px 10px; - float:left; -} -.dhx_btn_set div{ - float:left; - height:21px; - line-height:21px; - vertical-align:middle; - cursor:pointer; -} -.dhx_save_btn{ - background-image:url('./imgs/controls.gif'); - background-position:-84px 0px; - width:21px; - -} -.dhx_cancel_btn{ - background-image:url('./imgs/controls.gif'); - background-position:-63px 0px; - width:20px; -} -.dhx_delete_btn{ - background-image:url('./imgs/controls.gif'); - background-position:-42px 0px; - width:20px; -} -.dhx_cal_cover{ - width:100%; - height:100%; - position:absolute; - z-index:10000; - top:0px; - left:0px; - background-color:black; - - opacity:0.1; - filter:alpha(opacity=10); -} -.dhx_custom_button{ - padding:0px 3px 0px 3px; - color:#887A2E; - font-family:Tahoma; - font-size:8pt; - background-color:#FFE763; - font-weight:normal; - margin-right:5px; - margin-top:0px; - cursor:pointer; -} -.dhx_custom_button div{ - cursor:pointer; - float:left; - height:21px; - line-height:21px; - vertical-align:middle; -} - - -.dhx_cal_light_wide .dhx_cal_larea{ - border-top-width:0px; -} -.dhx_cal_light_wide .dhx_cal_lsection{ - border:0px; - float:left; - text-align:right; - width:100px; - height:20px; - font-size:16px; - padding: 5px 0px 0px 10px; -} -.dhx_cal_light_wide .dhx_wrap_section{ - border-top:1px solid #DBCF8C; - position:relative; - background-color:#DBCF8C; - overflow:hidden; -} -.dhx_cal_light_wide .dhx_section_time{ - padding-top:2px !important; - height:20px !important; -} -.dhx_section_time{ - text-align: center; -} -.dhx_cal_light_wide .dhx_cal_larea{ - width:730px; -} -.dhx_cal_light_wide{ - width:738px; -} - -.dhx_cal_light_wide .dhx_section_time{ - background:transparent; -} -.dhx_cal_light_wide .dhx_cal_checkbox label{ - padding-left:0px; -} -.dhx_cal_wide_checkbox input{ - margin-top:8px; - margin-left:14px; -} -.dhx_cal_light input{ - font-family:Tahoma; - font-size:8pt; - color:#887A2E; -} -.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday{ - float:none; - margin-right:0px; - color:#FFF4B5; - font-weight:bold; - font-size:16px; - font-family:Arial; - cursor:pointer; -} -.dhx_custom_button{ - float: right; - height: 21px; - width:90px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - -ms-border-radius: 4px; - -o-border-radius: 4px; - border-radius: 4px; -} -.dhx_cal_light_wide .dhx_custom_button { - position:absolute; - top:0; - right:0; - margin-top: 2px; -} -.dhx_cal_light_wide .dhx_repeat_right { - margin-right: 55px; -} -.dhx_minical_popup{ - position:absolute;z-index:10100; - width:251px; height:175px; -} -.dhx_scale_bar_header { - position: absolute; - border-bottom: 1px dotted #8894A3; - width: 100%; -} -.dhx_expand_icon { - position:absolute; top:0px; right:0px; - background-image:url(./imgs/collapse_expand_icon.gif); - width:18px; height:18px; - cursor:pointer; - background-position:0px 18px; - z-index:16; -} -.dhx_scheduler_agenda .dhx_cal_data { - background-image:url(./imgs/databg.png); -} -.dhx_agenda_area{ - width:100%; - overflow-y:auto; - background-image:url(./imgs/databg.png); -} -.dhx_agenda_line{ - height:21px; - clear:both; - overflow:hidden; -} -.dhx_agenda_line div{ - float:left; - width:188px; - border-right:1px dotted #8894A3; - text-align:center; - line-height:21px; - overflow:hidden; -} -.dhx_agenda_area .dhx_agenda_line div{ - border-right:0px dotted #8894A3; -} -.dhx_v_border{ - position:absolute; - left:187px; - top:0; - border-right:1px dotted #8894A3; - width:1px; - height:100%; -} -.dhx_agenda_line .dhx_event_icon{ - width:20px; - border-width:0px; - background:url(./imgs/icon.png) no-repeat; - background-position: 5px 4px; - cursor:pointer; -} -.dhx_agenda_line span{ - padding-left:5px; - line-height:21px; -} - - -.dhx_year_body{ - border-left:1px dotted #586A7E; -} -.dhx_year_week{ - position:relative; -} -.dhx_scale_bar_last{ - border-right:1px dotted #586A7E; -} -.dhx_year_month{ - height:18px; - padding-top:3px; - border:1px dotted #586A7E; - text-align:center; - vertical-align:middle; -} -.dhx_year_body .dhx_before .dhx_month_head, .dhx_year_body .dhx_after .dhx_month_head, .dhx_year_body .dhx_before .dhx_month_head a, .dhx_year_body .dhx_after .dhx_month_head a{ - color:#E2E3E6 !important; -} -.dhx_year_body .dhx_month_body{ - height:0px; - overflow:hidden; -} -.dhx_month_head.dhx_year_event{ - background-color:#FFE763; -} -.dhx_year_body .dhx_before .dhx_month_head, .dhx_year_body .dhx_after .dhx_month_head{ - cursor: default; -} -.dhx_tooltip{ - border:1px solid #BBBBBB; - background-image:url(./imgs/databg.png); - position:absolute; - z-index:9998; - width:300px; - height:auto; - font-family:Tahoma; - font-size:8pt; - overflow:hidden; -} - -.dhx_tooltip_line{ - line-height:20px; - height:20px; - overflow:hidden; -} - -.dhx_tooltip_line .dhx_event_icon{ - width:20px; height:20px; - padding-right:10px; - float:left; - border-width:0px; - position:relative; - background:url(./imgs/icon.png) no-repeat; - background-position: 5px 4px; - cursor:pointer; -} - -.dhx_tooltip_date{ - float:left; - width:auto; - padding-left:5px; - text-align:center; -} - -.dhx_text_disabled{ - color:#887A2E; - font-family:Tahoma; - font-size:8pt; -} - -.dhx_mini_calendar{ - -moz-box-shadow:5px 5px 5px #888; /*Doesn't work in IE*/ - -khtml-box-shadow: 5px 5px 5px #888; -} - -.dhx_mini_calendar .dhx_month_head{ - cursor:pointer; -} -.dhx_mini_calendar .dhx_calendar_click{ - background-color: #C2D5FC; -} -.dhx_cal_navline div.dhx_minical_icon{ - width:18px; - height:18px; - left:190px; - top:1px; - cursor:pointer; - background-image:url(./imgs/calendar.gif); -} - -.dhx_matrix_scell { - height: 100%; -} - -.dhx_matrix_cell, .dhx_matrix_scell{ - overflow:hidden; - text-align:center; - vertical-align:middle; - border-bottom:1px dotted #8894A3; - border-right:1px dotted #8894A3; -} -.dhx_matrix_cell{ - background-color:white; -} -.dhx_matrix_line{ - overflow: hidden; -} -.dhx_matrix_cell div, .dhx_matrix_scell div{ - overflow:hidden; - text-align:center; - height:auto; -} - -.dhx_cal_lsection .dhx_readonly{ - font-size:9pt; - font-size:8pt; - padding:2px; - color:#887A2E; -} -.dhx_cal_event_line .dhx_event_resize { - cursor: w-resize; - background: url(./imgs/resize_dots.png) repeat-y; - position: absolute; - top: 0; - width: 4px; -} -.dhx_event_resize_start { - left: 0; -} -.dhx_event_resize_end { - right: 0; -} - -/* Tree view */ -.dhx_matrix_scell.folder, .dhx_data_table.folder .dhx_matrix_cell{ - background-color: #969394; - cursor: pointer; -} -.dhx_matrix_scell .dhx_scell_level0{ - padding-left: 5px; -} -.dhx_matrix_scell .dhx_scell_level1{ - padding-left: 20px; -} -.dhx_matrix_scell .dhx_scell_level2{ - padding-left: 35px; -} -.dhx_matrix_scell .dhx_scell_level3{ - padding-left: 50px; -} -.dhx_matrix_scell .dhx_scell_level4{ - padding-left: 65px; -} - -.dhx_matrix_scell.folder{ - font-weight: bold; - text-align: left; -} -.dhx_matrix_scell.folder .dhx_scell_expand{ - float: left; - width: 10px; - padding-right:3px; -} -.dhx_matrix_scell.folder .dhx_scell_name{ - float: left; - width: auto; -} -.dhx_matrix_scell.item .dhx_scell_name{ - padding-left:15px; - text-align: left; -} -.dhx_data_table.folder .dhx_matrix_cell{ - border-right: 0; -} -.dhx_section_timeline { - overflow: hidden; - padding: 4px 0 2px 10px; -} -.dhx_section_timeline select{ - width: 552px; -} - -/* Tree view end*/ - -/* Map view */ -.dhx_map_area{ - width:100%; - height:100%; - overflow-y: auto; - overflow-x: hidden; - background-image:url(./imgs/databg.png); -} -.dhx_map_line .dhx_event_icon{ - width:20px; - border-width:0px; - background:url(./imgs/icon.png) no-repeat; - background-position: 5px 4px; - cursor:pointer; -} -.dhx_map_line{ - height:21px; - clear:both; - overflow:hidden; -} -.dhx_map { - position:absolute; -} -.dhx_map_line div{ - float:left; - border-right:1px dotted #8894A3; - text-align:center; - line-height:21px; - overflow:hidden; -} -.dhx_map_line .headline_description{ - float:left; - - border-right:1px dotted #8894A3; - text-align:center; - line-height:21px; - overflow:hidden; -} -.dhx_map_line .dhx_map_description{ - float:left; - border-right: 0 dotted #8894A3; - text-align:center; - line-height:21px; - overflow:hidden; -} -.dhx_map_line .headline_date, .dhx_map_line .headline_description { - border-left: 0; -} -.dhx_map_line .line_description { - float:left; - border-right:1px dotted #8894A3; - text-align:left; - padding-left:5px; - line-height:21px; - overflow:hidden; -} -.dhx_map_line.highlight{ - background-color: #C4C5CC; -} -.dhx_map_area .dhx_map_line div{ - border-right:0px dotted #8894A3; -} -/* Map view end */ - -/* dhtmlXTooltip start */ -.dhtmlXTooltip.tooltip{ - -moz-box-shadow:3px 3px 3px #888888; - -webkit-box-shadow:3px 3px 3px #888888; - -o-box-shadow:3px 3px 3px #888888; - box-shadow:3px 3px 3px #888888; - filter: - progid:DXImageTransform.Microsoft.Shadow(color='#888888', Direction=135, Strength=5) - ; - background-color:white; - border-left:1px dotted #887A2E; - border-top:1px dotted #887A2E; - color:#887A2E; - cursor:default; - padding:10px; - position:absolute; - z-index:500; -} -/* dhtmlXTooltip end */ - -/* Lightbox checkbox section */ -.dhx_cal_checkbox label { - padding-left: 5px; -} -/* Lightbox checkbox section end */ - - -/* Lightbox radiobuttons section */ -.dhx_cal_light .radio { - padding: 2px 0px 2px 10px; -} -.dhx_cal_light .radio input, .dhx_cal_light .radio label{ - line-height: 15px; -} -.dhx_cal_light .radio input { - vertical-align: middle; - margin: 0px; - padding: 0px; -} -.dhx_cal_light .radio label { - vertical-align: middle; - padding-right: 10px; -} -/* Lightbox radiobuttons section end */ - - -/* Lightbox dhtmlx combo section */ -.dhx_cal_light .combo { - padding: 4px; -} -.dhx_cal_light_wide .dhx_combo_box/*, .dhx_cal_light_wide .combo*/ { - width: 608px !important; - left: 10px; -} -/* Lightbox dhtmlx combo section end */ - -/* Agenda week start */ -.dhx_wa_column { - float: left; -} -.dhx_wa_column_last .dhx_wa_day_cont{ - border-left: 1px dotted #8894A3; -} -.dhx_wa_scale_bar { - font-family: Tahoma; - padding-left: 10px; - font-size: 11px; - border-top: 1px dotted #8894A3; - border-bottom: 1px dotted #8894A3; -} -.dhx_wa_day_data { - background-color: #FCFEFC; - overflow-y: auto; -} -.dhx_wa_ev_body { - border-bottom: 1px dotted #778899; - font-size: 12px; - padding: 5px 0 5px 7px; -} -.dhx_wa_dnd { - font-family: Tahoma; - position: absolute; - padding-right: 7px; - color: #887AE2 !important; - background-color: #FFE763 !important; - border: 1px solid #B7A543; -} -.dhx_cal_event_selected{ - background-color: #9cc1db; - color: white; -} -/* Agenda week end */ - -/* timeline second scale start */ -.dhx_second_scale_bar { - border-bottom: 1px dotted #586A7E; - padding-top: 2px; -} -/* timeline second scale end */ - - -/* grid view */ - -.dhx_cal_header div div{ - border-left: 1px dotted #8894A3; -} - -.dhx_grid_area{ - width:100%; - height:100%; - overflow-y:auto; - background-color:#FCFEFC; -} -.dhx_grid_area table{ - border-collapse: collapse; - border-spacing: 0; - width:100%; - table-layout:fixed; -} -.dhx_grid_area td{ - table-layout:fixed; - text-align:center; -} - -.dhx_grid_line{ - height:21px; - clear:both; - overflow:hidden; -} -.dhx_grid_line div{ - float:left; - cursor:default; - padding-top: 0; - padding-bottom: 0; - text-align:center; - line-height:21px; - overflow:hidden; -} - -.dhx_grid_area td, .dhx_grid_line div{ - padding-left:8px; - padding-right:8px; -} - - -.dhx_grid_area tr.dhx_grid_event{ - height:21px; - overflow:hidden; - margin:0 0 1px 0; -} -.dhx_grid_area tr.dhx_grid_event td{ - /*borders for old ies*/ - border-bottom:1px solid #ECEEF4; -} -.dhx_grid_area tr.dhx_grid_event:nth-child(2n+1) td, .dhx_grid_area tr.dhx_grid_event:nth-child(2n) td{ - border-bottom-width:0px; - border-bottom-style:none; -} -.dhx_grid_area tr.dhx_grid_event:nth-child(2n){ - background-color:#ECEEF4;; -} -.dhx_grid_area .dhx_grid_dummy{ - table-layout:auto; - margin:0 !important; - padding:0 !important; -} - -.dhx_grid_v_border{ - position:absolute; - border-right:1px solid #A4BED4; - width:1px; - height:100%; -} - -.dhx_grid_event_selected{ - background-color: #9cc1db !important; - color: white !important; -} - -.dhx_grid_sort_desc .dhx_grid_view_sort{ - background-position: 0 -55px; -} -.dhx_grid_sort_asc .dhx_grid_view_sort{ - background-position: 0 -66px; -} -.dhx_grid_view_sort{ - width:10px; - height:10px; - position: absolute; - border:none !important; - top: 5px; - background-repeat:no-repeat; - background-image: url(./imgs/images.png); -} -/* end grid */ - -/* marked timespans */ -.dhx_marked_timespan { - position: absolute; - width: 100%; -} -.dhx_time_block { - position:absolute; - width:100%; - background:silver; - opacity:0.4; - filter:alpha(opacity=40); - z-index:1; -} -.dhx_time_block_reset { - opacity: 1; - filter:alpha(opacity=100); -} -.dhx_scheduler_month .dhx_marked_timespan { - display: none; -} -.dhx_mini_calendar .dhx_marked_timespan { - display: none; -} -/* now time */ -.dhx_now_time { - width:100%; - border-bottom:2px dotted red; - z-index: 1; -} -.dhx_scheduler_month .dhx_now_time { - border-bottom: 0; - border-left: 2px dotted red; -} -.dhx_matrix_now_time { - border-left:2px dotted red; - z-index: 1; -} - - -/*IE*/ -div.dhx_form_repeat input.radio { margin:-4px 0 0 -4px !ie; } -div.dhx_form_repeat input.checkbox { margin:0 0 0 -4px !ie; } - -/*All*/ -.dhx_form_repeat, .dhx_form_repeat input { - padding:0; - margin:0; - padding-left:5px; - font-family:Tahoma, Verdana; - font-size:11px; - line-height:24px; -} - -.dhx_form_repeat { - overflow:hidden; - /*height:115px;*/ - height:0px; - background-color: #FFF4B5; - /*border: 1px solid #DCC43E;*/ -} - -.dhx_cal_light_wide .dhx_form_repeat { - background-color: transparent; -} - - -.dhx_repeat_center, .dhx_repeat_left{ - height:115px; - padding:10px 0 10px 10px; - float:left; -} - -.dhx_repeat_left{ - width:95px; -} - -.dhx_repeat_center{ - width:335px; - margin-top:12px; -} - -.dhx_repeat_divider{ - float:left; - height:115px; - border-left:1px dotted #DCC43E; - /*background-color: #DCC43E;*/ - width:1px; -} - -.dhx_repeat_right { - float:right; - height:115px; - width:160px; - padding:10px 3px 10px 10px; - margin-top:7px; -} - -input.dhx_repeat_text { - height:16px; - width: 27px; - margin: 0 4px 0 4px; - line-height:18px; - padding: 0 0 0 2px; -} - -.dhx_form_repeat select { - height: 20px; - width: 87px; - padding:0 0 0 2px; - margin: 0 4px 0 4px; -} - -input.dhx_repeat_date{ - height: 18px; - width: 80px; - padding:0 0 0 2px; - margin: 0 4px 0 4px; - background-repeat:no-repeat; - background-position:64px 0; - border:1px #7f9db9 solid; - line-height:18px; -} - -input.dhx_repeat_radio { - margin-right:4px; -} - -input.dhx_repeat_checkbox { - margin:4px 4px 0 0; -} - -.dhx_repeat_days td { - padding-right:5px; -} -.dhx_repeat_days label { - font-size:10px; -} -.dhx_custom_button{ - width:90px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - -ms-border-radius: 4px; - -o-border-radius: 4px; - border-radius: 4px; -} -.dhx_custom_button_recurring{ - background-image:url(./imgs/but_repeat.gif); - background-position:-5px 20px; - width:20px; - margin-right:10px; -} - -/* increase width of lightbox */ -.dhx_cal_light_rec{ - width:640px; -} -.dhx_cal_light_rec .dhx_cal_larea{ - width:632px; -} -.dhx_cal_light_rec.dhx_cal_light_wide{ - width:816px; -} -.dhx_cal_light_rec.dhx_cal_light_wide .dhx_cal_larea{ - width:808px; -} \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.js deleted file mode 100644 index 3dc9dc4e46f..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxscheduler.js +++ /dev/null @@ -1,4806 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ - -if (!window.dhtmlx) { - dhtmlx = function(obj){ - for (var a in obj) dhtmlx[a]=obj[a]; - return dhtmlx; //simple singleton - }; -} -dhtmlx.extend_api=function(name,map,ext){ - var t = window[name]; - if (!t) return; //component not defined - window[name]=function(obj){ - if (obj && typeof obj == "object" && !obj.tagName){ - var that = t.apply(this,(map._init?map._init(obj):arguments)); - //global settings - for (var a in dhtmlx) - if (map[a]) this[map[a]](dhtmlx[a]); - //local settings - for (var a in obj){ - if (map[a]) this[map[a]](obj[a]); - else if (a.indexOf("on")==0){ - this.attachEvent(a,obj[a]); - } - } - } else - var that = t.apply(this,arguments); - if (map._patch) map._patch(this); - return that||this; - }; - window[name].prototype=t.prototype; - if (ext) - dhtmlXHeir(window[name].prototype,ext); -}; - -dhtmlxAjax={ - get:function(url,callback){ - var t=new dtmlXMLLoaderObject(true); - t.async=(arguments.length<3); - t.waitCall=callback; - t.loadXML(url) - return t; - }, - post:function(url,post,callback){ - var t=new dtmlXMLLoaderObject(true); - t.async=(arguments.length<4); - t.waitCall=callback; - t.loadXML(url,true,post) - return t; - }, - getSync:function(url){ - return this.get(url,null,true) - }, - postSync:function(url,post){ - return this.post(url,post,null,true); - } -} - -/** - * @desc: xmlLoader object - * @type: private - * @param: funcObject - xml parser function - * @param: object - jsControl object - * @param: async - sync/async mode (async by default) - * @param: rSeed - enable/disable random seed ( prevent IE caching) - * @topic: 0 - */ -function dtmlXMLLoaderObject(funcObject, dhtmlObject, async, rSeed){ - this.xmlDoc=""; - - if (typeof (async) != "undefined") - this.async=async; - else - this.async=true; - - this.onloadAction=funcObject||null; - this.mainObject=dhtmlObject||null; - this.waitCall=null; - this.rSeed=rSeed||false; - return this; -}; - -dtmlXMLLoaderObject.count = 0; - -/** - * @desc: xml loading handler - * @type: private - * @param: dtmlObject - xmlLoader object - * @topic: 0 - */ -dtmlXMLLoaderObject.prototype.waitLoadFunction=function(dhtmlObject){ - var once = true; - this.check=function (){ - if ((dhtmlObject)&&(dhtmlObject.onloadAction != null)){ - if ((!dhtmlObject.xmlDoc.readyState)||(dhtmlObject.xmlDoc.readyState == 4)){ - if (!once) - return; - - once=false; //IE 5 fix - dtmlXMLLoaderObject.count++; - if (typeof dhtmlObject.onloadAction == "function") - dhtmlObject.onloadAction(dhtmlObject.mainObject, null, null, null, dhtmlObject); - - if (dhtmlObject.waitCall){ - dhtmlObject.waitCall.call(this,dhtmlObject); - dhtmlObject.waitCall=null; - } - } - } - }; - return this.check; -}; - -/** - * @desc: return XML top node - * @param: tagName - top XML node tag name (not used in IE, required for Safari and Mozilla) - * @type: private - * @returns: top XML node - * @topic: 0 - */ -dtmlXMLLoaderObject.prototype.getXMLTopNode=function(tagName, oldObj){ - if (this.xmlDoc.responseXML){ - var temp = this.xmlDoc.responseXML.getElementsByTagName(tagName); - if(temp.length==0 && tagName.indexOf(":")!=-1) - var temp = this.xmlDoc.responseXML.getElementsByTagName((tagName.split(":"))[1]); - var z = temp[0]; - } else - var z = this.xmlDoc.documentElement; - - if (z){ - this._retry=false; - return z; - } - - if (!this._retry){ - this._retry=true; - var oldObj = this.xmlDoc; - this.loadXMLString(this.xmlDoc.responseText.replace(/^[\s]+/,""), true); - return this.getXMLTopNode(tagName, oldObj); - } - - dhtmlxError.throwError("LoadXML", "Incorrect XML", [ - (oldObj||this.xmlDoc), - this.mainObject - ]); - - return document.createElement("DIV"); -}; - -/** - * @desc: load XML from string - * @type: private - * @param: xmlString - xml string - * @topic: 0 - */ -dtmlXMLLoaderObject.prototype.loadXMLString=function(xmlString, silent){ - - if (!_isIE){ - var parser = new DOMParser(); - this.xmlDoc=parser.parseFromString(xmlString, "text/xml"); - } else { - this.xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); - this.xmlDoc.async=this.async; - this.xmlDoc.onreadystatechange = function(){}; - this.xmlDoc["loadXM"+"L"](xmlString); - } - - if (silent) - return; - - if (this.onloadAction) - this.onloadAction(this.mainObject, null, null, null, this); - - if (this.waitCall){ - this.waitCall(); - this.waitCall=null; - } -} -/** - * @desc: load XML - * @type: private - * @param: filePath - xml file path - * @param: postMode - send POST request - * @param: postVars - list of vars for post request - * @topic: 0 - */ -dtmlXMLLoaderObject.prototype.loadXML=function(filePath, postMode, postVars, rpc){ - if (this.rSeed) - filePath+=((filePath.indexOf("?") != -1) ? "&" : "?")+"a_dhx_rSeed="+(new Date()).valueOf(); - this.filePath=filePath; - - if ((!_isIE)&&(window.XMLHttpRequest)) - this.xmlDoc=new XMLHttpRequest(); - else { - this.xmlDoc=new ActiveXObject("Microsoft.XMLHTTP"); - } - - if (this.async) - this.xmlDoc.onreadystatechange=new this.waitLoadFunction(this); - this.xmlDoc.open(postMode ? "POST" : "GET", filePath, this.async); - - if (rpc){ - this.xmlDoc.setRequestHeader("User-Agent", "dhtmlxRPC v0.1 ("+navigator.userAgent+")"); - this.xmlDoc.setRequestHeader("Content-type", "text/xml"); - } - - else if (postMode) - this.xmlDoc.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - - this.xmlDoc.setRequestHeader("X-Requested-With","XMLHttpRequest"); - this.xmlDoc.send(null||postVars); - - if (!this.async) - (new this.waitLoadFunction(this))(); -}; -/** - * @desc: destructor, cleans used memory - * @type: private - * @topic: 0 - */ -dtmlXMLLoaderObject.prototype.destructor=function(){ - this._filterXPath = null; - this._getAllNamedChilds = null; - this._retry = null; - this.async = null; - this.rSeed = null; - this.filePath = null; - this.onloadAction = null; - this.mainObject = null; - this.xmlDoc = null; - this.doXPath = null; - this.doXPathOpera = null; - this.doXSLTransToObject = null; - this.doXSLTransToString = null; - this.loadXML = null; - this.loadXMLString = null; - // this.waitLoadFunction = null; - this.doSerialization = null; - this.xmlNodeToJSON = null; - this.getXMLTopNode = null; - this.setXSLParamValue = null; - return null; -} - -dtmlXMLLoaderObject.prototype.xmlNodeToJSON = function(node){ - var t={}; - for (var i=0; i-1) - _isChrome=true; - -if ((navigator.userAgent.indexOf('Safari') != -1)||(navigator.userAgent.indexOf('Konqueror') != -1)){ - _KHTMLrv = parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Safari')+7, 5)); - - if (_KHTMLrv > 525){ //mimic FF behavior for Safari 3.1+ - _isFF=true; - _FFrv = 1.9; - } else - _isKHTML=true; -} else if (navigator.userAgent.indexOf('Opera') != -1){ - _isOpera=true; - _OperaRv=parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Opera')+6, 3)); -} - - -else if (navigator.appName.indexOf("Microsoft") != -1){ - _isIE=true; - if ((navigator.appVersion.indexOf("MSIE 8.0")!= -1 || navigator.appVersion.indexOf("MSIE 9.0")!= -1 || navigator.appVersion.indexOf("MSIE 10.0")!= -1 ) && document.compatMode != "BackCompat"){ - _isIE=8; - } -} else { - _isFF=true; - _FFrv = parseFloat(navigator.userAgent.split("rv:")[1]) -} - - -//multibrowser Xpath processor -dtmlXMLLoaderObject.prototype.doXPath=function(xpathExp, docObj, namespace, result_type){ - if (_isKHTML || (!_isIE && !window.XPathResult)) - return this.doXPathOpera(xpathExp, docObj); - - if (_isIE){ //IE - if (!docObj) - if (!this.xmlDoc.nodeName) - docObj=this.xmlDoc.responseXML - else - docObj=this.xmlDoc; - - if (!docObj) - dhtmlxError.throwError("LoadXML", "Incorrect XML", [ - (docObj||this.xmlDoc), - this.mainObject - ]); - - if (namespace != null) - docObj.setProperty("SelectionNamespaces", "xmlns:xsl='"+namespace+"'"); // - - if (result_type == 'single'){ - return docObj.selectSingleNode(xpathExp); - } - else { - return docObj.selectNodes(xpathExp)||new Array(0); - } - } else { //Mozilla - var nodeObj = docObj; - - if (!docObj){ - if (!this.xmlDoc.nodeName){ - docObj=this.xmlDoc.responseXML - } - else { - docObj=this.xmlDoc; - } - } - - if (!docObj) - dhtmlxError.throwError("LoadXML", "Incorrect XML", [ - (docObj||this.xmlDoc), - this.mainObject - ]); - - if (docObj.nodeName.indexOf("document") != -1){ - nodeObj=docObj; - } - else { - nodeObj=docObj; - docObj=docObj.ownerDocument; - } - var retType = XPathResult.ANY_TYPE; - - if (result_type == 'single') - retType=XPathResult.FIRST_ORDERED_NODE_TYPE - var rowsCol = new Array(); - var col = docObj.evaluate(xpathExp, nodeObj, function(pref){ - return namespace - }, retType, null); - - if (retType == XPathResult.FIRST_ORDERED_NODE_TYPE){ - return col.singleNodeValue; - } - var thisColMemb = col.iterateNext(); - - while (thisColMemb){ - rowsCol[rowsCol.length]=thisColMemb; - thisColMemb=col.iterateNext(); - } - return rowsCol; - } -} - -function _dhtmlxError(type, name, params){ - if (!this.catches) - this.catches=new Array(); - - return this; -} - -_dhtmlxError.prototype.catchError=function(type, func_name){ - this.catches[type]=func_name; -} -_dhtmlxError.prototype.throwError=function(type, name, params){ - if (this.catches[type]) - return this.catches[type](type, name, params); - - if (this.catches["ALL"]) - return this.catches["ALL"](type, name, params); - - alert("Error type: "+arguments[0]+"\nDescription: "+arguments[1]); - return null; -} - -window.dhtmlxError=new _dhtmlxError(); - - -//opera fake, while 9.0 not released -//multibrowser Xpath processor -dtmlXMLLoaderObject.prototype.doXPathOpera=function(xpathExp, docObj){ - //this is fake for Opera - var z = xpathExp.replace(/[\/]+/gi, "/").split('/'); - var obj = null; - var i = 1; - - if (!z.length) - return []; - - if (z[0] == ".") - obj=[docObj]; else if (z[0] == ""){ - obj=(this.xmlDoc.responseXML||this.xmlDoc).getElementsByTagName(z[i].replace(/\[[^\]]*\]/g, "")); - i++; - } else - return []; - - for (i; i < z.length; i++)obj=this._getAllNamedChilds(obj, z[i]); - - if (z[i-1].indexOf("[") != -1) - obj=this._filterXPath(obj, z[i-1]); - return obj; -} - -dtmlXMLLoaderObject.prototype._filterXPath=function(a, b){ - var c = new Array(); - var b = b.replace(/[^\[]*\[\@/g, "").replace(/[\[\]\@]*/g, ""); - - for (var i = 0; i < a.length; i++) - if (a[i].getAttribute(b)) - c[c.length]=a[i]; - - return c; -} -dtmlXMLLoaderObject.prototype._getAllNamedChilds=function(a, b){ - var c = new Array(); - - if (_isKHTML) - b=b.toUpperCase(); - - for (var i = 0; i < a.length; i++)for (var j = 0; j < a[i].childNodes.length; j++){ - if (_isKHTML){ - if (a[i].childNodes[j].tagName&&a[i].childNodes[j].tagName.toUpperCase() == b) - c[c.length]=a[i].childNodes[j]; - } - - else if (a[i].childNodes[j].tagName == b) - c[c.length]=a[i].childNodes[j]; - } - - return c; -} - -function dhtmlXHeir(a, b){ - for (var c in b) - if (typeof (b[c]) == "function") - a[c]=b[c]; - return a; -} - -function dhtmlxEvent(el, event, handler){ - if (el.addEventListener) - el.addEventListener(event, handler, false); - - else if (el.attachEvent) - el.attachEvent("on"+event, handler); -} - -//============= XSL Extension =================================== - -dtmlXMLLoaderObject.prototype.xslDoc=null; -dtmlXMLLoaderObject.prototype.setXSLParamValue=function(paramName, paramValue, xslDoc){ - if (!xslDoc) - xslDoc=this.xslDoc - - if (xslDoc.responseXML) - xslDoc=xslDoc.responseXML; - var item = - this.doXPath("/xsl:stylesheet/xsl:variable[@name='"+paramName+"']", xslDoc, - "http:/\/www.w3.org/1999/XSL/Transform", "single"); - - if (item != null) - item.firstChild.nodeValue=paramValue -} -dtmlXMLLoaderObject.prototype.doXSLTransToObject=function(xslDoc, xmlDoc){ - if (!xslDoc) - xslDoc=this.xslDoc; - - if (xslDoc.responseXML) - xslDoc=xslDoc.responseXML - - if (!xmlDoc) - xmlDoc=this.xmlDoc; - - if (xmlDoc.responseXML) - xmlDoc=xmlDoc.responseXML - - //MOzilla - if (!_isIE){ - if (!this.XSLProcessor){ - this.XSLProcessor=new XSLTProcessor(); - this.XSLProcessor.importStylesheet(xslDoc); - } - var result = this.XSLProcessor.transformToDocument(xmlDoc); - } else { - var result = new ActiveXObject("Msxml2.DOMDocument.3.0"); - try{ - xmlDoc.transformNodeToObject(xslDoc, result); - }catch(e){ - result = xmlDoc.transformNode(xslDoc); - } - } - return result; -} - -dtmlXMLLoaderObject.prototype.doXSLTransToString=function(xslDoc, xmlDoc){ - var res = this.doXSLTransToObject(xslDoc, xmlDoc); - if(typeof(res)=="string") - return res; - return this.doSerialization(res); -} - -dtmlXMLLoaderObject.prototype.doSerialization=function(xmlDoc){ - if (!xmlDoc) - xmlDoc=this.xmlDoc; - if (xmlDoc.responseXML) - xmlDoc=xmlDoc.responseXML - if (!_isIE){ - var xmlSerializer = new XMLSerializer(); - return xmlSerializer.serializeToString(xmlDoc); - } else - return xmlDoc.xml; -} - -/** - * @desc: - * @type: private - */ -dhtmlxEventable=function(obj){ - obj.attachEvent=function(name, catcher, callObj){ - name='ev_'+name.toLowerCase(); - if (!this[name]) - this[name]=new this.eventCatcher(callObj||this); - - return(name+':'+this[name].addEvent(catcher)); //return ID (event name & event ID) - } - obj.callEvent=function(name, arg0){ - name='ev_'+name.toLowerCase(); - if (this[name]) - return this[name].apply(this, arg0); - return true; - } - obj.checkEvent=function(name){ - return (!!this['ev_'+name.toLowerCase()]) - } - obj.eventCatcher=function(obj){ - var dhx_catch = []; - var z = function(){ - var res = true; - for (var i = 0; i < dhx_catch.length; i++){ - if (dhx_catch[i] != null){ - var zr = dhx_catch[i].apply(obj, arguments); - res=res&&zr; - } - } - return res; - } - z.addEvent=function(ev){ - if (typeof (ev) != "function") - ev=eval(ev); - if (ev) - return dhx_catch.push(ev)-1; - return false; - } - z.removeEvent=function(id){ - dhx_catch[id]=null; - } - return z; - } - obj.detachEvent=function(id){ - if (id != false){ - var list = id.split(':'); //get EventName and ID - this[list[0]].removeEvent(list[1]); //remove event - } - } - obj.detachAllEvents = function(){ - for (var name in this){ - if (name.indexOf("ev_")==0) - delete this[name]; - } - } - obj = null; -}; - -if(!window.dhtmlx) - window.dhtmlx = {}; - -(function(){ - var _dhx_msg_cfg = null; - function callback(config, result){ - var usercall = config.callback; - modality(false); - config.box.parentNode.removeChild(config.box); - _dhx_msg_cfg = config.box = null; - if (usercall) - usercall(result); - } - function modal_key(e){ - if (_dhx_msg_cfg){ - e = e||event; - var code = e.which||event.keyCode; - if (dhtmlx.message.keyboard){ - if (code == 13 || code == 32) - callback(_dhx_msg_cfg, true); - if (code == 27) - callback(_dhx_msg_cfg, false); - } - if (e.preventDefault) - e.preventDefault(); - return !(e.cancelBubble = true); - } - } - if (document.attachEvent) - document.attachEvent("onkeydown", modal_key); - else - document.addEventListener("keydown", modal_key, true); - - function modality(mode){ - if(!modality.cover){ - modality.cover = document.createElement("DIV"); - //necessary for IE only - modality.cover.onkeydown = modal_key; - modality.cover.className = "dhx_modal_cover"; - document.body.appendChild(modality.cover); - } - var height = document.body.scrollHeight; - modality.cover.style.display = mode?"inline-block":"none"; - } - - function button(text, result){ - var button_css = "dhtmlx_"+text.toLowerCase().replace(/ /g, "_")+"_button"; // dhtmlx_ok_button, dhtmlx_click_me_button - return "

"+text+"
"; - } - - function info(text){ - if (!t.area){ - t.area = document.createElement("DIV"); - t.area.className = "dhtmlx_message_area"; - t.area.style[t.position]="5px"; - document.body.appendChild(t.area); - } - - t.hide(text.id); - var message = document.createElement("DIV"); - message.innerHTML = "
"+text.text+"
"; - message.className = "dhtmlx-info dhtmlx-" + text.type; - message.onclick = function(){ - t.hide(text.id); - text = null; - }; - - if (t.position == "bottom" && t.area.firstChild) - t.area.insertBefore(message,t.area.firstChild); - else - t.area.appendChild(message); - - if (text.expire > 0) - t.timers[text.id]=window.setTimeout(function(){ - t.hide(text.id); - }, text.expire); - - t.pull[text.id] = message; - message = null; - - return text.id; - } - function _boxStructure(config, ok, cancel){ - var box = document.createElement("DIV"); - box.className = " dhtmlx_modal_box dhtmlx-"+config.type; - box.setAttribute("dhxbox", 1); - - var inner = ''; - - if (config.width) - box.style.width = config.width; - if (config.height) - box.style.height = config.height; - if (config.title) - inner+='
'+config.title+'
'; - inner+='
'+(config.content?'':config.text)+'
'; - if (ok) - inner += button(config.ok || "OK", true); - if (cancel) - inner += button(config.cancel || "Cancel", false); - if (config.buttons){ - for (var i=0; i 0 ? "&dhx_no_header=1":""); - }; - var combine_urls=function(url){ - return clear_url.call(this,url)+(this._connector_sorting||"")+(this._connector_filter||""); - }; - var sorting_url=function(url,ind,dir){ - this._connector_sorting="&dhx_sort["+ind+"]="+dir; - return combine_urls.call(this,url); - }; - var filtering_url=function(url,inds,vals){ - for (var i=0; i 0) this.xy.nav_height = actual_height; - - var data_y=this.xy.scale_height+this.xy.nav_height+(this._quirks?-2:0); - this.set_xy(this._els["dhx_cal_data"][0],w,h-(data_y+2),0,data_y+2); -}; -scheduler.set_xy=function(node,w,h,x,y){ - node.style.width=Math.max(0,w)+"px"; - node.style.height=Math.max(0,h)+"px"; - if (arguments.length>3){ - node.style.left=x+"px"; - node.style.top=y+"px"; - } -}; -scheduler.get_elements=function(){ - //get all child elements as named hash - var els=this._obj.getElementsByTagName("DIV"); - for (var i=0; i < els.length; i++){ - var name=els[i].className; - if (name) name = name.split(" ")[0]; - if (!this._els[name]) this._els[name]=[]; - this._els[name].push(els[i]); - - //check if name need to be changed - var t=scheduler.locale.labels[els[i].getAttribute("name")||name]; - if (t) els[i].innerHTML=t; - } -}; -scheduler.set_actions=function(){ - for (var a in this._els) - if (this._click[a]) - for (var i=0; i < this._els[a].length; i++) - this._els[a][i].onclick=scheduler._click[a]; - this._obj.onselectstart=function(e){ return false; }; - this._obj.onmousemove=function(e){ - scheduler._on_mouse_move(e||event); - }; - this._obj.onmousedown=function(e){ - scheduler._on_mouse_down(e||event); - }; - this._obj.onmouseup=function(e){ - scheduler._on_mouse_up(e||event); - }; - this._obj.ondblclick=function(e){ - scheduler._on_dbl_click(e||event); - }; - this._obj.oncontextmenu = function(e) { - var ev = e||event; - var src = ev.target||ev.srcElement; - var returnValue = scheduler.callEvent("onContextMenu", [scheduler._locate_event(src), ev]); - return returnValue; - }; -}; -scheduler.select=function(id){ - if (this._select_id==id) return; - this.editStop(false); - this.unselect(); - this._select_id = id; - this.updateEvent(id); -}; -scheduler.unselect=function(id){ - if (id && id!=this._select_id) return; - var t=this._select_id; - this._select_id = null; - if (t) this.updateEvent(t); -}; -scheduler.getState=function(){ - return { - mode: this._mode, - date: this._date, - min_date: this._min_date, - max_date: this._max_date, - editor_id: this._edit_id, - lightbox_id: this._lightbox_id, - new_event: this._new_event, - select_id: this._select_id, - expanded: this.expanded, - drag_id: this._drag_id, - drag_mode: this._drag_mode - }; -}; -scheduler._click={ - dhx_cal_data:function(e){ - var trg = e?e.target:event.srcElement; - var id = scheduler._locate_event(trg); - - e = e || event; - - if (!id) { - scheduler.callEvent("onEmptyClick",[scheduler.getActionData(e).date, e]); - } else { - if ( !scheduler.callEvent("onClick",[id,e]) || scheduler.config.readonly ) return; - } - - if (id && scheduler.config.select) { - - scheduler.select(id); - var mask = trg.className; - if (mask.indexOf("_icon")!=-1) - scheduler._click.buttons[mask.split(" ")[1].replace("icon_","")](id); - } else - scheduler._close_not_saved(); - }, - dhx_cal_prev_button:function(){ - scheduler._click.dhx_cal_next_button(0,-1); - }, - dhx_cal_next_button:function(dummy,step){ - scheduler.setCurrentView(scheduler.date.add( //next line changes scheduler._date , but seems it has not side-effects - scheduler.date[scheduler._mode+"_start"](scheduler._date),(step||1),scheduler._mode)); - }, - dhx_cal_today_button:function(){ - scheduler.setCurrentView(new Date()); - }, - dhx_cal_tab:function(){ - var name = this.getAttribute("name"); - var mode = name.substring(0, name.search("_tab")); - scheduler.setCurrentView(scheduler._date,mode); - }, - buttons:{ - "delete":function(id){ - var c = scheduler.locale.labels.confirm_deleting; - scheduler._dhtmlx_confirm(c, scheduler.locale.labels.title_confirm_deleting, function(){ scheduler.deleteEvent(id) }); - }, - edit:function(id){ scheduler.edit(id); }, - save:function(id){ scheduler.editStop(true); }, - details:function(id){ scheduler.showLightbox(id); }, - cancel:function(id){ scheduler.editStop(false); } - } -}; -scheduler._dhtmlx_confirm = function(message, title, callback) { - if (!message) - return callback(); - var opts = { text: message }; - if (title) - opts.title = title; - if (callback) { - opts.callback = function(result) { - if (result) - callback(); - }; - } - dhtmlx.confirm(opts); -}; -scheduler.addEventNow=function(start,end,e){ - var base = {}; - if (start && start.constructor.toString().match(/object/i) !== null){ - base = start; - start = null; - } - - var d = (this.config.event_duration||this.config.time_step)*60000; - if (!start) start = Math.round((new Date()).valueOf()/d)*d; - var start_date = new Date(start); - if (!end){ - var start_hour = this.config.first_hour; - if (start_hour > start_date.getHours()){ - start_date.setHours(start_hour); - start = start_date.valueOf(); - } - end = start.valueOf()+d; - } - var end_date = new Date(end); - - // scheduler.addEventNow(new Date(), new Date()) + collision though get_visible events defect (such event was not retrieved) - if(start_date.valueOf() == end_date.valueOf()) - end_date.setTime(end_date.valueOf()+d); - - base.start_date = base.start_date||start_date; - base.end_date = base.end_date||end_date; - base.text = base.text||this.locale.labels.new_event; - base.id = this._drag_id = this.uid(); - this._drag_mode="new-size"; - - this._loading=true; - this.addEvent(base); - this.callEvent("onEventCreated",[this._drag_id,e]); - this._loading=false; - - this._drag_event={}; //dummy , to trigger correct event updating logic - this._on_mouse_up(e); -}; -scheduler._on_dbl_click=function(e,src){ - src = src||(e.target||e.srcElement); - if (this.config.readonly) return; - var name = src.className.split(" ")[0]; - switch(name){ - case "dhx_scale_holder": - case "dhx_scale_holder_now": - case "dhx_month_body": - case "dhx_wa_day_data": - case "dhx_marked_timespan": - if (!scheduler.config.dblclick_create) break; - this.addEventNow(this.getActionData(e).date,null,e); - break; - case "dhx_cal_event": - case "dhx_wa_ev_body": - case "dhx_agenda_line": - case "dhx_grid_event": - case "dhx_cal_event_line": - case "dhx_cal_event_clear": - var id = this._locate_event(src); - if (!this.callEvent("onDblClick",[id,e])) return; - if (this.config.details_on_dblclick || this._table_view || !this.getEvent(id)._timed || !this.config.select) - this.showLightbox(id); - else - this.edit(id); - break; - case "dhx_time_block": - case "dhx_cal_container": - return; - break; - default: - var t = this["dblclick_"+name]; - if (t) { - t.call(this,e); - } - else { - if (src.parentNode && src != this) - return scheduler._on_dbl_click(e,src.parentNode); - } - break; - } -}; - -scheduler._mouse_coords=function(ev){ - var pos; - var b=document.body; - var d = document.documentElement; - if(ev.pageX || ev.pageY) - pos={x:ev.pageX, y:ev.pageY}; - else pos={ - x:ev.clientX + (b.scrollLeft||d.scrollLeft||0) - b.clientLeft, - y:ev.clientY + (b.scrollTop||d.scrollTop||0) - b.clientTop - }; - - //apply layout - pos.x-=getAbsoluteLeft(this._obj)+(this._table_view?0:this.xy.scale_width); - pos.y-=getAbsoluteTop(this._obj)+this.xy.nav_height+(this._dy_shift||0)+this.xy.scale_height-this._els["dhx_cal_data"][0].scrollTop; - pos.ev = ev; - - var handler = this["mouse_"+this._mode]; - if (handler) - return handler.call(this,pos); - - //transform to date - if (!this._table_view) { - pos.x=Math.min(this._cols.length-1, Math.max(0,Math.ceil(pos.x/this._cols[0])-1)); - pos.y=Math.max(0,Math.ceil(pos.y*60/(this.config.time_step*this.config.hour_size_px))-1)+this.config.first_hour*(60/this.config.time_step); - } else { - if (!this._cols || !this._colsS) // agenda/map views - return pos; - var dy=0; - for (dy=1; dy < this._colsS.heights.length; dy++) - if (this._colsS.heights[dy]>pos.y) break; - - pos.y=Math.ceil( (Math.max(0, pos.x/this._cols[0])+Math.max(0,dy-1)*7)*24*60/this.config.time_step ); - - if (scheduler._drag_mode || this._mode == "month") - pos.y=(Math.max(0,Math.ceil(pos.x/this._cols[0])-1)+Math.max(0,dy-1)*7)*24*60/this.config.time_step; - - pos.x=0; - } - - return pos; -}; -scheduler._close_not_saved=function(){ - if (new Date().valueOf()-(scheduler._new_event||0) > 500 && scheduler._edit_id){ - var c=scheduler.locale.labels.confirm_closing; - - scheduler._dhtmlx_confirm(c, scheduler.locale.labels.title_confirm_closing, function() { scheduler.editStop(scheduler.config.positive_closing); }); - } -}; -scheduler._correct_shift=function(start, back){ - return start-=((new Date(scheduler._min_date)).getTimezoneOffset()-(new Date(start)).getTimezoneOffset())*60000*(back?-1:1); -}; -scheduler._on_mouse_move=function(e){ - if (this._drag_mode){ - var pos=this._mouse_coords(e); - if (!this._drag_pos || pos.custom || this._drag_pos.x!=pos.x || this._drag_pos.y!=pos.y){ - var start, end; - if (this._edit_id!=this._drag_id) - this._close_not_saved(); - - this._drag_pos=pos; - - if (this._drag_mode=="create"){ - this._close_not_saved(); - this._loading=true; //will be ignored by dataprocessor - - start = this._get_date_from_pos(pos).valueOf(); - - var res = this.callEvent("onBeforeEventCreated", [e]); - if (!res) - return; - - if (!this._drag_start){ - this._drag_start=start; return; - } - end = start; - if (end==this._drag_start) return; - - this._drag_id=this.uid(); - this.addEvent(new Date(this._drag_start), new Date(end),this.locale.labels.new_event,this._drag_id, pos.fields); - - this.callEvent("onEventCreated",[this._drag_id,e]); - this._loading=false; - this._drag_mode="new-size"; - - } - - var ev=this.getEvent(this._drag_id); - - if (this._drag_mode=="move"){ - start = this._min_date.valueOf()+(pos.y*this.config.time_step+pos.x*24*60)*60000; - if (!pos.custom && this._table_view) start+=this.date.time_part(ev.start_date)*1000; - start = this._correct_shift(start); - end = ev.end_date.valueOf()-(ev.start_date.valueOf()-start); - } else { // resize - start = ev.start_date.valueOf(); - end = ev.end_date.valueOf(); - if (this._table_view) { - var resize_date = this._min_date.valueOf()+pos.y*this.config.time_step*60000 + (pos.custom?0:24*60*60000); - if (this._mode == "month") - resize_date = this._correct_shift(resize_date, false); - - if (pos.resize_from_start) - start = resize_date; - else - end = resize_date; - } else { - end = this.date.date_part(new Date(ev.end_date)).valueOf()+pos.y*this.config.time_step*60000; - this._els["dhx_cal_data"][0].style.cursor="s-resize"; - if (this._mode == "week" || this._mode == "day") - end = this._correct_shift(end); - } - if (this._drag_mode == "new-size") { - if (end <= this._drag_start){ - var shift = pos.shift||((this._table_view && !pos.custom)?24*60*60000:0); - start = end-(pos.shift?0:shift); - end = this._drag_start+(shift||(this.config.time_step*60000)); - } else { - start = this._drag_start; - } - } else { - if (end<=start) - end=start+this.config.time_step*60000; - } - } - var new_end = new Date(end-1); - var new_start = new Date(start); - //prevent out-of-borders situation for day|week view - if ( this._table_view || (new_end.getDate()==new_start.getDate() && new_end.getHours()=ed) - cls='dhx_after'; - else if (sd.valueOf()==cd.valueOf()) - cls='dhx_now'; - html+=" class='"+cls+" "+this.templates.month_date_class(sd,cd)+"' "; - html+=">
"+this.templates.month_day(sd)+"
"; - rendered_dates.push(sd); - sd=this.date.add(sd,1,"day"); - } - html+=""; - h[i] = cellheight; - cellheight+=this._colsS.height; - } - html+=""; - this._max_date=sd; - - b.innerHTML=html; - - this._scales = {}; - var divs = b.getElementsByTagName('div'); - for (var i=0; i11?\"pm\":\"am\")+\""; - case "%A": return "\"+(date.getHours()>11?\"PM\":\"AM\")+\""; - case "%s": return "\"+scheduler.date.to_fixed(date.getSeconds())+\""; - case "%W": return "\"+scheduler.date.to_fixed(scheduler.date.getISOWeek(date))+\""; - default: return a; - } - }); - if (utc) format=format.replace(/date\.get/g,"date.getUTC"); - return new Function("date","return \""+format+"\";"); - }, - str_to_date:function(format,utc){ - var splt="var temp=date.match(/[a-zA-Z]+|[0-9]+/g);"; - var mask=format.match(/%[a-zA-Z]/g); - for (var i=0; i50?1900:2000);"; - break; - case "%g": - case "%G": - case "%h": - case "%H": - splt+="set[3]=temp["+i+"]||0;"; - break; - case "%i": - splt+="set[4]=temp["+i+"]||0;"; - break; - case "%Y": splt+="set[0]=temp["+i+"]||0;"; - break; - case "%a": - case "%A": splt+="set[3]=set[3]%12+((temp["+i+"]||'').toLowerCase()=='am'?0:12);"; - break; - case "%s": splt+="set[5]=temp["+i+"]||0;"; - break; - case "%M": splt+="set[1]=scheduler.locale.date.month_short_hash[temp["+i+"]]||0;"; - break; - case "%F": splt+="set[1]=scheduler.locale.date.month_full_hash[temp["+i+"]]||0;"; - break; - default: - break; - } - } - var code ="set[0],set[1],set[2],set[3],set[4],set[5]"; - if (utc) code =" Date.UTC("+code+")"; - return new Function("date","var set=[0,0,1,0,0,0]; "+splt+" return new Date("+code+");"); - }, - getISOWeek: function(ndate) { - if(!ndate) return false; - var nday = ndate.getDay(); - if (nday === 0) { - nday = 7; - } - var first_thursday = new Date(ndate.valueOf()); - first_thursday.setDate(ndate.getDate() + (4 - nday)); - var year_number = first_thursday.getFullYear(); // year of the first Thursday - var ordinal_date = Math.round( (first_thursday.getTime() - new Date(year_number, 0, 1).getTime()) / 86400000); //ordinal date of the first Thursday - 1 (so not really ordinal date) - var week_number = 1 + Math.floor( ordinal_date / 7); - return week_number; - }, - getUTCISOWeek: function(ndate){ - return this.getISOWeek(ndate); - }, - convert_to_utc: function(date) { - return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); - } -}; -scheduler.locale = { - date:{ - month_full:["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - month_short:["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], - day_full:["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - day_short:["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] - }, - labels:{ - dhx_cal_today_button:"Today", - day_tab:"Day", - week_tab:"Week", - month_tab:"Month", - new_event:"New event", - icon_save:"Save", - icon_cancel:"Cancel", - icon_details:"Details", - icon_edit:"Edit", - icon_delete:"Delete", - confirm_closing:"",//Your changes will be lost, are your sure ? - confirm_deleting:"Event will be deleted permanently, are you sure?", - section_description:"Description", - section_time:"Time period", - full_day:"Full day", - - /*recurring events*/ - confirm_recurring:"Do you want to edit the whole set of repeated events?", - section_recurring:"Repeat event", - button_recurring:"Disabled", - button_recurring_open:"Enabled", - button_edit_series: "Edit series", - button_edit_occurrence: "Edit occurrence", - - /*agenda view extension*/ - agenda_tab:"Agenda", - date:"Date", - description:"Description", - - /*year view extension*/ - year_tab:"Year", - - /* week agenda extension */ - week_agenda_tab: "Agenda", - - /*grid view extension*/ - grid_tab: "Grid" - } -}; - - -/* -%e Day of the month without leading zeros (01..31) -%d Day of the month, 2 digits with leading zeros (01..31) -%j Day of the year, 3 digits with leading zeros (001..366) -%a A textual representation of a day, two letters -%W A full textual representation of the day of the week - -%c Numeric representation of a month, without leading zeros (0..12) -%m Numeric representation of a month, with leading zeros (00..12) -%b A short textual representation of a month, three letters (Jan..Dec) -%M A full textual representation of a month, such as January or March (January..December) - -%y A two digit representation of a year (93..03) -%Y A full numeric representation of a year, 4 digits (1993..03) -*/ - -scheduler.config={ - default_date: "%j %M %Y", - month_date: "%F %Y", - load_date: "%Y-%m-%d", - week_date: "%l", - day_date: "%D, %F %j", - hour_date: "%H:%i", - month_day: "%d", - xml_date: "%m/%d/%Y %H:%i", - api_date: "%d-%m-%Y %H:%i", - - hour_size_px: 42, - time_step: 5, - - start_on_monday: 1, - first_hour: 0, - last_hour: 24, - readonly: false, - drag_resize: 1, - drag_move: 1, - drag_create: 1, - dblclick_create: 1, - edit_on_create: 1, - details_on_create: 0, - click_form_details: 0, - cascade_event_display: false, - cascade_event_count: 4, - cascade_event_margin: 30, - drag_lightbox: true, - preserve_scroll: true, - select: true, - - server_utc: false, - - positive_closing: false, - - icons_edit: ["icon_save", "icon_cancel"], - icons_select: ["icon_details", "icon_edit", "icon_delete"], - buttons_left: ["dhx_save_btn", "dhx_cancel_btn"], - buttons_right: ["dhx_delete_btn"], - lightbox: { - sections: [ - {name: "description", height: 200, map_to: "text", type: "textarea", focus: true}, - {name: "time", height: 72, type: "time", map_to: "auto"} - ] - }, - highlight_displayed_event: true, - displayed_event_color: "#ffc5ab", - displayed_event_text_color: "#7e2727" -}; -scheduler.templates={}; -scheduler.init_templates=function(){ - var labels = scheduler.locale.labels; - labels.dhx_save_btn = labels.icon_save; - labels.dhx_cancel_btn = labels.icon_cancel; - labels.dhx_delete_btn = labels.icon_delete; - - - var d=scheduler.date.date_to_str; - var c=scheduler.config; - var f = function(a,b){ - for (var c in b) - if (!a[c]) a[c]=b[c]; - }; - f(scheduler.templates,{ - day_date:d(c.default_date), - month_date:d(c.month_date), - week_date:function(d1,d2){ - return scheduler.templates.day_date(d1)+" – "+scheduler.templates.day_date(scheduler.date.add(d2,-1,"day")); - }, - day_scale_date:d(c.default_date), - month_scale_date:d(c.week_date), - week_scale_date:d(c.day_date), - hour_scale:d(c.hour_date), - time_picker:d(c.hour_date), - event_date:d(c.hour_date), - month_day:d(c.month_day), - xml_date:scheduler.date.str_to_date(c.xml_date,c.server_utc), - load_format:d(c.load_date,c.server_utc), - xml_format:d(c.xml_date,c.server_utc), - api_date:scheduler.date.str_to_date(c.api_date), - event_header:function(start,end,ev){ - return scheduler.templates.event_date(start)+" - "+scheduler.templates.event_date(end); - }, - event_text:function(start,end,ev){ - return ev.text; - }, - event_class:function(start,end,ev){ - return ""; - }, - month_date_class:function(d){ - return ""; - }, - week_date_class:function(d){ - return ""; - }, - event_bar_date:function(start,end,ev){ - return scheduler.templates.event_date(start)+" "; - }, - event_bar_text:function(start,end,ev){ - return ev.text; - } - }); - this.callEvent("onTemplatesReady",[]); -}; - - - -scheduler.uid = function() { - if (!this._seed) this._seed = (new Date).valueOf(); - return this._seed++; -}; -scheduler._events = {}; -scheduler.clearAll = function() { - this._events = {}; - this._loaded = {}; - this.clear_view(); -}; -scheduler.addEvent = function(start_date, end_date, text, id, extra_data) { - if (!arguments.length) - return this.addEventNow(); - var ev = start_date; - if (arguments.length != 1) { - ev = extra_data || {}; - ev.start_date = start_date; - ev.end_date = end_date; - ev.text = text; - ev.id = id; - } - ev.id = ev.id || scheduler.uid(); - ev.text = ev.text || ""; - - if (typeof ev.start_date == "string") ev.start_date = this.templates.api_date(ev.start_date); - if (typeof ev.end_date == "string") ev.end_date = this.templates.api_date(ev.end_date); - - var d = (this.config.event_duration || this.config.time_step) * 60000; - if (ev.start_date.valueOf() == ev.end_date.valueOf()) - ev.end_date.setTime(ev.end_date.valueOf() + d); - - ev._timed = this.is_one_day_event(ev); - - var is_new = !this._events[ev.id]; - this._events[ev.id] = ev; - this.event_updated(ev); - if (!this._loading) - this.callEvent(is_new ? "onEventAdded" : "onEventChanged", [ev.id, ev]); - return ev.id; -}; -scheduler.deleteEvent = function(id, silent) { - var ev = this._events[id]; - if (!silent && (!this.callEvent("onBeforeEventDelete", [id, ev]) || !this.callEvent("onConfirmedBeforeEventDelete", [id, ev]))) - return; - if (ev) { - delete this._events[id]; - this.unselect(id); - this.event_updated(ev); - } - - this.callEvent("onEventDeleted", [id, ev]); -}; -scheduler.getEvent = function(id) { - return this._events[id]; -}; -scheduler.setEvent = function(id, hash) { - this._events[id] = hash; -}; -scheduler.for_rendered = function(id, method) { - for (var i = this._rendered.length - 1; i >= 0; i--) - if (this._rendered[i].getAttribute("event_id") == id) - method(this._rendered[i], i); -}; -scheduler.changeEventId = function(id, new_id) { - if (id == new_id) return; - var ev = this._events[id]; - if (ev) { - ev.id = new_id; - this._events[new_id] = ev; - delete this._events[id]; - } - this.for_rendered(id, function(r) { - r.setAttribute("event_id", new_id); - }); - if (this._select_id == id) this._select_id = new_id; - if (this._edit_id == id) this._edit_id = new_id; - //if (this._drag_id==id) this._drag_id=new_id; - this.callEvent("onEventIdChange", [id, new_id]); -}; - -(function() { - var attrs = ["text", "Text", "start_date", "StartDate", "end_date", "EndDate"]; - var create_getter = function(name) { - return function(id) { return (scheduler.getEvent(id))[name]; }; - }; - var create_setter = function(name) { - return function(id, value) { - var ev = scheduler.getEvent(id); - ev[name] = value; - ev._changed = true; - ev._timed = this.is_one_day_event(ev); - scheduler.event_updated(ev, true); - }; - }; - for (var i = 0; i < attrs.length; i += 2) { - scheduler["getEvent" + attrs[i + 1]] = create_getter(attrs[i]); - scheduler["setEvent" + attrs[i + 1]] = create_setter(attrs[i]); - } -})(); - -scheduler.event_updated = function(ev, force) { - if (this.is_visible_events(ev)) - this.render_view_data(); - else - this.clear_event(ev.id); -}; -scheduler.is_visible_events = function(ev) { - return (ev.start_date < this._max_date && this._min_date < ev.end_date); -}; -scheduler.is_one_day_event = function(ev) { - var delta = ev.end_date.getDate() - ev.start_date.getDate(); - - if (!delta) - return ev.start_date.getMonth() == ev.end_date.getMonth() && ev.start_date.getFullYear() == ev.end_date.getFullYear(); - else { - if (delta < 0) delta = Math.ceil((ev.end_date.valueOf() - ev.start_date.valueOf()) / (24 * 60 * 60 * 1000)); - return (delta == 1 && !ev.end_date.getHours() && !ev.end_date.getMinutes() && (ev.start_date.getHours() || ev.start_date.getMinutes() )); - } - -}; -scheduler.get_visible_events = function(only_timed) { - //not the best strategy for sure - var stack = []; - - for (var id in this._events) - if (this.is_visible_events(this._events[id])) - if (!only_timed || this._events[id]._timed) - if (this.filter_event(id, this._events[id])) - stack.push(this._events[id]); - - return stack; -}; -scheduler.filter_event = function(id, ev) { - var filter = this["filter_" + this._mode]; - return (filter) ? filter(id, ev) : true; -}; -scheduler.render_view_data = function(evs, hold) { - if (!evs) { - if (this._not_render) { - this._render_wait = true; - return; - } - this._render_wait = false; - - this.clear_view(); - evs = this.get_visible_events(!(this._table_view || this.config.multi_day)); - } - - if (this.config.multi_day && !this._table_view) { - - var tvs = []; - var tvd = []; - for (var i = 0; i < evs.length; i++) { - if (evs[i]._timed) - tvs.push(evs[i]); - else - tvd.push(evs[i]); - } - - // multiday events - this._rendered_location = this._els['dhx_multi_day'][0]; - this._table_view = true; - this.render_data(tvd, hold); - this._table_view = false; - - // normal events - this._rendered_location = this._els['dhx_cal_data'][0]; - this._table_view = false; - this.render_data(tvs, hold); - - } else { - this._rendered_location = this._els['dhx_cal_data'][0]; - this.render_data(evs, hold); - } -}; -scheduler.render_data = function(evs, hold) { - evs = this._pre_render_events(evs, hold); - for (var i = 0; i < evs.length; i++) - if (this._table_view) - this.render_event_bar(evs[i]); - else - this.render_event(evs[i]); -}; -scheduler._pre_render_events = function(evs, hold) { - var hb = this.xy.bar_height; - var h_old = this._colsS.heights; - var h = this._colsS.heights = [0, 0, 0, 0, 0, 0, 0]; - var data = this._els["dhx_cal_data"][0]; - - if (!this._table_view) - evs = this._pre_render_events_line(evs, hold); //ignore long events for now - else - evs = this._pre_render_events_table(evs, hold); - - if (this._table_view) { - if (hold) - this._colsS.heights = h_old; - else { - var evl = data.firstChild; - if (evl.rows) { - for (var i = 0; i < evl.rows.length; i++) { - h[i]++; - if ((h[i]) * hb > this._colsS.height - 22) { // 22 - height of cell's header - //we have overflow, update heights - var cells = evl.rows[i].cells; - for (var j = 0; j < cells.length; j++) { - cells[j].childNodes[1].style.height = h[i] * hb + "px"; - } - h[i] = (h[i - 1] || 0) + cells[0].offsetHeight; - } - h[i] = (h[i - 1] || 0) + evl.rows[i].cells[0].offsetHeight; - } - h.unshift(0); - if (evl.parentNode.offsetHeight < evl.parentNode.scrollHeight && !evl._h_fix) { - //we have v-scroll, decrease last day cell - for (var i = 0; i < evl.rows.length; i++) { - var cell = evl.rows[i].cells[6].childNodes[0]; - var w = cell.offsetWidth - scheduler.xy.scroll_width + "px"; - cell.style.width = w; - cell.nextSibling.style.width = w; - } - evl._h_fix = true; - } - } else { - if (!evs.length && this._els["dhx_multi_day"][0].style.visibility == "visible") - h[0] = -1; - if (evs.length || h[0] == -1) { - //shift days to have space for multiday events - var childs = evl.parentNode.childNodes; - var dh = ((h[0] + 1) * hb + 1) + "px"; // +1 so multiday events would have 2px from top and 2px from bottom by default - data.style.top = (this._els["dhx_cal_navline"][0].offsetHeight + this._els["dhx_cal_header"][0].offsetHeight + parseInt(dh, 10)) + 'px'; - data.style.height = (this._obj.offsetHeight - parseInt(data.style.top, 10) - (this.xy.margin_top || 0)) + 'px'; - var last = this._els["dhx_multi_day"][0]; - last.style.height = dh; - last.style.visibility = (h[0] == -1 ? "hidden" : "visible"); - last = this._els["dhx_multi_day"][1]; - last.style.height = dh; - last.style.visibility = (h[0] == -1 ? "hidden" : "visible"); - last.className = h[0] ? "dhx_multi_day_icon" : "dhx_multi_day_icon_small"; - this._dy_shift = (h[0] + 1) * hb; - h[0] = 0; - } - } - } - } - - return evs; -}; -scheduler._get_event_sday = function(ev) { - return Math.floor((ev.start_date.valueOf() - this._min_date.valueOf()) / (24 * 60 * 60 * 1000)); -}; -scheduler._get_event_mapped_end_date = function(ev) { - var end_date = ev.end_date; - if (this.config.separate_short_events) { - var ev_duration = (ev.end_date - ev.start_date) / 60000; // minutes - if (ev_duration < this._min_mapped_duration) { - end_date = this.date.add(end_date, this._min_mapped_duration - ev_duration, "minute"); - } - } - return end_date; -}; -scheduler._pre_render_events_line = function(evs, hold) { - evs.sort(function(a, b) { - if (a.start_date.valueOf() == b.start_date.valueOf()) - return a.id > b.id ? 1 : -1; - return a.start_date > b.start_date ? 1 : -1; - }); - var days = []; //events by weeks - var evs_originals = []; - - this._min_mapped_duration = Math.ceil(this.xy.min_event_height * 60 / this.config.hour_size_px); // values could change along the way - - for (var i = 0; i < evs.length; i++) { - var ev = evs[i]; - - //check date overflow - var sd = ev.start_date; - var ed = ev.end_date; - //check scale overflow - var sh = sd.getHours(); - var eh = ed.getHours(); - - ev._sday = this._get_event_sday(ev); // sday based on event start_date - if (!days[ev._sday]) days[ev._sday] = []; - - if (!hold) { - ev._inner = false; - - var stack = days[ev._sday]; - - while (stack.length) { - var t_ev = stack[stack.length - 1]; - var t_end_date = this._get_event_mapped_end_date(t_ev); - if (t_end_date.valueOf() <= ev.start_date.valueOf()) { - stack.splice(stack.length - 1, 1); - } else { - break; - } - } - - var sorderSet = false; - for (var j = 0; j < stack.length; j++) { - var t_ev = stack[j]; - var t_end_date = this._get_event_mapped_end_date(t_ev); - if (t_end_date.valueOf() <= ev.start_date.valueOf()) { - sorderSet = true; - ev._sorder = t_ev._sorder; - stack.splice(j, 1); - ev._inner = true; - break; - } - } - - if (stack.length) - stack[stack.length - 1]._inner = true; - - if (!sorderSet) { - if (stack.length) { - if (stack.length <= stack[stack.length - 1]._sorder) { - if (!stack[stack.length - 1]._sorder) - ev._sorder = 0; - else - for (j = 0; j < stack.length; j++) { - var _is_sorder = false; - for (var k = 0; k < stack.length; k++) { - if (stack[k]._sorder == j) { - _is_sorder = true; - break; - } - } - if (!_is_sorder) { - ev._sorder = j; - break; - } - } - ev._inner = true; - } else { - var _max_sorder = stack[0]._sorder; - for (j = 1; j < stack.length; j++) { - if (stack[j]._sorder > _max_sorder) - _max_sorder = stack[j]._sorder; - } - ev._sorder = _max_sorder + 1; - ev._inner = false; - } - - } else - ev._sorder = 0; - } - - stack.push(ev); - - if (stack.length > (stack.max_count || 0)) { - stack.max_count = stack.length; - ev._count = stack.length; - } else { - ev._count = (ev._count) ? ev._count : 1; - } - } - - if (sh < this.config.first_hour || eh >= this.config.last_hour) { - // Need to create copy of event as we will be changing it's start/end date - // e.g. first_hour = 11 and event.start_date hours = 9. Need to preserve that info - evs_originals.push(ev); - evs[i] = ev = this._copy_event(ev); - - if (sh < this.config.first_hour) { - ev.start_date.setHours(this.config.first_hour); - ev.start_date.setMinutes(0); - } - if (eh >= this.config.last_hour) { - ev.end_date.setMinutes(0); - ev.end_date.setHours(this.config.last_hour); - } - - if (ev.start_date > ev.end_date || sh == this.config.last_hour) { - evs.splice(i, 1); - i--; - continue; - } - } - } - if (!hold) { - for (var i = 0; i < evs.length; i++) { - evs[i]._count = days[evs[i]._sday].max_count; - } - for (var i = 0; i < evs_originals.length; i++) - evs_originals[i]._count = days[evs_originals[i]._sday].max_count; - } - - return evs; -}; -scheduler._time_order = function(evs) { - evs.sort(function(a, b) { - if (a.start_date.valueOf() == b.start_date.valueOf()) { - if (a._timed && !b._timed) return 1; - if (!a._timed && b._timed) return -1; - return a.id > b.id ? 1 : -1; - } - return a.start_date > b.start_date ? 1 : -1; - }); -}; -scheduler._pre_render_events_table = function(evs, hold) { // max - max height of week slot - this._time_order(evs); - var out = []; - var weeks = [ - [], - [], - [], - [], - [], - [], - [] - ]; //events by weeks - var max = this._colsS.heights; - var start_date; - var cols = this._cols.length; - var chunks_info = {}; - - for (var i = 0; i < evs.length; i++) { - var ev = evs[i]; - var id = ev.id; - if (!chunks_info[id]) { - chunks_info[id] = { - first_chunk: true, - last_chunk: true - }; - } - var chunk_info = chunks_info[id]; - var sd = (start_date || ev.start_date); - var ed = ev.end_date; - //trim events which are crossing through current view - if (sd < this._min_date) { - chunk_info.first_chunk = false; - sd = this._min_date; - } - if (ed > this._max_date) { - chunk_info.last_chunk = false; - ed = this._max_date; - } - - var locate_s = this.locate_holder_day(sd, false, ev); - ev._sday = locate_s % cols; - var locate_e = this.locate_holder_day(ed, true, ev) || cols; - ev._eday = (locate_e % cols) || cols; //cols used to fill full week, when event end on monday - ev._length = locate_e - locate_s; - - //3600000 - compensate 1 hour during winter|summer time shift - ev._sweek = Math.floor((this._correct_shift(sd.valueOf(), 1) - this._min_date.valueOf()) / (60 * 60 * 1000 * 24 * cols)); - - //current slot - var stack = weeks[ev._sweek]; - //check order position - var stack_line; - - for (stack_line = 0; stack_line < stack.length; stack_line++) - if (stack[stack_line]._eday <= ev._sday) - break; - - if (!ev._sorder || !hold) { - ev._sorder = stack_line; - } - - if (ev._sday + ev._length <= cols) { - start_date = null; - out.push(ev); - stack[stack_line] = ev; - //get max height of slot - max[ev._sweek] = stack.length - 1; - ev._first_chunk = chunk_info.first_chunk; - ev._last_chunk = chunk_info.last_chunk; - } else { // split long event in chunks - var copy = this._copy_event(ev); - copy.id = ev.id; - copy._length = cols - ev._sday; - copy._eday = cols; - copy._sday = ev._sday; - copy._sweek = ev._sweek; - copy._sorder = ev._sorder; - copy.end_date = this.date.add(sd, copy._length, "day"); - copy._first_chunk = chunk_info.first_chunk; - if (chunk_info.first_chunk) { - chunk_info.first_chunk = false; - } - - out.push(copy); - stack[stack_line] = copy; - start_date = copy.end_date; - //get max height of slot - max[ev._sweek] = stack.length - 1; - i--; - continue; //repeat same step - } - } - return out; -}; -scheduler._copy_dummy = function() { - var a = new Date(this.start_date); - var b = new Date(this.end_date); - this.start_date = a; - this.end_date = b; -}; -scheduler._copy_event = function(ev) { - this._copy_dummy.prototype = ev; - return new this._copy_dummy(); - //return {start_date:ev.start_date, end_date:ev.end_date, text:ev.text, id:ev.id} -}; -scheduler._rendered = []; -scheduler.clear_view = function() { - for (var i = 0; i < this._rendered.length; i++) { - var obj = this._rendered[i]; - if (obj.parentNode) obj.parentNode.removeChild(obj); - } - this._rendered = []; -}; -scheduler.updateEvent = function(id) { - var ev = this.getEvent(id); - this.clear_event(id); - - if (ev && this.is_visible_events(ev) && this.filter_event(id, ev) && (this._table_view || this.config.multi_day || ev._timed)) { - if (this.config.update_render) - this.render_view_data(); - else - this.render_view_data([ev], true); - } -}; -scheduler.clear_event = function(id) { - this.for_rendered(id, function(node, i) { - if (node.parentNode) - node.parentNode.removeChild(node); - scheduler._rendered.splice(i, 1); - }); -}; -scheduler.render_event = function(ev) { - var menu = scheduler.xy.menu_width; - if (ev._sday < 0) return; //can occur in case of recurring event during time shift - var parent = scheduler.locate_holder(ev._sday); - if (!parent) return; //attempt to render non-visible event - var sm = ev.start_date.getHours() * 60 + ev.start_date.getMinutes(); - var em = (ev.end_date.getHours() * 60 + ev.end_date.getMinutes()) || (scheduler.config.last_hour * 60); - var ev_count = ev._count || 1; - var ev_sorder = ev._sorder || 0; - var top = (Math.round((sm * 60 * 1000 - this.config.first_hour * 60 * 60 * 1000) * this.config.hour_size_px / (60 * 60 * 1000))) % (this.config.hour_size_px * 24); //42px/hour - var height = Math.max(scheduler.xy.min_event_height, (em - sm) * this.config.hour_size_px / 60); //42px/hour - var width = Math.floor((parent.clientWidth - menu) / ev_count); - var left = ev_sorder * width + 1; - if (!ev._inner) width = width * (ev_count - ev_sorder); - if (this.config.cascade_event_display) { - var limit = this.config.cascade_event_count; - var margin = this.config.cascade_event_margin; - left = ev_sorder % limit * margin; - var right = (ev._inner) ? (ev_count - ev_sorder - 1) % limit * margin / 2 : 0; - width = Math.floor(parent.clientWidth - menu - left - right); - } - - var d = this._render_v_bar(ev.id, menu + left, top, width, height, ev._text_style, scheduler.templates.event_header(ev.start_date, ev.end_date, ev), scheduler.templates.event_text(ev.start_date, ev.end_date, ev)); - - this._rendered.push(d); - parent.appendChild(d); - - left = left + parseInt(parent.style.left, 10) + menu; - - if (this._edit_id == ev.id) { - - d.style.zIndex = 1; //fix overlapping issue - width = Math.max(width - 4, scheduler.xy.editor_width); - d = document.createElement("DIV"); - d.setAttribute("event_id", ev.id); - this.set_xy(d, width, height - 20, left, top + 14); - d.className = "dhx_cal_editor"; - - var d2 = document.createElement("DIV"); - this.set_xy(d2, width - 6, height - 26); - d2.style.cssText += ";margin:2px 2px 2px 2px;overflow:hidden;"; - - d.appendChild(d2); - this._els["dhx_cal_data"][0].appendChild(d); - this._rendered.push(d); - - d2.innerHTML = ""; - if (this._quirks7) d2.firstChild.style.height = height - 12 + "px"; //IEFIX - this._editor = d2.firstChild; - this._editor.onkeydown = function(e) { - if ((e || event).shiftKey) return true; - var code = (e || event).keyCode; - if (code == scheduler.keys.edit_save) scheduler.editStop(true); - if (code == scheduler.keys.edit_cancel) scheduler.editStop(false); - }; - this._editor.onselectstart = function (e) { - return (e || event).cancelBubble = true; - }; - d2.firstChild.focus(); - //IE and opera can add x-scroll during focusing - this._els["dhx_cal_data"][0].scrollLeft = 0; - d2.firstChild.select(); - - } - if (this.xy.menu_width !== 0 && this._select_id == ev.id) { - if (this.config.cascade_event_display && this._drag_mode) - d.style.zIndex = 1; //fix overlapping issue for cascade view in case of dnd of selected event - var icons = this.config["icons_" + ((this._edit_id == ev.id) ? "edit" : "select")]; - var icons_str = ""; - var bg_color = (ev.color ? ("background-color: " + ev.color + ";") : ""); - var color = (ev.textColor ? ("color: " + ev.textColor + ";") : ""); - for (var i = 0; i < icons.length; i++) - icons_str += "
"; - var obj = this._render_v_bar(ev.id, left - menu + 1, top, menu, icons.length * 20 + 26 - 2, "", "
", icons_str, true); - obj.style.left = left - menu + 1; - this._els["dhx_cal_data"][0].appendChild(obj); - this._rendered.push(obj); - } -}; -scheduler._render_v_bar = function (id, x, y, w, h, style, contentA, contentB, bottom) { - var d = document.createElement("DIV"); - var ev = this.getEvent(id); - - var cs = (bottom) ? "dhx_cal_event dhx_cal_select_menu" : "dhx_cal_event"; - - var cse = scheduler.templates.event_class(ev.start_date, ev.end_date, ev); - if (cse) cs = cs + " " + cse; - - var bg_color = (ev.color ? ("background:" + ev.color + ";") : ""); - var color = (ev.textColor ? ("color:" + ev.textColor + ";") : ""); - - var html = '
'; - d.innerHTML = html; - - var container = d.cloneNode(true).firstChild; - - if (scheduler.renderEvent && !bottom && scheduler.renderEvent(container, ev)) { - return container; - } else { - container = d.firstChild; - - var inner_html = '
 
'; - inner_html += '
' + contentA + '
'; - inner_html += '
' + contentB + '
'; // +2 css specific, moved from render_event - - var footer_class = "dhx_event_resize dhx_footer"; - if (bottom) - footer_class = "dhx_resize_denied " + footer_class; - - inner_html += ''; - - container.innerHTML = inner_html; - } - - return container; -}; -scheduler.locate_holder = function(day) { - if (this._mode == "day") return this._els["dhx_cal_data"][0].firstChild; //dirty - return this._els["dhx_cal_data"][0].childNodes[day]; -}; -scheduler.locate_holder_day = function(date, past) { - var day = Math.floor((this._correct_shift(date, 1) - this._min_date) / (60 * 60 * 24 * 1000)); - //when locating end data of event , we need to use next day if time part was defined - if (past && this.date.time_part(date)) day++; - return day; -}; -scheduler.render_event_bar = function (ev) { - var parent = this._rendered_location; - - var x = this._colsS[ev._sday]; - var x2 = this._colsS[ev._eday]; - if (x2 == x) x2 = this._colsS[ev._eday + 1]; - var hb = this.xy.bar_height; - - var y = this._colsS.heights[ev._sweek] + (this._colsS.height ? (this.xy.month_scale_height + 2) : 2 ) + (ev._sorder * hb); - - var d = document.createElement("DIV"); - var cs = "dhx_cal_event_clear"; - if (!ev._timed) { - cs = "dhx_cal_event_line"; - if (ev.hasOwnProperty("_first_chunk") && ev._first_chunk) - cs += " dhx_cal_event_line_start"; - if (ev.hasOwnProperty("_last_chunk") && ev._last_chunk) - cs += " dhx_cal_event_line_end"; - } - - var cse = scheduler.templates.event_class(ev.start_date, ev.end_date, ev); - if (cse) cs = cs + " " + cse; - - var bg_color = (ev.color ? ("background:" + ev.color + ";") : ""); - var color = (ev.textColor ? ("color:" + ev.textColor + ";") : ""); - - var html = '
'; - - ev = scheduler.getEvent(ev.id); // ev at this point could be a part of a larged event - if (ev._timed) - html += scheduler.templates.event_bar_date(ev.start_date, ev.end_date, ev); - html += scheduler.templates.event_bar_text(ev.start_date, ev.end_date, ev) + '
'; - html += '
'; - - d.innerHTML = html; - - this._rendered.push(d.firstChild); - parent.appendChild(d.firstChild); -}; - -scheduler._locate_event = function(node) { - var id = null; - while (node && !id && node.getAttribute) { - id = node.getAttribute("event_id"); - node = node.parentNode; - } - return id; -}; - -scheduler.edit = function(id) { - if (this._edit_id == id) return; - this.editStop(false, id); - this._edit_id = id; - this.updateEvent(id); -}; -scheduler.editStop = function(mode, id) { - if (id && this._edit_id == id) return; - var ev = this.getEvent(this._edit_id); - if (ev) { - if (mode) ev.text = this._editor.value; - this._edit_id = null; - this._editor = null; - this.updateEvent(ev.id); - this._edit_stop_event(ev, mode); - } -}; -scheduler._edit_stop_event = function(ev, mode) { - if (this._new_event) { - if (!mode) { - if (ev) // in case of custom lightbox user can already delete event - this.deleteEvent(ev.id, true); - } else { - this.callEvent("onEventAdded", [ev.id, ev]); - } - this._new_event = null; - } else { - if (mode) - this.callEvent("onEventChanged", [ev.id, ev]); - } -}; - -scheduler.getEvents = function(from, to) { - var result = []; - for (var a in this._events) { - var ev = this._events[a]; - if (ev && ( (!from && !to) || (ev.start_date < to && ev.end_date > from) )) - result.push(ev); - } - return result; -}; -scheduler.getRenderedEvent = function(id) { - if (!id) - return; - var rendered_events = scheduler._rendered; - for (var i=0; ithis._min_date) from=this.date.add(from,-1,this._load_mode); - to = from; - - var cache_line = true; - while (tofrom && this._loaded[lf(temp_to)]); - - if (to<=from) - return false; //already loaded - dhtmlxAjax.get(url+"&from="+lf(from)+"&to="+lf(to),function(l){scheduler.on_load(l);}); - while(from"; - }, - set_value:function(node,value,ev,config){ - node.innerHTML = value||""; - }, - get_value:function(node,ev,config){ - return node.innerHTML||""; - }, - focus: function(node){ - } - }, - textarea:{ - render:function(sns){ - var height=(sns.height||"130")+"px"; - return "
"; - }, - set_value:function(node,value,ev){ - node.firstChild.value=value||""; - }, - get_value:function(node,ev){ - return node.firstChild.value; - }, - focus:function(node){ - var a=node.firstChild; a.select(); a.focus(); - } - }, - select:{ - render:function(sns){ - var height=(sns.height||"23")+"px"; - var html="
"; - return html; - }, - set_value:function(node,value,ev,sns){ - var select = node.firstChild; - if (!select._dhx_onchange && sns.onchange) { - select.onchange = sns.onchange; - select._dhx_onchange = true; - } - if (typeof value == "undefined") - value = (select.options[0]||{}).value; - select.value=value||""; - }, - get_value:function(node,ev){ - return node.firstChild.value; - }, - focus:function(node){ - var a=node.firstChild; if (a.select) a.select(); a.focus(); - } - }, - time:{ - render:function(sns){ - //hours - var cfg = scheduler.config; - var dt = this.date.date_part(new Date()); - var last = 24*60, first = 0; - if(scheduler.config.limit_time_select){ - last = 60*cfg.last_hour+1; - first = 60*cfg.first_hour; - dt.setHours(cfg.first_hour); - } - - var html=" "; - - return "
"+html+"  –  "+html+"
"; - - }, - set_value:function(node,value,ev,config){ - var cfg = scheduler.config; - var s=node.getElementsByTagName("select"); - - if(cfg.full_day) { - if (!node._full_day){ - var html = ""; - if (!scheduler.config.wide_form) - html = node.previousSibling.innerHTML+html; - node.previousSibling.innerHTML=html; - node._full_day=true; - } - var input=node.previousSibling.getElementsByTagName("input")[0]; - input.checked = (scheduler.date.time_part(ev.start_date)===0 && scheduler.date.time_part(ev.end_date)===0); - - s[0].disabled=input.checked; - s[ s.length/2 ].disabled=input.checked; - - input.onclick = function(){ - if(input.checked) { - var obj = {}; - scheduler.form_blocks.time.get_value(node,obj); - - var start_date = scheduler.date.date_part(obj.start_date); - var end_date = scheduler.date.date_part(obj.end_date); - - if (+end_date == +start_date || (+end_date >= +start_date && (ev.end_date.getHours() != 0 || ev.end_date.getMinutes() != 0))) - end_date = scheduler.date.add(end_date, 1, "day"); - } - - s[0].disabled=input.checked; - s[ s.length/2 ].disabled=input.checked; - - _fill_lightbox_select(s,0,start_date||ev.start_date); - _fill_lightbox_select(s,4,end_date||ev.end_date); - }; - } - - if(cfg.auto_end_date && cfg.event_duration) { - function _update_lightbox_select() { - var start_date = new Date(s[3].value,s[2].value,s[1].value,0,s[0].value); - var end_date = new Date(start_date.getTime() + (scheduler.config.event_duration * 60 * 1000)); - _fill_lightbox_select(s, 4, end_date); - } - for(var i=0; i<4; i++) { - s[i].onchange = _update_lightbox_select; - } - } - - function _fill_lightbox_select(s,i,d) { - var time_values = config._time_values; - var direct_value = d.getHours()*60+d.getMinutes(); - var fixed_value = direct_value; - var value_found = false; - for (var k=0; k document.body.offsetWidth) // if horizontal scroll on the window - box.style.left=Math.round(scroll_left+(document.body.offsetWidth-box.offsetWidth)/2)+"px"; - else // horizontal scroll on the body - box.style.left=Math.round((document.body.offsetWidth-box.offsetWidth)/2)+"px"; - } - this.show_cover(); -}; -scheduler.showLightbox=function(id){ - if (!id) return; - if (!this.callEvent("onBeforeLightbox",[id])) { - if (this._new_event) - this._new_event = null; - return; - } - var box = this.getLightbox(); - this.showCover(box); - this._fill_lightbox(id,box); - this.callEvent("onLightbox",[id]); -}; -scheduler._fill_lightbox = function(id, box) { - var ev = this.getEvent(id); - var s = box.getElementsByTagName("span"); - if (scheduler.templates.lightbox_header) { - s[1].innerHTML = ""; - s[2].innerHTML = scheduler.templates.lightbox_header(ev.start_date, ev.end_date, ev); - } else { - s[1].innerHTML = this.templates.event_header(ev.start_date, ev.end_date, ev); - s[2].innerHTML = (this.templates.event_bar_text(ev.start_date, ev.end_date, ev) || "").substr(0, 70); //IE6 fix - } - - var sns = this.config.lightbox.sections; - for (var i = 0; i < sns.length; i++) { - var current_sns = sns[i]; - var node = document.getElementById(current_sns.id).nextSibling; - var block = this.form_blocks[current_sns.type]; - var value = (ev[current_sns.map_to] !== undefined) ? ev[current_sns.map_to] : current_sns.default_value; - block.set_value.call(this, node, value, ev, current_sns); - if (sns[i].focus) - block.focus.call(this, node); - } - - scheduler._lightbox_id = id; -}; -scheduler._lightbox_out=function(ev){ - var sns = this.config.lightbox.sections; - for (var i=0; i < sns.length; i++) { - var node = document.getElementById(sns[i].id); - node=(node?node.nextSibling:node); - var block=this.form_blocks[sns[i].type]; - var res=block.get_value.call(this,node,ev, sns[i]); - if (sns[i].map_to!="auto") - ev[sns[i].map_to]=res; - } - return ev; -}; -scheduler._empty_lightbox=function(data){ - var id=scheduler._lightbox_id; - var ev=this.getEvent(id); - var box=this.getLightbox(); - - this._lame_copy(ev, data); - - ev._timed=this.is_one_day_event(ev); - this.setEvent(ev.id,ev); - this._edit_stop_event(ev,true); - this.render_view_data(); -}; -scheduler.hide_lightbox=function(id){ - this.hideCover(this.getLightbox()); - this._lightbox_id=null; - this.callEvent("onAfterLightbox",[]); -}; -scheduler.hideCover=function(box){ - if (box) box.style.display="none"; - this.hide_cover(); -}; -scheduler.hide_cover=function(){ - if (this._cover) - this._cover.parentNode.removeChild(this._cover); - this._cover=null; -}; -scheduler.show_cover=function(){ - this._cover=document.createElement("DIV"); - this._cover.className="dhx_cal_cover"; - var _document_height = ((document.height !== undefined) ? document.height : document.body.offsetHeight); - var _scroll_height = ((document.documentElement) ? document.documentElement.scrollHeight : 0); - this._cover.style.height = Math.max(_document_height, _scroll_height) + 'px'; - document.body.appendChild(this._cover); -}; -scheduler.save_lightbox=function(){ - var data = this._lightbox_out({}, this._lame_copy(this.getEvent(this._lightbox_id))); - if (this.checkEvent("onEventSave") && !this.callEvent("onEventSave",[this._lightbox_id, data, this._new_event])) - return; - this._empty_lightbox(data); - this.hide_lightbox(); -}; -scheduler.startLightbox = function(id, box){ - this._lightbox_id=id; - this._lightbox = box; - this.showCover(box); -}; -scheduler.endLightbox = function(mode, box){ - this._edit_stop_event(scheduler.getEvent(this._lightbox_id),mode); - if (mode) - scheduler.render_view_data(); - this.hideCover(box); - this._lightbox_id = null; // in case of custom lightbox user only calls endLightbox so we need to reset _lightbox_id -}; -scheduler.resetLightbox = function(){ - if (scheduler._lightbox) - scheduler._lightbox.parentNode.removeChild(scheduler._lightbox); - scheduler._lightbox = null; -}; -scheduler.cancel_lightbox=function(){ - this.callEvent("onEventCancel",[this._lightbox_id, this._new_event]); - this.endLightbox(false); - this.hide_lightbox(); -}; -scheduler._init_lightbox_events=function(){ - this.getLightbox().onclick=function(e){ - var src=e?e.target:event.srcElement; - if (!src.className) src=src.previousSibling; - if (src && src.className) - switch(src.className){ - case "dhx_save_btn": - scheduler.save_lightbox(); - break; - case "dhx_delete_btn": - var c=scheduler.locale.labels.confirm_deleting; - - scheduler._dhtmlx_confirm(c, scheduler.locale.labels.title_confirm_deleting, function(){ - scheduler.deleteEvent(scheduler._lightbox_id); - scheduler._new_event = null; //clear flag, if it was unsaved event - scheduler.hide_lightbox(); - }); - - break; - case "dhx_cancel_btn": - scheduler.cancel_lightbox(); - break; - - default: - if (src.getAttribute("dhx_button")) { - scheduler.callEvent("onLightboxButton", [src.className, src, e]); - } else { - var index, block, sec; - if (src.className.indexOf("dhx_custom_button") != -1) { - if (src.className.indexOf("dhx_custom_button_") != -1) { - index = src.parentNode.getAttribute("index"); - sec = src.parentNode.parentNode; - } else { - index = src.getAttribute("index"); - sec = src.parentNode; - src = src.firstChild; - } - } - if (index) { - block = scheduler.form_blocks[scheduler.config.lightbox.sections[index].type]; - block.button_click(index, src, sec, sec.nextSibling); - } - } - break; - } - }; - this.getLightbox().onkeydown=function(e){ - switch((e||event).keyCode){ - case scheduler.keys.edit_save: - if ((e||event).shiftKey) return; - scheduler.save_lightbox(); - break; - case scheduler.keys.edit_cancel: - scheduler.cancel_lightbox(); - break; - default: - break; - } - }; -}; -scheduler.setLightboxSize=function(){ - var d = this._lightbox; - if (!d) return; - - var con = d.childNodes[1]; - con.style.height="0px"; - con.style.height=con.scrollHeight+"px"; - d.style.height=con.scrollHeight+scheduler.xy.lightbox_additional_height+"px"; - con.style.height=con.scrollHeight+"px"; //it is incredible , how ugly IE can be -}; - -scheduler._init_dnd_events = function(){ - dhtmlxEvent(document.body, "mousemove", scheduler._move_while_dnd); - dhtmlxEvent(document.body, "mouseup", scheduler._finish_dnd); - scheduler._init_dnd_events = function(){}; -}; -scheduler._move_while_dnd = function(e){ - if (scheduler._dnd_start_lb){ - if (!document.dhx_unselectable){ - document.body.className += " dhx_unselectable"; - document.dhx_unselectable = true; - } - var lb = scheduler.getLightbox(); - var now = (e&&e.target)?[e.pageX, e.pageY]:[event.clientX, event.clientY]; - lb.style.top = scheduler._lb_start[1]+now[1]-scheduler._dnd_start_lb[1]+"px"; - lb.style.left = scheduler._lb_start[0]+now[0]-scheduler._dnd_start_lb[0]+"px"; - } -}; -scheduler._ready_to_dnd = function(e){ - var lb = scheduler.getLightbox(); - scheduler._lb_start = [parseInt(lb.style.left,10), parseInt(lb.style.top,10)]; - scheduler._dnd_start_lb = (e&&e.target)?[e.pageX, e.pageY]:[event.clientX, event.clientY]; -}; -scheduler._finish_dnd = function(){ - if (scheduler._lb_start){ - scheduler._lb_start = scheduler._dnd_start_lb = false; - document.body.className = document.body.className.replace(" dhx_unselectable",""); - document.dhx_unselectable = false; - } -}; -scheduler.getLightbox=function(){ //scheduler.config.wide_form=true; - if (!this._lightbox){ - var d=document.createElement("DIV"); - d.className="dhx_cal_light"; - if (scheduler.config.wide_form) - d.className+=" dhx_cal_light_wide"; - if (scheduler.form_blocks.recurring) - d.className+=" dhx_cal_light_rec"; - - if (/msie|MSIE 6/.test(navigator.userAgent)) - d.className+=" dhx_ie6"; - d.style.visibility="hidden"; - var html = this._lightbox_template; - - var buttons = this.config.buttons_left; - for (var i = 0; i < buttons.length; i++) - html+="
"+scheduler.locale.labels[buttons[i]]+"
"; - - buttons = this.config.buttons_right; - for (var i = 0; i < buttons.length; i++) - html+="
"+scheduler.locale.labels[buttons[i]]+"
"; - - html+=""; - d.innerHTML=html; - if (scheduler.config.drag_lightbox){ - d.firstChild.onmousedown = scheduler._ready_to_dnd; - d.firstChild.onselectstart = function(){ return false; }; - d.firstChild.style.cursor = "pointer"; - scheduler._init_dnd_events(); - - } - document.body.insertBefore(d,document.body.firstChild); - this._lightbox=d; - - var sns=this.config.lightbox.sections; - html=""; - for (var i=0; i < sns.length; i++) { - var block=this.form_blocks[sns[i].type]; - if (!block) continue; //ignore incorrect blocks - sns[i].id="area_"+this.uid(); - var button = ""; - if (sns[i].button){ - button = "
"+this.locale.labels["button_"+sns[i].button]+"
"; - } - - if (this.config.wide_form){ - html+="
"; - } - html+="
"+button+this.locale.labels["section_"+sns[i].name]+"
"+block.render.call(this,sns[i]); - html+="
" - } - - var ds=d.getElementsByTagName("div"); - for (var i=0; i" + month_x(date) + ""; - }; - var week_x = scheduler.templates.week_scale_date; - scheduler.templates.week_scale_date = function(date) { - return "" + week_x(date) + ""; - }; - dhtmlxEvent(this._obj, "click", function(e) { - var start = e.target || event.srcElement; - var to = start.getAttribute("jump_to"); - if (to) { - scheduler.setCurrentView(s_d(to), scheduler.config.active_link_view); - if (e && e.preventDefault) - e.preventDefault(); - return false; - } - }) -}); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_agenda_view.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_agenda_view.js deleted file mode 100644 index ff93a8876fe..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_agenda_view.js +++ /dev/null @@ -1,120 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.date.add_agenda = function(date){ - return scheduler.date.add(date, 1, "year"); -}; - -scheduler.templates.agenda_time = function(start,end,ev){ - if (ev._timed) - return this.day_date(ev.start_date, ev.end_date, ev)+" "+this.event_date(start); - else - return scheduler.templates.day_date(start)+" – "+scheduler.templates.day_date(end); -}; -scheduler.templates.agenda_text = function(start,end,event){ - return event.text; -}; -scheduler.templates.agenda_date = function(){ return ""; }; - -scheduler.date.agenda_start=function(){ return scheduler.date.date_part(new Date()); }; - -scheduler.attachEvent("onTemplatesReady",function() { - var old_dblclick_dhx_cal_data = scheduler.dblclick_dhx_cal_data; - scheduler.dblclick_dhx_cal_data = function() { - if (this._mode == "agenda") { - if (!this.config.readonly && this.config.dblclick_create) - this.addEventNow(); - } else { - if (old_dblclick_dhx_cal_data) - return old_dblclick_dhx_cal_data.apply(this, arguments); - } - }; - scheduler.attachEvent("onSchedulerResize",function(){ - if (this._mode == "agenda"){ - this.agenda_view(true); - return false; - } - return true; - }); - - - var old = scheduler.render_data; - scheduler.render_data=function(evs){ - if (this._mode == "agenda") - fill_agenda_tab(); - else - return old.apply(this,arguments); - }; - - var old_render_view_data = scheduler.render_view_data; - scheduler.render_view_data = function(){ - if(this._mode == "agenda") { - scheduler._agendaScrollTop = scheduler._els["dhx_cal_data"][0].childNodes[0].scrollTop; - scheduler._els["dhx_cal_data"][0].childNodes[0].scrollTop = 0; - } - return old_render_view_data.apply(this,arguments); - }; - - - function set_full_view(mode){ - if (mode){ - var l = scheduler.locale.labels; - scheduler._els["dhx_cal_header"][0].innerHTML="
"+l.date+"
"+l.description+"
"; - scheduler._table_view=true; - scheduler.set_sizes(); - } - } - - function fill_agenda_tab(){ - //get current date - var date = scheduler._date; - //select events for which data need to be printed - - var events = scheduler.get_visible_events(); - events.sort(function(a,b){ return a.start_date>b.start_date?1:-1}); - - //generate html for the view - var html="
"; - for (var i=0; i
"+scheduler.templates.agenda_time(ev.start_date, ev.end_date,ev)+"
"; - html+="
 
"; - html+=""+scheduler.templates.agenda_text(ev.start_date, ev.end_date, ev)+"
"; - } - html+="
"; - - //render html - scheduler._els["dhx_cal_data"][0].innerHTML = html; - scheduler._els["dhx_cal_data"][0].childNodes[0].scrollTop = scheduler._agendaScrollTop||0; - - // setting up dhx_v_border size - var agenda_area = scheduler._els["dhx_cal_data"][0].childNodes[0]; - var v_border = agenda_area.childNodes[agenda_area.childNodes.length-1]; - v_border.style.height = (agenda_area.offsetHeight < scheduler._els["dhx_cal_data"][0].offsetHeight) ? "100%" : (agenda_area.offsetHeight+"px"); - - var t=scheduler._els["dhx_cal_data"][0].firstChild.childNodes; - scheduler._els["dhx_cal_date"][0].innerHTML=scheduler.templates.agenda_date(scheduler._min_date, scheduler._max_date, scheduler._mode); - - scheduler._rendered=[]; - for (var i=0; i < t.length-1; i++) - scheduler._rendered[i]=t[i] - - } - - scheduler.agenda_view=function(mode){ - scheduler._min_date = scheduler.config.agenda_start||scheduler.date.agenda_start(scheduler._date); - scheduler._max_date = scheduler.config.agenda_end||scheduler.date.add_agenda(scheduler._min_date, 1); - scheduler._table_view = true; - set_full_view(mode); - if (mode){ - //agenda tab activated - fill_agenda_tab(); - } else { - //agenda tab de-activated - } - } -}); diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_all_timed.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_all_timed.js deleted file mode 100644 index 30d1d7066ef..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_all_timed.js +++ /dev/null @@ -1,133 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -(function(){ - - scheduler.config.all_timed = "short"; - scheduler.config.update_render = true; - - var is_event_short = function (ev) { - return !((ev.end_date - ev.start_date)/(1000*60*60) >= 24); - }; - - var old_prerender_events_line = scheduler._pre_render_events_line; - scheduler._pre_render_events_line = function(evs, hold){ - if (!this.config.all_timed) - return old_prerender_events_line.call(this, evs, hold); - - for (var i=0; i < evs.length; i++) { - var ev=evs[i]; - - if (!ev._timed) { - - if (this.config.all_timed == "short") { - if (!is_event_short(ev)) { - evs.splice(i--,1); - continue; - } - } - - var ce = this._lame_copy({}, ev); // current event (event for one specific day) is copy of original with modified dates - - ce.start_date = new Date(ce.start_date); // as lame copy doesn't copy date objects - - var next_day = scheduler.date.add(ev.start_date, 1, "day"); - next_day = scheduler.date.date_part(next_day); - - if (ev.end_date < next_day) { - ce.end_date = new Date(ev.end_date); - } - else { - ce.end_date = next_day; - if (this.config.last_hour != 24) { // if specific last_hour was set (e.g. 20) - ce.end_date = scheduler.date.date_part(new Date(ce.start_date)); - ce.end_date.setHours(this.config.last_hour); - } - } - - var event_changed = false; - if (ce.start_date < this._max_date && ce.end_date > this._min_date && ce.start_date < ce.end_date) { - evs[i] = ce; // adding another event in collection - event_changed = true; - } - if (ce.start_date > ce.end_date) { - evs.splice(i--,1); - } - - var re = this._lame_copy({}, ev); // remaining event, copy of original with modified start_date (making range more narrow) - re.end_date = new Date(re.end_date); - if (re.start_date < this._min_date) - re.start_date = new Date(this._min_date); - else - re.start_date = this.date.add(ev.start_date, 1, "day"); - - re.start_date.setHours(this.config.first_hour); - re.start_date.setMinutes(0); // as we are starting only with whole hours - if (re.start_date < this._max_date && re.start_date < re.end_date) { - if (event_changed) - evs.splice(i+1,0,re); - else { - evs[i--] = re; - continue; - } - } - } - } - // in case of all_timed pre_render is not applied to the original event - // so we need to force redraw in case of dnd - var redraw = (this._drag_mode == 'move')?false:hold; - return old_prerender_events_line.call(this, evs, redraw); - }; - var old_get_visible_events = scheduler.get_visible_events; - scheduler.get_visible_events = function(only_timed){ - if (!this.config.all_timed) - return old_get_visible_events.call(this, only_timed); - return old_get_visible_events.call(this, false); // only timed = false - }; - scheduler.attachEvent("onBeforeViewChange", function (old_mode, old_date, mode, date) { - scheduler._allow_dnd = (mode == "day" || mode == "week"); - return true; - }); - - scheduler.render_view_data=function(evs, hold){ - if(!evs){ - if (this._not_render) { - this._render_wait=true; - return; - } - this._render_wait=false; - - this.clear_view(); - evs=this.get_visible_events( !(this._table_view || this.config.multi_day) ); - } - - if (this.config.multi_day && !this._table_view){ - - var tvs = []; - var tvd = []; - for (var i=0; i < evs.length; i++){ - if (evs[i]._timed || this.config.all_timed === true || (this.config.all_timed == "short" && is_event_short(evs[i])) ) - tvs.push(evs[i]); - else - tvd.push(evs[i]); - } - - // normal events - this._rendered_location = this._els['dhx_cal_data'][0]; - this._table_view=false; - this.render_data(tvs, hold); - - // multiday events - this._rendered_location = this._els['dhx_multi_day'][0]; - this._table_view = true; - this.render_data(tvd, hold); - this._table_view=false; - - } else { - this._rendered_location = this._els['dhx_cal_data'][0]; - this.render_data(evs, hold); - } - }; - -})(); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_collision.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_collision.js deleted file mode 100644 index 700b8de19ed..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_collision.js +++ /dev/null @@ -1,119 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -(function(){ - -var temp_section; -var before; - -scheduler.config.collision_limit = 1; - -function _setTempSection(event_id) { // for custom views (matrix, timeline, units) - var pr = scheduler._props?scheduler._props[scheduler._mode]:null; - var matrix = scheduler.matrix?scheduler.matrix[scheduler._mode]:null; - var checked_mode = pr||matrix; // units or matrix mode - if(pr) - var map_to = checked_mode.map_to; - if(matrix) - var map_to = checked_mode.y_property; - if ((checked_mode) && event_id){ - temp_section = scheduler.getEvent(event_id)[map_to]; - } -} - -scheduler.attachEvent("onBeforeDrag",function(id){ - _setTempSection(id); - return true; -}); -scheduler.attachEvent("onBeforeLightbox",function(id){ - var ev = scheduler.getEvent(id); - before = [ev.start_date, ev.end_date]; - _setTempSection(id); - return true; -}); -scheduler.attachEvent("onEventChanged",function(id){ - if (!id) return true; - var ev = scheduler.getEvent(id); - if (!collision_check(ev)){ - if (!before) return false; - ev.start_date = before[0]; - ev.end_date = before[1]; - ev._timed=this.is_one_day_event(ev); - } - return true; -}); -scheduler.attachEvent("onBeforeEventChanged",function(ev,e,is_new){ - return collision_check(ev); -}); -scheduler.attachEvent("onEventSave",function(id, edited_ev, is_new){ - edited_ev = scheduler._lame_clone(edited_ev); - edited_ev.id = id; - - if(edited_ev.rec_type){ - scheduler._roll_back_dates(data_copy); - } - return collision_check(edited_ev); // in case user creates event on one date but then edited it another -}); - -function collision_check(ev){ - var evs = []; - var collision_limit = scheduler.config.collision_limit; - if (ev.rec_type) { - var evs_dates = scheduler.getRecDates(ev); - for(var k=0; k= collision_limit) { - - single = false; - } - } - else { - if ( evs.length >= collision_limit ) - single = false; - } - if (!single) { - var res = !scheduler.callEvent("onEventCollision",[ev,evs]); - if (!res) { - ev[map_to] = temp_section||ev[map_to]; // from _setTempSection for custom views - } - return res; - } - return single; - -} - -})(); diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_cookie.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_cookie.js deleted file mode 100644 index f989ee8ddc5..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_cookie.js +++ /dev/null @@ -1,42 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -(function(){ - function setCookie(name,cookie_param,value) { - var str = name + "=" + value + (cookie_param?("; "+cookie_param):""); - document.cookie = str; - } - function getCookie(name) { - var search = name + "="; - if (document.cookie.length > 0) { - var offset = document.cookie.indexOf(search); - if (offset != -1) { - offset += search.length; - var end = document.cookie.indexOf(";", offset); - if (end == -1) - end = document.cookie.length; - return document.cookie.substring(offset, end); - } - } - return ""; - } - var first = true; - scheduler.attachEvent("onBeforeViewChange",function(om,od,m,d){ - if (first){ - first = false; - var data=getCookie("scheduler_settings"); - if (data){ - data = unescape(data).split("@"); - data[0] = this.templates.xml_date(data[0]); - window.setTimeout(function(){ - scheduler.setCurrentView(data[0],data[1]); - },1); - return false; - } - } - var text = escape(this.templates.xml_format(d||od)+"@"+(m||om)); - setCookie("scheduler_settings","expires=Sun, 31 Jan 9999 22:00:00 GMT",text); - return true; - }); -})(); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_dhx_terrace.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_dhx_terrace.js deleted file mode 100644 index 613741bac43..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_dhx_terrace.js +++ /dev/null @@ -1,90 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -(function(){ - - scheduler.config.fix_tab_position = true; - scheduler.config.use_select_menu_space = true; - scheduler.config.hour_size_px = 44; - scheduler.xy.nav_height = 59; - scheduler.xy.bar_height = 24; - scheduler.config.wide_form = true; - scheduler.xy.lightbox_additional_height = 90; - - scheduler.config.displayed_event_color = "#ff4a4a"; - scheduler.config.displayed_event_text_color = "#ffef80"; - - scheduler.templates.event_bar_date = function(start,end,ev) { - return "• "+scheduler.templates.event_date(start)+" "; - }; - - scheduler.attachEvent("onLightbox", function(){ - var lightbox = scheduler.getLightbox(); - var divs = lightbox.getElementsByTagName('div'); - for (var i=0; i"; - return res; - }, - set_value:function(node,value,ev,config){ - if(node._combo) { - node._combo.destructor(); - } - window.dhx_globalImgPath = config.image_path||'/'; - node._combo = new dhtmlXCombo(node, config.name, node.offsetWidth-8); - if (config.options_height) - node._combo.setOptionHeight(config.options_height); - var combo = node._combo; - combo.enableFilteringMode(!!config.filtering, config.script_path||null, !!config.cache); - - if (!config.script_path) { // script-side filtration is used - var all_options = []; - for (var i = 0; i < config.options.length; i++) { - var single_option = []; - single_option.push(config.options[i].key); - single_option.push(config.options[i].label); - all_options.push(single_option); - } - combo.addOption(all_options); - if (ev[config.map_to]) { - var index = combo.getIndexByValue(ev[config.map_to]); - combo.selectOption(index); - } - } else { // server-side filtration is used - var selected_id = ev[config.map_to]; - if (selected_id) { - if (config.cached_options[selected_id]) { - combo.addOption(selected_id, config.cached_options[selected_id]); - combo.disable(1); - combo.selectOption(0); - combo.disable(0); - } else { - dhtmlxAjax.get(config.script_path+"?id="+selected_id+"&uid="+scheduler.uid(), function(result){ - var option = result.doXPath("//option")[0]; - var label = option.childNodes[0].nodeValue; - config.cached_options[selected_id] = label; - combo.addOption(selected_id, label); - combo.disable(1); - combo.selectOption(0); - combo.disable(0); - }); - } - } else { - combo.setComboValue(null); - } - } - }, - get_value:function(node,ev,config) { - var selected_id = node._combo.getSelectedValue(); // value = key - if (config.script_path) { - config.cached_options[selected_id] = node._combo.getSelectedText(); - } - return selected_id; - }, - focus:function(node){ - } -}; - -scheduler.form_blocks['radio']={ - render:function(sns) { - var res = ''; - res += "
"; - for (var i=0; i"; - if(sns.vertical) - res += "
"; - } - res += "
"; - - return res; - }, - set_value:function(node,value,ev,config){ - var radiobuttons = node.getElementsByTagName('input'); - for (var i = 0; i < radiobuttons.length; i++) { - radiobuttons[i].checked = false; - var checked_value = ev[config.map_to]||value; - if (radiobuttons[i].value == checked_value) { - radiobuttons[i].checked = true; - } - } - }, - get_value:function(node,ev,config){ - var radiobuttons = node.getElementsByTagName('input'); - for(var i=0; i'; - else - return ''; - }, - set_value:function(node,value,ev,config){ - node=document.getElementById(config.id); - var id = scheduler.uid(); - var isChecked = (typeof config.checked_value != "undefined") ? ev[config.map_to] == config.checked_value : !!value; - node.className += " dhx_cal_checkbox"; - var check_html = ""; - var label_html = ""; - if (scheduler.config.wide_form){ - node.innerHTML = label_html; - node.nextSibling.innerHTML=check_html; - } else - node.innerHTML=check_html+label_html; - - if (config.handler) { - var checkbox = node.getElementsByTagName('input')[0]; - checkbox.onclick = config.handler; - } - }, - get_value:function(node,ev,config){ - node=document.getElementById(config.id); - var checkbox = node.getElementsByTagName('input')[0]; // moved to the header - if (!checkbox) - checkbox = node.nextSibling.getElementsByTagName('input')[0]; - return (checkbox.checked)?(config.checked_value||true):(config.unchecked_value||false); - }, - focus:function(node){ - } -}; \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_expand.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_expand.js deleted file mode 100644 index 1f00aa4e5ab..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_expand.js +++ /dev/null @@ -1,74 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.expand = function(){ - var t = scheduler._obj; - do { - t._position = t.style.position||""; - t.style.position = "static"; - } while ((t = t.parentNode) && t.style ); - t = scheduler._obj; - t.style.position="absolute"; - t._width = t.style.width; - t._height = t.style.height; - t.style.width = t.style.height = "100%"; - t.style.top = t.style.left = "0px"; - - var top = document.body; - top.scrollTop = 0; - - top = top.parentNode; - if (top) - top.scrollTop = 0; - document.body._overflow=document.body.style.overflow||""; - document.body.style.overflow = "hidden"; - scheduler._maximize(); -}; -scheduler.collapse = function(){ - var t = scheduler._obj; - do { - t.style.position = t._position; - } while ((t = t.parentNode) && t.style ); - t = scheduler._obj; - t.style.width = t._width; - t.style.height = t._height; - document.body.style.overflow=document.body._overflow; - scheduler._maximize(); -}; -scheduler.attachEvent("onTemplatesReady",function(){ - var t = document.createElement("DIV"); - t.className="dhx_expand_icon"; - scheduler.toggleIcon = t; - scheduler._obj.appendChild(t); - t.onclick = function(){ - if (!scheduler.expanded) - scheduler.expand(); - else - scheduler.collapse(); - } -}); - -scheduler._maximize = function(){ - this.expanded = !this.expanded; - this.toggleIcon.style.backgroundPosition="0px "+(this.expanded?"0":"18")+"px"; - - var directions = ['left', 'top']; - for(var i=0; i new Date(0) && scheduler._max_date < (new Date(9999,1,1))) - scheduler._els["dhx_cal_date"][0].innerHTML=scheduler.templates[name+"_date"](scheduler._min_date,scheduler._max_date); - else - scheduler._els["dhx_cal_date"][0].innerHTML=""; - - //grid tab activated - scheduler.grid._fill_grid_tab(objName); - scheduler._gridView = objName; - } else { - scheduler.grid._sort_marker = null; - delete scheduler._gridView; - scheduler._rendered=[]; - scheduler[objName]._selected_divs = []; - //grid tab de-activated - } - }; - - -} - - -scheduler.dblclick_dhx_grid_area=function(){ - if (!this.config.readonly && this.config.dblclick_create) - this.addEventNow(); -}; - -if(scheduler._click.dhx_cal_header){ - scheduler._old_header_click = scheduler._click.dhx_cal_header; -} -scheduler._click.dhx_cal_header=function(e){ - if(scheduler._gridView){ - var event = e||window.event; - var params = scheduler.grid.get_sort_params(event, scheduler._gridView); - - scheduler.grid.draw_sort_marker(event.originalTarget || event.srcElement, params.dir); - - scheduler.clear_view(); - scheduler.grid._fill_grid_tab(scheduler._gridView, params); - } - else if(scheduler._old_header_click) - return scheduler._old_header_click.apply(this,arguments); -}; - -scheduler.grid.selectEvent = function(id, view_name, native_event_object){ - if(scheduler.callEvent("onBeforeRowSelect",[id,native_event_object])){ - var objName = scheduler.grid._getObjName(view_name); - - scheduler.for_rendered(id, function(event_div){ - event_div.className += " dhx_grid_event_selected"; - scheduler[objName]._selected_divs.push(event_div); - }); - scheduler._select_id = id; - } -}; - -scheduler.grid._unselectDiv= function(div){ - div.className = div.className.replace(/ dhx_grid_event_selected/,''); -} -scheduler.grid.unselectEvent = function(id, view_name){ - var objName = scheduler.grid._getObjName(view_name); - if(!objName || !scheduler[objName]._selected_divs) - return; - - if(!id){ - for(var i=0; i "; - node.innerHTML += html; - -}; - -scheduler.grid.sort_grid=function(sort){ - - var sort = sort || {dir:'desc', value:function(ev){return ev.start_date;}, rule:scheduler.grid.sort_rules['date']}; - - var events = scheduler.get_visible_events(); - - if(sort.dir == 'desc') - events.sort(function(a,b){return sort.rule(a,b,sort.value)}); - else - events.sort(function(a,b){return -sort.rule(a,b, sort.value)}); - return events; -}; - - - -scheduler.grid.set_full_view = function(mode){ - if (mode){ - var l = scheduler.locale.labels; - var html =scheduler.grid._print_grid_header(mode); - - scheduler._els["dhx_cal_header"][0].innerHTML= html; - scheduler._table_view=true; - scheduler.set_sizes(); - } -}; -scheduler.grid._calcPadding = function(column, parent){ - var padding = (column.paddingLeft !== undefined ? 1*column.paddingLeft : scheduler[parent].defPadding) - + (column.paddingRight !== undefined ? 1*column.paddingRight : scheduler[parent].defPadding); - return padding; -}; - -scheduler.grid._getStyles = function(column, items){ - var cell_style = [], style = ""; - for(var i=0; items[i]; i++ ){ - style = items[i] + ":"; - switch (items[i]){ - case "text-align": - if(column.align) - cell_style.push(style+column.align); - break; - case "vertical-align": - if(column.valign) - cell_style.push(style+column.valign); - break; - case "padding-left": - if(column.paddingLeft != undefined) - cell_style.push(style+(column.paddingLeft||'0') + "px"); - break; - case "padding-left": - if(column.paddingRight != undefined) - cell_style.push(style+(column.paddingRight||'0') + "px"); - break; - } - } - return cell_style; -}; - -scheduler.grid._fill_grid_tab = function(objName, sort){ - //get current date - var date = scheduler._date; - //select events for which data need to be printed - var events = scheduler.grid.sort_grid(sort) - - //generate html for the view - var columns = scheduler[objName].columns; - - var html = "
"; - var left = -2;//column borders at the same pos as header borders... - for(var i=0; i < columns.length; i++){ - var padding = scheduler.grid._calcPadding(columns[i], objName); - left +=columns[i].width + padding ;// - if(i < columns.length - 1) - html += "
"; - } - html += "
" - html +="
"; - - for (var i=0; i"; - - var name = scheduler.grid._getViewName(objName); - var availStyles = ["text-align", "vertical-align", "padding-left","padding-right"]; - for(var i =0; i < columns.length; i++){ - var value; - if(columns[i].template){ - value = columns[i].template(ev.start_date, ev.end_date, ev); - }else if(columns[i].id == 'date') { - value = scheduler.templates[name + '_full_date'](ev.start_date, ev.end_date, ev); - }else if(columns[i].id == 'start_date' || columns[i].id == 'end_date' ){ - value = scheduler.templates[name + '_single_date'](ev[columns[i].id]); - }else{ - value = scheduler.templates[name + '_field'](columns[i].id, ev); - } - - var cell_style = scheduler.grid._getStyles(columns[i], availStyles); - - var className = columns[i].css ? (" class=\""+columns[i].css+"\"") : ""; - - html+= ""; - - } - html+=""; - - return html; -}; - -scheduler.grid._print_grid_header = function(objName){ - var head = "
"; - - var columns = scheduler[objName].columns; - var widths = []; - - var unsized_columns = columns.length; - var avail_width = scheduler._obj.clientWidth - 2*columns.length -20;//-20 for possible scrollbar, -length for borders - for(var ind=0; ind < columns.length; ind++){ - - var val = columns[ind].initialWidth*1; - if(!isNaN(val) && columns[ind].initialWidth != '' && columns[ind].initialWidth != null && typeof columns[ind].initialWidth != 'boolean'){ - - unsized_columns--; - avail_width -= val; - widths[ind] = val; - }else { - widths[ind] = null; - } - } - - var unsized_width = Math.floor(avail_width / unsized_columns); - var availStyles = ["text-align", "padding-left","padding-right"]; - for(var i=0; i < columns.length; i++){ - var column_width = !widths[i] ? unsized_width : widths[i]; - columns[i].width = column_width - scheduler.grid._calcPadding(columns[i], objName); - var cell_style = scheduler.grid._getStyles(columns[i], availStyles); - head += "
" + (columns[i].label === undefined ? columns[i].id : columns[i].label) + "
"; - } - head +="
"; - - return head; -}; diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_html_templates.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_html_templates.js deleted file mode 100644 index 89f6a0ca984..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_html_templates.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.attachEvent("onTemplatesReady",function(){ - var els = document.body.getElementsByTagName("DIV"); - for (var i=0; i < els.length; i++) { - var cs = els[i].className||""; - cs = cs.split(":"); - if (cs.length == 2 && cs[0] == "template"){ - var code = "return \""+(els[i].innerHTML||"").replace(/\"/g,"\\\"").replace(/[\n\r]+/g,"")+"\";"; - code = unescape(code).replace(/\{event\.([a-z]+)\}/g,function(all,mask){ - return '"+ev.'+mask+'+"'; - }); - scheduler.templates[cs[1]]=Function("start","end","ev",code); - els[i].style.display='none'; - } - }; -}) \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_key_nav.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_key_nav.js deleted file mode 100644 index 087a71cdaec..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_key_nav.js +++ /dev/null @@ -1,79 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -//Initial idea and implementation by Steve MC -(function (){ - -var isLightboxOpen = false; -var date; // used for copy and paste operations -var isCopy = null; - -scheduler.attachEvent("onBeforeLightbox",function(){ isLightboxOpen = true; return true; }); -scheduler.attachEvent("onAfterLightbox",function(){ isLightboxOpen = false; return true; }); - -scheduler.attachEvent("onMouseMove", function(id,e){ - date = scheduler.getActionData(e).date; -}); - -dhtmlxEvent(document,(_isOpera?"keypress":"keydown"),function(e){ - e=e||event; - if (!isLightboxOpen){ - - var scheduler = window.scheduler; - - if (e.keyCode == 37 || e.keyCode == 39) { // Left, Right arrows - e.cancelBubble = true; - - var next = scheduler.date.add(scheduler._date,(e.keyCode == 37 ? -1 : 1 ),scheduler._mode); - scheduler.setCurrentView(next); - return true; - } - - var select_id = scheduler._select_id; - if (e.ctrlKey && e.keyCode == 67) { // CTRL+C - if (select_id) { - scheduler._buffer_id = select_id; - isCopy = true; - scheduler.callEvent("onEventCopied", [scheduler.getEvent(select_id)]); - } - return true; - } - if (e.ctrlKey && e.keyCode == 88) { // CTRL+X - if (select_id) { - isCopy = false; - scheduler._buffer_id = select_id; - var ev = scheduler.getEvent(select_id); - scheduler.updateEvent(ev.id); - scheduler.callEvent("onEventCut", [ev]); - } - } - - if (e.ctrlKey && e.keyCode == 86) { // CTRL+V - var ev = scheduler.getEvent(scheduler._buffer_id); - if (ev) { - var event_duration = ev.end_date-ev.start_date; - if (isCopy) { - var new_ev = scheduler._lame_clone(ev); - new_ev.id = scheduler.uid(); - new_ev.start_date = new Date(date); - new_ev.end_date = new Date(new_ev.start_date.valueOf() + event_duration); - scheduler.addEvent(new_ev); - scheduler.callEvent("onEventPasted", [isCopy, new_ev, ev]); - } - else { // cut operation - var copy = scheduler._lame_copy({}, ev); - ev.start_date = new Date(date); - ev.end_date = new Date(ev.start_date.valueOf() + event_duration); - scheduler.render_view_data(); // need to redraw all events - - scheduler.callEvent("onEventPasted", [isCopy, ev, copy]); - isCopy = true; // switch to copy after first paste operation - } - } - return true; - } - } -}); - -})(); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_limit.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_limit.js deleted file mode 100644 index 0892024eb46..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_limit.js +++ /dev/null @@ -1,831 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.config.limit_start = null; -scheduler.config.limit_end = null; -scheduler.config.limit_view = false; -scheduler.config.check_limits = true; -scheduler.config.mark_now = true; -scheduler.config.display_marked_timespans = true; - -(function(){ - var before = null; - var dhx_time_block = "dhx_time_block"; - - var fix_options = function(options, days, zones) { - if (days instanceof Date && zones instanceof Date) { - options.start_date = days; - options.end_date = zones - } else { - options.days = days; - options.zones = zones; - } - return options; - }; - var get_resulting_options = function(days, zones, sections) { - var options = (typeof days == "object") ? days : { days: days }; - options.type = dhx_time_block; - options.css = ""; - if (zones) { - if (sections) - options.sections = sections; - options = fix_options(options, days, zones); - } - return options; - }; - scheduler.blockTime = function(days, zones, sections){ - var options = get_resulting_options(days, zones, sections); - return scheduler.addMarkedTimespan(options); - }; - scheduler.unblockTime = function(days, zones, sections) { - zones = zones || "fullday"; - var options = get_resulting_options(days, zones, sections); - return scheduler.deleteMarkedTimespan(options); - }; - scheduler.attachEvent("onBeforeViewChange",function(om,od,nm,nd){ - nd = nd||od; nm = nm||om; - if (scheduler.config.limit_view){ - if (nd.valueOf()>scheduler.config.limit_end.valueOf() || this.date.add(nd,1,nm)<=scheduler.config.limit_start.valueOf()){ - setTimeout(function(){ - scheduler.setCurrentView(scheduler._date, nm); - },1); - return false; - } - } - return true; - }); - var get_relevant_blocked_zones = function(day_index, day_value, zones) { - var relevant_zones = (zones[day_value] && zones[day_value][dhx_time_block]) ? zones[day_value][dhx_time_block] : - (zones[day_index] && zones[day_index][dhx_time_block]) ? zones[day_index][dhx_time_block] : []; - return relevant_zones; - }; - var blocker = function(event){ - if(!event) - return true; - if (!scheduler.config.check_limits) - return true; - var s = scheduler; - var mode = s._mode; - var timespans = scheduler._marked_timespans; - var c = s.config; - var evs = []; - if (event.rec_type) { - evs = scheduler.getRecDates(event); - } else { - evs = [event]; - } - - var res = true; - for (var p=0; p= c.limit_start.valueOf() && ev.end_date.valueOf() <= c.limit_end.valueOf()) : true; - if (res){ - var temp_start_date = new Date(ev.start_date.valueOf()); - var temp_end_date = scheduler.date.add(temp_start_date, 1, "day"); - - for (; temp_start_date < ev.end_date; temp_start_date = scheduler.date.date_part(temp_end_date), temp_end_date = s.date.add(temp_start_date, 1, "day") ) { - var day_value = +scheduler.date.date_part( new Date(temp_start_date) ); // the first part of event not necessarily contains only date part - var day_index = temp_start_date.getDay(); - - var zones = []; - if(s._props && s._props[mode]){ - var view = s._props[mode]; - var block_units = timespans[mode]; - if(block_units && block_units[ev[view.map_to]]) { - var unit_zones = block_units[ev[view.map_to]]; - var blocked_unit_zones = get_relevant_blocked_zones(day_index, day_value, unit_zones); - for (var i=0; itemp_end_date || ev.end_date.getDate() != temp_start_date.getDate() ) ? 1440 : scheduler._get_zone_minutes(ev.end_date); - - if (zones){ - for (var i = 0; i < zones.length; i+=2){ - var sz = zones[i]; - var ez = zones[i+1]; - if (szsm) { - if (sm<=ez && sm >=sz){ - if (ez == 24*60 || em=sz && em ez)){ - if(ev._timed && s._drag_id && s._drag_mode == "new-size"){ - ev.end_date.setHours(0); - ev.end_date.setMinutes(sz); - } - else { - res = false; - break; - } - } - } - } - } - } - } - if (!res) { - s._drag_id = null; - s._drag_mode = null; - res = (s.checkEvent("onLimitViolation")) ? s.callEvent("onLimitViolation",[ev.id, ev]) : res; - } - } - return res; - }; - scheduler.attachEvent("onMouseDown", function(classname) { - return !(classname = dhx_time_block); - }); - scheduler.attachEvent("onBeforeDrag",function(id){ - if (!id) return true; - return blocker(scheduler.getEvent(id)); - }); - scheduler.attachEvent("onClick", function (event_id, native_event_object){ - return blocker(scheduler.getEvent(event_id)); - }); - scheduler.attachEvent("onBeforeLightbox",function(id){ - - var ev = scheduler.getEvent(id); - before = [ev.start_date, ev.end_date]; - return blocker(ev); - }); - scheduler.attachEvent("onEventSave", function(id, data, is_new_event) { - if(data.rec_type){ - var data_copy = scheduler._lame_clone(data); - scheduler._roll_back_dates(data_copy); - return blocker(data); - } - return blocker(data); - }); - scheduler.attachEvent("onEventAdded",function(id){ - if (!id) return true; - var ev = scheduler.getEvent(id); - if (!blocker(ev) && scheduler.config.limit_start && scheduler.config.limit_end) { - if (ev.start_date < scheduler.config.limit_start) { - ev.start_date = new Date(scheduler.config.limit_start); - } - if (ev.start_date.valueOf() >= scheduler.config.limit_end.valueOf()) { - ev.start_date = this.date.add(scheduler.config.limit_end, -1, "day"); - } - if (ev.end_date < scheduler.config.limit_start) { - ev.end_date = new Date(scheduler.config.limit_start); - } - if (ev.end_date.valueOf() >= scheduler.config.limit_end.valueOf()) { - ev.end_date = this.date.add(scheduler.config.limit_end, -1, "day"); - } - if (ev.start_date.valueOf() >= ev.end_date.valueOf()) { - ev.end_date = this.date.add(ev.start_date, (this.config.event_duration||this.config.time_step), "minute"); - } - ev._timed=this.is_one_day_event(ev); - } - return true; - }); - scheduler.attachEvent("onEventChanged",function(id){ - if (!id) return true; - var ev = scheduler.getEvent(id); - if (!blocker(ev)){ - if (!before) return false; - ev.start_date = before[0]; - ev.end_date = before[1]; - ev._timed=this.is_one_day_event(ev); - } - return true; - }); - scheduler.attachEvent("onBeforeEventChanged",function(ev, native_object, is_new){ - return blocker(ev); - }); - scheduler.attachEvent("onBeforeEventCreated", function(ev) { // native event - var start_date = scheduler.getActionData(ev).date; - var event = { - _timed: true, - start_date: start_date, - end_date: scheduler.date.add(start_date, scheduler.config.time_step, "minute") - }; - return blocker(event); - }); - - scheduler.attachEvent("onViewChange", function(){ - scheduler.markNow(); - }); - scheduler.attachEvent("onSchedulerResize", function(){ - window.setTimeout(function(){ scheduler.markNow(); }, 1); - return true; - }); - scheduler.attachEvent("onTemplatesReady", function() { - scheduler._mark_now_timer = window.setInterval(function() { - scheduler.markNow(); - }, 60000); - }); - scheduler.markNow = function(hide) { - // day, week, units views - var dhx_now_time = 'dhx_now_time'; - if (!this._els[dhx_now_time]) { - this._els[dhx_now_time] = []; - } - var now = scheduler.config.now_date || new Date(); - var cfg = this.config; - scheduler._remove_mark_now(); // delete previous marks if they exist - if (!hide && cfg.mark_now && now < this._max_date && now > this._min_date && now.getHours() >= cfg.first_hour && now.getHours() config.start_date) || (config.days !== undefined && config.zones)) ) - return r_configs; // incorrect config was provided - - var min = 0; - var max = 24*60; - if (config.zones == "fullday") - config.zones = [min, max]; - if (config.zones && config.invert_zones) { - config.zones = scheduler.invertZones(config.zones); - } - - config.id = scheduler.uid(); - config.css = config.css||""; - config.type = config.type||"default"; - - var sections = config.sections; - if (sections) { - for (var view_key in sections) { - if (sections.hasOwnProperty(view_key)) { - var ids = sections[view_key]; - if (!(ids instanceof Array)) - ids = [ids]; - for (var i=0; i t_sd) ? scheduler._get_zone_minutes(start_date) : min; - var zone_end = ( end_date>t_ed || end_date.getDate() != t_sd.getDate() ) ? max : scheduler._get_zone_minutes(end_date); - t_config.zones = [zone_start, zone_end]; - r_configs.push(t_config); - - t_sd = t_ed; - t_ed = scheduler.date.add(t_ed, 1, "day"); - } - } else { - if (c_config.days instanceof Date) - c_config.days = (scheduler.date.date_part(c_config.days)).valueOf(); - c_config.zones = config.zones.slice(); - r_configs.push(c_config); - } - } - return r_configs; - }; - scheduler._get_dates_by_index = function(index, start, end) { - var dates = []; - start = start||scheduler._min_date; - end = end||scheduler._max_date; - var start_day = start.getDay(); - var delta = (index-start_day >= 0) ? (index-start_day) : (7-start.getDay()+index); - var t_date = scheduler.date.add(start, delta, "day"); - for (; t_date < end; t_date = scheduler.date.add(t_date, 1, "week")) { - dates.push(t_date); - } - return dates; - }; - scheduler._get_css_classes_by_config = function(config) { - var css_classes = []; - if (config.type == dhx_time_block) { - css_classes.push(dhx_time_block); - if (config.css) - css_classes.push(dhx_time_block+"_reset"); - } - css_classes.push("dhx_marked_timespan", config.css); - return css_classes.join(" "); - }; - scheduler._get_block_by_config = function(config) { - var block = document.createElement("DIV"); - if (config.html) { - if (typeof config.html == "string") - block.innerHTML = config.html; - else - block.appendChild(config.html); - } - return block; - }; - scheduler._render_marked_timespan = function(options, area, day) { - var blocks = []; // resulting block which will be rendered and returned - var c = scheduler.config; - var min_date = this._min_date; - var max_date = this._max_date; - var day_value = false; // if timespan for specific date should be displayed - - if (!c.display_marked_timespans) - return blocks; - - if (!day && day !== 0) { // in case of markTimespan - if (options.days < 7) - day = options.days; - else { - var date_to_display = new Date(options.days); - day_value = +date_to_display; - - // in case of markTimespan date could be not in the viewing range, need to return - if ( !(+max_date >= +date_to_display && +min_date <= +date_to_display) ) - return blocks; - - var day_index = date_to_display.getDay(); - if (scheduler.config.start_on_monday) { - day = (day_index == 0) ? 6 : day_index-1; - } else - day = day_index; - } - } - var zones = options.zones; - var css_classes = scheduler._get_css_classes_by_config(options); - - if (scheduler._table_view && scheduler._mode == "month") { - var areas = []; - var days = []; - - - if (!area) { - days = (day_value) ? [day_value] : scheduler._get_dates_by_index(day); - for (var i=0; i < days.length; i++) { - areas.push( this._scales[days[i]] ); - } - } else { - areas.push(area); - days.push(day); - } - - for (var i=0; i < areas.length; i++) { - area = areas[i]; - day = days[i]; - - for (var k=0; k < zones.length; k+=2) { - var start = zones[i]; - var end = zones[i+1]; - if (end <= start) - return []; - - var block = scheduler._get_block_by_config(options); - block.className = css_classes; - - var height = area.offsetHeight - 1; // 1 for bottom border - var width = area.offsetWidth - 1; // 1 for left border - - var sweek = Math.floor((this._correct_shift(day,1)-min_date.valueOf())/(60*60*1000*24*this._cols.length)); - var sday = this.locate_holder_day(day, false) % this._cols.length; - - var left = this._colsS[sday]; - var top = this._colsS.heights[sweek]+(this._colsS.height?(this.xy.month_scale_height+2):2)-1; - - block.style.top = top + "px"; - block.style.lineHeight = block.style.height = height + "px"; - - block.style.left = (left + Math.round( (start)/(24*60) * width)) + "px"; - block.style.width = Math.round( (end-start)/(24*60) * width) + "px"; - - area.appendChild(block); - blocks.push(block); - } - } - } else { - area = area ? area : scheduler.locate_holder(day); - - for (var i = 0; i < zones.length; i+=2){ - var start = Math.max(zones[i], c.first_hour*60); - var end = Math.min(zones[i+1], c.last_hour*60); - if (end <= start) - return []; - - var block = scheduler._get_block_by_config(options); - block.className = css_classes; - - block.style.top = (Math.round((start*60*1000-this.config.first_hour*60*60*1000)*this.config.hour_size_px/(60*60*1000)))%(this.config.hour_size_px*24)+"px"; - block.style.lineHeight = block.style.height = Math.max((Math.round(((end-start-1)*60*1000)*this.config.hour_size_px/(60*60*1000)))%(this.config.hour_size_px*24), 1)+"px"; - - area.appendChild(block); - blocks.push(block); - } - } - - return blocks; - }; - // just marks timespan, will be cleaned after refresh - scheduler.markTimespan = function(configuration) { - var configs = scheduler._prepare_timespan_options(configuration); - if (!configs.length) - return; - var divs = []; - for (var i=0; i c_zone_end && zone_start <= c_zone_end) || (zone_start < c_zone_start && zone_end >= c_zone_start)) { - resulting_zones[i] = Math.min(c_zone_start, zone_start); - resulting_zones[i+1] = Math.max(c_zone_end, zone_end); - i -= 2; - } else { - if (!isLast) // do nothing, maybe next current zone will match or will be last - continue; - - var offset = (c_zone_start > zone_start)?0:2; - resulting_zones.splice(i+offset, 0, zone_start, zone_end); // last current zone, need to add another - } - zones.splice(k--,2); // zone was merged or added, need to exclude it - break; - } - } - return resulting_zones; - }; - scheduler._subtract_timespan_zones = function(current_zones, zones) { - var resulting_zones = current_zones.slice(); - for (var i=0; i c_zone_start && zone_start < c_zone_end) { - var is_modified = false; - if (c_zone_start >= zone_start && c_zone_end <= zone_end) { - resulting_zones.splice(i, 2); - } - if (c_zone_start < zone_start) { - resulting_zones.splice(i, 2, c_zone_start, zone_start); - is_modified = true; - } - if (c_zone_end > zone_end) { - resulting_zones.splice( (is_modified)?(i+2):i, (is_modified)?0:2, zone_end, c_zone_end); - } - i -= 2; - break; - } else { - continue; - } - } - } - return resulting_zones; - }; - scheduler.invertZones = function(zones) { - return scheduler._subtract_timespan_zones([0, 1440], zones.slice()); - }; - scheduler._delete_marked_timespan_by_id = function(id) { - var configs = scheduler._marked_timespans_ids[id]; - if (configs) { - for (var i=0; i" + ev.text + "

" + (ev.event_location || '') + "

" + scheduler.templates.marker_date(start) + " - " + scheduler.templates.marker_date(end) + ""; -}; -scheduler.dblclick_dhx_map_area = function() { - if (!this.config.readonly && this.config.dblclick_create) - this.addEventNow({ - start_date: scheduler._date, - end_date: scheduler.date.add(scheduler._date, scheduler.config.time_step, "minute") - }); -}; -scheduler.templates.map_time = function(start, end, ev) { - if (ev._timed) - return this.day_date(ev.start_date, ev.end_date, ev) + " " + this.event_date(start); - else - return scheduler.templates.day_date(start) + " – " + scheduler.templates.day_date(end); -}; -scheduler.templates.map_text = function(start, end, ev) { - return ev.text; -}; - -scheduler.date.map_start = function(d) { - return d; -}; -scheduler.date.add_map = function(date, inc, mode) { - return (new Date(date.valueOf())); -}; - -scheduler.templates.map_date = function(dd, ed, mode) { - return ''; -}; - -scheduler._latLngUpdate = false; // flag for not displaying event second time in case of coordinates update - -scheduler.attachEvent("onSchedulerReady", function() { - - (function() { - scheduler._isMapPositionSet = false; // if user actual (geolocation) position was set on the map - - var gmap = document.createElement('div'); - gmap.className = 'dhx_map'; - gmap.id = 'dhx_gmap'; - gmap.style.dispay = "none"; - - var node = scheduler._obj; - - node.appendChild(gmap); - - scheduler._els.dhx_gmap = []; - scheduler._els.dhx_gmap.push(gmap); - - _setMapSize('dhx_gmap'); - - var mapOptions = { - zoom: scheduler.config.map_inital_zoom || 10, - center: scheduler.config.map_initial_position, - mapTypeId: scheduler.config.map_type || google.maps.MapTypeId.ROADMAP - }; - var map = new google.maps.Map(document.getElementById('dhx_gmap'), mapOptions); - map.disableDefaultUI = false; - map.disableDoubleClickZoom = !scheduler.config.readonly; - - google.maps.event.addListener(map, "dblclick", function(event) { - if (!scheduler.config.readonly && scheduler.config.dblclick_create) { - var point = event.latLng; - geocoder.geocode( - { 'latLng': point }, - function(results, status) { - if (status == google.maps.GeocoderStatus.OK) { - point = results[0].geometry.location; - scheduler.addEventNow({ - lat: point.lat(), - lng: point.lng(), - event_location: results[0].formatted_address, - start_date: scheduler._date, - end_date: scheduler.date.add(scheduler._date, scheduler.config.time_step, "minute") - }); - } - } - ); - } - }); - - var infoWindowOptions = { - content: '' - }; - - if (scheduler.config.map_infowindow_max_width) { - infoWindowOptions.maxWidth = scheduler.config.map_infowindow_max_width; - } - - scheduler.map = { - _points: [], - _markers: [], - _infowindow: new google.maps.InfoWindow(infoWindowOptions), - _infowindows_content: [], - _initialization_count: -1, - _obj: map - }; - - geocoder = new google.maps.Geocoder(); - - if (scheduler.config.map_resolve_user_location) { - if (navigator.geolocation) { - if (!scheduler._isMapPositionSet) { - navigator.geolocation.getCurrentPosition(function(position) { - var _userLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); - map.setCenter(_userLocation); - map.setZoom(scheduler.config.map_zoom_after_resolve || 10); - scheduler.map._infowindow.setContent(scheduler.locale.labels.marker_geo_success); - scheduler.map._infowindow.position = map.getCenter(); - scheduler.map._infowindow.open(map); - - scheduler._isMapPositionSet = true; - }, - function() { - scheduler.map._infowindow.setContent(scheduler.locale.labels.marker_geo_fail); - scheduler.map._infowindow.setPosition(map.getCenter()); - scheduler.map._infowindow.open(map); - scheduler._isMapPositionSet = true; - }); - } - } - } - google.maps.event.addListener(map, "resize", function(event) { - gmap.style.zIndex = '5'; - map.setZoom(map.getZoom()); - - }); - google.maps.event.addListener(map, "tilesloaded", function(event) { - gmap.style.zIndex = '5'; - }); - - gmap.style.display = 'none'; // property was changed after attaching map - })(); - - scheduler.attachEvent("onSchedulerResize", function() { - if (this._mode == "map") { - this.map_view(true); - return false - } - return true; - }); - - var old = scheduler.render_data; - scheduler.render_data = function(evs, hold) { - if (this._mode == "map") { - fill_map_tab(); - var events = scheduler.get_visible_events(); - for (var i = 0; i < events.length; i++) { - if (!scheduler.map._markers[events[i].id]) { - showAddress(events[i], false, false); - } - } - } else - return old.apply(this, arguments); - }; - - function set_full_view(mode) { - if (mode) { - var l = scheduler.locale.labels; - scheduler._els["dhx_cal_header"][0].innerHTML = "
" + l.date + "
" + l.description + "
"; - scheduler._table_view = true; - scheduler.set_sizes(); - } - } - - function clear_map_tab() { - scheduler._selected_event_id = null; - scheduler.map._infowindow.close(); - var markers = scheduler.map._markers; - for (var key in markers) { - if (markers.hasOwnProperty(key)) { - markers[key].setMap(null); - delete scheduler.map._markers[key]; - if (scheduler.map._infowindows_content[key]) - delete scheduler.map._infowindows_content[key]; - } - } - } - - function fill_map_tab() { - //select events for which data need to be printed - var events = scheduler.get_visible_events(); - events.sort(function(a, b) { - if(a.start_date.valueOf()==b.start_date.valueOf()) - return a.id>b.id?1:-1; - return a.start_date>b.start_date?1:-1; - }); - - //generate html for the view - var html = "
"; - for (var i = 0; i < events.length; i++) { - var ev = events[i]; - var event_class = (ev.id == scheduler._selected_event_id) ? 'dhx_map_line highlight' : 'dhx_map_line'; - var bg_color = (ev.color ? ("background:" + ev.color + ";") : ""); - var color = (ev.textColor ? ("color:" + ev.textColor + ";") : ""); - html += "
" + scheduler.templates.map_time(ev.start_date, ev.end_date, ev) + "
"; - html += "
 
"; - html += "
" + scheduler.templates.map_text(ev.start_date, ev.end_date, ev) + "
"; // -25 = icon size 20 and padding 5 - } - html += "
"; - - //render html - scheduler._els["dhx_cal_data"][0].scrollTop = 0; //fix flickering in FF - scheduler._els["dhx_cal_data"][0].innerHTML = html; - scheduler._els["dhx_cal_data"][0].style.width = (scheduler.xy.map_date_width + scheduler.xy.map_description_width + 1) + 'px'; - - var t = scheduler._els["dhx_cal_data"][0].firstChild.childNodes; - scheduler._els["dhx_cal_date"][0].innerHTML = scheduler.templates[scheduler._mode + "_date"](scheduler._min_date, scheduler._max_date, scheduler._mode); - - scheduler._rendered = []; - for (var i = 0; i < t.length - 2; i++) { - scheduler._rendered[i] = t[i]; - } - } - - function _setMapSize(elem_id) { //input - map's div id - var map = document.getElementById(elem_id); - var height = scheduler._y - scheduler.xy.nav_height; - if (height < 0) - height = 0; - var width = scheduler._x - scheduler.xy.map_date_width - scheduler.xy.map_description_width - 1; - if (width < 0) - width = 0; - map.style.height = height + 'px'; - map.style.width = width + 'px'; - map.style.marginLeft = (scheduler.xy.map_date_width + scheduler.xy.map_description_width + 1) + 'px'; - map.style.marginTop = (scheduler.xy.nav_height + 2) + 'px'; - } - - scheduler.map_view = function(mode) { - scheduler.map._initialization_count++; - var gmap = scheduler._els.dhx_gmap[0]; - scheduler._els.dhx_cal_data[0].style.width = (scheduler.xy.map_date_width + scheduler.xy.map_description_width + 1) + 'px'; - - scheduler._min_date = scheduler.config.map_start || (new Date()); - scheduler._max_date = scheduler.config.map_end || scheduler.date.add(new Date(), 1, "year"); - - scheduler._table_view = true; - set_full_view(mode); - - if (mode) { //map tab activated - clear_map_tab(); - fill_map_tab(); - gmap.style.display = 'block'; - - // need to resize block everytime window is resized - _setMapSize('dhx_gmap'); - var temp_center = scheduler.map._obj.getCenter(); - - var events = scheduler.get_visible_events(); - for (var i = 0; i < events.length; i++) { - if (!scheduler.map._markers[events[i].id]) { - showAddress(events[i]); - } - } - - } else { //map tab de-activated - gmap.style.display = 'none'; - } - google.maps.event.trigger(scheduler.map._obj, 'resize'); - - if (scheduler.map._initialization_count === 0 && temp_center) { // if tab is activated for the first time need to fix position - scheduler.map._obj.setCenter(temp_center); - } - - if (scheduler._selected_event_id) { - selectEvent(scheduler._selected_event_id); - } - }; - - var selectEvent = function(event_id) { - scheduler.map._obj.setCenter(scheduler.map._points[event_id]); - scheduler.callEvent("onClick", [event_id]); - }; - - var showAddress = function(event, setCenter, performClick) { // what if event have incorrect position from the start? - var point = scheduler.config.map_error_position; - if (event.lat && event.lng) { - point = new google.maps.LatLng(event.lat, event.lng); - } - var message = scheduler.templates.marker_text(event.start_date, event.end_date, event); - if (!scheduler._new_event) { - - scheduler.map._infowindows_content[event.id] = message; - - if (scheduler.map._markers[event.id]) - scheduler.map._markers[event.id].setMap(null); - - scheduler.map._markers[event.id] = new google.maps.Marker({ - position: point, - map: scheduler.map._obj - }); - - google.maps.event.addListener(scheduler.map._markers[event.id], 'click', function() { - scheduler.map._infowindow.setContent(scheduler.map._infowindows_content[event.id]); - scheduler.map._infowindow.open(scheduler.map._obj, scheduler.map._markers[event.id]); - scheduler._selected_event_id = event.id; - scheduler.render_data(); - }); - scheduler.map._points[event.id] = point; - - if (setCenter) scheduler.map._obj.setCenter(scheduler.map._points[event.id]); - if (performClick) scheduler.callEvent("onClick", [event.id]); - } - }; - - scheduler.attachEvent("onClick", function(event_id, native_event_object) { - if (this._mode == "map") { - scheduler._selected_event_id = event_id; - for (var i = 0; i < scheduler._rendered.length; i++) { - scheduler._rendered[i].className = 'dhx_map_line'; - if (scheduler._rendered[i].getAttribute("event_id") == event_id) { - scheduler._rendered[i].className += " highlight"; - } - } - if (scheduler.map._points[event_id] && scheduler.map._markers[event_id]) { - scheduler.map._obj.setCenter(scheduler.map._points[event_id]); // was panTo - google.maps.event.trigger(scheduler.map._markers[event_id], 'click'); - } - } - return true; - }); - - var _displayEventOnMap = function(event) { - if (event.event_location && geocoder) { - geocoder.geocode( - { - 'address': event.event_location, - 'language': scheduler.uid().toString() - }, - function(results, status) { - var point = {}; - if (status != google.maps.GeocoderStatus.OK) { - point = scheduler.callEvent("onLocationError", [event.id]); - if (!point || point === true) - point = scheduler.config.map_error_position; - } else { - point = results[0].geometry.location; - } - event.lat = point.lat(); - event.lng = point.lng(); - - scheduler._selected_event_id = event.id; - - scheduler._latLngUpdate = true; - scheduler.callEvent("onEventChanged", [event.id, event]); - showAddress(event, true, true); - } - ); - } else { - showAddress(event, true, true); - } - }; - - var _updateEventLocation = function(event) { // update lat and lng in database - if (event.event_location && geocoder) { - geocoder.geocode( - { - 'address': event.event_location, - 'language': scheduler.uid().toString() - }, - function(results, status) { - var point = {}; - if (status != google.maps.GeocoderStatus.OK) { - point = scheduler.callEvent("onLocationError", [event.id]); - if (!point || point === true) - point = scheduler.config.map_error_position; - } else { - point = results[0].geometry.location; - } - event.lat = point.lat(); - event.lng = point.lng(); - scheduler._latLngUpdate = true; - scheduler.callEvent("onEventChanged", [event.id, event]); - } - ); - } - }; - - var _delay = function(method, object, params, delay) { - setTimeout(function() { - var ret = method.apply(object, params); - method = object = params = null; - return ret; - }, delay || 1); - }; - - scheduler.attachEvent("onEventChanged", function(event_id, event_object) { - if (!this._latLngUpdate) { - var event = scheduler.getEvent(event_id); - if ((event.start_date < scheduler._min_date && event.end_date > scheduler._min_date) || (event.start_date < scheduler._max_date && event.end_date > scheduler._max_date) || (event.start_date.valueOf() >= scheduler._min_date && event.end_date.valueOf() <= scheduler._max_date)) { - if (scheduler.map._markers[event_id]) - scheduler.map._markers[event_id].setMap(null); - _displayEventOnMap(event); - } else { // event no longer should be displayed on the map view - scheduler._selected_event_id = null; - scheduler.map._infowindow.close(); - if (scheduler.map._markers[event_id]) - scheduler.map._markers[event_id].setMap(null); - } - } - else - this._latLngUpdate = false; - return true; - }); - - - scheduler.attachEvent("onEventIdChange", function(old_event_id, new_event_id) { - var event = scheduler.getEvent(new_event_id); - if ((event.start_date < scheduler._min_date && event.end_date > scheduler._min_date) || (event.start_date < scheduler._max_date && event.end_date > scheduler._max_date) || (event.start_date.valueOf() >= scheduler._min_date && event.end_date.valueOf() <= scheduler._max_date)) { - if (scheduler.map._markers[old_event_id]) { - scheduler.map._markers[old_event_id].setMap(null); - delete scheduler.map._markers[old_event_id]; - } - if (scheduler.map._infowindows_content[old_event_id]) - delete scheduler.map._infowindows_content[old_event_id]; - _displayEventOnMap(event); - } - return true; - }); - - scheduler.attachEvent("onEventAdded", function(event_id, event_object) { - if (!scheduler._dataprocessor) { - if ((event_object.start_date < scheduler._min_date && event_object.end_date > scheduler._min_date) || (event_object.start_date < scheduler._max_date && event_object.end_date > scheduler._max_date) || (event_object.start_date.valueOf() >= scheduler._min_date && event_object.end_date.valueOf() <= scheduler._max_date)) { - if (scheduler.map._markers[event_id]) - scheduler.map._markers[event_id].setMap(null); - _displayEventOnMap(event_object); - } - } - return true; - }); - - /* Test/example - scheduler.attachEvent("onLocationError", function(event_id,event_object){ - return new google.maps.LatLng(8, 8); - }); - */ - - scheduler.attachEvent("onBeforeEventDelete", function(event_id, event_object) { - if (scheduler.map._markers[event_id]) { - scheduler.map._markers[event_id].setMap(null); // if new event is deleted tab != map then it doesn't have marker yet - } - scheduler._selected_event_id = null; - scheduler.map._infowindow.close(); - return true; - }); - - scheduler._event_resolve_delay = 1500; - scheduler.attachEvent("onEventLoading", function(event) { - if (scheduler.config.map_resolve_event_location && event.event_location && !event.lat && !event.lng) { // don't delete !event.lat && !event.lng as location could change - scheduler._event_resolve_delay += 1500; - _delay(_updateEventLocation, this, [event], scheduler._event_resolve_delay); - } - return true; - }); - - scheduler.attachEvent("onEventCancel", function(event_id, is_new) { - if (is_new) { - if (scheduler.map._markers[event_id]) - scheduler.map._markers[event_id].setMap(null); - scheduler.map._infowindow.close(); - } - return true; - }); -}); diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_minical.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_minical.js deleted file mode 100644 index 595af055fce..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_minical.js +++ /dev/null @@ -1,435 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.templates.calendar_month = scheduler.date.date_to_str("%F %Y"); -scheduler.templates.calendar_scale_date = scheduler.date.date_to_str("%D"); -scheduler.templates.calendar_date = scheduler.date.date_to_str("%d"); -scheduler.config.minicalendar = { - mark_events: true -}; -scheduler._synced_minicalendars = []; -scheduler.renderCalendar = function(obj, _prev, is_refresh) { - var cal = null; - var date = obj.date || (new Date()); - if (typeof date == "string") - date = this.templates.api_date(date); - - if (!_prev) { - var cont = obj.container; - var pos = obj.position; - - if (typeof cont == "string") - cont = document.getElementById(cont); - - if (typeof pos == "string") - pos = document.getElementById(pos); - if (pos && (typeof pos.left == "undefined")) { - var tpos = getOffset(pos); - pos = { - top: tpos.top + pos.offsetHeight, - left: tpos.left - }; - } - if (!cont) - cont = scheduler._get_def_cont(pos); - - cal = this._render_calendar(cont, date, obj); - cal.onclick = function(e) { - e = e || event; - var src = e.target || e.srcElement; - - if (src.className.indexOf("dhx_month_head") != -1) { - var pname = src.parentNode.className; - if (pname.indexOf("dhx_after") == -1 && pname.indexOf("dhx_before") == -1) { - var newdate = scheduler.templates.xml_date(this.getAttribute("date")); - newdate.setDate(parseInt(src.innerHTML, 10)); - scheduler.unmarkCalendar(this); - scheduler.markCalendar(this, newdate, "dhx_calendar_click"); - this._last_date = newdate; - if (this.conf.handler) this.conf.handler.call(scheduler, newdate, this); - } - } - }; - } else { - cal = this._render_calendar(_prev.parentNode, date, obj, _prev); - scheduler.unmarkCalendar(cal); - } - - if (scheduler.config.minicalendar.mark_events) { - var start = scheduler.date.month_start(date); - var end = scheduler.date.add(start, 1, "month"); - var evs = this.getEvents(start, end); - var filter = this["filter_" + this._mode]; - for (var i = 0; i < evs.length; i++) { - var ev = evs[i]; - if (filter && !filter(ev.id, ev)) - continue; - var d = ev.start_date; - if (d.valueOf() < start.valueOf()) - d = start; - d = scheduler.date.date_part(new Date(d.valueOf())); - while (d < ev.end_date) { - this.markCalendar(cal, d, "dhx_year_event"); - d = this.date.add(d, 1, "day"); - if (d.valueOf() >= end.valueOf()) - break; - } - } - } - - this._markCalendarCurrentDate(cal); - - cal.conf = obj; - if (obj.sync && !is_refresh) - this._synced_minicalendars.push(cal); - - return cal; -}; -scheduler._get_def_cont = function(pos) { - if (!this._def_count) { - this._def_count = document.createElement("DIV"); - this._def_count.className = "dhx_minical_popup"; - this._def_count.onclick = function(e) { (e || event).cancelBubble = true; }; - document.body.appendChild(this._def_count); - } - - this._def_count.style.left = pos.left + "px"; - this._def_count.style.top = pos.top + "px"; - this._def_count._created = new Date(); - - return this._def_count; -}; -scheduler._locateCalendar = function(cal, date) { - var table = cal.childNodes[2].childNodes[0]; - if (typeof date == "string") - date = scheduler.templates.api_date(date); - - var d = cal.week_start + date.getDate() - 1; - return table.rows[Math.floor(d / 7)].cells[d % 7].firstChild; -}; -scheduler.markCalendar = function(cal, date, css) { - this._locateCalendar(cal, date).className += " " + css; -}; -scheduler.unmarkCalendar = function(cal, date, css) { - date = date || cal._last_date; - css = css || "dhx_calendar_click"; - if (!date) return; - var el = this._locateCalendar(cal, date); - el.className = (el.className || "").replace(RegExp(css, "g")); -}; -scheduler._week_template = function(width) { - var summ = (width || 250); - var left = 0; - - var week_template = document.createElement("div"); - var dummy_date = this.date.week_start(new Date()); - for (var i = 0; i < 7; i++) { - this._cols[i] = Math.floor(summ / (7 - i)); - this._render_x_header(i, left, dummy_date, week_template); - dummy_date = this.date.add(dummy_date, 1, "day"); - summ -= this._cols[i]; - left += this._cols[i]; - } - week_template.lastChild.className += " dhx_scale_bar_last"; - return week_template; -}; -scheduler.updateCalendar = function(obj, sd) { - obj.conf.date = sd; - this.renderCalendar(obj.conf, obj, true); -}; -scheduler._mini_cal_arrows = [" ", " "]; -scheduler._render_calendar = function(obj, sd, conf, previous) { - /*store*/ - var ts = scheduler.templates; - var temp = this._cols; - this._cols = []; - var temp2 = this._mode; - this._mode = "calendar"; - var temp3 = this._colsS; - this._colsS = {height: 0}; - var temp4 = new Date(this._min_date); - var temp5 = new Date(this._max_date); - var temp6 = new Date(scheduler._date); - var temp7 = ts.month_day; - ts.month_day = ts.calendar_date; - - sd = this.date.month_start(sd); - var week_template = this._week_template(obj.offsetWidth - 1); - - var d; - if (previous) - d = previous; else { - d = document.createElement("DIV"); - d.className = "dhx_cal_container dhx_mini_calendar"; - } - d.setAttribute("date", this.templates.xml_format(sd)); - d.innerHTML = "
" + week_template.innerHTML + "
"; - - d.childNodes[0].innerHTML = this.templates.calendar_month(sd); - if (conf.navigation) { - var move_minicalendar_date = function(calendar, diff) { - var date = scheduler.date.add(calendar._date, diff, "month"); - scheduler.updateCalendar(calendar, date); - if (scheduler._date.getMonth() == calendar._date.getMonth() && scheduler._date.getFullYear() == calendar._date.getFullYear()) { - scheduler._markCalendarCurrentDate(calendar); - } - }; - - var css_classnames = ["dhx_cal_prev_button", "dhx_cal_next_button"]; - var css_texts = ["left:1px;top:2px;position:absolute;", "left:auto; right:1px;top:2px;position:absolute;"]; - var diffs = [-1, 1]; - var handler = function(diff) { - return function() { - if (conf.sync) { - var calendars = scheduler._synced_minicalendars; - for (var k = 0; k < calendars.length; k++) { - move_minicalendar_date(calendars[k], diff); - } - } else { - move_minicalendar_date(d, diff); - } - } - }; - for (var j = 0; j < 2; j++) { - var arrow = document.createElement("DIV"); - //var diff = diffs[j]; - arrow.className = css_classnames[j]; - arrow.style.cssText = css_texts[j]; - arrow.innerHTML = this._mini_cal_arrows[j]; - d.firstChild.appendChild(arrow); - arrow.onclick = handler(diffs[j]) - } - } - d._date = new Date(sd); - - d.week_start = (sd.getDay() - (this.config.start_on_monday ? 1 : 0) + 7) % 7; - - var dd = this.date.week_start(sd); - this._reset_month_scale(d.childNodes[2], sd, dd); - - var r = d.childNodes[2].firstChild.rows; - for (var k = r.length; k < 6; k++) { - var last_row = r[r.length - 1]; - r[0].parentNode.appendChild(last_row.cloneNode(true)); - var last_day_number = parseInt(last_row.childNodes[last_row.childNodes.length - 1].childNodes[0].innerHTML); - last_day_number = (last_day_number < 10) ? last_day_number : 0; // previous week could end on 28-31, so we should start with 0 - for (var ri = 0; ri < r[k].childNodes.length; ri++) { - r[k].childNodes[ri].className = "dhx_after"; - r[k].childNodes[ri].childNodes[0].innerHTML = scheduler.date.to_fixed(++last_day_number); - } - } - - if (!previous) - obj.appendChild(d); - - d.childNodes[1].style.height = (d.childNodes[1].childNodes[0].offsetHeight - 1) + "px"; // dhx_year_week should have height property so that day dates would get correct position. dhx_year_week height = height of it's child (with the day name) - - /*restore*/ - this._cols = temp; - this._mode = temp2; - this._colsS = temp3; - this._min_date = temp4; - this._max_date = temp5; - scheduler._date = temp6; - ts.month_day = temp7; - return d; -}; -scheduler.destroyCalendar = function(cal, force) { - if (!cal && this._def_count && this._def_count.firstChild) { - if (force || (new Date()).valueOf() - this._def_count._created.valueOf() > 500) - cal = this._def_count.firstChild; - } - if (!cal) return; - cal.onclick = null; - cal.innerHTML = ""; - if (cal.parentNode) - cal.parentNode.removeChild(cal); - if (this._def_count) - this._def_count.style.top = "-1000px"; -}; -scheduler.isCalendarVisible = function() { - if (this._def_count && parseInt(this._def_count.style.top, 10) > 0) - return this._def_count; - return false; -}; -scheduler.attachEvent("onTemplatesReady", function() { - dhtmlxEvent(document.body, "click", function() { scheduler.destroyCalendar(); }); -}); - -scheduler.templates.calendar_time = scheduler.date.date_to_str("%d-%m-%Y"); - -scheduler.form_blocks.calendar_time = { - render: function() { - var html = ""; - - var cfg = scheduler.config; - var dt = this.date.date_part(new Date()); - - var last = 24 * 60, first = 0; - if (cfg.limit_time_select) { - first = 60 * cfg.first_hour; - last = 60 * cfg.last_hour + 1; // to include "17:00" option if time select is limited - } - dt.setHours(first / 60); - - html += " "; - - var full_day = scheduler.config.full_day; - - return "
" + html + "  –  " + html + "
"; - }, - set_value: function(node, value, ev) { - - var inputs = node.getElementsByTagName("input"); - var selects = node.getElementsByTagName("select"); - - var _init_once = function(inp, date, number) { - inp.onclick = function() { - scheduler.destroyCalendar(null, true); - scheduler.renderCalendar({ - position: inp, - date: new Date(this._date), - navigation: true, - handler: function(new_date) { - inp.value = scheduler.templates.calendar_time(new_date); - inp._date = new Date(new_date); - scheduler.destroyCalendar(); - if (scheduler.config.event_duration && scheduler.config.auto_end_date && number == 0) { //first element = start date - _update_minical_select(); - } - } - }); - }; - }; - - if (scheduler.config.full_day) { - if (!node._full_day) { - var html = ""; - if (!scheduler.config.wide_form) - html = node.previousSibling.innerHTML + html; - node.previousSibling.innerHTML = html; - node._full_day = true; - } - var input = node.previousSibling.getElementsByTagName("input")[0]; - - var isFulldayEvent = (scheduler.date.time_part(ev.start_date) == 0 && scheduler.date.time_part(ev.end_date) == 0); - input.checked = isFulldayEvent; - - selects[0].disabled = input.checked; - selects[1].disabled = input.checked; - - input.onclick = function() { - if (input.checked == true) { - var obj = {}; - scheduler.form_blocks.calendar_time.get_value(node, obj); - - var start_date = scheduler.date.date_part(obj.start_date); - var end_date = scheduler.date.date_part(obj.end_date); - - if (+end_date == +start_date || (+end_date >= +start_date && (ev.end_date.getHours() != 0 || ev.end_date.getMinutes() != 0))) - end_date = scheduler.date.add(end_date, 1, "day"); - } - - var start = start_date || ev.start_date; - var end = end_date || ev.end_date; - _attach_action(inputs[0], start); - _attach_action(inputs[1], end); - selects[0].value = start.getHours() * 60 + start.getMinutes(); - selects[1].value = end.getHours() * 60 + end.getMinutes(); - - selects[0].disabled = input.checked; - selects[1].disabled = input.checked; - - }; - } - - if (scheduler.config.event_duration && scheduler.config.auto_end_date) { - - function _update_minical_select() { - start_date = scheduler.date.add(inputs[0]._date, selects[0].value, "minute"); - end_date = new Date(start_date.getTime() + (scheduler.config.event_duration * 60 * 1000)); - - inputs[1].value = scheduler.templates.calendar_time(end_date); - inputs[1]._date = scheduler.date.date_part(new Date(end_date)); - - selects[1].value = end_date.getHours() * 60 + end_date.getMinutes(); - } - - selects[0].onchange = _update_minical_select; // only update on first select should trigger update so user could define other end date if he wishes too - } - - function _attach_action(inp, date, number) { - _init_once(inp, date, number); - inp.value = scheduler.templates.calendar_time(date); - inp._date = scheduler.date.date_part(new Date(date)); - } - - _attach_action(inputs[0], ev.start_date, 0); - _attach_action(inputs[1], ev.end_date, 1); - _init_once = function() {}; - - selects[0].value = ev.start_date.getHours() * 60 + ev.start_date.getMinutes(); - selects[1].value = ev.end_date.getHours() * 60 + ev.end_date.getMinutes(); - - }, - get_value: function(node, ev) { - var inputs = node.getElementsByTagName("input"); - var selects = node.getElementsByTagName("select"); - - ev.start_date = scheduler.date.add(inputs[0]._date, selects[0].value, "minute"); - ev.end_date = scheduler.date.add(inputs[1]._date, selects[1].value, "minute"); - - if (ev.end_date <= ev.start_date) - ev.end_date = scheduler.date.add(ev.start_date, scheduler.config.time_step, "minute"); - }, - focus: function(node) { - } -}; -scheduler.linkCalendar = function(calendar, datediff) { - var action = function() { - var date = scheduler._date; - var dateNew = new Date(date.valueOf()); - if (datediff) dateNew = datediff(dateNew); - dateNew.setDate(1); - scheduler.updateCalendar(calendar, dateNew); - return true; - }; - - scheduler.attachEvent("onViewChange", action); - scheduler.attachEvent("onXLE", action); - scheduler.attachEvent("onEventAdded", action); - scheduler.attachEvent("onEventChanged", action); - scheduler.attachEvent("onAfterEventDelete", action); - action(); -}; - -scheduler._markCalendarCurrentDate = function(calendar) { - var date = scheduler._date; - var mode = scheduler._mode; - var month_start = scheduler.date.month_start(new Date(calendar._date)); - var month_end = scheduler.date.add(month_start, 1, "month"); - - if (mode == 'day' || (this._props && !!this._props[mode])) { // if day or units view - if (month_start.valueOf() <= date.valueOf() && month_end > date) { - scheduler.markCalendar(calendar, date, "dhx_calendar_click"); - } - } else if (mode == 'week') { - var dateNew = scheduler.date.week_start(new Date(date.valueOf())); - for (var i = 0; i < 7; i++) { - if (month_start.valueOf() <= dateNew.valueOf() && month_end > dateNew) // >= would mean mark first day of the next month - scheduler.markCalendar(calendar, dateNew, "dhx_calendar_click"); - dateNew = scheduler.date.add(dateNew, 1, "day"); - } - } -}; - -scheduler.attachEvent("onEventCancel", function(){ - scheduler.destroyCalendar(null, true); -}); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multiselect.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multiselect.js deleted file mode 100644 index ccf9b911900..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multiselect.js +++ /dev/null @@ -1,66 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.form_blocks["multiselect"]={ - render:function(sns) { - var _result = "
"; - for (var i=0; i"+sns.options[i].label+""; - if(convertStringToBoolean(sns.vertical)) _result += '
'; - } - _result += "
"; - return _result; - }, - set_value:function(node,value,ev,config){ - - var _children = node.getElementsByTagName('input'); - for(var i=0;i<_children.length;i++) { - _children[i].checked = false; //unchecking all inputs on the form - } - - function _mark_inputs(ids) { // ids = [ 0: undefined, 1: undefined, 2: true ... ] - var _children = node.getElementsByTagName('input'); - for(var i=0;i<_children.length; i++) { - _children[i].checked = !! ids[_children[i].value]; - } - } - - var _ids = []; - if (ev[config.map_to]) { - var results = ev[config.map_to].split(','); - for (var i = 0; i < results.length; i++) { - _ids[results[i]] = true; - } - _mark_inputs(_ids); - } else { - if (scheduler._new_event || !config.script_url) - return; - var divLoading = document.createElement('div'); - divLoading.className = 'dhx_loading'; - divLoading.style.cssText = "position: absolute; top: 40%; left: 40%;"; - node.appendChild(divLoading); - dhtmlxAjax.get(config.script_url + '?dhx_crosslink_' + config.map_to + '=' + ev.id + '&uid=' + scheduler.uid(), function(loader) { - var _result = loader.doXPath("//data/item"); - var _ids = []; - for (var i = 0; i < _result.length; i++) { - _ids[_result[i].getAttribute(config.map_to)] = true; - } - _mark_inputs(_ids); - node.removeChild(divLoading); - }); - } - }, - get_value:function(node,ev,config){ - var _result = []; - var _children = node.getElementsByTagName("input"); - for(var i=0;i<_children.length;i++) { - if(_children[i].checked) - _result.push(_children[i].value); - } - return _result.join(','); - }, - - focus:function(node){ - } -}; \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multisource.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multisource.js deleted file mode 100644 index eb8e193ca82..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_multisource.js +++ /dev/null @@ -1,26 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -(function(){ - - function backup(obj){ - var t = function(){}; - t.prototype = obj; - return t; - } - - var old = scheduler._load; - scheduler._load=function(url,from){ - url=url||this._load_url; - if (typeof url == "object"){ - var t = backup(this._loaded); - for (var i=0; i < url.length; i++) { - this._loaded=new t(); - old.call(this,url[i],from); - } - } else - old.apply(this,arguments); - } - -})(); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_offline.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_offline.js deleted file mode 100644 index 0e8e2a21678..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_offline.js +++ /dev/null @@ -1,79 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.load=function(url,call){ - if (typeof call == "string"){ - this._process=call; - var type = call; - call = arguments[2]; - } - - this._load_url=url; - this._after_call=call; - if (url.$proxy) { - url.load(this, typeof type == "string" ? type : null); - return; - } - - this._load(url,this._date); -}; - -scheduler._dp_init_backup = scheduler._dp_init; -scheduler._dp_init = function(dp) { - dp._sendData = function(a1,rowId){ - if (!a1) return; //nothing to send - if (!this.callEvent("onBeforeDataSending",rowId?[rowId,this.getState(rowId),a1]:[null, null, a1])) return false; - if (rowId) - this._in_progress[rowId]=(new Date()).valueOf(); - if (this.serverProcessor.$proxy) { - var mode = this._tMode!="POST" ? 'get' : 'post'; - var to_send = []; - for (var i in a1) - to_send.push({ id: i, data: a1[i], operation: this.getState(i)}); - this.serverProcessor._send(to_send, mode, this); - return; - } - - var a2=new dtmlXMLLoaderObject(this.afterUpdate,this,true); - var a3 = this.serverProcessor+(this._user?(getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+this.obj.getUserData(0,"version")].join("&")):""); - if (this._tMode!="POST") - a2.loadXML(a3+((a3.indexOf("?")!=-1)?"&":"?")+this.serialize(a1,rowId)); - else - a2.loadXML(a3,true,this.serialize(a1,rowId)); - this._waitMode++; - }; - - dp._updatesToParams = function(items) { - var stack = {}; - for (var i = 0; i < items.length; i++) - stack[items[i].id] = items[i].data; - return this.serialize(stack); - }; - - dp._processResult = function(text, xml, loader) { - if (loader.status != 200) { - for (var i in this._in_progress) { - var state = this.getState(i); - this.afterUpdateCallback(i, i, state, null); - } - return; - } - xml = new dtmlXMLLoaderObject(function() {},this,true); - xml.loadXMLString(text); - xml.xmlDoc = loader; - - this.afterUpdate(this, null, null, null, xml); - }; - this._dp_init_backup(dp); -} - -if (window.dataProcessor) - dataProcessor.prototype.init=function(obj){ - this.init_original(obj); - obj._dataprocessor=this; - - this.setTransactionMode("POST",true); - if (!this.serverProcessor.$proxy) - this.serverProcessor+=(this.serverProcessor.indexOf("?")!=-1?"&":"?")+"editing=true"; - }; \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_outerdrag.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_outerdrag.js deleted file mode 100644 index 10cf72e6424..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_outerdrag.js +++ /dev/null @@ -1,51 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -//lame old code doesn't provide raw event object -scheduler.attachEvent("onTemplatesReady", function(){ - - var dragger = (new dhtmlDragAndDropObject()); - var old = dragger.stopDrag; - var last_event; - dragger.stopDrag = function(e){ - last_event = e||event; - return old.apply(this, arguments); - }; - dragger.addDragLanding(scheduler._els["dhx_cal_data"][0],{ - _drag:function(sourceHtmlObject,dhtmlObject,targetHtmlObject,targetHtml){ - - if (scheduler.checkEvent("onBeforeExternalDragIn") && !scheduler.callEvent("onBeforeExternalDragIn", [sourceHtmlObject,dhtmlObject,targetHtmlObject,targetHtml,last_event])) - return; - - var temp = scheduler.attachEvent("onEventCreated", function(id,e){ - if (!scheduler.callEvent("onExternalDragIn", [id, sourceHtmlObject, e])){ - this._drag_mode = this._drag_id = null; - this.deleteEvent(id); - } - }); - - if (scheduler.matrix && scheduler.matrix[scheduler._mode]) - scheduler.dblclick_dhx_matrix_cell(last_event); - else { - - var div = document.createElement('div'); - div.className = 'dhx_month_body'; - var eventCopy = {}; - for (var i in last_event) eventCopy[i] = last_event[i]; - eventCopy.target = eventCopy.srcElement = div; - - scheduler._on_dbl_click(eventCopy); - } - scheduler.detachEvent(temp); - - - }, - _dragIn:function(htmlObject,shtmlObject){ - return htmlObject; - }, - _dragOut:function(htmlObject){ - return this; - } - }); -}); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_pdf.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_pdf.js deleted file mode 100644 index fad86c2e5d6..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_pdf.js +++ /dev/null @@ -1,276 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.toPDF=function(url,mode,header,footer){ - var dx = 0; - var dy = 0; - var colors = false; - if (mode == "fullcolor"){ - colors = true; - mode = "color"; - } - - mode = mode||"color"; - html_regexp = new RegExp("<[^>]*>","g"); - newline_regexp = new RegExp("]*>","g"); - function clean_html(val){ - return val.replace(newline_regexp, "\n").replace(html_regexp,""); - } - function x_norm(x) { - x = parseFloat(x); - if (isNaN(x)) return "auto"; - return 100 * x / (dx + 1); - } - function y_norm(y) { - y = parseFloat(y); - if (isNaN(y)) return "auto"; - return 100 * y / dy; - } - function xml_month_scale(xh){ - var xml=""; - if (scheduler.matrix && scheduler.matrix[scheduler._mode]) { - if (scheduler.matrix[scheduler._mode].second_scale) - var xhs = xh[1].childNodes; - - xh = xh[0].childNodes; - } - - - for (var i = 0; i < xh.length; i++) - xml += "\n"; - dx = xh[0].offsetWidth; - - if (xhs) { - var width = 0; - var top_width = xh[0].offsetWidth; - var top_col = 1; - for (var i = 0; i < xhs.length; i++) { - xml += "\n"; - width+=xhs[i].offsetWidth; - if (width>=top_width){ - top_width+=(xh[top_col] ? xh[top_col].offsetWidth: 0); - top_col++; - } - dx = xhs[0].offsetWidth; - } - } - return xml; - } - function de_day(node,n){ - var x = parseInt(node.style.left,10); - - for (var dx=0; dx < scheduler._cols.length; dx++){ - x-=scheduler._cols[dx]; - if (x<0) return dx; - } - return n; - } - function de_week(node,n){ - var y = parseInt(node.style.top,10); - for (var dy=0; dy < scheduler._colsS.heights.length; dy++) - if (scheduler._colsS.heights[dy]>y) return dy; - return n; - } - function xml_month(yh){ - var xml=""; - var r = yh.firstChild.rows; - for (var i = 0; i < r.length; i++) { - var days = []; - for (var j = 0; j < r[i].cells.length; j++){ - /* var dd = r[i].cells[j]; - var css = dd.className; - - if (css!=" " && css!="dhx_now ") - days.push(""); - else*/ - days.push(r[i].cells[j].firstChild.innerHTML); - } - - xml += "\n"; - dy = yh.firstChild.rows[0].cells[0].offsetHeight; - } - return xml; - } - function xml_top(profile) { - var xml = ""; - - if (scheduler._mode == "week_agenda"){ - var xh = scheduler._els.dhx_cal_data[0].getElementsByTagName("DIV"); - for (var i=0; i"; - } else if (scheduler._mode == "agenda" || scheduler._mode == "map"){ - var xh = scheduler._els.dhx_cal_header[0].childNodes[0].childNodes; - - xml+=""+clean_html(xh[0].innerHTML)+""+clean_html(xh[1].innerHTML)+""; - } else if (scheduler._mode == "year"){ - var xh = scheduler._els.dhx_cal_data[0].childNodes; - for (var i=0; i < xh.length; i++) { - xml+=""; - xml+=xml_month_scale(xh[i].childNodes[1].childNodes); - xml+=xml_month(xh[i].childNodes[2]); - xml+=""; - } - } else { - xml += ""; - var xh = scheduler._els.dhx_cal_header[0].childNodes; - xml+=xml_month_scale(xh); - xml += ""; - - var yh = scheduler._els.dhx_cal_data[0]; - if (scheduler.matrix && scheduler.matrix[scheduler._mode]) { - xml += ""; - for (var i=0; i < yh.firstChild.rows.length; i++) { - var el = yh.firstChild.rows[i]; - xml+=""; - } - xml+=""; - dy = yh.firstChild.rows[0].cells[0].offsetHeight; - } else if (yh.firstChild.tagName == "TABLE") { - xml += xml_month(yh); - } else { - yh = yh.childNodes[yh.childNodes.length - 1]; - while (yh.className.indexOf("dhx_scale_holder") == -1) - yh = yh.previousSibling; - yh = yh.childNodes; - - xml += ""; - for (var i = 0; i < yh.length; i++) - xml += "\n"; - xml += ""; - dy = yh[0].offsetHeight; - } - } - xml += ""; - return xml; - } - function get_style(node, style){ - return (window.getComputedStyle?(window.getComputedStyle(node, null)[style]):(node.currentStyle?node.currentStyle[style]:null))||""; - } - function xml_body() { - var xml = ""; - var evs = scheduler._rendered; - if (scheduler._mode == "agenda" || scheduler._mode == "map"){ - for (var i=0; i < evs.length; i++) - xml+=""+clean_html(evs[i].childNodes[0].innerHTML)+""+clean_html(evs[i].childNodes[2].innerHTML)+""; - } else if (scheduler._mode == "week_agenda"){ - for (var i=0; i < evs.length; i++) - xml+=""+clean_html(evs[i].innerHTML)+""; - } else if (scheduler._mode == "year"){ - var evs = scheduler.get_visible_events(); - for (var i=0; i < evs.length; i++) { - var d = evs[i].start_date; - if (d.valueOf()"; - d = scheduler.date.add(d,1,"day"); - if (d.valueOf()>=scheduler._max_date.valueOf()) - break; - } - } - } else { - var matrix = scheduler.matrix && scheduler.matrix[scheduler._mode]; - if (matrix && matrix.render == "cell"){ - var evs = scheduler._els.dhx_cal_data[0].getElementsByTagName("TD"); - for (var i = 0; i < evs.length; i++){ - var text_color = colors?get_style(evs[i],"color"):""; - var bg_color = colors?get_style(evs[i],"backgroundColor"):""; - xml += "\n"; - } - } else { - for (var i = 0; i < evs.length; i++) { - var zx = x_norm(evs[i].style.left); - var zdx = x_norm(evs[i].style.width); - if (isNaN(zdx*1)) continue; - var zy = y_norm(evs[i].style.top); - var zdy = y_norm(evs[i].style.height); - var e_type = evs[i].className.split(" ")[0].replace("dhx_cal_", ""); - if (e_type === 'dhx_tooltip_line') continue; - var dets = scheduler.getEvent(evs[i].getAttribute("event_id")); -// if (evs[i].parentNode == scheduler._els.dhx_cal_data[0]) continue; - var day = dets._sday; - var week = dets._sweek; - var length = dets._length || 0; - if (scheduler._mode != "month") { - if (scheduler.matrix && scheduler.matrix[scheduler._mode]){ - day = 0; - var el = evs[i].parentNode.parentNode.parentNode; - week = el.rowIndex; - zdx += x_norm(10); - } else { - - if (scheduler.xy.menu_width){ - zdx+=x_norm(zdx*20/100); - zx-=x_norm(15-zx*20/100); - } - - if (evs[i].parentNode == scheduler._els.dhx_cal_data[0]) continue; - zx += x_norm(evs[i].parentNode.style.left); - zx -= x_norm(51); - } - if (scheduler.matrix && scheduler.matrix[scheduler._mode]) { - var dy_copy = dy; - dy = evs[i].parentNode.offsetHeight; - zy = y_norm(evs[i].style.top); - zy -= zy*0.2; - dy = dy_copy; - } - } else { - zdy = parseInt(evs[i].offsetHeight,10); - zy = parseInt(evs[i].style.top,10) - 22; - - day = de_day(evs[i],day); - week = de_week(evs[i],week); - } - - xml += "\n"; - - - if (e_type == "event") { - xml += "
"; - var text_color = colors?get_style(evs[i].childNodes[2],"color"):""; - var bg_color = colors?get_style(evs[i].childNodes[2],"backgroundColor"):""; - xml += ""; - } else { - var text_color = colors?get_style(evs[i],"color"):""; - var bg_color = colors?get_style(evs[i],"backgroundColor"):""; - xml += ""; - } - xml += "
"; - } - } - } - return xml; - } - function xml_end(){ - var xml = "
"; - return xml; - } - - var uid = (new Date()).valueOf(); - var d=document.createElement("div"); - d.style.display="none"; - document.body.appendChild(d); - - d.innerHTML = '
'; - document.getElementById(uid).firstChild.value = encodeURIComponent(xml_top(mode).replace("\u2013", "-") + xml_body() + xml_end()); - document.getElementById(uid).submit(); - d.parentNode.removeChild(d);grid = null; -}; \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_readonly.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_readonly.js deleted file mode 100644 index df888122424..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_readonly.js +++ /dev/null @@ -1,144 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.attachEvent("onTemplatesReady", function() { - var original_sns = scheduler.config.lightbox.sections; - var recurring_section = null; - var original_left_buttons = scheduler.config.buttons_left.slice(); - var original_right_buttons = scheduler.config.buttons_right.slice(); - - - scheduler.attachEvent("onBeforeLightbox", function(id) { - if (this.config.readonly_form || this.getEvent(id).readonly) { - this.config.readonly_active = true; - - for (var i = 0; i < this.config.lightbox.sections.length; i++) { - this.config.lightbox.sections[i].focus = false; - } - } - else { - this.config.readonly_active = false; - scheduler.config.buttons_left = original_left_buttons.slice(); - scheduler.config.buttons_right = original_right_buttons.slice(); - } - - var sns = this.config.lightbox.sections; - if (this.config.readonly_active) { - var is_rec_found = false; - for (var i = 0; i < sns.length; i++) { - if (sns[i].type == 'recurring') { - recurring_section = sns[i]; - if (this.config.readonly_active) { - sns.splice(i, 1); - } - break; - } - } - if (!is_rec_found && !this.config.readonly_active && recurring_section) { - // need to restore restore section - sns.splice(sns.length-2,0,recurring_section); - } - - var forbidden_buttons = ["dhx_delete_btn", "dhx_save_btn"]; - var button_arrays = [scheduler.config.buttons_left, scheduler.config.buttons_right]; - for (var i = 0; i < forbidden_buttons.length; i++) { - var forbidden_button = forbidden_buttons[i]; - for (var k = 0; k < button_arrays.length; k++) { - var button_array = button_arrays[k]; - var index = -1; - for (var p = 0; p < button_array.length; p++) { - if (button_array[p] == forbidden_button) { - index = p; - break; - } - } - if (index != -1) { - button_array.splice(index, 1); - } - } - } - - - } - - this.resetLightbox(); - - return true; - }); - - function txt_replace(tag, d, n, text) { - var txts = d.getElementsByTagName(tag); - var txtt = n.getElementsByTagName(tag); - for (var i = txtt.length - 1; i >= 0; i--) { - var n = txtt[i]; - if (!text) - n.disabled = true; - else { - var t = document.createElement("SPAN"); - t.className = "dhx_text_disabled"; - t.innerHTML = text(txts[i]); - n.parentNode.insertBefore(t, n); - n.parentNode.removeChild(n); - } - } - } - - var old = scheduler._fill_lightbox; - scheduler._fill_lightbox = function() { - var res = old.apply(this, arguments); - - if (this.config.readonly_active) { - - var d = this.getLightbox(); - var n = this._lightbox_r = d.cloneNode(true); - n.id = scheduler.uid(); - - txt_replace("textarea", d, n, function(a) { - return a.value; - }); - txt_replace("input", d, n, false); - txt_replace("select", d, n, function(a) { - return a.options[Math.max((a.selectedIndex || 0), 0)].text; - }); - - d.parentNode.insertBefore(n, d); - - olds.call(this, n); - if (scheduler._lightbox) - scheduler._lightbox.parentNode.removeChild(scheduler._lightbox); - this._lightbox = n; - this.setLightboxSize(); - this._lightbox = null; - n.onclick = function(e) { - var src = e ? e.target : event.srcElement; - if (!src.className) src = src.previousSibling; - if (src && src.className) - switch (src.className) { - case "dhx_cancel_btn": - scheduler.callEvent("onEventCancel", [scheduler._lightbox_id]); - scheduler._edit_stop_event(scheduler.getEvent(scheduler._lightbox_id), false); - scheduler.hide_lightbox(); - break; - } - }; - } - return res; - }; - - var olds = scheduler.showCover; - scheduler.showCover = function() { - if (!this.config.readonly_active) - olds.apply(this, arguments); - }; - - var hold = scheduler.hide_lightbox; - scheduler.hide_lightbox = function() { - if (this._lightbox_r) { - this._lightbox_r.parentNode.removeChild(this._lightbox_r); - this._lightbox_r = null; - } - - return hold.apply(this, arguments); - }; -}); diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_recurring.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_recurring.js deleted file mode 100644 index 998fe8bedd2..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_recurring.js +++ /dev/null @@ -1,750 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ - -scheduler.config.occurrence_timestamp_in_utc = false; -scheduler.form_blocks["recurring"] = { - render:function(sns) { - return scheduler.__recurring_template; - }, - _ds: {}, - _init_set_value:function(node, value, ev) { - scheduler.form_blocks["recurring"]._ds = {start:ev.start_date, end:ev._end_date}; - - var str_date_format = scheduler.date.str_to_date(scheduler.config.repeat_date); - var str_date = function(str_date) { - var date = str_date_format(str_date); - if (scheduler.config.include_end_by) - date = scheduler.date.add(date, 1, 'day'); - return date; - }; - - var date_str = scheduler.date.date_to_str(scheduler.config.repeat_date); - - var top = node.getElementsByTagName("FORM")[0]; - var els = []; - - function register_els(inps) { - for (var i = 0; i < inps.length; i++) { - var inp = inps[i]; - if (inp.type == "checkbox" || inp.type == "radio") { - if (!els[inp.name]) - els[inp.name] = []; - els[inp.name].push(inp); - } else - els[inp.name] = inp; - } - } - - register_els(top.getElementsByTagName("INPUT")); - register_els(top.getElementsByTagName("SELECT")); - - if (!scheduler.config.repeat_date_of_end) { - var formatter = scheduler.date.date_to_str(scheduler.config.repeat_date); - scheduler.config.repeat_date_of_end = formatter(scheduler.date.add(new Date(), 30, "day")); - } - els["date_of_end"].value = scheduler.config.repeat_date_of_end; - - var $ = function(a) { - return document.getElementById(a); - }; - - function get_radio_value(name) { - var col = els[name]; - for (var i = 0; i < col.length; i++) - if (col[i].checked) return col[i].value; - } - - function change_current_view() { - $("dhx_repeat_day").style.display = "none"; - $("dhx_repeat_week").style.display = "none"; - $("dhx_repeat_month").style.display = "none"; - $("dhx_repeat_year").style.display = "none"; - $("dhx_repeat_" + this.value).style.display = "block"; - } - - function get_repeat_code(dates) { - var code = [get_radio_value("repeat")]; - get_rcode[code[0]](code, dates); - - while (code.length < 5) code.push(""); - var repeat = ""; - if (els["end"][0].checked) { - dates.end = new Date(9999, 1, 1); - repeat = "no"; - } - else if (els["end"][2].checked) { - dates.end = str_date(els["date_of_end"].value); - } - else { - scheduler.transpose_type(code.join("_")); - repeat = Math.max(1, els["occurences_count"].value); - var transp = ((code[0] == "week" && code[4] && code[4].toString().indexOf(scheduler.config.start_on_monday ? 1 : 0) == -1) ? 1 : 0); - dates.end = scheduler.date.add(new Date(dates.start), repeat + transp, code.join("_")); - } - - return code.join("_") + "#" + repeat; - } - - scheduler.form_blocks["recurring"]._get_repeat_code = get_repeat_code; - var get_rcode = { - month:function(code, dates) { - if (get_radio_value("month_type") == "d") { - code.push(Math.max(1, els["month_count"].value)); - dates.start.setDate(els["month_day"].value); - } else { - code.push(Math.max(1, els["month_count2"].value)); - code.push(els["month_day2"].value); - code.push(Math.max(1, els["month_week2"].value)); - dates.start.setDate(1); - } - dates._start = true; - }, - week:function(code, dates) { - code.push(Math.max(1, els["week_count"].value)); - code.push(""); - code.push(""); - var t = []; - var col = els["week_day"]; - for (var i = 0; i < col.length; i++) { - if (col[i].checked) t.push(col[i].value); - } - if (!t.length) - t.push(dates.start.getDay()); - - dates.start = scheduler.date.week_start(dates.start); - dates._start = true; - - code.push(t.sort().join(",")); - }, - day:function(code) { - if (get_radio_value("day_type") == "d") { - code.push(Math.max(1, els["day_count"].value)); - } - else { - code.push("week"); - code.push(1); - code.push(""); - code.push(""); - code.push("1,2,3,4,5"); - code.splice(0, 1); - } - }, - year:function(code, dates) { - if (get_radio_value("year_type") == "d") { - code.push("1"); - dates.start.setMonth(0); - dates.start.setDate(els["year_day"].value); - dates.start.setMonth(els["year_month"].value); - - } else { - code.push("1"); - code.push(els["year_day2"].value); - code.push(els["year_week2"].value); - dates.start.setDate(1); - dates.start.setMonth(els["year_month2"].value); - } - dates._start = true; - } - }; - var set_rcode = { - week:function(code, dates) { - els["week_count"].value = code[1]; - var col = els["week_day"]; - var t = code[4].split(","); - var d = {}; - for (var i = 0; i < t.length; i++) d[t[i]] = true; - for (var i = 0; i < col.length; i++) - col[i].checked = (!!d[col[i].value]); - }, - month:function(code, dates) { - if (code[2] == "") { - els["month_type"][0].checked = true; - els["month_count"].value = code[1]; - els["month_day"].value = dates.start.getDate(); - } else { - els["month_type"][1].checked = true; - els["month_count2"].value = code[1]; - els["month_week2"].value = code[3]; - els["month_day2"].value = code[2]; - } - }, - day:function(code, dates) { - els["day_type"][0].checked = true; - els["day_count"].value = code[1]; - }, - year:function(code, dates) { - if (code[2] == "") { - els["year_type"][0].checked = true; - els["year_day"].value = dates.start.getDate(); - els["year_month"].value = dates.start.getMonth(); - } else { - els["year_type"][1].checked = true; - els["year_week2"].value = code[3]; - els["year_day2"].value = code[2]; - els["year_month2"].value = dates.start.getMonth(); - } - } - }; - - function set_repeat_code(code, dates) { - var data = code.split("#"); - code = data[0].split("_"); - set_rcode[code[0]](code, dates); - var e = els["repeat"][({day:0, week:1, month:2, year:3})[code[0]]]; - switch (data[1]) { - case "no": - els["end"][0].checked = true; - break; - case "": - els["end"][2].checked = true; - els["date_of_end"].value = date_str(dates.end); - break; - default: - els["end"][1].checked = true; - els["occurences_count"].value = data[1]; - break; - } - - e.checked = true; - e.onclick(); - } - - scheduler.form_blocks["recurring"]._set_repeat_code = set_repeat_code; - - for (var i = 0; i < top.elements.length; i++) { - var el = top.elements[i]; - switch (el.name) { - case "repeat": - el.onclick = change_current_view; - break; - } - } - scheduler._lightbox._rec_init_done = true; - }, - set_value:function(node, value, ev) { - var rf = scheduler.form_blocks["recurring"]; - if (!scheduler._lightbox._rec_init_done) - rf._init_set_value(node, value, ev); - node.open = !ev.rec_type; - if (ev.event_pid && ev.event_pid != "0") - node.blocked = true; - else node.blocked = false; - - var ds = rf._ds; - ds.start = ev.start_date; - ds.end = ev._end_date; - - rf.button_click(0, node.previousSibling.firstChild.firstChild, node, node); - if (value) - rf._set_repeat_code(value, ds); - }, - get_value:function(node, ev) { - if (node.open) { - var ds = scheduler.form_blocks["recurring"]._ds; - var actual_dates = {}; - this.formSection('time').getValue(actual_dates); - ds.start = actual_dates.start_date; - ev.rec_type = scheduler.form_blocks["recurring"]._get_repeat_code(ds); - if (ds._start) { - ev.start_date = new Date(ds.start); - ev._start_date = new Date(ds.start); - ds._start = false; - } else - ev._start_date = null; - - ev._end_date = ev.end_date = ds.end; - ev.rec_pattern = ev.rec_type.split("#")[0]; - } else { - ev.rec_type = ev.rec_pattern = ""; - ev._end_date = ev.end_date; - } - return ev.rec_type; - }, - focus:function(node) { - }, - button_click:function(index, el, section, cont) { - if (!cont.open && !cont.blocked) { - cont.style.height = "115px"; - el.style.backgroundPosition = "-5px 0px"; - el.nextSibling.innerHTML = scheduler.locale.labels.button_recurring_open; - } else { - cont.style.height = "0px"; - el.style.backgroundPosition = "-5px 20px"; - el.nextSibling.innerHTML = scheduler.locale.labels.button_recurring; - } - cont.open = !cont.open; - - scheduler.setLightboxSize(); - } -}; - - -//problem may occur if we will have two repeating events in the same moment of time -scheduler._rec_markers = {}; -scheduler._rec_markers_pull = {}; -scheduler._add_rec_marker = function(ev, time) { - ev._pid_time = time; - this._rec_markers[ev.id] = ev; - if (!this._rec_markers_pull[ev.event_pid]) this._rec_markers_pull[ev.event_pid] = {}; - this._rec_markers_pull[ev.event_pid][time] = ev; -}; -scheduler._get_rec_marker = function(time, id) { - var ch = this._rec_markers_pull[id]; - if (ch) return ch[time]; - return null; -}; -scheduler._get_rec_markers = function(id) { - return (this._rec_markers_pull[id] || []); -}; -scheduler._rec_temp = []; -(function() { - var old_add_event = scheduler.addEvent; - scheduler.addEvent = function(start_date, end_date, text, id, extra_data) { - var ev_id = old_add_event.apply(this, arguments); - - if (ev_id) { - var ev = scheduler.getEvent(ev_id); - if (ev.event_pid != 0) - scheduler._add_rec_marker(ev, ev.event_length * 1000); - if (ev.rec_type) - ev.rec_pattern = ev.rec_type.split("#")[0]; - } - }; -})(); -scheduler.attachEvent("onEventIdChange", function(id, new_id) { - if (this._ignore_call) return; - this._ignore_call = true; - - for (var i = 0; i < this._rec_temp.length; i++) { - var tev = this._rec_temp[i]; - if (tev.event_pid == id) { - tev.event_pid = new_id; - this.changeEventId(tev.id, new_id + "#" + tev.id.split("#")[1]); - } - } - - delete this._ignore_call; -}); -scheduler.attachEvent("onBeforeEventDelete", function(id) { - var ev = this.getEvent(id); - if (id.toString().indexOf("#") != -1 || (ev.event_pid && ev.event_pid != "0" && ev.rec_type && ev.rec_type != 'none')) { - id = id.split("#"); - var nid = this.uid(); - var tid = (id[1]) ? id[1] : (ev._pid_time / 1000); - - var nev = this._copy_event(ev); - nev.id = nid; - nev.event_pid = ev.event_pid || id[0]; - var timestamp = tid; - nev.event_length = timestamp; - nev.rec_type = nev.rec_pattern = "none"; - this.addEvent(nev); - - this._add_rec_marker(nev, timestamp * 1000); - } else { - if (ev.rec_type && this._lightbox_id) - this._roll_back_dates(ev); - var sub = this._get_rec_markers(id); - for (var i in sub) { - if (sub.hasOwnProperty(i)) { - id = sub[i].id; - if (this.getEvent(id)) - this.deleteEvent(id, true); - } - } - } - return true; -}); - -scheduler.attachEvent("onEventChanged", function(id) { - if (this._loading) return true; - - var ev = this.getEvent(id); - if (id.toString().indexOf("#") != -1) { - var id = id.split("#"); - var nid = this.uid(); - this._not_render = true; - - var nev = this._copy_event(ev); - nev.id = nid; - nev.event_pid = id[0]; - var timestamp = id[1]; - nev.event_length = timestamp; - nev.rec_type = nev.rec_pattern = ""; - this.addEvent(nev); - - this._not_render = false; - this._add_rec_marker(nev, timestamp * 1000); - } else { - if (ev.rec_type && this._lightbox_id) - this._roll_back_dates(ev); - var sub = this._get_rec_markers(id); - for (var i in sub) { - if (sub.hasOwnProperty(i)) { - delete this._rec_markers[sub[i].id]; - this.deleteEvent(sub[i].id, true); - } - } - delete this._rec_markers_pull[id]; - - // it's possible that after editing event is no longer exists, in such case we need to remove _select_id flag - var isEventFound = false; - for (var k = 0; k < this._rendered.length; k++) { - if (this._rendered[k].getAttribute('event_id') == id) - isEventFound = true; - } - if (!isEventFound) - this._select_id = null; - } - return true; -}); -scheduler.attachEvent("onEventAdded", function(id) { - if (!this._loading) { - var ev = this.getEvent(id); - if (ev.rec_type && !ev.event_length) - this._roll_back_dates(ev); - } - return true; -}); -scheduler.attachEvent("onEventSave", function(id, data, is_new_event) { - var ev = this.getEvent(id); - if (!ev.rec_type && data.rec_type && (id + '').indexOf('#') == -1) - this._select_id = null; - return true; -}); -scheduler.attachEvent("onEventCreated", function(id) { - var ev = this.getEvent(id); - if (!ev.rec_type) - ev.rec_type = ev.rec_pattern = ev.event_length = ev.event_pid = ""; - return true; -}); -scheduler.attachEvent("onEventCancel", function(id) { - var ev = this.getEvent(id); - if (ev.rec_type) { - this._roll_back_dates(ev); - // a bit expensive, but we need to be sure that event re-rendered, because view can be corrupted by resize , during edit process - this.render_view_data(); - } -}); -scheduler._roll_back_dates = function(ev) { - ev.event_length = (ev.end_date.valueOf() - ev.start_date.valueOf()) / 1000; - ev.end_date = ev._end_date; - if (ev._start_date) { - ev.start_date.setMonth(0); - ev.start_date.setDate(ev._start_date.getDate()); - ev.start_date.setMonth(ev._start_date.getMonth()); - ev.start_date.setFullYear(ev._start_date.getFullYear()); - - } -}; - -scheduler.validId = function(id) { - return id.toString().indexOf("#") == -1; -}; - -scheduler.showLightbox_rec = scheduler.showLightbox; -scheduler.showLightbox = function(id) { - var locale = this.locale; - var c = scheduler.config.lightbox_recurring; - var pid = this.getEvent(id).event_pid; - var isVirtual = (id.toString().indexOf("#") != -1); - if (isVirtual) - pid = id.split("#")[0]; - if ( !pid || pid == 0 || ( (!locale.labels.confirm_recurring || c == 'instance') || (c == 'series' && !isVirtual)) ) { - return this.showLightbox_rec(id); // editing instance or non recurring event - } - // show series - var callback = function() { - pid = this.getEvent(pid); - pid._end_date = pid.end_date; - pid.end_date = new Date(pid.start_date.valueOf() + pid.event_length * 1000); - return this.showLightbox_rec(pid.id); // editing series - }; - if (c == 'ask') { - var that = this; - dhtmlx.modalbox({ - text: locale.labels.confirm_recurring, - title: locale.labels.title_confirm_recurring, - width: "500px", - position: "middle", - buttons:[locale.labels.button_edit_series, locale.labels.button_edit_occurrence, locale.labels.icon_cancel], - callback: function(index) { - switch(+index) { - case 0: - return callback.call(that); - case 1: - return that.showLightbox_rec(id); - case 2: - return; - } - } - }); - } else { - callback(); - } - -}; - - -scheduler.get_visible_events_rec = scheduler.get_visible_events; -scheduler.get_visible_events = function(only_timed) { - for (var i = 0; i < this._rec_temp.length; i++) - delete this._events[this._rec_temp[i].id]; - this._rec_temp = []; - - var stack = this.get_visible_events_rec(only_timed); - var out = []; - for (var i = 0; i < stack.length; i++) { - if (stack[i].rec_type) { - //deleted element of serie - if (stack[i].rec_pattern != "none") - this.repeat_date(stack[i], out); - } - else out.push(stack[i]); - } - return out; -}; - - -(function() { - var old = scheduler.is_one_day_event; - scheduler.is_one_day_event = function(ev) { - if (ev.rec_type) return true; - return old.call(this, ev); - }; - var old_update_event = scheduler.updateEvent; - scheduler.updateEvent = function(id) { - var ev = scheduler.getEvent(id); - if (ev && ev.rec_type && id.toString().indexOf('#') === -1) { - scheduler.update_view(); - } else { - old_update_event.call(this, id); - } - }; -})(); - -scheduler.transponse_size = { - day:1, week:7, month:1, year:12 -}; -scheduler.date.day_week = function(sd, day, week) { - sd.setDate(1); - week = (week - 1) * 7; - var cday = sd.getDay(); - var nday = day * 1 + week - cday + 1; - sd.setDate(nday <= week ? (nday + 7) : nday); -}; -scheduler.transpose_day_week = function(sd, list, cor, size, cor2) { - var cday = (sd.getDay() || (scheduler.config.start_on_monday ? 7 : 0)) - cor; - for (var i = 0; i < list.length; i++) { - if (list[i] > cday) - return sd.setDate(sd.getDate() + list[i] * 1 - cday - (size ? cor : cor2)); - } - this.transpose_day_week(sd, list, cor + size, null, cor); -}; -scheduler.transpose_type = function(type) { - var f = "transpose_" + type; - if (!this.date[f]) { - var str = type.split("_"); - var day = 60 * 60 * 24 * 1000; - var gf = "add_" + type; - var step = this.transponse_size[str[0]] * str[1]; - - if (str[0] == "day" || str[0] == "week") { - var days = null; - if (str[4]) { - days = str[4].split(","); - if (scheduler.config.start_on_monday) { - for (var i = 0; i < days.length; i++) - days[i] = (days[i] * 1) || 7; - days.sort(); - } - } - - - this.date[f] = function(nd, td) { - var delta = Math.floor((td.valueOf() - nd.valueOf()) / (day * step)); - if (delta > 0) - nd.setDate(nd.getDate() + delta * step); - if (days) - scheduler.transpose_day_week(nd, days, 1, step); - }; - this.date[gf] = function(sd, inc) { - var nd = new Date(sd.valueOf()); - if (days) { - for (var count = 0; count < inc; count++) - scheduler.transpose_day_week(nd, days, 0, step); - } else - nd.setDate(nd.getDate() + inc * step); - - return nd; - }; - } - else if (str[0] == "month" || str[0] == "year") { - this.date[f] = function(nd, td) { - var delta = Math.ceil(((td.getFullYear() * 12 + td.getMonth() * 1) - (nd.getFullYear() * 12 + nd.getMonth() * 1)) / (step)); - if (delta >= 0) - nd.setMonth(nd.getMonth() + delta * step); - if (str[3]) - scheduler.date.day_week(nd, str[2], str[3]); - }; - this.date[gf] = function(sd, inc) { - var nd = new Date(sd.valueOf()); - nd.setMonth(nd.getMonth() + inc * step); - if (str[3]) - scheduler.date.day_week(nd, str[2], str[3]); - return nd; - }; - } - } -}; -scheduler.repeat_date = function(ev, stack, non_render, from, to) { - - from = from || this._min_date; - to = to || this._max_date; - - var td = new Date(ev.start_date.valueOf()); - - if (!ev.rec_pattern && ev.rec_type) - ev.rec_pattern = ev.rec_type.split("#")[0]; - - this.transpose_type(ev.rec_pattern); - scheduler.date["transpose_" + ev.rec_pattern](td, from); - while (td < ev.start_date || scheduler._fix_daylight_saving_date(td,from,ev,td,new Date(td.valueOf() + ev.event_length * 1000)).valueOf() <= from.valueOf() || td.valueOf() + ev.event_length * 1000 <= from.valueOf()) - td = this.date.add(td, 1, ev.rec_pattern); - while (td < to && td < ev.end_date) { - var timestamp = (scheduler.config.occurrence_timestamp_in_utc) ? Date.UTC(td.getFullYear(), td.getMonth(), td.getDate(), td.getHours(), td.getMinutes(), td.getSeconds()) : td.valueOf(); - var ch = this._get_rec_marker(timestamp, ev.id); - if (!ch) { // unmodified element of series - var ted = new Date(td.valueOf() + ev.event_length * 1000); - var copy = this._copy_event(ev); - //copy._timed = ev._timed; - copy.text = ev.text; - copy.start_date = td; - copy.event_pid = ev.id; - copy.id = ev.id + "#" + Math.ceil(timestamp / 1000); - copy.end_date = ted; - - copy.end_date = scheduler._fix_daylight_saving_date(copy.start_date, copy.end_date, ev, td, copy.end_date); - - copy._timed = this.is_one_day_event(copy); - - if (!copy._timed && !this._table_view && !this.config.multi_day) return; - stack.push(copy); - - if (!non_render) { - this._events[copy.id] = copy; - this._rec_temp.push(copy); - } - - } else - if (non_render) stack.push(ch); - - td = this.date.add(td, 1, ev.rec_pattern); - } -}; -scheduler._fix_daylight_saving_date = function(start_date, end_date, ev, counter, default_date) { - var shift = start_date.getTimezoneOffset() - end_date.getTimezoneOffset(); - if (shift) { - if (shift > 0) { - // e.g. 24h -> 23h - return new Date(counter.valueOf() + ev.event_length * 1000 - shift * 60 * 1000); - } - else { - // e.g. 24h -> 25h - return new Date(end_date.valueOf() - shift * 60 * 1000); - } - } - return new Date(default_date.valueOf()); -}; -scheduler.getRecDates = function(id, max) { - var ev = typeof id == "object" ? id : scheduler.getEvent(id); - var count = 0; - var result = []; - max = max || 100; - - var td = new Date(ev.start_date.valueOf()); - var from = new Date(td.valueOf()); - - if (!ev.rec_type) { - return [ - { start_date: ev.start_date, end_date: ev.end_date } - ]; - } - if (ev.rec_type == "none") { - return []; - } - this.transpose_type(ev.rec_pattern); - scheduler.date["transpose_" + ev.rec_pattern](td, from); - - while (td < ev.start_date || (td.valueOf() + ev.event_length * 1000) <= from.valueOf()) - td = this.date.add(td, 1, ev.rec_pattern); - while (td < ev.end_date) { - var ch = this._get_rec_marker(td.valueOf(), ev.id); - var res = true; - if (!ch) { // unmodified element of series - var sed = new Date(td); - var ted = new Date(td.valueOf() + ev.event_length * 1000); - - ted = scheduler._fix_daylight_saving_date(sed, ted, ev, td, ted); - - result.push({start_date:sed, end_date:ted}); - } else { - (ch.rec_type == "none") ? - (res = false) : - result.push({ start_date: ch.start_date, end_date: ch.end_date }); - } - td = this.date.add(td, 1, ev.rec_pattern); - if (res) { - count++; - if (count == max) - break; - } - } - return result; -}; -scheduler.getEvents = function(from, to) { - var result = []; - for (var a in this._events) { - var ev = this._events[a]; - if (ev && ev.start_date < to && ev.end_date > from) { - if (ev.rec_pattern) { - if (ev.rec_pattern == "none") continue; - var sev = []; - this.repeat_date(ev, sev, true, from, to); - for (var i = 0; i < sev.length; i++) { - // if event is in rec_markers then it will be checked by himself, here need to skip it - if (!sev[i].rec_pattern && sev[i].start_date < to && sev[i].end_date > from && !this._rec_markers[sev[i].id]) { - result.push(sev[i]); - } - } - } else if (ev.id.toString().indexOf("#") == -1) { // if it's virtual event we can skip it - result.push(ev); - } - } - } - return result; -}; - -scheduler.config.repeat_date = "%m.%d.%Y"; -scheduler.config.lightbox.sections = [ - {name:"description", height:130, map_to:"text", type:"textarea" , focus:true}, - {name:"recurring", type:"recurring", map_to:"rec_type", button:"recurring"}, - {name:"time", height:72, type:"time", map_to:"auto"} -]; - - -//drop secondary attributes -scheduler._copy_dummy = function(ev) { - var start_date = new Date(this.start_date); - var end_date = new Date(this.end_date); - this.start_date = start_date; - this.end_date = end_date; - this.event_length = this.event_pid = this.rec_pattern = this.rec_type = null; -}; - -scheduler.config.include_end_by = false; -scheduler.config.lightbox_recurring = 'ask'; // series, instance -scheduler.__recurring_template='



"+value+"





day everymonth
everymonth

occurrences

'; - diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_serialize.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_serialize.js deleted file mode 100644 index 92273c13b44..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_serialize.js +++ /dev/null @@ -1,77 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -//redefine this method, if you want to provide a custom set of attributes for serialization -scheduler.data_attributes=function(){ - var attrs = []; - var format = scheduler.templates.xml_format; - for (var a in this._events){ - var ev = this._events[a]; - for (var name in ev) - if (name.substr(0,1) !="_") - attrs.push([name,((name == "start_date" || name == "end_date")?format:null)]); - break; - } - return attrs; -} - -scheduler.toXML = function(header){ - var xml = []; - var attrs = this.data_attributes(); - - - for (var a in this._events){ - var ev = this._events[a]; - if (ev.id.toString().indexOf("#")!=-1) continue; - xml.push(""); - for (var i=0; i < attrs.length; i++) - xml.push("<"+attrs[i][0]+">"); - - xml.push(""); - } - return (header||"")+""+xml.join("\n")+""; -}; - -scheduler.toJSON = function(){ - var json = []; - var attrs = this.data_attributes(); - for (var a in this._events){ - var ev = this._events[a]; - if (ev.id.toString().indexOf("#")!=-1) continue; - var ev = this._events[a]; - var line =[]; - for (var i=0; i < attrs.length; i++) - line.push(' "'+attrs[i][0]+'": "'+((attrs[i][1]?attrs[i][1](ev[attrs[i][0]]):ev[attrs[i][0]])||"").toString().replace(/\n/g,"")+'" '); - json.push("{"+line.join(",")+"}"); - } - return "["+json.join(",\n")+"]"; -}; - - -scheduler.toICal = function(header){ - var start = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//dhtmlXScheduler//NONSGML v2.2//EN\nDESCRIPTION:"; - var end = "END:VCALENDAR"; - var format = scheduler.date.date_to_str("%Y%m%dT%H%i%s"); - var full_day_format = scheduler.date.date_to_str("%Y%m%d"); - - var ical = []; - for (var a in this._events){ - var ev = this._events[a]; - if (ev.id.toString().indexOf("#")!=-1) continue; - - - ical.push("BEGIN:VEVENT"); - if (!ev._timed || (!ev.start_date.getHours() && !ev.start_date.getMinutes())) - ical.push("DTSTART:"+full_day_format(ev.start_date)); - else - ical.push("DTSTART:"+format(ev.start_date)); - if (!ev._timed || (!ev.end_date.getHours() && !ev.end_date.getMinutes())) - ical.push("DTEND:"+full_day_format(ev.end_date)); - else - ical.push("DTEND:"+format(ev.end_date)); - ical.push("SUMMARY:"+ev.text); - ical.push("END:VEVENT"); - } - return start+(header||"")+"\n"+ical.join("\n")+"\n"+end; -}; \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_timeline.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_timeline.js deleted file mode 100644 index 35ac0826158..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_timeline.js +++ /dev/null @@ -1,963 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -(function(){ -scheduler.matrix = {}; -scheduler._merge=function(a,b){ - for (var c in b) - if (typeof a[c] == "undefined") - a[c]=b[c]; -}; -scheduler.createTimelineView=function(obj){ - - scheduler._merge(obj,{ - section_autoheight: true, - name:"matrix", - x:"time", - y:"time", - x_step:1, - x_unit:"hour", - y_unit:"day", - y_step:1, - x_start:0, - x_size:24, - y_start:0, - y_size: 7, - render:"cell", - dx:200, - dy:50, - event_dy: scheduler.xy.bar_height-5, - event_min_dy: scheduler.xy.bar_height-5, - resize_events: true, - fit_events: true, - second_scale: false, - _logic: function(render_name, y_unit, timeline) { - var res = {}; - if(scheduler.checkEvent("onBeforeViewRender")) { - res = scheduler.callEvent("onBeforeViewRender", [render_name, y_unit, timeline]); - } - return res; - } - }); - - if (scheduler.checkEvent("onTimelineCreated")) { - scheduler.callEvent("onTimelineCreated", [obj]); - } - - var old = scheduler.render_data; - scheduler.render_data=function(evs, mode){ - - if (this._mode == obj.name){ - if (mode) //repaint single event, precision is not necessary - for (var i=0; i < evs.length; i++) { - this.clear_event(evs[i]); - this.render_timeline_event.call(this.matrix[this._mode], evs[i], true); - } - else - scheduler.renderMatrix.call(obj, true, true); - } else - return old.apply(this,arguments); - }; - - scheduler.matrix[obj.name]=obj; - scheduler.templates[obj.name+"_cell_value"] = function(ar){ return ar?ar.length:""; }; - scheduler.templates[obj.name+"_cell_class"] = function(arr){ return ""; }; - scheduler.templates[obj.name+"_scalex_class"] = function(date){ return ""; }; - scheduler.templates[obj.name+"_second_scalex_class"] = function(date){ return ""; }; - - scheduler.templates[obj.name+"_scaley_class"] = function(section_id, section_label, section_options){ return ""; }; - scheduler.templates[obj.name+"_scale_label"] = function(section_id, section_label, section_options){ return section_label; }; - - scheduler.templates[obj.name+"_tooltip"] = function(a,b,e){ return e.text; }; - scheduler.templates[obj.name+"_date"] = function(datea, dateb){ - if (datea.getDay()==dateb.getDay() && dateb-datea<(24*60*60*1000)) - return scheduler.templates.day_date(datea); - return scheduler.templates.week_date(datea, dateb); - }; - - scheduler.templates[obj.name+"_scale_date"] = scheduler.date.date_to_str(obj.x_date||scheduler.config.hour_date); - scheduler.templates[obj.name+"_second_scale_date"] = scheduler.date.date_to_str((obj.second_scale && obj.second_scale.x_date)?obj.second_scale.x_date:scheduler.config.hour_date); - - scheduler.date["add_"+obj.name]=function(a, b, c){ - return scheduler.date.add(a, (obj.x_length||obj.x_size)*b*obj.x_step, obj.x_unit); - }; - - scheduler.date[obj.name+"_start"] = function(date) { - var func = scheduler.date[obj.x_unit+"_start"] || scheduler.date.day_start; - var start_date = func.call(scheduler.date, date); - start_date = scheduler.date.add(start_date, obj.x_step*obj.x_start, obj.x_unit); - return start_date; - }; - - scheduler.attachEvent("onSchedulerResize",function(){ - if (this._mode == obj.name){ - scheduler.renderMatrix.call(obj, true, true); - return false; - } - return true; - }); - - scheduler.attachEvent("onOptionsLoad",function(){ - obj.order = {}; - scheduler.callEvent('onOptionsLoadStart', []); - for(var i=0; ipos.x){ //index of section - var ratio = (pos.x-(summ-column_width))/column_width; - ratio = (ratio < 0) ? 0: ratio; - break; - } - } - - summ = 0; - for (yind; yind < this._colsS.heights.length; yind++) { - summ+=this._colsS.heights[yind]; - if (summ>pos.y) - break; - } - - pos.fields={}; - if(!obj.y_unit[yind]) { - yind=obj.y_unit.length-1; - } - - if (yind >= 0 && obj.y_unit[yind]) { - pos.section = pos.fields[obj.y_property] = obj.y_unit[yind].key; - if (ev) { - ev[obj.y_property] = pos.section; - } - } - - pos.x = 0; - - var end_date; - if(xind >= obj._trace_x.length) { // if our event is at the end of the view - end_date = scheduler.date.add(obj._trace_x[obj._trace_x.length-1], obj.x_step, obj.x_unit); - } else { - var max_date = (obj._trace_x[xind+1]) ? obj._trace_x[xind+1] : scheduler.date.add(obj._trace_x[obj._trace_x.length-1], obj.x_step, obj.x_unit); - var timestamp_diff = Math.ceil(ratio*(max_date-obj._trace_x[xind])); - end_date = new Date(+obj._trace_x[xind]+timestamp_diff); - } - - if (this._drag_mode == "move" && this._drag_id && this._drag_event) { // as we can simply be calling _locate_cell_timeline - var ev = this.getEvent(this._drag_id); - var drag_event = this._drag_event; - - if (!drag_event._move_delta) { - drag_event._move_delta = (ev.start_date-end_date)/60000; - } - - end_date = scheduler.date.add(end_date, drag_event._move_delta, "minute"); - } - - if (this._drag_mode == "resize" && ev) { - pos.resize_from_start = !!(Math.abs(ev.start_date-end_date) < Math.abs(ev.end_date-end_date)); - } - - pos.y = Math.round((end_date-this._min_date)/(1000*60*this.config.time_step)); - pos.custom = true; - pos.shift = this.config.time_step //step_diff; - return pos; - } -}; - -scheduler.render_timeline_event = function(ev, attach){ - var section = ev[this.y_property]; // section id - - var sorder = ev._sorder; - - var x_start = _getX(ev, false, this._step); - var x_end = _getX(ev, true, this._step); - - var event_height = this.event_dy; - if (this.event_dy == "full") { - if (this.section_autoheight) { - event_height = this._section_height[section] - 6; - } else { - event_height = this.dy - 3; - } - } - - if (this.resize_events) { - event_height = Math.max(Math.floor(event_height / ev._count), this.event_min_dy); - } - - var hb = event_height - 2;// takes into account css sizes (border/padding) - if (!ev._inner && this.event_dy == "full") { - hb=(hb+2)*(ev._count-sorder)-2; - } - - var y = 2+sorder*event_height+(sorder?(sorder*2):0); // original top + number_of_events * event_dy + default event top/bottom borders - if (scheduler.config.cascade_event_display) { - y =2+sorder*scheduler.config.cascade_event_margin+(sorder?(sorder*2):0); - } - - var section_height = event_height+y+2; - if(!this._events_height[section] || (this._events_height[section] < section_height)){ - this._events_height[section] = section_height; - } - - var cs = scheduler.templates.event_class(ev.start_date,ev.end_date,ev); - cs = "dhx_cal_event_line "+(cs||""); - - var bg_color = (ev.color?("background:"+ev.color+";"):""); - var color = (ev.textColor?("color:"+ev.textColor+";"):""); - var text = scheduler.templates.event_bar_text(ev.start_date,ev.end_date,ev); - - var html='
'; - if (scheduler.config.drag_resize){ - var dhx_event_resize = 'dhx_event_resize'; - html += ("
"); - } - html += (text+'
'); - - if (!attach) - return html; - else { - var d = document.createElement("DIV"); - d.innerHTML = html; - var ind = this.order[section]; - var parent = scheduler._els["dhx_cal_data"][0].firstChild.rows[ind].cells[1].firstChild; - - scheduler._rendered.push(d.firstChild); - parent.appendChild(d.firstChild); - } -}; -function trace_events(){ - //minimize event set - var evs = scheduler.get_visible_events(); - var matrix =[]; - for (var i=0; i < this.y_unit.length; i++) - matrix[i]=[]; - - //next code defines row for undefined key - //most possible it is an artifact of incorrect configuration - if (!matrix[y]) - matrix[y]=[]; - - for (var i=0; i < evs.length; i++) { - var y = this.order[evs[i][this.y_property]]; - var x = 0; - while (this._trace_x[x+1] && evs[i].start_date>=this._trace_x[x+1]) x++; - while (this._trace_x[x] && evs[i].end_date>this._trace_x[x]) { - if (!matrix[y][x]) matrix[y][x]=[]; - matrix[y][x].push(evs[i]); - x++; - } - } - return matrix; -} - -// function used to get X (both start and end) coordinates for timeline bar view -function _getX(ev, isEndPoint, step) { - var x = 0; - var date = (isEndPoint) ? ev.end_date : ev.start_date; - if(date.valueOf()>scheduler._max_date.valueOf()) - date = scheduler._max_date; - var delta = date - scheduler._min_date_timeline; - if (delta<0) { - column_offset = 0; - } else { - var index = Math.round( delta/(step*scheduler._cols[0]) ); // results varies ~0.9 - ~24.17, e.g. that way we get 1 and 24 - if(index>scheduler._cols.length) // if columns really small it's possible to get incorrect index - index = scheduler._cols.length; - for (var k=0; kb.id?1:-1; - return a.start_date>b.start_date?1:-1; - }); - var stack=[]; - var evs_length = evs.length; - // prepare events for render - for (var j=0; j first event side - while (stack.length) { - if (stack[stack.length-1].end_date.valueOf() <= ev.start_date.valueOf()) { - stack.splice(stack.length-1,1); - } else { - break; - } - } - - // cutting stack from the first -> last event side - var sorderSet = false; - for(var p=0; p _max_sorder) - _max_sorder = stack[w]._sorder; - ev._sorder = _max_sorder + 1; - ev._inner = false; - } - } - else - ev._sorder = 0; - } - - stack.push(ev); - - if (stack.length>(stack.max_count||0)) { - stack.max_count=stack.length; - ev._count=stack.length; - } - else { - ev._count=(ev._count)?ev._count:1; - } - } - // fix _count for every event - for (var m=0; m < evs.length; m++) { - evs[m]._count = stack.max_count; - } - // render events - for (var v=0; vstats.height)?rendered_height:stats.height; - stats.style_height = "height:"+stats.height+"px;"; - this._section_height[this.y_unit[i].key] = stats.height; - } - - // section 1 - html+=""+stats.td_content+""; - - if (this.render == "cell"){ - for (var j=0; j < scheduler._cols.length; j++) { - html+="
"+scheduler.templates[this.name+"_cell_value"](evs[i][j])+"
"; - } - } else { - //section 2 - html+="
"; - - // adding events - html += events_html; - - //section 3 - html+=""; - for (var j=0; j < scheduler._cols.length; j++) - html+=""; - html+="
"; - html+="
"; - } - html+=""; - } - html += ""; - this._matrix = evs; - //d.scrollTop = 0; //fix flickering in FF; disabled as it was impossible to create dnd event if scroll was used (window jumped to the top) - d.innerHTML = html; - - scheduler._rendered = []; - var divs = scheduler._obj.getElementsByTagName("DIV"); - for (var i=0; i < divs.length; i++) - if (divs[i].getAttribute("event_id")) - scheduler._rendered.push(divs[i]); - - this._scales = {}; - for (var i=0; i < d.firstChild.rows.length; i++) { - heights.push(d.firstChild.rows[i].offsetHeight); - var unit_key = this.y_unit[i].key; - var scale = this._scales[unit_key] = (scheduler._isRender('cell')) ? d.firstChild.rows[i] : d.firstChild.rows[i].childNodes[1].getElementsByTagName('div')[0]; - scheduler.callEvent("onScaleAdd", [scale, unit_key]); - } -} -function x_scale(h){ - var current_sh = scheduler.xy.scale_height; - var original_sh = this._header_resized||scheduler.xy.scale_height; - scheduler._cols=[]; //store for data section, each column width - scheduler._colsS={height:0}; // heights of the y sections - this._trace_x =[]; // list of dates per cells - var summ = scheduler._x-this.dx-18; //border delta, whole width - var left = [this.dx]; // left margins, initial left margin - var header = scheduler._els['dhx_cal_header'][0]; - header.style.width = (left[0]+summ)+'px'; - - scheduler._min_date_timeline = scheduler._min_date; - - var start = scheduler._min_date; - for (var k=0; kb.start_date?1:-1; }); - - if (scheduler._tooltip){ - if (scheduler._tooltip.date == mark) return; - scheduler._tooltip.innerHTML=""; - } else { - var t = scheduler._tooltip = document.createElement("DIV"); - t.className = "dhx_tooltip"; - document.body.appendChild(t); - t.onclick = scheduler._click.dhx_cal_data; - } - - var html = ""; - - for (var i=0; i"; - html+="
"+(evs[i]._timed?scheduler.templates.event_date(evs[i].start_date):"")+"
"; - html+="
 
"; - html+=scheduler.templates[obj.name+"_tooltip"](evs[i].start_date, evs[i].end_date,evs[i])+""; - } - - scheduler._tooltip.style.display=""; - scheduler._tooltip.style.top = "0px"; - - if (document.body.offsetWidth-offset.left-scheduler._tooltip.offsetWidth < 0) - scheduler._tooltip.style.left = offset.left-scheduler._tooltip.offsetWidth+"px"; - else - scheduler._tooltip.style.left = offset.left+pos.src.offsetWidth+"px"; - - scheduler._tooltip.date = mark; - scheduler._tooltip.innerHTML = html; - - if (document.body.offsetHeight-offset.top-scheduler._tooltip.offsetHeight < 0) - scheduler._tooltip.style.top= offset.top-scheduler._tooltip.offsetHeight+pos.src.offsetHeight+"px"; - else - scheduler._tooltip.style.top= offset.top+"px"; -} - -function _init_matrix_tooltip() { - dhtmlxEvent(scheduler._els["dhx_cal_data"][0], "mouseover", function(e){ - var obj = scheduler.matrix[scheduler._mode]; - if (!obj || obj.render != "cell") - return; - if (obj){ - var pos = scheduler._locate_cell_timeline(e); - var e = e || event; - var src = e.target||e.srcElement; - if (pos) - return showToolTip(obj,pos,getOffset(pos.src)); - } - hideToolTip(); - }); - _init_matrix_tooltip=function(){}; -} - -scheduler.renderMatrix = function(mode, refresh) { - if (!refresh) - scheduler._els['dhx_cal_data'][0].scrollTop=0; - - scheduler._min_date = scheduler.date[this.name+"_start"](scheduler._date); - scheduler._max_date = scheduler.date.add(scheduler._min_date, this.x_size*this.x_step, this.x_unit); - scheduler._table_view = true; - if (this.second_scale) { - if (mode && !this._header_resized) { - this._header_resized = scheduler.xy.scale_height; - scheduler.xy.scale_height *= 2; - scheduler._els['dhx_cal_header'][0].className += " dhx_second_cal_header"; - } - if (!mode && this._header_resized) { - scheduler.xy.scale_height /= 2; - this._header_resized = false; - var header = scheduler._els['dhx_cal_header'][0]; - header.className = header.className.replace(/ dhx_second_cal_header/gi,""); - } - } - set_full_view.call(this,mode); -}; - -function html_index(el) { - var p = el.parentNode.childNodes; - for (var i=0; i < p.length; i++) - if (p[i] == el) return i; - return -1; -} -function locate_hcell(e){ - e = e||event; - var trg = e.target?e.target:e.srcElement; - while (trg && trg.tagName != "DIV") - trg=trg.parentNode; - if (trg && trg.tagName == "DIV"){ - var cs = trg.className.split(" ")[0]; - if (cs == "dhx_scale_bar") - return { x:html_index(trg), y:-1, src:trg, scale:true }; - } -} -scheduler._locate_cell_timeline = function(e){ - e = e||event; - var trg = e.target?e.target:e.srcElement; - - var res = {}; - var view = scheduler.matrix[scheduler._mode]; - var pos = scheduler.getActionData(e); - - for (var xind = 0; xind < view._trace_x.length-1; xind++) { - if (+pos.date <= view._trace_x[xind+1]) // | 8:00, 8:30 | 8:15 should be checked against 8:30 - break; - } - - res.x = xind; - res.y = view.order[pos.section]; - var diff = scheduler._isRender('cell') ? 1 : 0; - res.src = view._scales[pos.section].getElementsByTagName('td')[xind+diff]; - - if (trg.className.split(" ")[0] == "dhx_matrix_scell") { // Y scale - res.x = -1; - res.src = trg; - res.scale = true; - } - - return res; -}; - -var old_click = scheduler._click.dhx_cal_data; -scheduler._click.dhx_marked_timespan = scheduler._click.dhx_cal_data = function(e){ - var ret = old_click.apply(this,arguments); - var obj = scheduler.matrix[scheduler._mode]; - if (obj){ - var pos = scheduler._locate_cell_timeline(e); - if (pos){ - if (pos.scale) - scheduler.callEvent("onYScaleClick",[pos.y, obj.y_unit[pos.y], e||event]); - else - scheduler.callEvent("onCellClick",[pos.x, pos.y, obj._trace_x[pos.x], (((obj._matrix[pos.y]||{})[pos.x])||[]), e||event]); - } - } - return ret; -}; - -scheduler.dblclick_dhx_marked_timespan = scheduler.dblclick_dhx_matrix_cell = function(e){ - var obj = scheduler.matrix[scheduler._mode]; - if (obj){ - var pos = scheduler._locate_cell_timeline(e); - if (pos){ - if (pos.scale) - scheduler.callEvent("onYScaleDblClick",[pos.y, obj.y_unit[pos.y], e||event]); - else - scheduler.callEvent("onCellDblClick",[pos.x, pos.y, obj._trace_x[pos.x], (((obj._matrix[pos.y]||{})[pos.x])||[]), e||event]); - } - } -}; -scheduler.dblclick_dhx_matrix_scell = function(e){ - return scheduler.dblclick_dhx_matrix_cell(e); -}; - -scheduler._isRender = function(mode){ - return (scheduler.matrix[scheduler._mode] && scheduler.matrix[scheduler._mode].render == mode); -}; - -scheduler.attachEvent("onCellDblClick", function (x, y, a, b, event){ - if (this.config.readonly|| (event.type == "dblclick" && !this.config.dblclick_create)) return; - - var obj = scheduler.matrix[scheduler._mode]; - var event_options = {}; - event_options['start_date'] = obj._trace_x[x]; - event_options['end_date'] = (obj._trace_x[x+1]) ? obj._trace_x[x+1] : scheduler.date.add(obj._trace_x[x], obj.x_step, obj.x_unit); - event_options[scheduler.matrix[scheduler._mode].y_property] = obj.y_unit[y].key; - scheduler.addEventNow(event_options, null, event); -}); - -scheduler.attachEvent("onBeforeDrag", function (event_id, mode, native_event_object){ - return !scheduler._isRender("cell"); -}); -scheduler.attachEvent("onEventChanged", function(id, ev) { - ev._timed = this.is_one_day_event(ev); -}); -var old_render_marked_timespan = scheduler._render_marked_timespan; -scheduler._render_marked_timespan = function(options, area, unit_id) { - if (!scheduler.config.display_marked_timespans) - return []; - - if (scheduler.matrix && scheduler.matrix[scheduler._mode]) { - if (scheduler._isRender('cell')) - return; - - var view_opts = scheduler.matrix[scheduler._mode]; - var blocks = []; - - var units = []; - var areas = []; - if (!unit_id) { // should draw for every unit - var order = view_opts.order; - for (var key in order) { - if (order.hasOwnProperty(key)) { - units.push(key); - areas.push(view_opts._scales[key]); - } - } - } else { - areas = [area]; - units = [unit_id] - } - - var min_date = scheduler._min_date; - var max_date = scheduler._max_date; - var dates = []; - - if (options.days > 6) { - var specific_date = new Date(options.days); - if (scheduler.date.date_part(new Date(min_date)) <= +specific_date && +max_date >= +specific_date) - dates.push(specific_date); - } else { - dates.push.apply(dates, scheduler._get_dates_by_index(options.days)); - } - - var zones = options.zones; - var css_classes = scheduler._get_css_classes_by_config(options); - - for (var j=0; j start_date)) - continue; - - var block = scheduler._get_block_by_config(options); - block.className = css_classes; - - var start_pos = _getX({start_date: start_date}, false, view_opts._step)-1; - var end_pos = _getX({start_date: end_date}, false, view_opts._step)-1; - var width = end_pos - start_pos-1; - var height = view_opts._section_height[unit_id]-1; - - block.style.cssText = "height: "+height+"px; left: "+start_pos+"px; width: "+width+"px; top: 0;"; - - area.insertBefore(block, area.firstChild); - blocks.push(block); - } - } - } - - return blocks; - - } else { - return old_render_marked_timespan.apply(scheduler, [options, area, unit_id]); - } -}; - -var old_append_mark_now = scheduler._append_mark_now; -scheduler._append_mark_now = function(day_index) { - if (scheduler.matrix && scheduler.matrix[scheduler._mode]) { - var n_date = new Date(); - var zone_start = scheduler._get_zone_minutes(n_date); - var options = { - days: +scheduler.date.date_part(n_date), - zones: [zone_start, zone_start+1], - css: "dhx_matrix_now_time", - type: "dhx_now_time" - }; - return scheduler._render_marked_timespan(options); - } else { - return old_append_mark_now.apply(scheduler, [day_index]); - } -}; -scheduler.attachEvent("onViewChange", function(date, mode) { - if (scheduler.matrix && scheduler.matrix[mode]) { - if (scheduler.markNow) { - scheduler.markNow(); - } - } -}); - -scheduler.attachEvent("onScaleAdd", function(scale, unit_key) { - var timespans = scheduler._marked_timespans; - - if (timespans && scheduler.matrix && scheduler.matrix[scheduler._mode]) { - var mode = scheduler._mode; - - var min_date = scheduler._min_date; - var max_date = scheduler._max_date; - var global_data = timespans["global"]; - - for (var t_date = scheduler.date.date_part(new Date(min_date)); t_date < max_date; t_date = scheduler.date.add(t_date, 1, "day")) { - var day_value = +t_date; - var day_index = t_date.getDay(); - var r_configs = []; - - var day_types = global_data[day_value]||global_data[day_index]; - r_configs.push.apply(r_configs, scheduler._get_configs_to_render(day_types)); - - if (timespans[mode] && timespans[mode][unit_key]) { - var unit_types = scheduler._get_types_to_render(timespans[mode][unit_key][day_index], timespans[mode][unit_key][day_value]); - r_configs.push.apply(r_configs, scheduler._get_configs_to_render(unit_types)); - } - - for (var i=0; iEvent: " + event.text + "
Start date: " + scheduler.templates.tooltip_date_format(start) + "
End date: " + scheduler.templates.tooltip_date_format(end); -}; diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_treetimeline.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_treetimeline.js deleted file mode 100644 index 001b8b0ae6d..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_treetimeline.js +++ /dev/null @@ -1,292 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.attachEvent("onTimelineCreated", function (obj){ - - if(obj.render == "tree") { - obj.y_unit_original = obj.y_unit; - obj.y_unit = scheduler._getArrayToDisplay(obj.y_unit_original); - - scheduler.attachEvent('onOptionsLoadStart', function(){ - obj.y_unit = scheduler._getArrayToDisplay(obj.y_unit_original); - }); - - scheduler.form_blocks[obj.name]={ - render:function(sns) { - var _result = "
"; - return _result; - }, - set_value:function(node,value,ev,config){ - var options = scheduler._getArrayForSelect(scheduler.matrix[config.type].y_unit_original, config.type); - node.innerHTML = ''; - var temp_select = document.createElement('select'); - node.appendChild(temp_select); - - var select = node.getElementsByTagName('select')[0]; - - for(var i=0; i"; - table_className = (timeline.folder_events_available)?"dhx_data_table folder_events":"dhx_data_table folder"; - } else { - height = timeline.dy; - tr_className = "dhx_row_item"; - td_className = "dhx_matrix_scell item"; - div_expand = ''; - table_className = "dhx_data_table"; - } - td_content = "
"+div_expand+"
"+(scheduler.templates[timeline.name+'_scale_label'](y_unit.key, y_unit.label, y_unit)||y_unit.label)+"
"; - - res = { - height: height, - style_height: style_height, - //section 1 - tr_className: tr_className, - td_className: td_className, - td_content: td_content, - //section 3 - table_className: table_className - }; - }; - return res; -}); - -var section_id_before; // section id of the event before dragging (to bring it back if user drop's event on folder without folder_events_available) - -scheduler.attachEvent("onBeforeEventChanged", function(event_object, native_event, is_new) { - if (scheduler._isRender("tree")) { // if mode's render == tree - var section = scheduler.getSection(event_object[scheduler.matrix[scheduler._mode].y_property]); - if (section && typeof section.children != 'undefined' && !scheduler.matrix[scheduler._mode].folder_events_available) { // section itself could be not defined in case of new event (addEventNow) - if (!is_new) { //if old - move back - event_object[scheduler.matrix[scheduler._mode].y_property] = section_id_before; - } - return false; - } - } - return true; -}); - -scheduler.attachEvent("onBeforeDrag", function (event_id, mode, native_event_object){ - if(scheduler._isRender("tree")) { - var cell = scheduler._locate_cell_timeline(native_event_object); - if(cell) { - var section_id = scheduler.matrix[scheduler._mode].y_unit[cell.y].key; - if(typeof scheduler.matrix[scheduler._mode].y_unit[cell.y].children != "undefined" && !scheduler.matrix[scheduler._mode].folder_events_available) { - return false; - } - } - - var ev = scheduler.getEvent(event_id); - section_id_before = section_id||ev[scheduler.matrix[scheduler._mode].y_property]; // either event id or section_id will be available - } - return true; -}); - -scheduler._getArrayToDisplay = function(array){ // function to flatten out hierarhical array, used for tree view - var result = []; - var fillResultArray = function(array, lvl){ - var level = lvl||0; - for(var i=0; i open) -scheduler._toggleFolderDisplay(4, true) -- open section with the key 4 (doesn't matter what status was before). False - close. -scheduler._toggleFolderDisplay(4, false, true) -- close ALL sections. Key is not used in such condition. -*/ -scheduler._toggleFolderDisplay = function(key, status, all_sections){ // used for tree view - var marked; - var toggleElement = function(key, array, status, all_sections) { - for (var i=0; ischeduler._props[name].options.length){ - scheduler._props[name]._original_size = size; - size = 0; - } - scheduler._props[name].size = size; - scheduler._props[name].skip_incorrect = skip_incorrect||false; - - scheduler.date[name+"_start"]= scheduler.date.day_start; - scheduler.templates[name+"_date"] = function(date){ - return scheduler.templates.day_date(date); - }; - - scheduler.templates[name+"_scale_date"] = function(date){ - var list = scheduler._props[name].options; - if (!list.length) return ""; - var index = (scheduler._props[name].position||0)+Math.floor((scheduler._correct_shift(date.valueOf(),1)-scheduler._min_date.valueOf())/(60*60*24*1000)); - if (list[index].css) - return ""+list[index].label+""; - else - return list[index].label; - }; - - scheduler.date["add_"+name]=function(date,inc){ return scheduler.date.add(date,inc,"day"); }; - scheduler.date["get_"+name+"_end"]=function(date){ - return scheduler.date.add(date,scheduler._props[name].size||scheduler._props[name].options.length,"day"); - }; - - scheduler.attachEvent("onOptionsLoad",function(){ - var pr = scheduler._props[name]; - var order = pr.order = {}; - var list = pr.options; - for(var i=0; i list.length) { - pr._original_size = pr.size; - pr.size = 0; - } - else - pr.size = pr._original_size||pr.size; - if (scheduler._date && scheduler._mode == name) - scheduler.setCurrentView(scheduler._date, scheduler._mode); - }); - scheduler.callEvent("onOptionsLoad",[]); -}; -scheduler.scrollUnit=function(step){ - var pr = scheduler._props[this._mode]; - if (pr){ - pr.position=Math.min(Math.max(0,pr.position+step),pr.options.length-pr.size); - this.update_view(); - } -}; -(function(){ - var _removeIncorrectEvents = function(evs) { - var pr = scheduler._props[scheduler._mode]; - if(pr && pr.order && pr.skip_incorrect) { - var correct_events = []; - for(var i=0; i= pr.size+pr.position ) - return false; - } - } - return res; - }; - scheduler._reset_scale = function(){ - var pr = scheduler._props[this._mode]; - var ret = t.apply(this,arguments); - if (pr){ - this._max_date=this.date.add(this._min_date,1,"day"); - - var d = this._els["dhx_cal_data"][0].childNodes; - for (var i=0; i < d.length; i++) - d[i].className = d[i].className.replace("_now",""); //clear now class - - if (pr.size && pr.size < pr.options.length){ - - var h = this._els["dhx_cal_header"][0]; - var arrow = document.createElement("DIV"); - if (pr.position){ - arrow.className = "dhx_cal_prev_button"; - arrow.style.cssText="left:1px;top:2px;position:absolute;" - arrow.innerHTML = " " - h.firstChild.appendChild(arrow); - arrow.onclick=function(){ - scheduler.scrollUnit(pr.step*-1); - } - } - if (pr.position+pr.sizepr.order[b[pr.map_to]]?1:-1; - }); - } else - o.apply(this,arguments); - }; - scheduler.attachEvent("onEventAdded",function(id,ev){ - if (this._loading) return true; - for (var a in scheduler._props){ - var pr = scheduler._props[a]; - if (typeof ev[pr.map_to] == "undefined") - ev[pr.map_to] = pr.options[0].key; - } - return true; - }); - scheduler.attachEvent("onEventCreated",function(id,n_ev){ - var pr = scheduler._props[this._mode]; - if (pr && n_ev){ - var ev = this.getEvent(id); - this._mouse_coords(n_ev); - fix_und(pr,ev); - this.event_updated(ev); - } - return true; - }) -})(); diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_url.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_url.js deleted file mode 100644 index 2d39d36d326..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_url.js +++ /dev/null @@ -1,34 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.attachEvent("onTemplatesReady",function(){ - var first = true; - var s2d = scheduler.date.str_to_date("%Y-%m-%d"); - var d2s = scheduler.date.date_to_str("%Y-%m-%d"); - scheduler.attachEvent("onBeforeViewChange",function(om,od,m,d){ - if (first){ - first = false; - var p={}; - var data=(document.location.hash||"").replace("#","").split(","); - for (var i=0; i < data.length; i++) { - var s = data[i].split("="); - if (s.length==2) - p[s[0]]=s[1]; - } - - if (p.date || p.mode){ - try{ - this.setCurrentView((p.date?s2d(p.date):null),(p.mode||null)); - } catch(e){ - //assuming that mode is not available anymore - this.setCurrentView((p.date?s2d(p.date):null),m); - } - return false; - } - } - var text = "#date="+d2s(d||od)+",mode="+(m||om); - document.location.hash = text; - return true; - }); -}); \ No newline at end of file diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_week_agenda.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_week_agenda.js deleted file mode 100644 index 78e275b9d58..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_week_agenda.js +++ /dev/null @@ -1,256 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler._wa = {}; -scheduler.xy.week_agenda_scale_height = 20; -scheduler.templates.week_agenda_event_text = function(start_date, end_date, event, date) { - return scheduler.templates.event_date(start_date) + " " + event.text; -}; -scheduler.date.week_agenda_start = scheduler.date.week_start; -scheduler.date.week_agenda_end = function(date) { - return scheduler.date.add(date, 7, "day"); -}; -scheduler.date.add_week_agenda = function(date, inc) { - return scheduler.date.add(date, inc * 7, "day"); -}; - -scheduler.attachEvent("onSchedulerReady", function() { - var t = scheduler.templates; - if (!t.week_agenda_date) - t.week_agenda_date = t.week_date; -}); - -(function() { - var scale_date_format = scheduler.date.date_to_str("%l, %F %d"); - scheduler.templates.week_agenda_scale_date = function(date) { - return scale_date_format(date); - }; -})(); - -scheduler.attachEvent("onTemplatesReady", function() { - - scheduler.attachEvent("onSchedulerResize", function() { - if (this._mode == "week_agenda") { - this.week_agenda_view(true); - return false; - } - return true; - }); - - var old = scheduler.render_data; - scheduler.render_data = function(evs) { - if (this._mode == "week_agenda") { - scheduler.week_agenda_view(true); - } else - return old.apply(this, arguments); - }; - - var getColumnSizes = function() { - // widths - scheduler._cols = []; - var twidth = parseInt(scheduler._els['dhx_cal_data'][0].style.width); - scheduler._cols.push(Math.floor(twidth / 2)); - scheduler._cols.push(twidth - scheduler._cols[0] - 1); // To add border between columns - - // heights - scheduler._colsS = { - 0: [], - 1: [] - }; - var theight = parseInt(scheduler._els['dhx_cal_data'][0].style.height); - for (var i = 0; i < 3; i++) { - scheduler._colsS[0].push(Math.floor(theight / (3 - scheduler._colsS[0].length))); - theight -= scheduler._colsS[0][i]; - } - scheduler._colsS[1].push(scheduler._colsS[0][0]); - scheduler._colsS[1].push(scheduler._colsS[0][1]); - // last two days - theight = scheduler._colsS[0][scheduler._colsS[0].length - 1]; - scheduler._colsS[1].push(Math.floor(theight / 2)); - scheduler._colsS[1].push(theight - scheduler._colsS[1][scheduler._colsS[1].length - 1]); - }; - var fillWeekAgendaTab = function() { - getColumnSizes(); - scheduler._els["dhx_cal_data"][0].innerHTML = ''; - scheduler._rendered = []; - var html = ''; - for (var i = 0; i < 2; i++) { - var width = scheduler._cols[i]; - var column_css = 'dhx_wa_column'; - if (i == 1) - column_css += ' dhx_wa_column_last'; - html += "
"; - for (var k = 0; k < scheduler._colsS[i].length; k++) { - var scale_height = scheduler.xy.week_agenda_scale_height - 2; - var height = scheduler._colsS[i][k] - scale_height - 2; - var day = Math.min(6, k * 2 + i); - html += "
"; - } - html += "
"; - } - scheduler._els["dhx_cal_date"][0].innerHTML = scheduler.templates[scheduler._mode + "_date"](scheduler._min_date, scheduler._max_date, scheduler._mode); - scheduler._els["dhx_cal_data"][0].innerHTML = html; - var all_divs = scheduler._els["dhx_cal_data"][0].getElementsByTagName('div'); - var day_divs = []; - for (var i = 0; i < all_divs.length; i++) { - if (all_divs[i].className == 'dhx_wa_day_cont') - day_divs.push(all_divs[i]); - } - scheduler._wa._selected_divs = []; - var events = scheduler.get_visible_events(); // list of events to be displayed in current week - var tstart = scheduler.date.week_start(scheduler._date); - var tend = scheduler.date.add(tstart, 1, "day"); - for (var i = 0; i < 7; i++) { - day_divs[i]._date = tstart; - var scale_bar = day_divs[i].childNodes[0]; - var events_div = day_divs[i].childNodes[1]; - scale_bar.innerHTML = scheduler.templates.week_agenda_scale_date(tstart); - var evs = []; // events which will be displayed in the current day - for (var j = 0; j < events.length; j++) { - var tev = events[j]; - if (tev.start_date < tend && tev.end_date > tstart) - evs.push(tev); - } - evs.sort(function(a, b) { - if (a.start_date.valueOf() == b.start_date.valueOf()) - return a.id > b.id ? 1 : -1; - return a.start_date > b.start_date ? 1 : -1; - }); - for (var k = 0; k < evs.length; k++) { - var ev = evs[k]; - var ev_div = document.createElement('div'); - scheduler._rendered.push(ev_div); - var ev_class = scheduler.templates.event_class(ev.start_date, ev.end_date, ev); - ev_div.className = 'dhx_wa_ev_body' + (ev_class ? (' ' + ev_class) : ''); - if (ev._text_style) - ev_div.style.cssText = ev._text_style; - if (ev.color) - ev_div.style.background = ev.color; - if (ev.textColor) - ev_div.style.color = ev.textColor; - if (scheduler._select_id && ev.id == scheduler._select_id && !(!scheduler.config.week_agenda_select && scheduler.config.week_agenda_select !== undefined)) { - ev_div.className += " dhx_cal_event_selected"; - scheduler._wa._selected_divs.push(ev_div); - } - var position = ""; - if (!ev._timed) { - position = "middle"; - if (ev.start_date.valueOf() >= tstart.valueOf() && ev.start_date.valueOf() <= tend.valueOf()) - position = "start"; - if (ev.end_date.valueOf() >= tstart.valueOf() && ev.end_date.valueOf() <= tend.valueOf()) - position = "end"; - } - ev_div.innerHTML = scheduler.templates.week_agenda_event_text(ev.start_date, ev.end_date, ev, tstart, position); - ev_div.setAttribute('event_id', ev.id); - events_div.appendChild(ev_div); - } - tstart = scheduler.date.add(tstart, 1, "day"); - tend = scheduler.date.add(tend, 1, "day"); - } - }; - scheduler.week_agenda_view = function(mode) { - scheduler._min_date = scheduler.date.week_start(scheduler._date); - scheduler._max_date = scheduler.date.add(scheduler._min_date, 1, "week"); - scheduler.set_sizes(); - if (mode) { // mode enabled - scheduler._table_view = scheduler._allow_dnd = true; - - // hiding default top border from dhx_cal_data - scheduler._wa._prev_data_border = scheduler._els['dhx_cal_data'][0].style.borderTop; - scheduler._els['dhx_cal_data'][0].style.borderTop = 0; - scheduler._els['dhx_cal_data'][0].style.overflowY = 'hidden'; - - // cleaning dhx_cal_date from the previous date - scheduler._els['dhx_cal_date'][0].innerHTML = ""; - - // 1 to make navline to be over data - scheduler._els['dhx_cal_data'][0].style.top = (parseInt(scheduler._els['dhx_cal_data'][0].style.top) - scheduler.xy.bar_height - 1) + 'px'; - scheduler._els['dhx_cal_data'][0].style.height = (parseInt(scheduler._els['dhx_cal_data'][0].style.height) + scheduler.xy.bar_height + 1) + 'px'; - - scheduler._els['dhx_cal_header'][0].style.display = 'none'; - fillWeekAgendaTab(); - } else { // leaving week_agenda mode - scheduler._table_view = scheduler._allow_dnd = false; - - // restoring default top border to dhx_cal_data - if (scheduler._wa._prev_data_border) - scheduler._els['dhx_cal_data'][0].style.borderTop = scheduler._wa._prev_data_border; - - scheduler._els['dhx_cal_data'][0].style.overflowY = 'auto'; - scheduler._els['dhx_cal_data'][0].style.top = (parseInt(scheduler._els['dhx_cal_data'][0].style.top) + scheduler.xy.bar_height) + 'px'; - scheduler._els['dhx_cal_data'][0].style.height = (parseInt(scheduler._els['dhx_cal_data'][0].style.height) - scheduler.xy.bar_height) + 'px'; - scheduler._els['dhx_cal_header'][0].style.display = 'block'; - } - }; - scheduler.mouse_week_agenda = function(pos) { - var native_event = pos.ev; - var src = native_event.srcElement || native_event.target; - while (src.parentNode) { - if (src._date) - var date = src._date; - src = src.parentNode; - } - if (!date) - return pos; - pos.x = 0; - var diff = date.valueOf() - scheduler._min_date.valueOf(); - pos.y = Math.ceil(( diff / (1000 * 60) ) / this.config.time_step); - if (this._drag_mode == 'move') { - this._drag_event._dhx_changed = true; - this._select_id = this._drag_id; - for (var i = 0; i < scheduler._rendered.length; i++) { - if (scheduler._drag_id == this._rendered[i].getAttribute('event_id')) - var event_div = this._rendered[i]; - } - if (!scheduler._wa._dnd) { - var div = event_div.cloneNode(true); - this._wa._dnd = div; - div.className = event_div.className; - div.id = 'dhx_wa_dnd'; - div.className += ' dhx_wa_dnd'; - document.body.appendChild(div); - } - var dnd_div = document.getElementById('dhx_wa_dnd'); - dnd_div.style.top = ((native_event.pageY || native_event.clientY) + 20) + "px"; - dnd_div.style.left = ((native_event.pageX || native_event.clientX) + 20) + "px"; - } - return pos; - }; - scheduler.attachEvent('onBeforeEventChanged', function(event_object, native_event, is_new) { - if (this._mode == 'week_agenda') { - if (this._drag_mode == 'move') { - var dnd = document.getElementById('dhx_wa_dnd'); - dnd.parentNode.removeChild(dnd); - scheduler._wa._dnd = false; - } - } - return true; - }); - - scheduler.attachEvent("onEventSave", function(id, data, is_new_event) { - if (is_new_event && this._mode == 'week_agenda') - this._select_id = id; - return true; - }); - - scheduler._wa._selected_divs = []; - - scheduler.attachEvent("onClick", function(event_id, native_event_object) { - if (this._mode == 'week_agenda' && !(!scheduler.config.week_agenda_select && scheduler.config.week_agenda_select !== undefined)) { - if (scheduler._wa._selected_divs) { - for (var i = 0; i < this._wa._selected_divs.length; i++) { - var div = this._wa._selected_divs[i]; - div.className = div.className.replace(/ dhx_cal_event_selected/, ''); - } - } - this.for_rendered(event_id, function(event_div) { - event_div.className += " dhx_cal_event_selected"; - scheduler._wa._selected_divs.push(event_div); - }); - scheduler.select(event_id); - return false; - } - return true; - }); -}); diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_year_view.js b/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_year_view.js deleted file mode 100644 index 3b01f67552d..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/sources/ext/dhtmlxscheduler_year_view.js +++ /dev/null @@ -1,276 +0,0 @@ -/* -This software is allowed to use under GPL or you need to obtain Commercial or Enterise License -to use it in non-GPL project. Please contact sales@dhtmlx.com for details -*/ -scheduler.config.year_x = 4; -scheduler.config.year_y = 3; -scheduler.config.year_mode_name = "year"; -scheduler.xy.year_top = 0; - -scheduler.templates.year_date = function(date) { - return scheduler.date.date_to_str(scheduler.locale.labels.year_tab + " %Y")(date); -}; -scheduler.templates.year_month = scheduler.date.date_to_str("%F"); -scheduler.templates.year_scale_date = scheduler.date.date_to_str("%D"); -scheduler.templates.year_tooltip = function(s, e, ev) { - return ev.text -}; - -(function() { - var is_year_mode = function() { - return scheduler._mode == scheduler.config.year_mode_name; - }; - - scheduler.dblclick_dhx_month_head = function(e) { - if (is_year_mode()) { - var t = (e.target || e.srcElement); - if (t.parentNode.className.indexOf("dhx_before") != -1 || t.parentNode.className.indexOf("dhx_after") != -1) return false; - var start = this.templates.xml_date(t.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.getAttribute("date")); - start.setDate(parseInt(t.innerHTML, 10)); - var end = this.date.add(start, 1, "day") - if (!this.config.readonly && this.config.dblclick_create) - this.addEventNow(start.valueOf(), end.valueOf(), e); - } - }; - - var chid = scheduler.changeEventId; - scheduler.changeEventId = function() { - chid.apply(this, arguments); - if (is_year_mode()) - this.year_view(true); - }; - - - var old = scheduler.render_data; - var to_attr = scheduler.date.date_to_str("%Y/%m/%d"); - var from_attr = scheduler.date.str_to_date("%Y/%m/%d"); - scheduler.render_data = function(evs) { - if (!is_year_mode()) return old.apply(this, arguments); - for (var i = 0; i < evs.length; i++) - this._year_render_event(evs[i]); - }; - - var clear = scheduler.clear_view; - scheduler.clear_view = function() { - if (!is_year_mode()) return clear.apply(this, arguments); - for (var date in marked) { - if (marked.hasOwnProperty(date)) { - var div = marked[date]; - div.className = "dhx_month_head"; - div.setAttribute("date", "") - } - } - marked = {}; - }; - - scheduler.hideToolTip = function() { - if (this._tooltip) { - this._tooltip.style.display = "none"; - this._tooltip.date = new Date(9999, 1, 1); - } - }; - - scheduler.showToolTip = function(date, pos, e, src) { - if (this._tooltip) { - if (this._tooltip.date.valueOf() == date.valueOf()) return; - this._tooltip.innerHTML = ""; - } else { - var t = this._tooltip = document.createElement("DIV"); - t.className = "dhx_tooltip"; - document.body.appendChild(t); - t.onclick = scheduler._click.dhx_cal_data; - - } - var evs = this.getEvents(date, this.date.add(date, 1, "day")); - var html = ""; - - for (var i = 0; i < evs.length; i++) { - var ev = evs[i]; - var bg_color = (ev.color ? ("background:" + ev.color + ";") : ""); - var color = (ev.textColor ? ("color:" + ev.textColor + ";") : ""); - - html += "
"; - html += "
" + (evs[i]._timed ? this.templates.event_date(evs[i].start_date) : "") + "
"; - html += "
 
"; - html += this.templates.year_tooltip(evs[i].start_date, evs[i].end_date, evs[i]) + "
"; - } - - this._tooltip.style.display = ""; - this._tooltip.style.top = "0px"; - - - if (document.body.offsetWidth - pos.left - this._tooltip.offsetWidth < 0) - this._tooltip.style.left = pos.left - this._tooltip.offsetWidth + "px"; - else - this._tooltip.style.left = pos.left + src.offsetWidth + "px"; - - this._tooltip.date = date; - this._tooltip.innerHTML = html; - - if (document.body.offsetHeight - pos.top - this._tooltip.offsetHeight < 0) - this._tooltip.style.top = pos.top - this._tooltip.offsetHeight + src.offsetHeight + "px"; - else - this._tooltip.style.top = pos.top + "px"; - }; - - scheduler._init_year_tooltip = function() { - dhtmlxEvent(scheduler._els["dhx_cal_data"][0], "mouseover", function(e) { - if (!is_year_mode()) return; - - var e = e || event; - var src = e.target || e.srcElement; - if (src.tagName.toLowerCase() == 'a') // fix for active links extension (it adds links to the date in the cell) - src = src.parentNode; - if ((src.className || "").indexOf("dhx_year_event") != -1) - scheduler.showToolTip(from_attr(src.getAttribute("date")), getOffset(src), e, src); - else - scheduler.hideToolTip(); - }); - this._init_year_tooltip = function() { - }; - }; - - scheduler.attachEvent("onSchedulerResize", function() { - if (is_year_mode()) { - this.year_view(true); - return false; - } - return true; - }); - scheduler._get_year_cell = function(d) { - //there can be more than 1 year in view - //year can start not from January - var m = d.getMonth() + 12 * (d.getFullYear() - this._min_date.getFullYear()) - this.week_starts._month; - var t = this._els["dhx_cal_data"][0].childNodes[m]; - var d = this.week_starts[m] + d.getDate() - 1; - - - return t.childNodes[2].firstChild.rows[Math.floor(d / 7)].cells[d % 7].firstChild; - }; - - var marked = {}; - scheduler._mark_year_date = function(d, ev) { - var date = to_attr(d); - var c = this._get_year_cell(d); - var ev_class = this.templates.event_class(ev.start_date, ev.end_date, ev); - if (!marked[date]) { - c.className = "dhx_month_head dhx_year_event"; - c.setAttribute("date", date); - marked[date] = c; - } - c.className += (ev_class) ? (" "+ev_class) : ""; - }; - scheduler._unmark_year_date = function(d) { - this._get_year_cell(d).className = "dhx_month_head"; - }; - scheduler._year_render_event = function(ev) { - var d = ev.start_date; - if (d.valueOf() < this._min_date.valueOf()) - d = this._min_date; - else d = this.date.date_part(new Date(d)); - - while (d < ev.end_date) { - this._mark_year_date(d, ev); - d = this.date.add(d, 1, "day"); - if (d.valueOf() >= this._max_date.valueOf()) - return; - } - }; - - scheduler.year_view = function(mode) { - if (mode) { - var temp = scheduler.xy.scale_height; - scheduler.xy.scale_height = -1; - } - - scheduler._els["dhx_cal_header"][0].style.display = mode ? "none" : ""; - scheduler.set_sizes(); - - if (mode) - scheduler.xy.scale_height = temp; - - - scheduler._table_view = mode; - if (this._load_mode && this._load()) return; - - if (mode) { - scheduler._init_year_tooltip(); - scheduler._reset_year_scale(); - if (scheduler._load_mode && scheduler._load()) return scheduler._render_wait = true; - scheduler.render_view_data(); - } else { - scheduler.hideToolTip(); - } - }; - scheduler._reset_year_scale = function() { - this._cols = []; - this._colsS = {}; - var week_starts = []; //start day of first week in each month - var b = this._els["dhx_cal_data"][0]; - - var c = this.config; - b.scrollTop = 0; //fix flickering in FF - b.innerHTML = ""; - - var dx = Math.floor(parseInt(b.style.width) / c.year_x); - var dy = Math.floor((parseInt(b.style.height) - scheduler.xy.year_top) / c.year_y); - if (dy < 190) { - dy = 190; - dx = Math.floor((parseInt(b.style.width) - scheduler.xy.scroll_width) / c.year_x); - } - - var summ = dx - 11; - var left = 0; - var week_template = document.createElement("div"); - var dummy_date = this.date.week_start(new Date()); - for (var i = 0; i < 7; i++) { - this._cols[i] = Math.floor(summ / (7 - i)); - this._render_x_header(i, left, dummy_date, week_template); - dummy_date = this.date.add(dummy_date, 1, "day"); - summ -= this._cols[i]; - left += this._cols[i]; - } - week_template.lastChild.className += " dhx_scale_bar_last"; - - var sd = this.date[this._mode + "_start"](this.date.copy(this._date)); - var ssd = sd; - - for (var i = 0; i < c.year_y; i++) - for (var j = 0; j < c.year_x; j++) { - var d = document.createElement("DIV"); - d.style.cssText = "position:absolute;"; - d.setAttribute("date", this.templates.xml_format(sd)); - d.innerHTML = "
" + week_template.innerHTML + "
"; - d.childNodes[0].innerHTML = this.templates.year_month(sd); - - var dd = this.date.week_start(sd); - var ed = this._reset_month_scale(d.childNodes[2], sd, dd); - - var r = d.childNodes[2].firstChild.rows; - for (var k=r.length; k<6; k++) { - r[0].parentNode.appendChild(r[0].cloneNode(true)); - for (var ri=0; ri < r[k].childNodes.length; ri++) { - r[k].childNodes[ri].className = "dhx_after"; - r[k].childNodes[ri].firstChild.innerHTML = scheduler.templates.month_day(ed); - ed = scheduler.date.add(ed,1,"day"); - } - } - b.appendChild(d); - - d.childNodes[1].style.height = d.childNodes[1].childNodes[0].offsetHeight + "px"; // dhx_year_week should have height property so that day dates would get correct position. dhx_year_week height = height of it's child (with the day name) - var dt = Math.round((dy - 190) / 2); - d.style.marginTop = dt + "px"; - this.set_xy(d, dx - 10, dy - dt - 10, dx * j + 5, dy * i + 5 + scheduler.xy.year_top); - - week_starts[i * c.year_x + j] = (sd.getDay() - (this.config.start_on_monday ? 1 : 0) + 7) % 7; - sd = this.date.add(sd, 1, "month"); - - } - this._els["dhx_cal_date"][0].innerHTML = this.templates[this._mode + "_date"](ssd, sd, this._mode); - this.week_starts = week_starts; - week_starts._month = ssd.getMonth(); - this._min_date = ssd; - this._max_date = sd; - } - -})(); diff --git a/addons/web_calendar/static/lib/dhtmlxScheduler/whatsnew.txt b/addons/web_calendar/static/lib/dhtmlxScheduler/whatsnew.txt deleted file mode 100644 index 32b22f42fc9..00000000000 --- a/addons/web_calendar/static/lib/dhtmlxScheduler/whatsnew.txt +++ /dev/null @@ -1,48 +0,0 @@ -3.5 - Ability to show multiple scheduler's per page (PRO version only) - Supports loading JSON directly from Connectors - Custom events rendering - Timeline view improved (support for drag, resize, event height control) - New 'dhx_terrace' skin - New options for blocking dates - Marking time intervals - Highlighting time intervals - New API methods: updateView, showEvent, getRenderedEvent, getActionData - JSMessage included - Grid view - New configuration options - Simplified access to lightbox section objects - - - -3.0 - Version of scheduler for touch phones - WeekAgenda view - Netbook friendly lightbox form - Cascade event display - Simple way to define a color for event - Drag and drop of the details form - Custom buttons for the details form - Current time marker in day and week view - Multiline header for timeline view - Configurable work-time bounds - API to access lightbox values - - build 120111: - - updated dhtmlxscheduker_mobile.js - - - -2.3 - Map view was added - Cell mode for Timeline view was added - Tree mode for Timeline view was added - Tooltips for all views were added - Abbility to create new events by double click or by drag-and-drop in Timeline mode - Abbility to move events by drop-and-drag in Timeline mode - Abbility to create new events by external drag and drop - Multiselect section for details form - Checkbox, combo, radio - sections for details form - Api of mini-calendar extension extended - Custom form implementation simplified - diff --git a/addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css b/addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css new file mode 100644 index 00000000000..acae725d28c --- /dev/null +++ b/addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css @@ -0,0 +1,579 @@ +/*! + * FullCalendar v1.6.1 Stylesheet + * Docs & License: http://arshaw.com/fullcalendar/ + * (c) 2013 Adam Shaw + */ + + +.fc { + direction: ltr; + text-align: left; + } + +.fc table { + border-collapse: collapse; + border-spacing: 0; + } + +html .fc, +.fc table { + font-size: 1em; + } + +.fc td, +.fc th { + padding: 0; + vertical-align: top; + } + + + +/* Header +------------------------------------------------------------------------*/ + +.fc-header td { + white-space: nowrap; + } + +.fc-header-left { + width: 25%; + text-align: left; + } + +.fc-header-center { + text-align: center; + } + +.fc-header-right { + width: 25%; + text-align: right; + } + +.fc-header-title { + display: inline-block; + vertical-align: top; + } + +.fc-header-title h2 { + margin-top: 0; + white-space: nowrap; + } + +.fc .fc-header-space { + padding-left: 10px; + } + +.fc-header .fc-button { + margin-bottom: 1em; + vertical-align: top; + } + +/* buttons edges butting together */ + +.fc-header .fc-button { + margin-right: -1px; + } + +.fc-header .fc-corner-right, /* non-theme */ +.fc-header .ui-corner-right { /* theme */ + margin-right: 0; /* back to normal */ + } + +/* button layering (for border precedence) */ + +.fc-header .fc-state-hover, +.fc-header .ui-state-hover { + z-index: 2; + } + +.fc-header .fc-state-down { + z-index: 3; + } + +.fc-header .fc-state-active, +.fc-header .ui-state-active { + z-index: 4; + } + + + +/* Content +------------------------------------------------------------------------*/ + +.fc-content { + clear: both; + } + +.fc-view { + width: 100%; /* needed for view switching (when view is absolute) */ + overflow: hidden; + } + + + +/* Cell Styles +------------------------------------------------------------------------*/ + +.fc-widget-header, /* , usually */ +.fc-widget-content { /* , usually */ + border: 1px solid #ddd; + } + +.fc-state-highlight { /* today cell */ /* TODO: add .fc-today to */ + background: #fcf8e3; + } + +.fc-cell-overlay { /* semi-transparent rectangle while dragging */ + background: #bce8f1; + opacity: .3; + filter: alpha(opacity=30); /* for IE */ + } + + + +/* Buttons +------------------------------------------------------------------------*/ + +.fc-button { + position: relative; + display: inline-block; + padding: 0 .6em; + overflow: hidden; + height: 1.9em; + line-height: 1.9em; + white-space: nowrap; + cursor: pointer; + } + +.fc-state-default { /* non-theme */ + border: 1px solid; + } + +.fc-state-default.fc-corner-left { /* non-theme */ + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + } + +.fc-state-default.fc-corner-right { /* non-theme */ + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + } + +/* + Our default prev/next buttons use HTML entities like ‹ › « » + and we'll try to make them look good cross-browser. +*/ + +.fc-text-arrow { + margin: 0 .1em; + font-size: 2em; + font-family: "Courier New", Courier, monospace; + vertical-align: baseline; /* for IE7 */ + } + +.fc-button-prev .fc-text-arrow, +.fc-button-next .fc-text-arrow { /* for ‹ › */ + font-weight: bold; + } + +/* icon (for jquery ui) */ + +.fc-button .fc-icon-wrap { + position: relative; + float: left; + top: 50%; + } + +.fc-button .ui-icon { + position: relative; + float: left; + margin-top: -50%; + *margin-top: 0; + *top: -50%; + } + +/* + button states + borrowed from twitter bootstrap (http://twitter.github.com/bootstrap/) +*/ + +.fc-state-default { + background-color: #f5f5f5; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + color: #333; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + } + +.fc-state-hover, +.fc-state-down, +.fc-state-active, +.fc-state-disabled { + color: #333333; + background-color: #e6e6e6; + } + +.fc-state-hover { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; + } + +.fc-state-down, +.fc-state-active { + background-color: #cccccc; + background-image: none; + outline: 0; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + } + +.fc-state-disabled { + cursor: default; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + box-shadow: none; + } + + + +/* Global Event Styles +------------------------------------------------------------------------*/ + +.fc-event { + border: 1px solid #3a87ad; /* default BORDER color */ + background-color: #3a87ad; /* default BACKGROUND color */ + color: #fff; /* default TEXT color */ + font-size: .85em; + cursor: default; + } + +a.fc-event { + text-decoration: none; + } + +a.fc-event, +.fc-event-draggable { + cursor: pointer; + } + +.fc-rtl .fc-event { + text-align: right; + } + +.fc-event-inner { + width: 100%; + height: 100%; + overflow: hidden; + } + +.fc-event-time, +.fc-event-title { + padding: 0 1px; + } + +.fc .ui-resizable-handle { + display: block; + position: absolute; + z-index: 99999; + overflow: hidden; /* hacky spaces (IE6/7) */ + font-size: 300%; /* */ + line-height: 50%; /* */ + } + + + +/* Horizontal Events +------------------------------------------------------------------------*/ + +.fc-event-hori { + border-width: 1px 0; + margin-bottom: 1px; + } + +.fc-ltr .fc-event-hori.fc-event-start, +.fc-rtl .fc-event-hori.fc-event-end { + border-left-width: 1px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + } + +.fc-ltr .fc-event-hori.fc-event-end, +.fc-rtl .fc-event-hori.fc-event-start { + border-right-width: 1px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + } + +/* resizable */ + +.fc-event-hori .ui-resizable-e { + top: 0 !important; /* importants override pre jquery ui 1.7 styles */ + right: -3px !important; + width: 7px !important; + height: 100% !important; + cursor: e-resize; + } + +.fc-event-hori .ui-resizable-w { + top: 0 !important; + left: -3px !important; + width: 7px !important; + height: 100% !important; + cursor: w-resize; + } + +.fc-event-hori .ui-resizable-handle { + _padding-bottom: 14px; /* IE6 had 0 height */ + } + + + +/* Reusable Separate-border Table +------------------------------------------------------------*/ + +table.fc-border-separate { + border-collapse: separate; + } + +.fc-border-separate th, +.fc-border-separate td { + border-width: 1px 0 0 1px; + } + +.fc-border-separate th.fc-last, +.fc-border-separate td.fc-last { + border-right-width: 1px; + } + +.fc-border-separate tr.fc-last th, +.fc-border-separate tr.fc-last td { + border-bottom-width: 1px; + } + +.fc-border-separate tbody tr.fc-first td, +.fc-border-separate tbody tr.fc-first th { + border-top-width: 0; + } + + + +/* Month View, Basic Week View, Basic Day View +------------------------------------------------------------------------*/ + +.fc-grid th { + text-align: center; + } + +.fc .fc-week-number { + width: 22px; + text-align: center; + } + +.fc .fc-week-number div { + padding: 0 2px; + } + +.fc-grid .fc-day-number { + float: right; + padding: 0 2px; + } + +.fc-grid .fc-other-month .fc-day-number { + opacity: 0.3; + filter: alpha(opacity=30); /* for IE */ + /* opacity with small font can sometimes look too faded + might want to set the 'color' property instead + making day-numbers bold also fixes the problem */ + } + +.fc-grid .fc-day-content { + clear: both; + padding: 2px 2px 1px; /* distance between events and day edges */ + } + +/* event styles */ + +.fc-grid .fc-event-time { + font-weight: bold; + } + +/* right-to-left */ + +.fc-rtl .fc-grid .fc-day-number { + float: left; + } + +.fc-rtl .fc-grid .fc-event-time { + float: right; + } + + + +/* Agenda Week View, Agenda Day View +------------------------------------------------------------------------*/ + +.fc-agenda table { + border-collapse: separate; + } + +.fc-agenda-days th { + text-align: center; + } + +.fc-agenda .fc-agenda-axis { + width: 50px; + padding: 0 4px; + vertical-align: middle; + text-align: right; + white-space: nowrap; + font-weight: normal; + } + +.fc-agenda .fc-week-number { + font-weight: bold; + } + +.fc-agenda .fc-day-content { + padding: 2px 2px 1px; + } + +/* make axis border take precedence */ + +.fc-agenda-days .fc-agenda-axis { + border-right-width: 1px; + } + +.fc-agenda-days .fc-col0 { + border-left-width: 0; + } + +/* all-day area */ + +.fc-agenda-allday th { + border-width: 0 1px; + } + +.fc-agenda-allday .fc-day-content { + min-height: 34px; /* TODO: doesnt work well in quirksmode */ + _height: 34px; + } + +/* divider (between all-day and slots) */ + +.fc-agenda-divider-inner { + height: 2px; + overflow: hidden; + } + +.fc-widget-header .fc-agenda-divider-inner { + background: #eee; + } + +/* slot rows */ + +.fc-agenda-slots th { + border-width: 1px 1px 0; + } + +.fc-agenda-slots td { + border-width: 1px 0 0; + background: none; + } + +.fc-agenda-slots td div { + height: 20px; + } + +.fc-agenda-slots tr.fc-slot0 th, +.fc-agenda-slots tr.fc-slot0 td { + border-top-width: 0; + } + +.fc-agenda-slots tr.fc-minor th, +.fc-agenda-slots tr.fc-minor td { + border-top-style: dotted; + } + +.fc-agenda-slots tr.fc-minor th.ui-widget-header { + *border-top-style: solid; /* doesn't work with background in IE6/7 */ + } + + + +/* Vertical Events +------------------------------------------------------------------------*/ + +.fc-event-vert { + border-width: 0 1px; + } + +.fc-event-vert.fc-event-start { + border-top-width: 1px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + } + +.fc-event-vert.fc-event-end { + border-bottom-width: 1px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + } + +.fc-event-vert .fc-event-time { + white-space: nowrap; + font-size: 10px; + } + +.fc-event-vert .fc-event-inner { + position: relative; + z-index: 2; + } + +.fc-event-vert .fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay */ + position: absolute; + z-index: 1; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #fff; + opacity: .25; + filter: alpha(opacity=25); + } + +.fc .ui-draggable-dragging .fc-event-bg, /* TODO: something nicer like .fc-opacity */ +.fc-select-helper .fc-event-bg { + display: none\9; /* for IE6/7/8. nested opacity filters while dragging don't work */ + } + +/* resizable */ + +.fc-event-vert .ui-resizable-s { + bottom: 0 !important; /* importants override pre jquery ui 1.7 styles */ + width: 100% !important; + height: 8px !important; + overflow: hidden !important; + line-height: 8px !important; + font-size: 11px !important; + font-family: monospace; + text-align: center; + cursor: s-resize; + } + +.fc-agenda .ui-resizable-resizing { /* TODO: better selector */ + _overflow: hidden; + } + + diff --git a/addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js b/addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js new file mode 100644 index 00000000000..7853d3c1e51 --- /dev/null +++ b/addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js @@ -0,0 +1,5377 @@ +/*! + * FullCalendar v1.6.1 + * Docs & License: http://arshaw.com/fullcalendar/ + * (c) 2013 Adam Shaw + */ + +/* + * Use fullcalendar.css for basic styling. + * For event drag & drop, requires jQuery UI draggable. + * For event resizing, requires jQuery UI resizable. + */ + +(function($, undefined) { + + ;; + + var defaults = { + + // display + defaultView: 'month', + aspectRatio: 1.35, + header: { + left: 'title', + center: '', + right: 'today prev,next' + }, + weekends: true, + weekNumbers: false, + weekNumberCalculation: 'iso', + weekNumberTitle: 'W', + + // editing + //editable: false, + //disableDragging: false, + //disableResizing: false, + + allDayDefault: true, + ignoreTimezone: true, + + // event ajax + lazyFetching: true, + startParam: 'start', + endParam: 'end', + + // time formats + titleFormat: { + month: 'MMMM yyyy', + week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}", + day: 'dddd, MMM d, yyyy' + }, + columnFormat: { + month: 'ddd', + week: 'ddd M/d', + day: 'dddd M/d' + }, + timeFormat: { // for event elements + '': 'h(:mm)t' // default + }, + + // locale + isRTL: false, + firstDay: 0, + monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], + monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], + dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], + dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], + buttonText: { + prev: "", + next: "", + prevYear: "«", + nextYear: "»", + today: 'today', + month: 'month', + week: 'week', + day: 'day' + }, + + // jquery-ui theming + theme: false, + buttonIcons: { + prev: 'circle-triangle-w', + next: 'circle-triangle-e' + }, + + //selectable: false, + unselectAuto: true, + + dropAccept: '*' + + }; + + // right-to-left defaults + var rtlDefaults = { + header: { + left: 'next,prev today', + center: '', + right: 'title' + }, + buttonText: { + prev: "", + next: "", + prevYear: "»", + nextYear: "«" + }, + buttonIcons: { + prev: 'circle-triangle-e', + next: 'circle-triangle-w' + } + }; + + + + ;; + + var fc = $.fullCalendar = { version: "1.6.1" }; + var fcViews = fc.views = {}; + + + $.fn.fullCalendar = function(options) { + + + // method calling + if (typeof options == 'string') { + var args = Array.prototype.slice.call(arguments, 1); + var res; + this.each(function() { + var calendar = $.data(this, 'fullCalendar'); + if (calendar && $.isFunction(calendar[options])) { + var r = calendar[options].apply(calendar, args); + if (res === undefined) { + res = r; + } + if (options == 'destroy') { + $.removeData(this, 'fullCalendar'); + } + } + }); + if (res !== undefined) { + return res; + } + return this; + } + + + // would like to have this logic in EventManager, but needs to happen before options are recursively extended + var eventSources = options.eventSources || []; + delete options.eventSources; + if (options.events) { + eventSources.push(options.events); + delete options.events; + } + + + options = $.extend(true, {}, + defaults, + (options.isRTL || options.isRTL===undefined && defaults.isRTL) ? rtlDefaults : {}, + options + ); + + + this.each(function(i, _element) { + var element = $(_element); + var calendar = new Calendar(element, options, eventSources); + element.data('fullCalendar', calendar); // TODO: look into memory leak implications + calendar.render(); + }); + + + return this; + + }; + + + // function for adding/overriding defaults + function setDefaults(d) { + $.extend(true, defaults, d); + } + + + + ;; + + + function Calendar(element, options, eventSources) { + var t = this; + + + // exports + t.options = options; + t.render = render; + t.destroy = destroy; + t.refetchEvents = refetchEvents; + t.reportEvents = reportEvents; + t.reportEventChange = reportEventChange; + t.rerenderEvents = rerenderEvents; + t.changeView = changeView; + t.select = select; + t.unselect = unselect; + t.prev = prev; + t.next = next; + t.prevYear = prevYear; + t.nextYear = nextYear; + t.today = today; + t.gotoDate = gotoDate; + t.incrementDate = incrementDate; + t.formatDate = function(format, date) { return formatDate(format, date, options) }; + t.formatDates = function(format, date1, date2) { return formatDates(format, date1, date2, options) }; + t.getDate = getDate; + t.getView = getView; + t.option = option; + t.trigger = trigger; + + + // imports + EventManager.call(t, options, eventSources); + var isFetchNeeded = t.isFetchNeeded; + var fetchEvents = t.fetchEvents; + + + // locals + var _element = element[0]; + var header; + var headerElement; + var content; + var tm; // for making theme classes + var currentView; + var viewInstances = {}; + var elementOuterWidth; + var suggestedViewHeight; + var absoluteViewElement; + var resizeUID = 0; + var ignoreWindowResize = 0; + var date = new Date(); + var events = []; + var _dragElement; + + + + /* Main Rendering + -----------------------------------------------------------------------------*/ + + + setYMD(date, options.year, options.month, options.date); + + + function render(inc) { + if (!content) { + initialRender(); + }else{ + calcSize(); + markSizesDirty(); + markEventsDirty(); + renderView(inc); + } + } + + + function initialRender() { + tm = options.theme ? 'ui' : 'fc'; + element.addClass('fc'); + if (options.isRTL) { + element.addClass('fc-rtl'); + } + else { + element.addClass('fc-ltr'); + } + if (options.theme) { + element.addClass('ui-widget'); + } + content = $("
") + .prependTo(element); + header = new Header(t, options); + headerElement = header.render(); + if (headerElement) { + element.prepend(headerElement); + } + changeView(options.defaultView); + $(window).resize(windowResize); + // needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize + if (!bodyVisible()) { + lateRender(); + } + } + + + // called when we know the calendar couldn't be rendered when it was initialized, + // but we think it's ready now + function lateRender() { + setTimeout(function() { // IE7 needs this so dimensions are calculated correctly + if (!currentView.start && bodyVisible()) { // !currentView.start makes sure this never happens more than once + renderView(); + } + },0); + } + + + function destroy() { + $(window).unbind('resize', windowResize); + header.destroy(); + content.remove(); + element.removeClass('fc fc-rtl ui-widget'); + } + + + + function elementVisible() { + return (_element.offsetWidth !== 0) || options.height; + } + + + function bodyVisible() { + return $('body')[0].offsetWidth !== 0; + } + + + + /* View Rendering + -----------------------------------------------------------------------------*/ + + // TODO: improve view switching (still weird transition in IE, and FF has whiteout problem) + + function changeView(newViewName) { + if (!currentView || newViewName != currentView.name) { + ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached + + unselect(); + + var oldView = currentView; + var newViewElement; + + if (oldView) { + (oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera) + setMinHeight(content, content.height()); + oldView.element.hide(); + }else{ + setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated + } + content.css('overflow', 'hidden'); + + currentView = viewInstances[newViewName]; + if (currentView) { + currentView.element.show(); + }else{ + currentView = viewInstances[newViewName] = new fcViews[newViewName]( + newViewElement = absoluteViewElement = + $("
") + .appendTo(content), + t // the calendar object + ); + } + + if (oldView) { + header.deactivateButton(oldView.name); + } + header.activateButton(newViewName); + + renderView(); // after height has been set, will make absoluteViewElement's position=relative, then set to null + + content.css('overflow', ''); + if (oldView) { + setMinHeight(content, 1); + } + + if (!newViewElement) { + (currentView.afterShow || noop)(); // called after setting min-height/overflow, so in final scroll state (for Opera) + } + + ignoreWindowResize--; + } + } + + + + function renderView(inc) { + if (elementVisible()) { + ignoreWindowResize++; // because renderEvents might temporarily change the height before setSize is reached + + unselect(); + + if (suggestedViewHeight === undefined) { + calcSize(); + } + + var forceEventRender = false; + if (!currentView.start || inc || date < currentView.start || date >= currentView.end) { + // view must render an entire new date range (and refetch/render events) + currentView.render(date, inc || 0); // responsible for clearing events + setSize(true); + forceEventRender = true; + } + else if (currentView.sizeDirty) { + // view must resize (and rerender events) + currentView.clearEvents(); + setSize(); + forceEventRender = true; + } + else if (currentView.eventsDirty) { + currentView.clearEvents(); + forceEventRender = true; + } + currentView.sizeDirty = false; + currentView.eventsDirty = false; + updateEvents(forceEventRender); + + elementOuterWidth = element.outerWidth(); + + header.updateTitle(currentView.title); + var today = new Date(); + if (today >= currentView.start && today < currentView.end) { + header.disableButton('today'); + }else{ + header.enableButton('today'); + } + + ignoreWindowResize--; + currentView.trigger('viewDisplay', _element); + } + } + + + + /* Resizing + -----------------------------------------------------------------------------*/ + + + function updateSize() { + markSizesDirty(); + if (elementVisible()) { + calcSize(); + setSize(); + unselect(); + currentView.clearEvents(); + currentView.renderEvents(events); + currentView.sizeDirty = false; + } + } + + + function markSizesDirty() { + $.each(viewInstances, function(i, inst) { + inst.sizeDirty = true; + }); + } + + + function calcSize() { + if (options.contentHeight) { + suggestedViewHeight = options.contentHeight; + } + else if (options.height) { + suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content); + } + else { + suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5)); + } + } + + + function setSize(dateChanged) { // todo: dateChanged? + ignoreWindowResize++; + currentView.setHeight(suggestedViewHeight, dateChanged); + if (absoluteViewElement) { + absoluteViewElement.css('position', 'relative'); + absoluteViewElement = null; + } + currentView.setWidth(content.width(), dateChanged); + ignoreWindowResize--; + } + + + function windowResize() { + if (!ignoreWindowResize) { + if (currentView.start) { // view has already been rendered + var uid = ++resizeUID; + setTimeout(function() { // add a delay + if (uid == resizeUID && !ignoreWindowResize && elementVisible()) { + if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) { + ignoreWindowResize++; // in case the windowResize callback changes the height + updateSize(); + currentView.trigger('windowResize', _element); + ignoreWindowResize--; + } + } + }, 200); + }else{ + // calendar must have been initialized in a 0x0 iframe that has just been resized + lateRender(); + } + } + } + + + + /* Event Fetching/Rendering + -----------------------------------------------------------------------------*/ + + + // fetches events if necessary, rerenders events if necessary (or if forced) + function updateEvents(forceRender) { + if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) { + refetchEvents(); + } + else if (forceRender) { + rerenderEvents(); + } + } + + + function refetchEvents() { + fetchEvents(currentView.visStart, currentView.visEnd); // will call reportEvents + } + + + // called when event data arrives + function reportEvents(_events) { + events = _events; + rerenderEvents(); + } + + + // called when a single event's data has been changed + function reportEventChange(eventID) { + rerenderEvents(eventID); + } + + + // attempts to rerenderEvents + function rerenderEvents(modifiedEventID) { + markEventsDirty(); + if (elementVisible()) { + currentView.clearEvents(); + currentView.renderEvents(events, modifiedEventID); + currentView.eventsDirty = false; + } + } + + + function markEventsDirty() { + $.each(viewInstances, function(i, inst) { + inst.eventsDirty = true; + }); + } + + + + /* Selection + -----------------------------------------------------------------------------*/ + + + function select(start, end, allDay) { + currentView.select(start, end, allDay===undefined ? true : allDay); + } + + + function unselect() { // safe to be called before renderView + if (currentView) { + currentView.unselect(); + } + } + + + + /* Date + -----------------------------------------------------------------------------*/ + + + function prev() { + renderView(-1); + } + + + function next() { + renderView(1); + } + + + function prevYear() { + addYears(date, -1); + renderView(); + } + + + function nextYear() { + addYears(date, 1); + renderView(); + } + + + function today() { + date = new Date(); + renderView(); + } + + + function gotoDate(year, month, dateOfMonth) { + if (year instanceof Date) { + date = cloneDate(year); // provided 1 argument, a Date + }else{ + setYMD(date, year, month, dateOfMonth); + } + renderView(); + } + + + function incrementDate(years, months, days) { + if (years !== undefined) { + addYears(date, years); + } + if (months !== undefined) { + addMonths(date, months); + } + if (days !== undefined) { + addDays(date, days); + } + renderView(); + } + + + function getDate() { + return cloneDate(date); + } + + + + /* Misc + -----------------------------------------------------------------------------*/ + + + function getView() { + return currentView; + } + + + function option(name, value) { + if (value === undefined) { + return options[name]; + } + if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') { + options[name] = value; + updateSize(); + } + } + + + function trigger(name, thisObj) { + if (options[name]) { + return options[name].apply( + thisObj || _element, + Array.prototype.slice.call(arguments, 2) + ); + } + } + + + + /* External Dragging + ------------------------------------------------------------------------*/ + + if (options.droppable) { + $(document) + .bind('dragstart', function(ev, ui) { + var _e = ev.target; + var e = $(_e); + if (!e.parents('.fc').length) { // not already inside a calendar + var accept = options.dropAccept; + if ($.isFunction(accept) ? accept.call(_e, e) : e.is(accept)) { + _dragElement = _e; + currentView.dragStart(_dragElement, ev, ui); + } + } + }) + .bind('dragstop', function(ev, ui) { + if (_dragElement) { + currentView.dragStop(_dragElement, ev, ui); + _dragElement = null; + } + }); + } + + + } + + ;; + + function Header(calendar, options) { + var t = this; + + + // exports + t.render = render; + t.destroy = destroy; + t.updateTitle = updateTitle; + t.activateButton = activateButton; + t.deactivateButton = deactivateButton; + t.disableButton = disableButton; + t.enableButton = enableButton; + + + // locals + var element = $([]); + var tm; + + + + function render() { + tm = options.theme ? 'ui' : 'fc'; + var sections = options.header; + if (sections) { + element = $("") + .append( + $("") + .append(renderSection('left')) + .append(renderSection('center')) + .append(renderSection('right')) + ); + return element; + } + } + + + function destroy() { + element.remove(); + } + + + function renderSection(position) { + var e = $("" + + ""; + + if (showWeekNumbers) { + s += ""; + } + + for (i=0; i"; // fc- needed for setDayID + } + s += + "" + + "" + + "" + + "" + + "" + + ""; + for (i=0; i" + // fc- needed for setDayID + "
" + + "
" + + "
 
" + + "
" + + "
" + + ""; + } + s += + "
" + + "" + + "" + + "
"); + var buttonStr = options.header[position]; + if (buttonStr) { + $.each(buttonStr.split(' '), function(i) { + if (i > 0) { + e.append(""); + } + var prevButton; + $.each(this.split(','), function(j, buttonName) { + if (buttonName == 'title') { + e.append("

 

"); + if (prevButton) { + prevButton.addClass(tm + '-corner-right'); + } + prevButton = null; + }else{ + var buttonClick; + if (calendar[buttonName]) { + buttonClick = calendar[buttonName]; // calendar method + } + else if (fcViews[buttonName]) { + buttonClick = function() { + button.removeClass(tm + '-state-hover'); // forget why + calendar.changeView(buttonName); + }; + } + if (buttonClick) { + var icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null; // why are we using smartProperty here? + var text = smartProperty(options.buttonText, buttonName); // why are we using smartProperty here? + var button = $( + "" + + (icon ? + "" + + "" + + "" : + text + ) + + "" + ) + .click(function() { + if (!button.hasClass(tm + '-state-disabled')) { + buttonClick(); + } + }) + .mousedown(function() { + button + .not('.' + tm + '-state-active') + .not('.' + tm + '-state-disabled') + .addClass(tm + '-state-down'); + }) + .mouseup(function() { + button.removeClass(tm + '-state-down'); + }) + .hover( + function() { + button + .not('.' + tm + '-state-active') + .not('.' + tm + '-state-disabled') + .addClass(tm + '-state-hover'); + }, + function() { + button + .removeClass(tm + '-state-hover') + .removeClass(tm + '-state-down'); + } + ) + .appendTo(e); + disableTextSelection(button); + if (!prevButton) { + button.addClass(tm + '-corner-left'); + } + prevButton = button; + } + } + }); + if (prevButton) { + prevButton.addClass(tm + '-corner-right'); + } + }); + } + return e; + } + + + function updateTitle(html) { + element.find('h2') + .html(html); + } + + + function activateButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .addClass(tm + '-state-active'); + } + + + function deactivateButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .removeClass(tm + '-state-active'); + } + + + function disableButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .addClass(tm + '-state-disabled'); + } + + + function enableButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .removeClass(tm + '-state-disabled'); + } + + + } + + ;; + + fc.sourceNormalizers = []; + fc.sourceFetchers = []; + + var ajaxDefaults = { + dataType: 'json', + cache: false + }; + + var eventGUID = 1; + + + function EventManager(options, _sources) { + var t = this; + + + // exports + t.isFetchNeeded = isFetchNeeded; + t.fetchEvents = fetchEvents; + t.addEventSource = addEventSource; + t.removeEventSource = removeEventSource; + t.updateEvent = updateEvent; + t.renderEvent = renderEvent; + t.removeEvents = removeEvents; + t.clientEvents = clientEvents; + t.normalizeEvent = normalizeEvent; + + + // imports + var trigger = t.trigger; + var getView = t.getView; + var reportEvents = t.reportEvents; + + + // locals + var stickySource = { events: [] }; + var sources = [ stickySource ]; + var rangeStart, rangeEnd; + var currentFetchID = 0; + var pendingSourceCnt = 0; + var loadingLevel = 0; + var cache = []; + + + for (var i=0; i<_sources.length; i++) { + _addEventSource(_sources[i]); + } + + + + /* Fetching + -----------------------------------------------------------------------------*/ + + + function isFetchNeeded(start, end) { + return !rangeStart || start < rangeStart || end > rangeEnd; + } + + + function fetchEvents(start, end) { + rangeStart = start; + rangeEnd = end; + cache = []; + var fetchID = ++currentFetchID; + var len = sources.length; + pendingSourceCnt = len; + for (var i=0; i)), return null instead + return null; + } + + + function parseISO8601(s, ignoreTimezone) { // ignoreTimezone defaults to false + // derived from http://delete.me.uk/2005/03/iso8601.html + // TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html + var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/); + if (!m) { + return null; + } + var date = new Date(m[1], 0, 1); + if (ignoreTimezone || !m[13]) { + var check = new Date(m[1], 0, 1, 9, 0); + if (m[3]) { + date.setMonth(m[3] - 1); + check.setMonth(m[3] - 1); + } + if (m[5]) { + date.setDate(m[5]); + check.setDate(m[5]); + } + fixDate(date, check); + if (m[7]) { + date.setHours(m[7]); + } + if (m[8]) { + date.setMinutes(m[8]); + } + if (m[10]) { + date.setSeconds(m[10]); + } + if (m[12]) { + date.setMilliseconds(Number("0." + m[12]) * 1000); + } + fixDate(date, check); + }else{ + date.setUTCFullYear( + m[1], + m[3] ? m[3] - 1 : 0, + m[5] || 1 + ); + date.setUTCHours( + m[7] || 0, + m[8] || 0, + m[10] || 0, + m[12] ? Number("0." + m[12]) * 1000 : 0 + ); + if (m[14]) { + var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0); + offset *= m[15] == '-' ? 1 : -1; + date = new Date(+date + (offset * 60 * 1000)); + } + } + return date; + } + + + function parseTime(s) { // returns minutes since start of day + if (typeof s == 'number') { // an hour + return s * 60; + } + if (typeof s == 'object') { // a Date object + return s.getHours() * 60 + s.getMinutes(); + } + var m = s.match(/(\d+)(?::(\d+))?\s*(\w+)?/); + if (m) { + var h = parseInt(m[1], 10); + if (m[3]) { + h %= 12; + if (m[3].toLowerCase().charAt(0) == 'p') { + h += 12; + } + } + return h * 60 + (m[2] ? parseInt(m[2], 10) : 0); + } + } + + + + /* Date Formatting + -----------------------------------------------------------------------------*/ + // TODO: use same function formatDate(date, [date2], format, [options]) + + + function formatDate(date, format, options) { + return formatDates(date, null, format, options); + } + + + function formatDates(date1, date2, format, options) { + options = options || defaults; + var date = date1, + otherDate = date2, + i, len = format.length, c, + i2, formatter, + res = ''; + for (i=0; ii; i2--) { + if (formatter = dateFormatters[format.substring(i, i2)]) { + if (date) { + res += formatter(date, options); + } + i = i2 - 1; + break; + } + } + if (i2 == i) { + if (date) { + res += c; + } + } + } + } + return res; + }; + + + var dateFormatters = { + s : function(d) { return d.getSeconds() }, + ss : function(d) { return zeroPad(d.getSeconds()) }, + m : function(d) { return d.getMinutes() }, + mm : function(d) { return zeroPad(d.getMinutes()) }, + h : function(d) { return d.getHours() % 12 || 12 }, + hh : function(d) { return zeroPad(d.getHours() % 12 || 12) }, + H : function(d) { return d.getHours() }, + HH : function(d) { return zeroPad(d.getHours()) }, + d : function(d) { return d.getDate() }, + dd : function(d) { return zeroPad(d.getDate()) }, + ddd : function(d,o) { return o.dayNamesShort[d.getDay()] }, + dddd: function(d,o) { return o.dayNames[d.getDay()] }, + M : function(d) { return d.getMonth() + 1 }, + MM : function(d) { return zeroPad(d.getMonth() + 1) }, + MMM : function(d,o) { return o.monthNamesShort[d.getMonth()] }, + MMMM: function(d,o) { return o.monthNames[d.getMonth()] }, + yy : function(d) { return (d.getFullYear()+'').substring(2) }, + yyyy: function(d) { return d.getFullYear() }, + t : function(d) { return d.getHours() < 12 ? 'a' : 'p' }, + tt : function(d) { return d.getHours() < 12 ? 'am' : 'pm' }, + T : function(d) { return d.getHours() < 12 ? 'A' : 'P' }, + TT : function(d) { return d.getHours() < 12 ? 'AM' : 'PM' }, + u : function(d) { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'") }, + S : function(d) { + var date = d.getDate(); + if (date > 10 && date < 20) { + return 'th'; + } + return ['st', 'nd', 'rd'][date%10-1] || 'th'; + }, + w : function(d, o) { // local + return o.weekNumberCalculation(d); + }, + W : function(d) { // ISO + return iso8601Week(d); + } + }; + fc.dateFormatters = dateFormatters; + + + /* thanks jQuery UI (https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js) + * + * Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + * @param date Date - the date to get the week for + * @return number - the number of the week within the year that contains this date + */ + function iso8601Week(date) { + var time; + var checkDate = new Date(date.getTime()); + + // Find Thursday of this week starting on Monday + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + + time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } + + + ;; + + fc.applyAll = applyAll; + + + /* Event Date Math + -----------------------------------------------------------------------------*/ + + + function exclEndDay(event) { + if (event.end) { + return _exclEndDay(event.end, event.allDay); + }else{ + return addDays(cloneDate(event.start), 1); + } + } + + + function _exclEndDay(end, allDay) { + end = cloneDate(end); + return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end); + } + + + function segCmp(a, b) { + return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start); + } + + + function segsCollide(seg1, seg2) { + return seg1.end > seg2.start && seg1.start < seg2.end; + } + + + + /* Event Sorting + -----------------------------------------------------------------------------*/ + + + // event rendering utilities + function sliceSegs(events, visEventEnds, start, end) { + var segs = [], + i, len=events.length, event, + eventStart, eventEnd, + segStart, segEnd, + isStart, isEnd; + for (i=0; i start && eventStart < end) { + if (eventStart < start) { + segStart = cloneDate(start); + isStart = false; + }else{ + segStart = eventStart; + isStart = true; + } + if (eventEnd > end) { + segEnd = cloneDate(end); + isEnd = false; + }else{ + segEnd = eventEnd; + isEnd = true; + } + segs.push({ + event: event, + start: segStart, + end: segEnd, + isStart: isStart, + isEnd: isEnd, + msLength: segEnd - segStart + }); + } + } + return segs.sort(segCmp); + } + + + // event rendering calculation utilities + function stackSegs(segs) { + var levels = [], + i, len = segs.length, seg, + j, collide, k; + for (i=0; i=0; i--) { + res = obj[parts[i].toLowerCase()]; + if (res !== undefined) { + return res; + } + } + return obj['']; + } + + + function htmlEscape(s) { + return s.replace(/&/g, '&') + .replace(//g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"') + .replace(/\n/g, '
'); + } + + + function cssKey(_element) { + return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, ''); + } + + + function disableTextSelection(element) { + element + .attr('unselectable', 'on') + .css('MozUserSelect', 'none') + .bind('selectstart.ui', function() { return false; }); + } + + + /* + function enableTextSelection(element) { + element + .attr('unselectable', 'off') + .css('MozUserSelect', '') + .unbind('selectstart.ui'); + } + */ + + + function markFirstLast(e) { + e.children() + .removeClass('fc-first fc-last') + .filter(':first-child') + .addClass('fc-first') + .end() + .filter(':last-child') + .addClass('fc-last'); + } + + + function setDayID(cell, date) { + cell.each(function(i, _cell) { + _cell.className = _cell.className.replace(/^fc-\w*/, 'fc-' + dayIDs[date.getDay()]); + // TODO: make a way that doesn't rely on order of classes + }); + } + + + function getSkinCss(event, opt) { + var source = event.source || {}; + var eventColor = event.color; + var sourceColor = source.color; + var optionColor = opt('eventColor'); + var backgroundColor = + event.backgroundColor || + eventColor || + source.backgroundColor || + sourceColor || + opt('eventBackgroundColor') || + optionColor; + var borderColor = + event.borderColor || + eventColor || + source.borderColor || + sourceColor || + opt('eventBorderColor') || + optionColor; + var textColor = + event.textColor || + source.textColor || + opt('eventTextColor'); + var statements = []; + if (backgroundColor) { + statements.push('background-color:' + backgroundColor); + } + if (borderColor) { + statements.push('border-color:' + borderColor); + } + if (textColor) { + statements.push('color:' + textColor); + } + return statements.join(';'); + } + + + function applyAll(functions, thisObj, args) { + if ($.isFunction(functions)) { + functions = [ functions ]; + } + if (functions) { + var i; + var ret; + for (i=0; i") + .appendTo(element); + } + + + + function buildTable(showNumbers) { + var html = ''; + var i, j; + var headerClass = tm + "-widget-header"; + var contentClass = tm + "-widget-content"; + var month = t.start.getMonth(); + var today = clearTime(new Date()); + var cellDate; // not to be confused with local function. TODO: better names + var cellClasses; + var cell; + + html += "" + + "" + + ""; + + if (showWeekNumbers) { + html += "" + + "" + + ""; + + for (i=0; i" + + "
" + + ""; + } + + for (j=0; j" + + "
"; + if (showNumbers) { + html += "
" + cellDate.getDate() + "
"; + } + html += "
" + + "
 
" + + "
" + + "
" + + ""; + } + + html += ""; + } + html += "
" + + "
"; + } + + for (i=0; i"; + } + + html += "
"; + + lockHeight(); // the unlock happens later, in setHeight()... + if (table) { + table.remove(); + } + table = $(html).appendTo(element); + + head = table.find('thead'); + headCells = head.find('.fc-day-header'); + body = table.find('tbody'); + bodyRows = body.find('tr'); + bodyCells = body.find('.fc-day'); + bodyFirstCells = bodyRows.find('td:first-child'); + bodyCellTopInners = bodyRows.eq(0).find('.fc-day-content > div'); + + markFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's + markFirstLast(bodyRows); // marks first+last td's + bodyRows.eq(0).addClass('fc-first'); + bodyRows.filter(':last').addClass('fc-last'); + + if (showWeekNumbers) { + head.find('.fc-week-number').text(weekNumberTitle); + } + + headCells.each(function(i, _cell) { + var date = indexDate(i); + $(_cell).text(formatDate(date, colFormat)); + }); + + if (showWeekNumbers) { + body.find('.fc-week-number > div').each(function(i, _cell) { + var weekStart = _cellDate(i, 0); + $(_cell).text(formatDate(weekStart, weekNumberFormat)); + }); + } + + bodyCells.each(function(i, _cell) { + var date = indexDate(i); + trigger('dayRender', t, date, $(_cell)); + }); + + dayBind(bodyCells); + } + + + + function setHeight(height) { + viewHeight = height; + + var bodyHeight = viewHeight - head.height(); + var rowHeight; + var rowHeightLast; + var cell; + + if (opt('weekMode') == 'variable') { + rowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6)); + }else{ + rowHeight = Math.floor(bodyHeight / rowCnt); + rowHeightLast = bodyHeight - rowHeight * (rowCnt-1); + } + + bodyFirstCells.each(function(i, _cell) { + if (i < rowCnt) { + cell = $(_cell); + setMinHeight( + cell.find('> div'), + (i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell) + ); + } + }); + + unlockHeight(); + } + + + function setWidth(width) { + viewWidth = width; + colContentPositions.clear(); + + weekNumberWidth = 0; + if (showWeekNumbers) { + weekNumberWidth = head.find('th.fc-week-number').outerWidth(); + } + + colWidth = Math.floor((viewWidth - weekNumberWidth) / colCnt); + setOuterWidth(headCells.slice(0, -1), colWidth); + } + + + + /* Day clicking and binding + -----------------------------------------------------------*/ + + + function dayBind(days) { + days.click(dayClick) + .mousedown(daySelectionMousedown); + } + + + function dayClick(ev) { + if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick + var date = parseISO8601($(this).data('date')); + trigger('dayClick', this, date, true, ev); + } + } + + + + /* Semi-transparent Overlay Helpers + ------------------------------------------------------*/ + + + function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive + if (refreshCoordinateGrid) { + coordinateGrid.build(); + } + var rowStart = cloneDate(t.visStart); + var rowEnd = addDays(cloneDate(rowStart), colCnt); + for (var i=0; i" + + "
"; + } + else { + s += "  
  
"; + dayTable = $(s).appendTo(element); + dayHead = dayTable.find('thead'); + dayHeadCells = dayHead.find('th').slice(1, -1); + dayBody = dayTable.find('tbody'); + dayBodyCells = dayBody.find('td').slice(0, -1); + dayBodyCellInners = dayBodyCells.find('div.fc-day-content div'); + dayBodyFirstCell = dayBodyCells.eq(0); + dayBodyFirstCellStretcher = dayBodyFirstCell.find('> div'); + + markFirstLast(dayHead.add(dayHead.find('tr'))); + markFirstLast(dayBody.add(dayBody.find('tr'))); + + axisFirstCells = dayHead.find('th:first'); + gutterCells = dayTable.find('.fc-agenda-gutter'); + + slotLayer = + $("
") + .appendTo(element); + + if (opt('allDaySlot')) { + + daySegmentContainer = + $("
") + .appendTo(slotLayer); + + s = + "" + + "" + + "" + + "" + + "" + + "" + + "
" + opt('allDayText') + "" + + "
" + + "
 
"; + allDayTable = $(s).appendTo(slotLayer); + allDayRow = allDayTable.find('tr'); + + dayBind(allDayRow.find('td')); + + axisFirstCells = axisFirstCells.add(allDayTable.find('th:first')); + gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter')); + + slotLayer.append( + "
" + + "
" + + "
" + ); + + }else{ + + daySegmentContainer = $([]); // in jQuery 1.4, we can just do $() + + } + + slotScroller = + $("
") + .appendTo(slotLayer); + + slotContent = + $("
") + .appendTo(slotScroller); + + slotSegmentContainer = + $("
") + .appendTo(slotContent); + + s = + "" + + ""; + d = zeroDate(); + maxd = addMinutes(cloneDate(d), maxMinute); + addMinutes(d, minMinute); + slotCnt = 0; + for (i=0; d < maxd; i++) { + minutes = d.getMinutes(); + s += + "" + + "" + + "" + + ""; + addMinutes(d, opt('slotMinutes')); + slotCnt++; + } + s += + "" + + "
" + + ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') + + "" + + "
 
" + + "
"; + slotTable = $(s).appendTo(slotContent); + slotTableFirstInner = slotTable.find('div:first'); + + slotBind(slotTable.find('td')); + + axisFirstCells = axisFirstCells.add(slotTable.find('th:first')); + } + + + + function updateCells() { + var i; + var headCell; + var bodyCell; + var date; + var today = clearTime(new Date()); + + if (showWeekNumbers) { + var weekText = formatDate(colDate(0), weekNumberFormat); + if (rtl) { + weekText = weekText + weekNumberTitle; + } + else { + weekText = weekNumberTitle + weekText; + } + dayHead.find('.fc-week-number').text(weekText); + } + + for (i=0; i= 0) { + addMinutes(d, minMinute + slotIndex * snapMinutes); + } + return d; + } + + + function colDate(col) { // returns dates with 00:00:00 + return addDays(cloneDate(t.visStart), col*dis+dit); + } + + + function cellIsAllDay(cell) { + return opt('allDaySlot') && !cell.row; + } + + + function dayOfWeekCol(dayOfWeek) { + return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt)*dis+dit; + } + + + + + // get the Y coordinate of the given time on the given day (both Date objects) + function timePosition(day, time) { // both date objects. day holds 00:00 of current day + day = cloneDate(day, true); + if (time < addMinutes(cloneDate(day), minMinute)) { + return 0; + } + if (time >= addMinutes(cloneDate(day), maxMinute)) { + return slotTable.height(); + } + var slotMinutes = opt('slotMinutes'), + minutes = time.getHours()*60 + time.getMinutes() - minMinute, + slotI = Math.floor(minutes / slotMinutes), + slotTop = slotTopCache[slotI]; + if (slotTop === undefined) { + slotTop = slotTopCache[slotI] = slotTable.find('tr:eq(' + slotI + ') td div')[0].offsetTop; //.position().top; // need this optimization??? + } + return Math.max(0, Math.round( + slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes) + )); + } + + + function allDayBounds() { + return { + left: axisWidth, + right: viewWidth - gutterWidth + } + } + + + function getAllDayRow(index) { + return allDayRow; + } + + + function defaultEventEnd(event) { + var start = cloneDate(event.start); + if (event.allDay) { + return start; + } + return addMinutes(start, opt('defaultEventMinutes')); + } + + + + /* Selection + ---------------------------------------------------------------------------------*/ + + + function defaultSelectionEnd(startDate, allDay) { + if (allDay) { + return cloneDate(startDate); + } + return addMinutes(cloneDate(startDate), opt('slotMinutes')); + } + + + function renderSelection(startDate, endDate, allDay) { // only for all-day + if (allDay) { + if (opt('allDaySlot')) { + renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true); + } + }else{ + renderSlotSelection(startDate, endDate); + } + } + + + function renderSlotSelection(startDate, endDate) { + var helperOption = opt('selectHelper'); + coordinateGrid.build(); + if (helperOption) { + var col = dayDiff(startDate, t.visStart) * dis + dit; + if (col >= 0 && col < colCnt) { // only works when times are on same day + var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only for horizontal coords + var top = timePosition(startDate, startDate); + var bottom = timePosition(startDate, endDate); + if (bottom > top) { // protect against selections that are entirely before or after visible range + rect.top = top; + rect.height = bottom - top; + rect.left += 2; + rect.width -= 5; + if ($.isFunction(helperOption)) { + var helperRes = helperOption(startDate, endDate); + if (helperRes) { + rect.position = 'absolute'; + rect.zIndex = 8; + selectionHelper = $(helperRes) + .css(rect) + .appendTo(slotContent); + } + }else{ + rect.isStart = true; // conside rect a "seg" now + rect.isEnd = true; // + selectionHelper = $(slotSegHtml( + { + title: '', + start: startDate, + end: endDate, + className: ['fc-select-helper'], + editable: false + }, + rect + )); + selectionHelper.css('opacity', opt('dragOpacity')); + } + if (selectionHelper) { + slotBind(selectionHelper); + slotContent.append(selectionHelper); + setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended + setOuterHeight(selectionHelper, rect.height, true); + } + } + } + }else{ + renderSlotOverlay(startDate, endDate); + } + } + + + function clearSelection() { + clearOverlays(); + if (selectionHelper) { + selectionHelper.remove(); + selectionHelper = null; + } + } + + + function slotSelectionMousedown(ev) { + if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button + unselect(ev); + var dates; + hoverListener.start(function(cell, origCell) { + clearSelection(); + if (cell && cell.col == origCell.col && !cellIsAllDay(cell)) { + var d1 = cellDate(origCell); + var d2 = cellDate(cell); + dates = [ + d1, + addMinutes(cloneDate(d1), snapMinutes), // calculate minutes depending on selection slot minutes + d2, + addMinutes(cloneDate(d2), snapMinutes) + ].sort(cmp); + renderSlotSelection(dates[0], dates[3]); + }else{ + dates = null; + } + }, ev); + $(document).one('mouseup', function(ev) { + hoverListener.stop(); + if (dates) { + if (+dates[0] == +dates[1]) { + reportDayClick(dates[0], false, ev); + } + reportSelection(dates[0], dates[3], false, ev); + } + }); + } + } + + + function reportDayClick(date, allDay, ev) { + trigger('dayClick', dayBodyCells[dayOfWeekCol(date.getDay())], date, allDay, ev); + } + + + + /* External Dragging + --------------------------------------------------------------------------------*/ + + + function dragStart(_dragElement, ev, ui) { + hoverListener.start(function(cell) { + clearOverlays(); + if (cell) { + if (cellIsAllDay(cell)) { + renderCellOverlay(cell.row, cell.col, cell.row, cell.col); + }else{ + var d1 = cellDate(cell); + var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes')); + renderSlotOverlay(d1, d2); + } + } + }, ev); + } + + + function dragStop(_dragElement, ev, ui) { + var cell = hoverListener.stop(); + clearOverlays(); + if (cell) { + trigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui); + } + } + + + } + + ;; + + function AgendaEventRenderer() { + var t = this; + + + // exports + t.renderEvents = renderEvents; + t.compileDaySegs = compileDaySegs; // for DayEventRenderer + t.clearEvents = clearEvents; + t.slotSegHtml = slotSegHtml; + t.bindDaySeg = bindDaySeg; + + + // imports + DayEventRenderer.call(t); + var opt = t.opt; + var trigger = t.trigger; + //var setOverflowHidden = t.setOverflowHidden; + var isEventDraggable = t.isEventDraggable; + var isEventResizable = t.isEventResizable; + var eventEnd = t.eventEnd; + var reportEvents = t.reportEvents; + var reportEventClear = t.reportEventClear; + var eventElementHandlers = t.eventElementHandlers; + var setHeight = t.setHeight; + var getDaySegmentContainer = t.getDaySegmentContainer; + var getSlotSegmentContainer = t.getSlotSegmentContainer; + var getHoverListener = t.getHoverListener; + var getMaxMinute = t.getMaxMinute; + var getMinMinute = t.getMinMinute; + var timePosition = t.timePosition; + var colContentLeft = t.colContentLeft; + var colContentRight = t.colContentRight; + var renderDaySegs = t.renderDaySegs; + var resizableDayEvent = t.resizableDayEvent; // TODO: streamline binding architecture + var getColCnt = t.getColCnt; + var getColWidth = t.getColWidth; + var getSnapHeight = t.getSnapHeight; + var getSnapMinutes = t.getSnapMinutes; + var getBodyContent = t.getBodyContent; + var reportEventElement = t.reportEventElement; + var showEvents = t.showEvents; + var hideEvents = t.hideEvents; + var eventDrop = t.eventDrop; + var eventResize = t.eventResize; + var renderDayOverlay = t.renderDayOverlay; + var clearOverlays = t.clearOverlays; + var calendar = t.calendar; + var formatDate = calendar.formatDate; + var formatDates = calendar.formatDates; + + + + /* Rendering + ----------------------------------------------------------------------------*/ + + + function renderEvents(events, modifiedEventId) { + reportEvents(events); + var i, len=events.length, + dayEvents=[], + slotEvents=[]; + for (i=0; i" + + "
" + + "
" + + htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) + + "
" + + "
" + + htmlEscape(event.title) + + "
" + + "
" + + "
"; + if (seg.isEnd && isEventResizable(event)) { + html += + "
=
"; + } + html += + ""; + return html; + } + + + function bindDaySeg(event, eventElement, seg) { + if (isEventDraggable(event)) { + draggableDayEvent(event, eventElement, seg.isStart); + } + if (seg.isEnd && isEventResizable(event)) { + resizableDayEvent(event, eventElement, seg); + } + eventElementHandlers(event, eventElement); + // needs to be after, because resizableDayEvent might stopImmediatePropagation on click + } + + + function bindSlotSeg(event, eventElement, seg) { + var timeElement = eventElement.find('div.fc-event-time'); + if (isEventDraggable(event)) { + draggableSlotEvent(event, eventElement, timeElement); + } + if (seg.isEnd && isEventResizable(event)) { + resizableSlotEvent(event, eventElement, timeElement); + } + eventElementHandlers(event, eventElement); + } + + + + /* Dragging + -----------------------------------------------------------------------------------*/ + + + // when event starts out FULL-DAY + + function draggableDayEvent(event, eventElement, isStart) { + var origWidth; + var revert; + var allDay=true; + var dayDelta; + var dis = opt('isRTL') ? -1 : 1; + var hoverListener = getHoverListener(); + var colWidth = getColWidth(); + var snapHeight = getSnapHeight(); + var snapMinutes = getSnapMinutes(); + var minMinute = getMinMinute(); + eventElement.draggable({ + zIndex: 9, + opacity: opt('dragOpacity', 'month'), // use whatever the month view was using + revertDuration: opt('dragRevertDuration'), + start: function(ev, ui) { + trigger('eventDragStart', eventElement, event, ev, ui); + hideEvents(event, eventElement); + origWidth = eventElement.width(); + hoverListener.start(function(cell, origCell, rowDelta, colDelta) { + clearOverlays(); + if (cell) { + //setOverflowHidden(true); + revert = false; + dayDelta = colDelta * dis; + if (!cell.row) { + // on full-days + renderDayOverlay( + addDays(cloneDate(event.start), dayDelta), + addDays(exclEndDay(event), dayDelta) + ); + resetElement(); + }else{ + // mouse is over bottom slots + if (isStart) { + if (allDay) { + // convert event to temporary slot-event + eventElement.width(colWidth - 10); // don't use entire width + setOuterHeight( + eventElement, + snapHeight * Math.round( + (event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes')) / + snapMinutes + ) + ); + eventElement.draggable('option', 'grid', [colWidth, 1]); + allDay = false; + } + }else{ + revert = true; + } + } + revert = revert || (allDay && !dayDelta); + }else{ + resetElement(); + //setOverflowHidden(false); + revert = true; + } + eventElement.draggable('option', 'revert', revert); + }, ev, 'drag'); + }, + stop: function(ev, ui) { + hoverListener.stop(); + clearOverlays(); + trigger('eventDragStop', eventElement, event, ev, ui); + if (revert) { + // hasn't moved or is out of bounds (draggable has already reverted) + resetElement(); + eventElement.css('filter', ''); // clear IE opacity side-effects + showEvents(event, eventElement); + }else{ + // changed! + var minuteDelta = 0; + if (!allDay) { + minuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / snapHeight) + * snapMinutes + + minMinute + - (event.start.getHours() * 60 + event.start.getMinutes()); + } + eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui); + } + //setOverflowHidden(false); + } + }); + function resetElement() { + if (!allDay) { + eventElement + .width(origWidth) + .height('') + .draggable('option', 'grid', null); + allDay = true; + } + } + } + + + // when event starts out IN TIMESLOTS + + function draggableSlotEvent(event, eventElement, timeElement) { + var origPosition; + var allDay=false; + var dayDelta; + var minuteDelta; + var prevMinuteDelta; + var dis = opt('isRTL') ? -1 : 1; + var hoverListener = getHoverListener(); + var colCnt = getColCnt(); + var colWidth = getColWidth(); + var snapHeight = getSnapHeight(); + var snapMinutes = getSnapMinutes(); + eventElement.draggable({ + zIndex: 9, + scroll: false, + grid: [colWidth, snapHeight], + axis: colCnt==1 ? 'y' : false, + opacity: opt('dragOpacity'), + revertDuration: opt('dragRevertDuration'), + start: function(ev, ui) { + trigger('eventDragStart', eventElement, event, ev, ui); + hideEvents(event, eventElement); + origPosition = eventElement.position(); + minuteDelta = prevMinuteDelta = 0; + hoverListener.start(function(cell, origCell, rowDelta, colDelta) { + eventElement.draggable('option', 'revert', !cell); + clearOverlays(); + if (cell) { + dayDelta = colDelta * dis; + if (opt('allDaySlot') && !cell.row) { + // over full days + if (!allDay) { + // convert to temporary all-day event + allDay = true; + timeElement.hide(); + eventElement.draggable('option', 'grid', null); + } + renderDayOverlay( + addDays(cloneDate(event.start), dayDelta), + addDays(exclEndDay(event), dayDelta) + ); + }else{ + // on slots + resetElement(); + } + } + }, ev, 'drag'); + }, + drag: function(ev, ui) { + minuteDelta = Math.round((ui.position.top - origPosition.top) / snapHeight) * snapMinutes; + if (minuteDelta != prevMinuteDelta) { + if (!allDay) { + updateTimeText(minuteDelta); + } + prevMinuteDelta = minuteDelta; + } + }, + stop: function(ev, ui) { + var cell = hoverListener.stop(); + clearOverlays(); + trigger('eventDragStop', eventElement, event, ev, ui); + if (cell && (dayDelta || minuteDelta || allDay)) { + // changed! + eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui); + }else{ + // either no change or out-of-bounds (draggable has already reverted) + resetElement(); + eventElement.css('filter', ''); // clear IE opacity side-effects + eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position + updateTimeText(0); + showEvents(event, eventElement); + } + } + }); + function updateTimeText(minuteDelta) { + var newStart = addMinutes(cloneDate(event.start), minuteDelta); + var newEnd; + if (event.end) { + newEnd = addMinutes(cloneDate(event.end), minuteDelta); + } + timeElement.text(formatDates(newStart, newEnd, opt('timeFormat'))); + } + function resetElement() { + // convert back to original slot-event + if (allDay) { + timeElement.css('display', ''); // show() was causing display=inline + eventElement.draggable('option', 'grid', [colWidth, snapHeight]); + allDay = false; + } + } + } + + + + /* Resizing + --------------------------------------------------------------------------------------*/ + + + function resizableSlotEvent(event, eventElement, timeElement) { + var snapDelta, prevSnapDelta; + var snapHeight = getSnapHeight(); + var snapMinutes = getSnapMinutes(); + eventElement.resizable({ + handles: { + s: '.ui-resizable-handle' + }, + grid: snapHeight, + start: function(ev, ui) { + snapDelta = prevSnapDelta = 0; + hideEvents(event, eventElement); + eventElement.css('z-index', 9); + trigger('eventResizeStart', this, event, ev, ui); + }, + resize: function(ev, ui) { + // don't rely on ui.size.height, doesn't take grid into account + snapDelta = Math.round((Math.max(snapHeight, eventElement.height()) - ui.originalSize.height) / snapHeight); + if (snapDelta != prevSnapDelta) { + timeElement.text( + formatDates( + event.start, + (!snapDelta && !event.end) ? null : // no change, so don't display time range + addMinutes(eventEnd(event), snapMinutes*snapDelta), + opt('timeFormat') + ) + ); + prevSnapDelta = snapDelta; + } + }, + stop: function(ev, ui) { + trigger('eventResizeStop', this, event, ev, ui); + if (snapDelta) { + eventResize(this, event, 0, snapMinutes*snapDelta, ev, ui); + }else{ + eventElement.css('z-index', 8); + showEvents(event, eventElement); + // BUG: if event was really short, need to put title back in span + } + } + }); + } + + + } + + + function countForwardSegs(levels) { + var i, j, k, level, segForward, segBack; + for (i=levels.length-1; i>0; i--) { + level = levels[i]; + for (j=0; j"); + var elements; + var segmentContainer = getDaySegmentContainer(); + var i; + var segCnt = segs.length; + var element; + tempContainer[0].innerHTML = daySegHTML(segs); // faster than .html() + elements = tempContainer.children(); + segmentContainer.append(elements); + daySegElementResolve(segs, elements); + daySegCalcHSides(segs); + daySegSetWidths(segs); + daySegCalcHeights(segs); + daySegSetTops(segs, getRowTops(getRowDivs())); + elements = []; + for (i=0; i" + + "
"; + if (!event.allDay && seg.isStart) { + html += + "" + + htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) + + ""; + } + html += + "" + htmlEscape(event.title) + "" + + "
"; + if (seg.isEnd && isEventResizable(event)) { + html += + "
" + + "   " + // makes hit area a lot better for IE6/7 + "
"; + } + html += + ""; + seg.left = left; + seg.outerWidth = right - left; + seg.startCol = leftCol; + seg.endCol = rightCol + 1; // needs to be exclusive + } + return html; + } + + + function daySegElementResolve(segs, elements) { // sets seg.element + var i; + var segCnt = segs.length; + var seg; + var event; + var element; + var triggerRes; + for (i=0; i div'); // optimal selector? + } + return rowDivs; + } + + + function getRowTops(rowDivs) { + var i; + var rowCnt = rowDivs.length; + var tops = []; + for (i=0; i selection for IE + element + .mousedown(function(ev) { // prevent native selection for others + ev.preventDefault(); + }) + .click(function(ev) { + if (isResizing) { + ev.preventDefault(); // prevent link from being visited (only method that worked in IE6) + ev.stopImmediatePropagation(); // prevent fullcalendar eventClick handler from being called + // (eventElementHandlers needs to be bound after resizableDayEvent) + } + }); + + handle.mousedown(function(ev) { + if (ev.which != 1) { + return; // needs to be left mouse button + } + isResizing = true; + var hoverListener = t.getHoverListener(); + var rowCnt = getRowCnt(); + var colCnt = getColCnt(); + var dis = rtl ? -1 : 1; + var dit = rtl ? colCnt-1 : 0; + var elementTop = element.css('top'); + var dayDelta; + var helpers; + var eventCopy = $.extend({}, event); + var minCell = dateCell(event.start); + clearSelection(); + $('body') + .css('cursor', direction + '-resize') + .one('mouseup', mouseup); + trigger('eventResizeStart', this, event, ev); + hoverListener.start(function(cell, origCell) { + if (cell) { + var r = Math.max(minCell.row, cell.row); + var c = cell.col; + if (rowCnt == 1) { + r = 0; // hack for all-day area in agenda views + } + if (r == minCell.row) { + if (rtl) { + c = Math.min(minCell.col, c); + }else{ + c = Math.max(minCell.col, c); + } + } + dayDelta = (r*7 + c*dis+dit) - (origCell.row*7 + origCell.col*dis+dit); + var newEnd = addDays(eventEnd(event), dayDelta, true); + if (dayDelta) { + eventCopy.end = newEnd; + var oldHelpers = helpers; + helpers = renderTempDaySegs(compileDaySegs([eventCopy]), seg.row, elementTop); + helpers.find('*').css('cursor', direction + '-resize'); + if (oldHelpers) { + oldHelpers.remove(); + } + hideEvents(event); + }else{ + if (helpers) { + showEvents(event); + helpers.remove(); + helpers = null; + } + } + clearOverlays(); + renderDayOverlay(event.start, addDays(cloneDate(newEnd), 1)); // coordinate grid already rebuild at hoverListener.start + } + }, ev); + + function mouseup(ev) { + trigger('eventResizeStop', this, event, ev); + $('body').css('cursor', ''); + hoverListener.stop(); + clearOverlays(); + if (dayDelta) { + eventResize(this, event, dayDelta, 0, ev); + // event redraw will clear helpers + } + // otherwise, the drag handler already restored the old events + + setTimeout(function() { // make this happen after the element's click event + isResizing = false; + },0); + } + + }); + } + + + } + + ;; + + //BUG: unselect needs to be triggered when events are dragged+dropped + + function SelectionManager() { + var t = this; + + + // exports + t.select = select; + t.unselect = unselect; + t.reportSelection = reportSelection; + t.daySelectionMousedown = daySelectionMousedown; + + + // imports + var opt = t.opt; + var trigger = t.trigger; + var defaultSelectionEnd = t.defaultSelectionEnd; + var renderSelection = t.renderSelection; + var clearSelection = t.clearSelection; + + + // locals + var selected = false; + + + + // unselectAuto + if (opt('selectable') && opt('unselectAuto')) { + $(document).mousedown(function(ev) { + var ignore = opt('unselectCancel'); + if (ignore) { + if ($(ev.target).parents(ignore).length) { // could be optimized to stop after first match + return; + } + } + unselect(ev); + }); + } + + + function select(startDate, endDate, allDay) { + unselect(); + if (!endDate) { + endDate = defaultSelectionEnd(startDate, allDay); + } + renderSelection(startDate, endDate, allDay); + reportSelection(startDate, endDate, allDay); + } + + + function unselect(ev) { + if (selected) { + selected = false; + clearSelection(); + trigger('unselect', null, ev); + } + } + + + function reportSelection(startDate, endDate, allDay, ev) { + selected = true; + trigger('select', null, startDate, endDate, allDay, ev); + } + + + function daySelectionMousedown(ev) { // not really a generic manager method, oh well + var cellDate = t.cellDate; + var cellIsAllDay = t.cellIsAllDay; + var hoverListener = t.getHoverListener(); + var reportDayClick = t.reportDayClick; // this is hacky and sort of weird + if (ev.which == 1 && opt('selectable')) { // which==1 means left mouse button + unselect(ev); + var _mousedownElement = this; + var dates; + hoverListener.start(function(cell, origCell) { // TODO: maybe put cellDate/cellIsAllDay info in cell + clearSelection(); + if (cell && cellIsAllDay(cell)) { + dates = [ cellDate(origCell), cellDate(cell) ].sort(cmp); + renderSelection(dates[0], dates[1], true); + }else{ + dates = null; + } + }, ev); + $(document).one('mouseup', function(ev) { + hoverListener.stop(); + if (dates) { + if (+dates[0] == +dates[1]) { + reportDayClick(dates[0], true, ev); + } + reportSelection(dates[0], dates[1], true, ev); + } + }); + } + } + + + } + + ;; + + function OverlayManager() { + var t = this; + + + // exports + t.renderOverlay = renderOverlay; + t.clearOverlays = clearOverlays; + + + // locals + var usedOverlays = []; + var unusedOverlays = []; + + + function renderOverlay(rect, parent) { + var e = unusedOverlays.shift(); + if (!e) { + e = $("
"); + } + if (e[0].parentNode != parent[0]) { + e.appendTo(parent); + } + usedOverlays.push(e.css(rect).show()); + return e; + } + + + function clearOverlays() { + var e; + while (e = usedOverlays.shift()) { + unusedOverlays.push(e.hide().unbind()); + } + } + + + } + + ;; + + function CoordinateGrid(buildFunc) { + + var t = this; + var rows; + var cols; + + + t.build = function() { + rows = []; + cols = []; + buildFunc(rows, cols); + }; + + + t.cell = function(x, y) { + var rowCnt = rows.length; + var colCnt = cols.length; + var i, r=-1, c=-1; + for (i=0; i= rows[i][0] && y < rows[i][1]) { + r = i; + break; + } + } + for (i=0; i= cols[i][0] && x < cols[i][1]) { + c = i; + break; + } + } + return (r>=0 && c>=0) ? { row:r, col:c } : null; + }; + + + t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive + var origin = originElement.offset(); + return { + top: rows[row0][0] - origin.top, + left: cols[col0][0] - origin.left, + width: cols[col1][1] - cols[col0][0], + height: rows[row1][1] - rows[row0][0] + }; + }; + + } + + ;; + + function HoverListener(coordinateGrid) { + + + var t = this; + var bindType; + var change; + var firstCell; + var cell; + + + t.start = function(_change, ev, _bindType) { + change = _change; + firstCell = cell = null; + coordinateGrid.build(); + mouse(ev); + bindType = _bindType || 'mousemove'; + $(document).bind(bindType, mouse); + }; + + + function mouse(ev) { + _fixUIEvent(ev); // see below + var newCell = coordinateGrid.cell(ev.pageX, ev.pageY); + if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) { + if (newCell) { + if (!firstCell) { + firstCell = newCell; + } + change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col); + }else{ + change(newCell, firstCell); + } + cell = newCell; + } + } + + + t.stop = function() { + $(document).unbind(bindType, mouse); + return cell; + }; + + + } + + + + // this fix was only necessary for jQuery UI 1.8.16 (and jQuery 1.7 or 1.7.1) + // upgrading to jQuery UI 1.8.17 (and using either jQuery 1.7 or 1.7.1) fixed the problem + // but keep this in here for 1.8.16 users + // and maybe remove it down the line + + function _fixUIEvent(event) { // for issue 1168 + if (event.pageX === undefined) { + event.pageX = event.originalEvent.pageX; + event.pageY = event.originalEvent.pageY; + } + } + ;; + + function HorizontalPositionCache(getElement) { + + var t = this, + elements = {}, + lefts = {}, + rights = {}; + + function e(i) { + return elements[i] = elements[i] || getElement(i); + } + + t.left = function(i) { + return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i]; + }; + + t.right = function(i) { + return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i]; + }; + + t.clear = function() { + elements = {}; + lefts = {}; + rights = {}; + }; + + } + + ;; + +})(jQuery); diff --git a/addons/web_calendar/static/lib/fullcalendar/js/gcal.js b/addons/web_calendar/static/lib/fullcalendar/js/gcal.js new file mode 100644 index 00000000000..e3008a93fcf --- /dev/null +++ b/addons/web_calendar/static/lib/fullcalendar/js/gcal.js @@ -0,0 +1,107 @@ +/*! + * FullCalendar v1.6.1 Google Calendar Plugin + * Docs & License: http://arshaw.com/fullcalendar/ + * (c) 2013 Adam Shaw + */ + +(function($) { + + +var fc = $.fullCalendar; +var formatDate = fc.formatDate; +var parseISO8601 = fc.parseISO8601; +var addDays = fc.addDays; +var applyAll = fc.applyAll; + + +fc.sourceNormalizers.push(function(sourceOptions) { + if (sourceOptions.dataType == 'gcal' || + sourceOptions.dataType === undefined && + (sourceOptions.url || '').match(/^(http|https):\/\/www.google.com\/calendar\/feeds\//)) { + sourceOptions.dataType = 'gcal'; + if (sourceOptions.editable === undefined) { + sourceOptions.editable = false; + } + } +}); + + +fc.sourceFetchers.push(function(sourceOptions, start, end) { + if (sourceOptions.dataType == 'gcal') { + return transformOptions(sourceOptions, start, end); + } +}); + + +function transformOptions(sourceOptions, start, end) { + + var success = sourceOptions.success; + var data = $.extend({}, sourceOptions.data || {}, { + 'start-min': formatDate(start, 'u'), + 'start-max': formatDate(end, 'u'), + 'singleevents': true, + 'max-results': 9999 + }); + + var ctz = sourceOptions.currentTimezone; + if (ctz) { + data.ctz = ctz = ctz.replace(' ', '_'); + } + + return $.extend({}, sourceOptions, { + url: sourceOptions.url.replace(/\/basic$/, '/full') + '?alt=json-in-script&callback=?', + dataType: 'jsonp', + data: data, + startParam: false, + endParam: false, + success: function(data) { + var events = []; + if (data.feed.entry) { + $.each(data.feed.entry, function(i, entry) { + var startStr = entry['gd$when'][0]['startTime']; + var start = parseISO8601(startStr, true); + var end = parseISO8601(entry['gd$when'][0]['endTime'], true); + var allDay = startStr.indexOf('T') == -1; + var url; + $.each(entry.link, function(i, link) { + if (link.type == 'text/html') { + url = link.href; + if (ctz) { + url += (url.indexOf('?') == -1 ? '?' : '&') + 'ctz=' + ctz; + } + } + }); + if (allDay) { + addDays(end, -1); // make inclusive + } + events.push({ + id: entry['gCal$uid']['value'], + title: entry['title']['$t'], + url: url, + start: start, + end: end, + allDay: allDay, + location: entry['gd$where'][0]['valueString'], + description: entry['content']['$t'] + }); + }); + } + var args = [events].concat(Array.prototype.slice.call(arguments, 1)); + var res = applyAll(success, this, args); + if ($.isArray(res)) { + return res; + } + return events; + } + }); + +} + + +// legacy +fc.gcalFeed = function(url, sourceOptions) { + return $.extend({}, sourceOptions, { url: url, dataType: 'gcal' }); +}; + + +})(jQuery); diff --git a/addons/web_calendar/static/lib/fullcalendar/license.txt b/addons/web_calendar/static/lib/fullcalendar/license.txt new file mode 100644 index 00000000000..dd7b48e8bee --- /dev/null +++ b/addons/web_calendar/static/lib/fullcalendar/license.txt @@ -0,0 +1,20 @@ +Copyright (c) 2013 Adam Shaw + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/addons/web_calendar/static/src/css/web_calendar.css b/addons/web_calendar/static/src/css/web_calendar.css deleted file mode 100644 index 214c777dbdc..00000000000 --- a/addons/web_calendar/static/src/css/web_calendar.css +++ /dev/null @@ -1,26 +0,0 @@ -@charset "utf-8"; -.openerp .oe_view_manager_view_calendar { - position: relative; -} - -.openerp .oe_calendar_sidebar { - width: 200px; - padding: 5px; -} -.openerp .oe_calendar { - background-color: white; - min-height: 600px; - border-right: 1px solid #eeeeee; -} -.openerp .oe_calendar .oe_calendar_filter { - padding: 0 10px; -} -.openerp .oe_calendar .dhx_cal_select_menu .dhx_menu_icon.icon_edit { - display: none; -} -.openerp .oe_calendar .dhx_cal_navline, .openerp .oe_calendar .dhx_cal_header { - z-index: auto; -} -.openerp .oe_calendar.oe_cal_month .dhx_cal_data table tr td:last-child div.dhx_month_body { - padding-right: 5px; -} diff --git a/addons/web_calendar/static/src/css/web_calendar.sass b/addons/web_calendar/static/src/css/web_calendar.sass deleted file mode 100644 index e4986981609..00000000000 --- a/addons/web_calendar/static/src/css/web_calendar.sass +++ /dev/null @@ -1,35 +0,0 @@ -@charset "utf-8" - -.openerp - .oe_view_manager_view_calendar - position: relative - -.openerp - .oe_calendar_sidebar - width: 200px - padding: 5px - - .oe_calendar - background-color: white - min-height: 600px - border-right: 1px solid #eee - - .oe_calendar_filter - padding: 0 10px - - // Dhtmlx Scheduler css overrides - .dhx_cal_select_menu .dhx_menu_icon.icon_edit - display: none - .dhx_cal_navline, .dhx_cal_header - // dhtmlx sets the index to 3 (in glossy theme) - // I didn't found the reason yet but it overlaps the - // dropdown menus and I want to avoid a z-index war. - z-index: auto - - &.oe_cal_month .dhx_cal_data - - table tr td:last-child div.dhx_month_body - padding-right: 5px - -// au BufWritePost,FileWritePost *.sass :!sass --style expanded --line-numbers > "%:p:r.css" -// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker: diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css new file mode 100644 index 00000000000..e2df45765d2 --- /dev/null +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -0,0 +1,30 @@ +@charset "utf-8"; +.openerp .oe_view_manager_view_calendar { + position: relative; +} + +.openerp .oe_fullcalendar_widget .fc-content .fc-event .close-btn { + color: white; + position: absolute; + top: 1px; + right: 1px; + display: inline-block; + line-height: 6px; + height: 8px; + width: 8px; + border: 1px solid white; + border-radius: 3px; + text-align: center; + padding: 1px; + background-color: #b40000; + box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.5); + visibility: hidden; +} +.openerp .oe_fullcalendar_widget .fc-content .fc-event:hover .close-btn { + visibility: visible; + opacity: 0.5; +} +.openerp .oe_fullcalendar_widget .fc-content .fc-event:hover .close-btn:hover { + visibility: visible; + opacity: 1; +} diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass new file mode 100644 index 00000000000..d1565c4860b --- /dev/null +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -0,0 +1,36 @@ +@charset "utf-8" + +.openerp + .oe_view_manager_view_calendar + position: relative + +.openerp + .oe_fullcalendar_widget + .fc-content + .fc-event + .close-btn + color: white + position: absolute + top: 1px + right: 1px + display: inline-block + line-height: 6px + height: 8px + width: 8px + border: 1px solid white + border-radius: 3px + text-align: center + padding: 1px + background-color: rgba(180, 0, 0, 1) + box-shadow: 0px 0px 2px rgba(0, 0, 0, .5) + visibility: hidden + z-index: 100 + .fc-event:hover + .close-btn + visibility: visible + opacity: 0.5 + .fc-event:hover + .close-btn:hover + visibility: visible + opacity: 1.0 + diff --git a/addons/web_calendar/static/src/img/cal_left.png b/addons/web_calendar/static/src/img/cal_left.png deleted file mode 100644 index acbc4565b4db997f9727a1fb8ea324f1c2453054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0y_I!_nJkcwMdFKy&%P!M2yP}QVS z@ct!>xv1<{!RjWBBUjaAjW>5(mwi{*Dazo{oPMVcS54D+ ziJl(A)y3~tl&*fy*yF_E-m@_xJDxv1<{!RjWBBUjaAgEt>M`SifA>CQX)ncuhhHwj2Bonow*qIX`9CtjuHhGa7P z(h}Ckm-c8Z)l2r#`npDfW$U%+-|eiQKiF|dz{yY3RD#7@VMnW};jx^xdo7ocZL|NZON z%^NpnPM_ZR<9{&F6vmPuzhDN3XE)M-94${5#}E!#)`P8#3<^94HuODQ_kX_^(*}`c qH(6`lta3Xdoc1I=+%bi5)qfFRhA(GsZ*~IeV(@hJb6Mw<&;$TByIT+d diff --git a/addons/web_calendar/static/src/img/minical_right.png b/addons/web_calendar/static/src/img/minical_right.png deleted file mode 100644 index fc83ac89bd6afbcfbf3b5c3acd5e3bdf9c851003..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1p!3-q7SC-!aQceLrA+A9B@WF%Y)~wmHd-w69 zNB{l(`{&P}Uq65T`0?ZW_wQFPU*5cNocZL|NZON z%^NpnPM_ZR<9{&F6vmPuzhDN3XE)M-94${5#}E!#)`P8#3<^94HuODQ_kX`vlU~E7 qvn_hhG{aI%*4&XeaZ>h!=ns*Z3}605IHv%0F?hQAxvX=', A], [this.date_start, '<=', B] - ]; - if (this.date_stop) { - domain.push( - '&', [this.date_stop, '>=', A], [this.date_stop, '<=', B], - '&', [this.date_start, '<', A], [this.date_stop, '>', B]); - domain.unshift("|", "|"); - } - domain = domain.concat(this.last_search[0].slice(0)); - return domain; - }, - do_show: function () { - var self = this; - $.when(this.has_been_loaded).done(function() { - self.$el.show(); - self.do_push_state({}); - }); - }, - get_selected_ids: function() { - // no way to select a record anyway - return []; - }, - current_mode: function() { - return scheduler.getState().mode; - }, - - quick_save: function(event_id, event_obj) { - var self = this; - var data = this.get_event_data(event_obj); - delete(data.name); - var index = this.dataset.get_id_index(event_id); - if (index !== null) { - event_id = this.dataset.ids[index]; - this.dataset.write(event_id, data, {}); - } - }, - quick_create: function(event_id, event_obj) { - var self = this; - var data = this.get_event_data(event_obj); - this.dataset.create(data).done(function(r) { - var id = r; - self.dataset.ids.push(id); - scheduler.changeEventId(event_id, id); - self.reload_event(id); - }).fail(function(r, event) { - event.preventDefault(); - self.slow_create(event_id, event_obj); - }); - }, - get_form_popup_infos: function() { - var parent = this.getParent(); - var infos = { - view_id: false, - title: this.name, - }; - if (parent instanceof instance.web.ViewManager) { - infos.view_id = parent.get_view_id('form'); - if (parent instanceof instance.web.ViewManagerAction && parent.action && parent.action.name) { - infos.title = parent.action.name; - } - } - return infos; - }, - slow_create: function(event_id, event_obj) { - var self = this; - if (this.current_mode() === 'month') { - event_obj['start_date'].addHours(8); - if (event_obj._length === 1) { - event_obj['end_date'] = new Date(event_obj['start_date']); - event_obj['end_date'].addHours(1); - } else { - event_obj['end_date'].addHours(-4); - } - } - var defaults = {}; - _.each(this.get_event_data(event_obj), function(val, field_name) { - defaults['default_' + field_name] = val; - }); - var something_saved = false; - var pop = new instance.web.form.FormOpenPopup(this); - var pop_infos = this.get_form_popup_infos(); - pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), { - title: _.str.sprintf(_t("Create: %s"), pop_infos.title), - disable_multiple_selection: true, - view_id: pop_infos.view_id, - }); - pop.on('closed', self, function() { - if (!something_saved) { - scheduler.deleteEvent(event_id); - } - }); - pop.on('create_completed', self, function(id) { - something_saved = true; - self.dataset.ids.push(id); - scheduler.changeEventId(event_id, id); - self.reload_event(id); - }); - }, - open_event: function(event_id) { - var self = this; - var index = this.dataset.get_id_index(event_id); - if (index === null) { - // Some weird behaviour in dhtmlx scheduler could lead to this case - // eg: making multiple days event in week view, dhtmlx doesn't trigger eventAdded !!?? - // so the user clicks back on the orphan event and we land here. We have to duplicate - // the dhtmlx internal event because it will delete it on next sheduler refresh. - var event_obj = scheduler.getEvent(event_id); - scheduler.deleteEvent(event_id); - scheduler.addEvent({ - start_date: event_obj.start_date, - end_date: event_obj.end_date, - text: event_obj.text, - _force_slow_create: true, - }); - } else { - var pop = new instance.web.form.FormOpenPopup(this); - var pop_infos = this.get_form_popup_infos(); - var id_from_dataset = this.dataset.ids[index]; // dhtmlx scheduler loses id's type - pop.show_element(this.dataset.model, id_from_dataset, this.dataset.get_context(), { - title: _.str.sprintf(_t("Edit: %s"), pop_infos.title), - view_id: pop_infos.view_id, - }); - pop.on('write_completed', self, function(){ - self.reload_event(id_from_dataset); - }); - } - }, - delete_event: function(event_id, event_obj) { - // dhtmlx sends this event even when it does not exist in openerp. - // Eg: use cancel in dhtmlx new event dialog - var self = this; - var index = this.dataset.get_id_index(event_id); - if (index !== null) { - this.dataset.unlink(this.dataset.ids[index]); - } - }, -}); - -instance.web_calendar.Sidebar = instance.web.Widget.extend({ - template: 'CalendarView.sidebar', - start: function() { - this._super(); - this.mini_calendar = scheduler.renderCalendar({ - container: this.$el.find('.oe_calendar_mini')[0], - navigation: true, - date: scheduler._date, - handler: function(date, calendar) { - scheduler.setCurrentView(date, 'day'); - } - }); - scheduler.linkCalendar(this.mini_calendar); - this.filter = new instance.web_calendar.SidebarFilter(this, this.getParent()); - this.filter.appendTo(this.$el.find('.oe_calendar_filter')); - } -}); -instance.web_calendar.SidebarFilter = instance.web.Widget.extend({ - events: { - 'change input:checkbox': 'filter_click' - }, - init: function(parent, view) { - this._super(parent); - this.view = view; - }, - events_loaded: function(filters) { - var selected_filters = this.view.selected_filters.slice(0); - this.$el.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters })); - this.$('div.oe_calendar_responsible input').each(function() { - if (_.indexOf(selected_filters, $(this).val()) > -1) { - $(this).click(); - } - }); - }, - filter_click: function(e) { - var self = this, - responsibles = [], - $e = $(e.target); - this.view.selected_filters = []; - this.$('div.oe_calendar_responsible input:checked').each(function() { - responsibles.push($(this).val()); - self.view.selected_filters.push($(this).val()); - }); - scheduler.clearAll(); - if (responsibles.length) { - this.view.events_loaded(this.view.dataset_events, function(filter_value) { - return _.indexOf(responsibles, filter_value.toString()) > -1; - }, true); - } else { - this.view.events_loaded(this.view.dataset_events, false, true); - } - } -}); - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js new file mode 100644 index 00000000000..e25e5cd34d6 --- /dev/null +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -0,0 +1,1078 @@ +/*globals: openerp, $, console */ + +/*--------------------------------------------------------- + * OpenERP web_calendar + *---------------------------------------------------------*/ + +openerp.web_calendar = function(instance) { + + var _t = instance.web._t, + _lt = instance.web._lt; + var QWeb = instance.web.qweb; + + function get_class(name) { + return new instance.web.Registry({'tmp' : name}).get_object("tmp"); + } + + var fc_defaultOptions = { + + /* + * Internationalization + */ + + // Dates + + monthNames: Date.CultureInfo.monthNames, + monthNamesShort: Date.CultureInfo.abbreviatedMonthNames, + dayNames: Date.CultureInfo.dayNames, + dayNamesShort: Date.CultureInfo.abbreviatedDayNames, + + // Label + + weekNumberTitle: _t("W"), + allDayText: _t("all-day"), + + // Functional + + firstDay: Date.CultureInfo.firstDayOfWeek, + + /* XXXvlab: propose a patch to formatDate + https://github.com/arshaw/fullcalendar/blob/0c20380d6967e6669633918c16047bc23eae50f2/src/date_util.js + So as to allow overriding of formatDate function only (and not formatDates), and + use datejs formatting codes. + */ + // columnFormat: { + // month: , + // week: , + // day: , + // } + + }; + + function is_virtual_id(id) { + return typeof id == "string" && id.indexOf('-') >= 0; + } + + instance.web.views.add('calendar', 'instance.web_calendar.FullCalendarView'); + + instance.web_calendar.FullCalendarView = instance.web.View.extend({ + template: "FullCalendarView", + display_name: _lt('Calendar'), + quick_create_class: 'instance.web_calendar.QuickCreate', + + init: function (parent, dataset, view_id, options) { + this._super(parent); + this.ready = $.Deferred(); + this.set_default_options(options); + this.dataset = dataset; + this.model = dataset.model; + this.fields_view = {}; + this.view_id = view_id; + this.view_type = 'calendar'; + + + this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', + '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f', + '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00', + '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ]; + + this.color_map = {}; + this.last_search = []; + this.range_start = null; + this.range_stop = null; + this.selected_filters = []; + + }, + + set_default_options: function(options) { + this._super(options); + _.defaults(this.options, { + // All possible views options should be defaulted here + confirm_on_delete: true, + }); + }, + + destroy: function() { + this.$calendar.fullCalendar('destroy'); + this._super.apply(this, arguments); + }, + + view_loading: function (fv) { + var self = this; + + this.fields_view = fv; + + this.$calendar = this.$el.find(".oe_fullcalendar_widget"); + + this.info_fields = []; + + /* buttons */ + + this.$buttons = $(QWeb.render("CalendarView.buttons", {'widget': this})); + if (this.options.$buttons) { + this.$buttons.appendTo(this.options.$buttons); + } else { + this.$el.find('.oe_calendar_buttons').replaceWith(this.$buttons); + } + + this.$buttons.on('click', 'button.oe_calendar_button_new', function () { + self.dataset.index = null; + self.do_switch_view('form'); + }); + + /* xml view calendar options */ + + var attrs = fv.arch.attrs; + + if (!attrs.date_start) { + throw new Error(_t("Calendar view has not defined 'date_start' attribute.")); + } + + this.$el.addClass(attrs['class']); + + this.name = fv.name || attrs.string; + this.view_id = fv.view_id; + + + this.mode = attrs.mode; // one of month, week or day + this.date_start = attrs.date_start; // Field name of starting date field + this.date_delay = attrs.date_delay; // duration + this.date_stop = attrs.date_stop; + this.all_day = attrs.all_day; // boolean + + this.color_field = attrs.color; + this.color_string = fv.fields[this.color_field] ? + fv.fields[this.color_field].string : _t("Filter"); + + if (this.color_field && this.selected_filters.length === 0) { + var default_filter; + if ((default_filter = this.dataset.context['calendar_default_' + this.color_field])) { + this.selected_filters.push(default_filter + ''); + } + } + this.fields = fv.fields; + + + for (var fld = 0; fld < fv.arch.children.length; fld++) { + this.info_fields.push(fv.arch.children[fld].attrs.name); + } + + return (new instance.web.Model(this.dataset.model)) + .call("check_access_rights", ["create", false]) + .then(function (create_right) { + self.create_right = create_right; + self.init_fullcalendar().then(function() { + self.trigger('calendar_view_loaded', fv); + self.ready.resolve(); + }); + }); + + }, + + get_fc_init_options: function () { + var self = this; + return $.extend({}, fc_defaultOptions, { + + defaultView: (this.mode == "month")?"month": + (this.mode == "week"?"agendaWeek": + (this.mode == "day"?"agendaDay":"month")), + header: { + left: 'prev,next today', + center: 'title', + right: 'month,agendaWeek,agendaDay' + }, + selectable: !this.options.read_only_mode && this.create_right, + selectHelper: true, + editable: !this.options.read_only_mode, + droppable: true, + + // callbacks + + eventDrop: function (event, _day_delta, _minute_delta, _all_day, _revertFunc) { + var data = self.get_event_data(event); + self.proxy('update_record')(event._id, data); // we don't revert the event, but update it. + }, + eventResize: function (event, _day_delta, _minute_delta, _revertFunc) { + var data = self.get_event_data(event); + self.proxy('update_record')(event._id, data); + }, + eventRender: function (event, element, view) { + if (!self.options.read_only_mode) { + self.append_deletion_handle(event, element, view); + } + }, + eventClick: function (event) { self.open_event(event._id); }, + select: function (start_date, end_date, all_day, _js_event, _view) { + var data_template = self.get_event_data({ + start: start_date, + end: end_date, + allDay: all_day, + }); + + // Opening quick create widget + self.open_quick_create(data_template); + + }, + drop: function(start_date, all_day) { + var data_template = self.get_event_data({ + start: start_date, + allDay: all_day, + }); + var stored_data = $(this).data('eventDefaults'); + + data_template = $.extend({}, stored_data, data_template); + + // Opening quick create widget + self.open_quick_create(data_template); + }, + unselectAuto: false, + + // Options + + weekNumbers: true, + snapMinutes: 15, + + }); + }, + + init_fullcalendar: function() { + this.$calendar.fullCalendar(this.get_fc_init_options()); + return $.when(); + }, + + open_quick_create: function(data_template) { + var self = this; + if (this.quick) { + return this.quick.trigger('close'); + } + this.quick = new (get_class(this.quick_create_class))( + this, this.dataset, true, this.options, data_template) + .on('added', this, this.proxy('quick_created')) + .on('close', this, function() { + this.quick.destroy(); + delete this.quick; + self.$calendar.fullCalendar('unselect'); + }); + this.quick.replace($(".oe_calendar_qc_placeholder")); + this.quick.focus(); + }, + + /** + * Refresh one fullcalendar event identified by it's 'id' by reading OpenERP record state. + * If event was not existent in fullcalendar, it'll be created. + */ + refresh_event: function(id) { + var self = this; + if (is_virtual_id(id)) + // Should avoid "refreshing" a virtual ID because it can't + // really be modified so it should never be refreshed. As upon + // edition, a NEW event with a non-virtual id will be created. + console.warn("Unwise use of refresh_event on a virtual ID."); + this.dataset.read_ids([id], _.keys(this.fields)).done(function (incomplete_records) { + self.perform_necessary_name_gets(incomplete_records).then(function(records) { + // Event boundaries were already changed by fullcalendar, but we need to reload them: + var new_event = self.event_data_transform(records[0]); + // fetch event_obj + var event_objs = self.$calendar.fullCalendar('clientEvents', id); + if (event_objs.length == 1) { // Already existing obj to update + var event_obj = event_objs[0]; + // update event_obj + _(new_event).each(function (value, key) { + event_obj[key] = value; + }); + self.$calendar.fullCalendar('updateEvent', event_obj); + } else { // New event object to create + self.$calendar.fullCalendar('renderEvent', new_event); + // By forcing attribution of this event to this source, we + // make sure that the event will be removed when the source + // will be removed (which occurs at each do_search) + self.$calendar.fullCalendar('clientEvents', id)[0].source = self.event_source; + } + }); + }); + }, + + get_color: function(key) { + if (this.color_map[key]) { + return this.color_map[key]; + } + var index = _.keys(this.color_map).length % this.COLOR_PALETTE.length; + var color = this.COLOR_PALETTE[index]; + this.color_map[key] = color; + return color; + }, + + /** + * In o2m case, records from dataset won't have names attached to their *2o values. + * We should make sure this is the case. + */ + perform_necessary_name_gets: function(evts) { + var def = $.Deferred(); + var self = this; + var to_get = {}; + _(this.info_fields).each(function (fieldname) { + if (!_(["many2one", "one2one"]).contains( + self.fields[fieldname].type)) + return; + to_get[fieldname] = []; + _(evts).each(function (evt) { + var value = evt[fieldname]; + if (value === false || (value instanceof Array)) + return; + to_get[fieldname].push(value); + }); + if (to_get[fieldname].length === 0) + delete to_get[fieldname]; + }); + var defs = _(to_get).map(function (ids, fieldname) { + return (new instance.web.Model(self.fields[fieldname].relation)) + .call('name_get', ids).then(function (vals) { + return [fieldname, vals]; + }); + }); + + $.when.apply(this, defs).then(function() { + var values = arguments; + _(values).each(function(value) { + var fieldname = value[0]; + var name_gets = value[1]; + _(name_gets).each(function(name_get) { + _(evts).chain() + .filter(function (e) {return e[fieldname] == name_get[0];}) + .each(function(evt) { + evt[fieldname] = name_get; + }); + }); + }); + def.resolve(evts); + }); + return def; + }, + + + /** + * Transform OpenERP event object to fullcalendar event object + */ + event_data_transform: function(evt) { + var self = this; + var date_start = instance.web.auto_str_to_date(evt[this.date_start]), + date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null, + date_delay = evt[this.date_delay] || 1.0, + all_day = this.all_day ? evt[this.all_day] : false, + res_text = ''; + + if (this.date_stop && this.fields[this.date_stop].type == 'date') { + date_stop.addDay(1); + } + + if (this.info_fields) { + res_text = _(this.info_fields) + .chain() + .map(function(fieldname) { + var value = evt[fieldname]; + if (_.contains(["one2many", "many2one", "one2one", "many2many"], + self.fields[fieldname].type)) { + if (value === false) return null; + if (value instanceof Array) + return value[1]; // Yipee, no name_get to make + throw new Error("Incomplete data received from dataset for record " + evt.id); + } + return value; + }).reject(function (x) { + return x === null; + }).value(); + } + if (!date_stop && date_delay) { + date_stop = date_start.clone().addHours(date_delay); + } + if (this.fields[this.date_start].type != "date" && all_day) { + date_stop.addDays(-1); + } + var r = { + 'start': date_start.toString('yyyy-MM-dd HH:mm:ss'), + 'end': date_stop.toString('yyyy-MM-dd HH:mm:ss'), + 'title': res_text.join(', '), + // check this with recurring data ! + 'allDay': (this.fields[this.date_start].type == 'date' || + (this.all_day && evt[this.all_day]) || false), + 'id': evt.id, + }; + if (this.color_field && evt[this.color_field]) { + var color_key = evt[this.color_field]; + if (typeof color_key === "object") { + color_key = color_key[0]; + } + r.color = this.get_color(color_key); + } + return r; + }, + + /** + * Transform fullcalendar event object to OpenERP Data object + */ + get_event_data: function(event) { + + // Normalize event_end without changing fullcalendars event. + var event_end = event.end; + if (event.allDay) { + // Sometimes fullcalendar doesn't give any event.end. + if (event_end === null || typeof evend_end === "undefined") + event_end = event.start; + // Avoid inplace changes + event_end = (new Date(event_end.getTime())).addDays(1); + } + + var data = { + name: event.title + }; + data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]); + if (this.date_stop) { + data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]); + } + if (this.all_day) { + data[this.all_day] = event.allDay; + } + if (this.date_delay) { + // XXXvlab: what if different dates ? + var diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000); + data[this.date_delay] = diff_seconds / 3600; + } + return data; + }, + do_search: function(domain, context, _group_by) { + var self = this; + if (typeof this.event_source !== "undefined") + this.$calendar.fullCalendar('removeEventSource', this.event_source); + this.event_source = { + events: function(start, end, callback) { + var current_event_source = self.event_source; + self.dataset.read_slice(_.keys(self.fields), { + offset: 0, + domain: self.get_range_domain(domain, start, end), + context: context, + }).done(function(events) { + if (self.event_source !== current_event_source) { + // Event source changed while waiting for AJAX response + console.log("Consecutive ``do_search`` called. Cancelling."); + return; + } + // We should make sure that *2many used in title of event have + // their extended form [ID, NAME]... + + return self.perform_necessary_name_gets(events).then(callback); + }); + }, + eventDataTransform: function (event) { + return self.event_data_transform(event); + }, + }; + this.$calendar.fullCalendar('addEventSource', this.event_source); + }, + /** + * Build OpenERP Domain to filter object by this.date_start field + * between given start, end dates. + */ + get_range_domain: function(domain, start, end) { + var format = instance.web.date_to_str; + return new instance.web.CompoundDomain( + domain, + [[this.date_start, '>=', format(start.clone())], + [this.date_start, '<=', format(end.clone())]]); + }, + + // do_show: function () { + // this.$el.show(); + // }, + + /** + * Updates record identified by ``id`` with values in object ``data`` + */ + update_record: function(id, data) { + var self = this; + delete(data.name); // Cannot modify actual name yet + var index = this.dataset.get_id_index(id); + if (index !== null) { + event_id = this.dataset.ids[index]; + this.dataset.write(event_id, data, {}).done(function() { + if (is_virtual_id(event_id)) { + // this is a virtual ID and so this will create a new event + // with an unknown id for us. + self.$calendar.fullCalendar('refetchEvents'); + } else { + // classical event that we can refresh + self.refresh_event(event_id); + } + }); + } + return false; + }, + open_event: function(id) { + var index = this.dataset.get_id_index(id); + this.dataset.index = index; + this.do_switch_view('form'); + return false; + }, + + do_show: function() { + if (this.$buttons) { + this.$buttons.show(); + } + this.do_push_state({}); + return this._super(); + }, + do_hide: function () { + if (this.$buttons) { + this.$buttons.hide(); + } + return this._super(); + }, + is_action_enabled: function(action) { + if (action === 'create' && !this.options.creatable) + return false; + return this._super(action); + }, + + /** + * Handles a newly created record + * + * @param {id} id of the newly created record + */ + quick_created: function (id) { + + /** Note: + * it's of the most utter importance NOT to use inplace + * modification on this.dataset.ids as reference to this + * data is spread out everywhere in the various widget. + * Some of these reference includes values that should + * trigger action upon modification. + */ + this.dataset.ids = this.dataset.ids.concat([id]); + // Inform every body that dataset changed + this.dataset.trigger("dataset_changed", id); + this.refresh_event(id); + }, + + append_deletion_handle: function (event, element, view) { + var self = this; + var $x = $("
x
") + .on('click', function(ev) { + self.remove_event(event.id); + ev.preventDefault(); + return false; + }); + element.prepend($x); + }, + + remove_event: function(id) { + var self = this; + function do_it() { + return $.when(self.dataset.unlink([id])).done(function() { + self.$calendar.fullCalendar('removeEvents', id); + }); + } + if (this.options.confirm_on_delete) { + if (confirm(_t("Are you sure you want to delete this record ?"))) { + return do_it(); + } + } else + return do_it(); + }, + }); + + + /** + * Quick creation view. + * + * Triggers a single event "added" with a single parameter "name", which is the + * name entered by the user + * + * @class + * @type {*} + */ + instance.web_calendar.QuickCreate = instance.web.Widget.extend({ + template: 'CalendarView.quick_create', + + /** + * close_btn: If true, the widget will display a "Close" button able to trigger + * a "close" event. + */ + init: function(parent, dataset, buttons, options, data_template) { + this._super(parent); + this.dataset = dataset; + this._buttons = buttons || false; + this.options = options; + + // Can hold data pre-set from where you clicked on agenda + this.data_template = data_template || {}; + }, + get_title: function () { + var parent = this.getParent(); + var title = + (typeof parent.field_widget === "undefined") ? + (parent.string || parent.name) : + parent.field_widget.string || parent.field_widget.name || ''; + return _t("Create: ") + title; + }, + start: function () { + var self = this; + + if (this.options.disable_quick_create) { + this.$el.hide(); + this.slow_create(); + return; + } + + self.$input = this.$el.find('input'); + self.$input.keyup(function(event) { + if(event.keyCode == 13){ + self.quick_add(); + } + }); + this.$el.find(".oe_calendar_quick_create_add").click(function () { + self.quick_add(); + self.focus(); + }); + this.$el.find(".oe_calendar_quick_create_close").click(function (ev) { + ev.preventDefault(); + self.trigger('close'); + }); + self.$input.keyup(function(e) { + if (e.keyCode == 27 && self._buttons) { + self.trigger('close'); + } + }); + self.$el.dialog({ title: this.get_title()}); + self.on('added', self, function() { + self.trigger('close'); + }); + }, + focus: function() { + this.$el.find('input').focus(); + }, + + /** + * Gathers data from the quick create dialog a launch quick_create(data) method + */ + quick_add: function() { + var val = this.$input.val(); + if (/^\s*$/.test(val)) { return; } + this.quick_create({'name': val}); + }, + + /** + * Handles saving data coming from quick create box + */ + quick_create: function(data, options) { + var self = this; + this.dataset.create($.extend({}, this.data_template, data), options) + .then(function(id) { + self.trigger('added', id); + self.$input.val(""); + }).fail(function(r, event) { + event.preventDefault(); + // This will occurs if there are some more fields required + self.slow_create(data); + }); + }, + + /** + * Show full form popup + */ + slow_create: function(data) { + var self = this; + var def = $.Deferred(); + var defaults = {}; + _.each($.extend({}, this.data_template, data), function(val, field_name) { + defaults['default_' + field_name] = val; + }); + + var pop = new instance.web.form.FormOpenPopup(this); + var context = new instance.web.CompoundContext(this.dataset.context, defaults) + pop.show_element(this.dataset.model, null, context +, { + title: this.get_title(), + disable_multiple_selection: true, + // Ensuring we use ``self.dataset`` and DO NOT create a new one. + create_function: function(data, options) { + return self.dataset.create(data, options).done(function(r) { + // Although ``self.dataset.create`` DOES not call ``dataset_changed`` in O2M + // it gets called thanks to ``create_completed`` -> ``added`` + // XXXvlab: why ``create`` does not call dataset_changed AND adds id in dataset.ids + // is a mystery for me ATM. + }).fail(function (r, event) { + throw new Error(r); + }); + }, + + // ATM this method should not be attainable as the current pop up is + // spawned only for newly created objects. + + // write_function: function(id, data, options) { + // return self.dataset.write(id, data, options).done(function() { + // }).fail(function (r, event) { + // throw new Error(r); + // }); + // }, + read_function: function(id, fields, options) { + return self.dataset.read_ids.apply(self.dataset, arguments).done(function() { + }).fail(function (r, event) { + throw new Error(r); + }); + }, + }); + pop.on('closed', self, function() { + // Hum, this is bad trick happening: we must avoid + // calling ``self.trigger('close')`` directly because + // it would itself destroy all child element including + // the slow create popup, which would then re-trigger + // recursively the 'closed' signal. + // + // Thus, here, we use a deferred and its state to cut + // the endless recurrence. + if (def.state() === "pending") + def.resolve(); + }); + pop.on('create_completed', self, function(id) { + self.trigger('added', id); + }); + def.then(function() { + self.trigger('close'); + }); + return def; + }, + }); + + + /** + * Form widgets + */ + + function widget_calendar_lazy_init() { + if (instance.web.form.Many2ManyCalendarView) + return; + + instance.web_fullcalendar.FieldFullCalendarView = instance.web_fullcalendar.FullCalendarView.extend({ + + init: function (parent) { + this._super.apply(this, arguments); + // Warning: this means only a field_widget should instanciate this Class + this.field_widget = parent; + }, + + view_loading: function (fv) { + var self = this; + return $.when(this._super.apply(this, arguments)).then(function() { + self.on('event_rendered', this, function (event, element, view) { + self.append_deletion_handle(event, element, view); + }); + }); + }, + + // In forms, we could be hidden in a notebook. Thus we couldn't + // render correctly fullcalendar so we try to detect when we are + // not visible to wait for when we will be visible. + init_fullcalendar: function() { + if (this.$calendar.width() !== 0) { // visible + return this._super(); + } + + // find all parents tabs. + var def = $.Deferred(); + var self = this; + this.$calendar.parents(".ui-tabs").on('tabsactivate', this, function() { + if (self.$calendar.width() !== 0) { // visible + self.$calendar.fullCalendar(self.get_fc_init_options()); + def.resolve(); + } + }); + return def; + }, + + + }); + + } + + instance.web_calendar.BufferedDataSet = instance.web.BufferedDataSet.extend({ + + /** + * Adds verification on possible missing fields for the sole purpose of + * O2M dataset being compatible with the ``slow_create`` detection of + * missing fields... which is as simple to try to write and upon failure + * go to ``slow_create``. Current BufferedDataSet would'nt fail because + * they do not send data to the server at create time. + */ + create: function (data, options) { + var def = $.Deferred(); + var self = this; + var create = this._super; + if (typeof this.required_fields === "undefined") { + this.required_fields = (new instance.web.Model(this.model)) + .call('fields_get').then(function (fields_def) { + return _(fields_def).chain() + // equiv to .pairs() + .map(function (value, key) { return [key, value]; }) + // equiv to .omit(self.field_widget.field.relation_field) + .filter(function (pair) { return pair[0] !== self.field_widget.field.relation_field; }) + .filter(function (pair) { return pair[1].required; }) + .map(function (pair) { return pair[0]; }) + .value(); + }); + } + $.when(this.required_fields).then(function (required_fields) { + var missing_fields = _(required_fields).filter(function (v) { + return typeof data[v] === "undefined"; + }); + var default_get = (missing_fields.length !== 0) ? + self.default_get(missing_fields) : []; + $.when(default_get).then(function (defaults) { + + // Remove all fields that have a default from the missing fields. + missing_fields = _(missing_fields).filter(function (f) { + return typeof defaults[f] === "undefined"; + }); + if (missing_fields.length !== 0) { + def.reject( + _.str.sprintf( + _t("Missing required fields %s"), missing_fields.join(", ")), + $.Event()); + return; + } + create.apply(self, [data, options]).then(function (result) { + def.resolve(result); + }); + }); + }); + return def; + }, + }); + + instance.web_calendar.fields_dataset = new instance.web.Registry({ + 'many2many': 'instance.web.DataSetStatic', + 'one2many': 'instance.web_calendar.BufferedDataSet', + }); + + + function get_field_dataset_class(type) { + var obj = instance.web_calendar.fields_dataset.get_any([type]); + if (!obj) { + throw new Error(_.str.sprintf(_t("Dataset for type '%s' is not defined."), type)); + } + + // Override definition of legacy datasets to add field_widget context + return obj.extend({ + init: function (parent) { + this._super.apply(this, arguments); + this.field_widget = parent; + }, + get_context: function() { + this.context = this.field_widget.build_context(); + return this.context; + } + }); + } + + /** + * Common part to manage any field using calendar view + */ + instance.web_calendar.FieldCalendar = instance.web.form.AbstractField.extend({ + + disable_utility_classes: true, + fullcalendar_view_class: 'instance.web_calendar.FieldFullCalendarView', + + init: function(field_manager, node) { + this._super(field_manager, node); + widget_calendar_lazy_init(); + this.is_loaded = $.Deferred(); + this.initial_is_loaded = this.is_loaded; + + var self = this; + + // This dataset will use current widget to '.build_context()'. + var field_type = field_manager.fields_view.fields[node.attrs.name].type; + this.dataset = new (get_field_dataset_class(field_type))( + this, this.field.relation); + + this.dataset.on('unlink', this, function(_ids) { + this.dataset.trigger('dataset_changed'); + }); + + // quick_create widget instance will be attached when spawned + this.quick_create = null; + + this.no_rerender = true; + + }, + + start: function() { + this._super.apply(this, arguments); + + var self = this; + + self.load_view(); + self.on("change:effective_readonly", self, function() { + self.is_loaded = self.is_loaded.then(function() { + self.calendar_view.destroy(); + return $.when(self.load_view()).done(function() { + self.render_value(); + }); + }); + }); + }, + + load_view: function() { + var self = this; + var calendar_view_class = get_class(this.fullcalendar_view_class); + this.calendar_view = new calendar_view_class(this, this.dataset, false, $.extend({ + 'create_text': _t("Add"), + 'creatable': self.get("effective_readonly") ? false : true, + 'quick_creatable': self.get("effective_readonly") ? false : true, + 'read_only_mode': self.get("effective_readonly") ? true : false, + 'confirm_on_delete': false, + }, this.options)); + var embedded = (this.field.views || {}).calendar; + if (embedded) { + this.calendar_view.set_embedded_view(embedded); + } + var loaded = $.Deferred(); + this.calendar_view.on("calendar_view_loaded", self, function() { + self.initial_is_loaded.resolve(); + loaded.resolve(); + }); + this.calendar_view.on('switch_mode', this, this.open_popup); + $.async_when().done(function () { + self.calendar_view.appendTo(self.$el); + }); + return loaded; + }, + + render_value: function() { + var self = this; + this.dataset.set_ids(this.get("value")); + this.is_loaded = this.is_loaded.then(function() { + return self.calendar_view.do_search(self.build_domain(), self.dataset.get_context(), []); + }); + }, + + open_popup: function(type, unused) { + if (type !== "form") + return; + if (this.dataset.index === null) { + if (typeof this.open_popup_add === "function") + this.open_popup_add(); + } else { + if (typeof this.open_popup_edit === "function") + this.open_popup_edit(); + } + }, + open_popup_add: function() { + throw new Error("Not Implemented"); + }, + open_popup_edit: function() { + var id = this.dataset.ids[this.dataset.index]; + var self = this; + var pop = (new instance.web.form.FormOpenPopup(this)); + pop.show_element(this.field.relation, id, this.build_context(), { + title: _t("Open: ") + this.string, + write_function: function(id, data, _options) { + return self.dataset.write(id, data, {}).done(function() { + // Note that dataset will trigger itself the + // ``dataset_changed`` signal + self.calendar_view.refresh_event(id); + }); + }, + read_function: function(id, fields, options) { + return self.dataset.read_ids.apply(self.dataset, arguments).done(function() { + }).fail(function (r, event) { + throw new Error(r); + }); + }, + + alternative_form_view: this.field.views ? this.field.views.form : undefined, + parent_view: this.view, //XXXvlab: to check ! this.view is likely undefined + child_name: this.name, + readonly: this.get("effective_readonly") + }); + } + }); + + instance.web_calendar.FieldMany2ManyCalendar = instance.web_calendar.FieldCalendar.extend({ + + init: function(field_manager, node) { + this._super(field_manager, node); + this.dataset.on('dataset_changed', this, function() { + // Will set dirty state if necessary + this.set({'value': this.dataset.ids}); + }); + }, + + set_value: function(value_) { + value_ = value_ || []; + if (value_.length >= 1 && value_[0] instanceof Array) { + value_ = value_[0][2]; + } + this._super(value_); + }, + + get_value: function() { + // see to use ``commands.replace_with`` provided in + // ``instance.web.form`` but not yet shared. + return [[6, false, this.get('value')]]; + }, + open_popup_add: function() { + var pop = (new instance.web.form.SelectCreatePopup(this)); + var self = this; + pop.select_element( + this.field.relation, + { + title: _t("Add: ") + this.string + }, + new instance.web.CompoundDomain( + this.build_domain(), + ["!", ["id", "in", this.dataset.ids]]), + this.build_context() + ); + pop.on("elements_selected", this, function(element_ids) { + _.each(element_ids, function(id) { + if (!_.detect(self.dataset.ids, function(x) {return x == id;})) { + self.dataset.set_ids([].concat(self.dataset.ids, [id])); + self.calendar_view.refresh_event(id); + } + self.dataset.trigger("dataset_changed"); + }); + }); + } + + }); + + + instance.web_calendar.FieldOne2ManyCalendar = instance.web_calendar.FieldCalendar.extend({ + + init: function(field_manager, node) { + this._super(field_manager, node); + this.dataset.on('dataset_changed', this, function() { + // Force dirty state, as if dataset changed, then 'get_value' + // result will change because it uses directly the dataset to + // compute its result. + this.trigger('changed_value'); + }); + }, + + set_value: instance.web.form.FieldOne2Many.prototype.set_value, + get_value: instance.web.form.FieldOne2Many.prototype.get_value, + // XXX needed by set_value for no reason at all, TO REMOVE when + // FieldOne2Many.set_value will be cleaned. + trigger_on_change: function() {}, + reload_current_view: function() {}, + + open_popup_add: false, // deactivate button "Add" + + }); + + + instance.web.form.widgets.add('many2many_calendar','instance.web_calendar.FieldMany2ManyCalendar'); + instance.web.form.widgets.add('one2many_calendar','instance.web_calendar.FieldOne2ManyCalendar'); + +}; + +// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/web_calendar/static/src/xml/web_calendar.xml b/addons/web_calendar/static/src/xml/web_calendar.xml deleted file mode 100644 index ee9175f06ed..00000000000 --- a/addons/web_calendar/static/src/xml/web_calendar.xml +++ /dev/null @@ -1,40 +0,0 @@ - diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml new file mode 100644 index 00000000000..8f867ad980d --- /dev/null +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -0,0 +1,33 @@ + From 956c1efe05bf5afa820aa5f748e3899a5c1d962e Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Thu, 7 Nov 2013 14:55:19 +0100 Subject: [PATCH 03/25] [IMP] Upgrade fullCal library from 1.6.1 with the last 1.6.4 bzr revid: jke@openerp.com-20131107135519-kmcmaoz969dhnrh2 --- addons/web_calendar/__openerp__.py | 2 +- .../lib/fullcalendar/css/fullcalendar.css | 35 +- .../lib/fullcalendar/js/fullcalendar.js | 11365 ++++++++-------- .../static/src/js/fullcalendar.js | 2 + 4 files changed, 6084 insertions(+), 5320 deletions(-) diff --git a/addons/web_calendar/__openerp__.py b/addons/web_calendar/__openerp__.py index 183d56787cb..ac8aeddea09 100644 --- a/addons/web_calendar/__openerp__.py +++ b/addons/web_calendar/__openerp__.py @@ -10,7 +10,7 @@ OpenERP Web Calendar view. 'depends': ['web'], 'js': [ 'static/lib/fullcalendar/js/fullcalendar.js', - 'static/lib/fullcalendar/js/gcal.js', + #'static/lib/fullcalendar/js/gcal.js', 'static/src/js/*.js' ], 'css': [ diff --git a/addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css b/addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css index acae725d28c..1c219b910cb 100644 --- a/addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css +++ b/addons/web_calendar/static/lib/fullcalendar/css/fullcalendar.css @@ -1,5 +1,5 @@ /*! - * FullCalendar v1.6.1 Stylesheet + * FullCalendar v1.6.4 Stylesheet * Docs & License: http://arshaw.com/fullcalendar/ * (c) 2013 Adam Shaw */ @@ -102,10 +102,11 @@ html .fc, .fc-content { clear: both; + zoom: 1; /* for IE7, gives accurate coordinates for [un]freezeContentHeight */ } .fc-view { - width: 100%; /* needed for view switching (when view is absolute) */ + width: 100%; overflow: hidden; } @@ -250,10 +251,19 @@ html .fc, /* Global Event Styles ------------------------------------------------------------------------*/ + +.fc-event-container > * { + z-index: 8; + } + +.fc-event-container > .ui-draggable-dragging, +.fc-event-container > .ui-resizable-resizing { + z-index: 9; + } .fc-event { border: 1px solid #3a87ad; /* default BORDER color */ - background-color: #3a87ad; /* default BACKGROUND color */ + background-color: #3a87ad; /* default BACKGROUND color */ color: #fff; /* default TEXT color */ font-size: .85em; cursor: default; @@ -577,3 +587,22 @@ table.fc-border-separate { } +@media print { + /* Events + -----------------------------------------------------*/ + + .fc-event { + background: #fff !important; + color: #000 !important; + } + + /* for vertical events */ + + .fc-event-bg { + display: none !important; + } + + .fc-event .ui-resizable-handle { + display: none !important; + } +} diff --git a/addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js b/addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js index 7853d3c1e51..bc85020afdc 100644 --- a/addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js +++ b/addons/web_calendar/static/lib/fullcalendar/js/fullcalendar.js @@ -1,5 +1,5 @@ /*! - * FullCalendar v1.6.1 + * FullCalendar v1.6.4 * Docs & License: http://arshaw.com/fullcalendar/ * (c) 2013 Adam Shaw */ @@ -9,5369 +9,6102 @@ * For event drag & drop, requires jQuery UI draggable. * For event resizing, requires jQuery UI resizable. */ - + (function($, undefined) { - ;; - - var defaults = { - - // display - defaultView: 'month', - aspectRatio: 1.35, - header: { - left: 'title', - center: '', - right: 'today prev,next' - }, - weekends: true, - weekNumbers: false, - weekNumberCalculation: 'iso', - weekNumberTitle: 'W', - - // editing - //editable: false, - //disableDragging: false, - //disableResizing: false, - - allDayDefault: true, - ignoreTimezone: true, - - // event ajax - lazyFetching: true, - startParam: 'start', - endParam: 'end', - - // time formats - titleFormat: { - month: 'MMMM yyyy', - week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}", - day: 'dddd, MMM d, yyyy' - }, - columnFormat: { - month: 'ddd', - week: 'ddd M/d', - day: 'dddd M/d' - }, - timeFormat: { // for event elements - '': 'h(:mm)t' // default - }, - - // locale - isRTL: false, - firstDay: 0, - monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], - monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], - dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], - dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], - buttonText: { - prev: "", - next: "", - prevYear: "«", - nextYear: "»", - today: 'today', - month: 'month', - week: 'week', - day: 'day' - }, - - // jquery-ui theming - theme: false, - buttonIcons: { - prev: 'circle-triangle-w', - next: 'circle-triangle-e' - }, - - //selectable: false, - unselectAuto: true, - - dropAccept: '*' - - }; - - // right-to-left defaults - var rtlDefaults = { - header: { - left: 'next,prev today', - center: '', - right: 'title' - }, - buttonText: { - prev: "", - next: "", - prevYear: "»", - nextYear: "«" - }, - buttonIcons: { - prev: 'circle-triangle-e', - next: 'circle-triangle-w' - } - }; - - - - ;; - - var fc = $.fullCalendar = { version: "1.6.1" }; - var fcViews = fc.views = {}; - - - $.fn.fullCalendar = function(options) { - - - // method calling - if (typeof options == 'string') { - var args = Array.prototype.slice.call(arguments, 1); - var res; - this.each(function() { - var calendar = $.data(this, 'fullCalendar'); - if (calendar && $.isFunction(calendar[options])) { - var r = calendar[options].apply(calendar, args); - if (res === undefined) { - res = r; - } - if (options == 'destroy') { - $.removeData(this, 'fullCalendar'); - } - } - }); - if (res !== undefined) { - return res; - } - return this; - } - - - // would like to have this logic in EventManager, but needs to happen before options are recursively extended - var eventSources = options.eventSources || []; - delete options.eventSources; - if (options.events) { - eventSources.push(options.events); - delete options.events; - } - - - options = $.extend(true, {}, - defaults, - (options.isRTL || options.isRTL===undefined && defaults.isRTL) ? rtlDefaults : {}, - options - ); - - - this.each(function(i, _element) { - var element = $(_element); - var calendar = new Calendar(element, options, eventSources); - element.data('fullCalendar', calendar); // TODO: look into memory leak implications - calendar.render(); - }); - - - return this; - - }; - - - // function for adding/overriding defaults - function setDefaults(d) { - $.extend(true, defaults, d); - } - - - - ;; - - - function Calendar(element, options, eventSources) { - var t = this; - - - // exports - t.options = options; - t.render = render; - t.destroy = destroy; - t.refetchEvents = refetchEvents; - t.reportEvents = reportEvents; - t.reportEventChange = reportEventChange; - t.rerenderEvents = rerenderEvents; - t.changeView = changeView; - t.select = select; - t.unselect = unselect; - t.prev = prev; - t.next = next; - t.prevYear = prevYear; - t.nextYear = nextYear; - t.today = today; - t.gotoDate = gotoDate; - t.incrementDate = incrementDate; - t.formatDate = function(format, date) { return formatDate(format, date, options) }; - t.formatDates = function(format, date1, date2) { return formatDates(format, date1, date2, options) }; - t.getDate = getDate; - t.getView = getView; - t.option = option; - t.trigger = trigger; - - - // imports - EventManager.call(t, options, eventSources); - var isFetchNeeded = t.isFetchNeeded; - var fetchEvents = t.fetchEvents; - - - // locals - var _element = element[0]; - var header; - var headerElement; - var content; - var tm; // for making theme classes - var currentView; - var viewInstances = {}; - var elementOuterWidth; - var suggestedViewHeight; - var absoluteViewElement; - var resizeUID = 0; - var ignoreWindowResize = 0; - var date = new Date(); - var events = []; - var _dragElement; - - - - /* Main Rendering - -----------------------------------------------------------------------------*/ - - - setYMD(date, options.year, options.month, options.date); - - - function render(inc) { - if (!content) { - initialRender(); - }else{ - calcSize(); - markSizesDirty(); - markEventsDirty(); - renderView(inc); - } - } - - - function initialRender() { - tm = options.theme ? 'ui' : 'fc'; - element.addClass('fc'); - if (options.isRTL) { - element.addClass('fc-rtl'); - } - else { - element.addClass('fc-ltr'); - } - if (options.theme) { - element.addClass('ui-widget'); - } - content = $("
") - .prependTo(element); - header = new Header(t, options); - headerElement = header.render(); - if (headerElement) { - element.prepend(headerElement); - } - changeView(options.defaultView); - $(window).resize(windowResize); - // needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize - if (!bodyVisible()) { - lateRender(); - } - } - - - // called when we know the calendar couldn't be rendered when it was initialized, - // but we think it's ready now - function lateRender() { - setTimeout(function() { // IE7 needs this so dimensions are calculated correctly - if (!currentView.start && bodyVisible()) { // !currentView.start makes sure this never happens more than once - renderView(); - } - },0); - } - - - function destroy() { - $(window).unbind('resize', windowResize); - header.destroy(); - content.remove(); - element.removeClass('fc fc-rtl ui-widget'); - } - - - - function elementVisible() { - return (_element.offsetWidth !== 0) || options.height; - } - - - function bodyVisible() { - return $('body')[0].offsetWidth !== 0; - } - - - - /* View Rendering - -----------------------------------------------------------------------------*/ - - // TODO: improve view switching (still weird transition in IE, and FF has whiteout problem) - - function changeView(newViewName) { - if (!currentView || newViewName != currentView.name) { - ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached - - unselect(); - - var oldView = currentView; - var newViewElement; - - if (oldView) { - (oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera) - setMinHeight(content, content.height()); - oldView.element.hide(); - }else{ - setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated - } - content.css('overflow', 'hidden'); - - currentView = viewInstances[newViewName]; - if (currentView) { - currentView.element.show(); - }else{ - currentView = viewInstances[newViewName] = new fcViews[newViewName]( - newViewElement = absoluteViewElement = - $("
") - .appendTo(content), - t // the calendar object - ); - } - - if (oldView) { - header.deactivateButton(oldView.name); - } - header.activateButton(newViewName); - - renderView(); // after height has been set, will make absoluteViewElement's position=relative, then set to null - - content.css('overflow', ''); - if (oldView) { - setMinHeight(content, 1); - } - - if (!newViewElement) { - (currentView.afterShow || noop)(); // called after setting min-height/overflow, so in final scroll state (for Opera) - } - - ignoreWindowResize--; - } - } - - - - function renderView(inc) { - if (elementVisible()) { - ignoreWindowResize++; // because renderEvents might temporarily change the height before setSize is reached - - unselect(); - - if (suggestedViewHeight === undefined) { - calcSize(); - } - - var forceEventRender = false; - if (!currentView.start || inc || date < currentView.start || date >= currentView.end) { - // view must render an entire new date range (and refetch/render events) - currentView.render(date, inc || 0); // responsible for clearing events - setSize(true); - forceEventRender = true; - } - else if (currentView.sizeDirty) { - // view must resize (and rerender events) - currentView.clearEvents(); - setSize(); - forceEventRender = true; - } - else if (currentView.eventsDirty) { - currentView.clearEvents(); - forceEventRender = true; - } - currentView.sizeDirty = false; - currentView.eventsDirty = false; - updateEvents(forceEventRender); - - elementOuterWidth = element.outerWidth(); - - header.updateTitle(currentView.title); - var today = new Date(); - if (today >= currentView.start && today < currentView.end) { - header.disableButton('today'); - }else{ - header.enableButton('today'); - } - - ignoreWindowResize--; - currentView.trigger('viewDisplay', _element); - } - } - - - - /* Resizing - -----------------------------------------------------------------------------*/ - - - function updateSize() { - markSizesDirty(); - if (elementVisible()) { - calcSize(); - setSize(); - unselect(); - currentView.clearEvents(); - currentView.renderEvents(events); - currentView.sizeDirty = false; - } - } - - - function markSizesDirty() { - $.each(viewInstances, function(i, inst) { - inst.sizeDirty = true; - }); - } - - - function calcSize() { - if (options.contentHeight) { - suggestedViewHeight = options.contentHeight; - } - else if (options.height) { - suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content); - } - else { - suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5)); - } - } - - - function setSize(dateChanged) { // todo: dateChanged? - ignoreWindowResize++; - currentView.setHeight(suggestedViewHeight, dateChanged); - if (absoluteViewElement) { - absoluteViewElement.css('position', 'relative'); - absoluteViewElement = null; - } - currentView.setWidth(content.width(), dateChanged); - ignoreWindowResize--; - } - - function windowResize() { - if (!ignoreWindowResize) { - if (currentView.start) { // view has already been rendered - var uid = ++resizeUID; - setTimeout(function() { // add a delay - if (uid == resizeUID && !ignoreWindowResize && elementVisible()) { - if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) { - ignoreWindowResize++; // in case the windowResize callback changes the height - updateSize(); - currentView.trigger('windowResize', _element); - ignoreWindowResize--; - } - } - }, 200); - }else{ - // calendar must have been initialized in a 0x0 iframe that has just been resized - lateRender(); - } - } - } +;; + +var defaults = { + + // display + defaultView: 'month', + aspectRatio: 1.35, + header: { + left: 'title', + center: '', + right: 'today prev,next' + }, + weekends: true, + weekNumbers: false, + weekNumberCalculation: 'iso', + weekNumberTitle: 'W', + + // editing + //editable: false, + //disableDragging: false, + //disableResizing: false, + + allDayDefault: true, + ignoreTimezone: true, + + // event ajax + lazyFetching: true, + startParam: 'start', + endParam: 'end', + + // time formats + titleFormat: { + month: 'MMMM yyyy', + week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}", + day: 'dddd, MMM d, yyyy' + }, + columnFormat: { + month: 'ddd', + week: 'ddd M/d', + day: 'dddd M/d' + }, + timeFormat: { // for event elements + '': 'h(:mm)t' // default + }, + + // locale + isRTL: false, + firstDay: 0, + monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], + monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], + dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], + dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], + buttonText: { + prev: "", + next: "", + prevYear: "«", + nextYear: "»", + today: 'today', + month: 'month', + week: 'week', + day: 'day' + }, + + // jquery-ui theming + theme: false, + buttonIcons: { + prev: 'circle-triangle-w', + next: 'circle-triangle-e' + }, + + //selectable: false, + unselectAuto: true, + + dropAccept: '*', + + handleWindowResize: true + +}; + +// right-to-left defaults +var rtlDefaults = { + header: { + left: 'next,prev today', + center: '', + right: 'title' + }, + buttonText: { + prev: "", + next: "", + prevYear: "»", + nextYear: "«" + }, + buttonIcons: { + prev: 'circle-triangle-e', + next: 'circle-triangle-w' + } +}; + + + +;; + +var fc = $.fullCalendar = { version: "1.6.4" }; +var fcViews = fc.views = {}; + + +$.fn.fullCalendar = function(options) { + + + // method calling + if (typeof options == 'string') { + var args = Array.prototype.slice.call(arguments, 1); + var res; + this.each(function() { + var calendar = $.data(this, 'fullCalendar'); + if (calendar && $.isFunction(calendar[options])) { + var r = calendar[options].apply(calendar, args); + if (res === undefined) { + res = r; + } + if (options == 'destroy') { + $.removeData(this, 'fullCalendar'); + } + } + }); + if (res !== undefined) { + return res; + } + return this; + } + + options = options || {}; + + // would like to have this logic in EventManager, but needs to happen before options are recursively extended + var eventSources = options.eventSources || []; + delete options.eventSources; + if (options.events) { + eventSources.push(options.events); + delete options.events; + } + + + options = $.extend(true, {}, + defaults, + (options.isRTL || options.isRTL===undefined && defaults.isRTL) ? rtlDefaults : {}, + options + ); + + + this.each(function(i, _element) { + var element = $(_element); + var calendar = new Calendar(element, options, eventSources); + element.data('fullCalendar', calendar); // TODO: look into memory leak implications + calendar.render(); + }); + + + return this; + +}; + + +// function for adding/overriding defaults +function setDefaults(d) { + $.extend(true, defaults, d); +} + + + +;; + + +function Calendar(element, options, eventSources) { + var t = this; + + + // exports + t.options = options; + t.render = render; + t.destroy = destroy; + t.refetchEvents = refetchEvents; + t.reportEvents = reportEvents; + t.reportEventChange = reportEventChange; + t.rerenderEvents = rerenderEvents; + t.changeView = changeView; + t.select = select; + t.unselect = unselect; + t.prev = prev; + t.next = next; + t.prevYear = prevYear; + t.nextYear = nextYear; + t.today = today; + t.gotoDate = gotoDate; + t.incrementDate = incrementDate; + t.formatDate = function(format, date) { return formatDate(format, date, options) }; + t.formatDates = function(format, date1, date2) { return formatDates(format, date1, date2, options) }; + t.getDate = getDate; + t.getView = getView; + t.option = option; + t.trigger = trigger; + + + // imports + EventManager.call(t, options, eventSources); + var isFetchNeeded = t.isFetchNeeded; + var fetchEvents = t.fetchEvents; + + + // locals + var _element = element[0]; + var header; + var headerElement; + var content; + var tm; // for making theme classes + var currentView; + var elementOuterWidth; + var suggestedViewHeight; + var resizeUID = 0; + var ignoreWindowResize = 0; + var date = new Date(); + var events = []; + var _dragElement; + + + + /* Main Rendering + -----------------------------------------------------------------------------*/ + + + setYMD(date, options.year, options.month, options.date); + + + function render(inc) { + if (!content) { + initialRender(); + } + else if (elementVisible()) { + // mainly for the public API + calcSize(); + _renderView(inc); + } + } + + + function initialRender() { + tm = options.theme ? 'ui' : 'fc'; + element.addClass('fc'); + if (options.isRTL) { + element.addClass('fc-rtl'); + } + else { + element.addClass('fc-ltr'); + } + if (options.theme) { + element.addClass('ui-widget'); + } + + content = $("
") + .prependTo(element); + + header = new Header(t, options); + headerElement = header.render(); + if (headerElement) { + element.prepend(headerElement); + } + + changeView(options.defaultView); + + if (options.handleWindowResize) { + $(window).resize(windowResize); + } + + // needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize + if (!bodyVisible()) { + lateRender(); + } + } + + + // called when we know the calendar couldn't be rendered when it was initialized, + // but we think it's ready now + function lateRender() { + setTimeout(function() { // IE7 needs this so dimensions are calculated correctly + if (!currentView.start && bodyVisible()) { // !currentView.start makes sure this never happens more than once + renderView(); + } + },0); + } + + + function destroy() { + + if (currentView) { + trigger('viewDestroy', currentView, currentView, currentView.element); + currentView.triggerEventDestroy(); + } + + $(window).unbind('resize', windowResize); + + header.destroy(); + content.remove(); + element.removeClass('fc fc-rtl ui-widget'); + } + + + function elementVisible() { + return element.is(':visible'); + } + + + function bodyVisible() { + return $('body').is(':visible'); + } + + + + /* View Rendering + -----------------------------------------------------------------------------*/ + + + function changeView(newViewName) { + if (!currentView || newViewName != currentView.name) { + _changeView(newViewName); + } + } + + + function _changeView(newViewName) { + ignoreWindowResize++; + + if (currentView) { + trigger('viewDestroy', currentView, currentView, currentView.element); + unselect(); + currentView.triggerEventDestroy(); // trigger 'eventDestroy' for each event + freezeContentHeight(); + currentView.element.remove(); + header.deactivateButton(currentView.name); + } + + header.activateButton(newViewName); + + currentView = new fcViews[newViewName]( + $("
") + .appendTo(content), + t // the calendar object + ); + + renderView(); + unfreezeContentHeight(); + + ignoreWindowResize--; + } + + + function renderView(inc) { + if ( + !currentView.start || // never rendered before + inc || date < currentView.start || date >= currentView.end // or new date range + ) { + if (elementVisible()) { + _renderView(inc); + } + } + } + + + function _renderView(inc) { // assumes elementVisible + ignoreWindowResize++; + + if (currentView.start) { // already been rendered? + trigger('viewDestroy', currentView, currentView, currentView.element); + unselect(); + clearEvents(); + } + + freezeContentHeight(); + currentView.render(date, inc || 0); // the view's render method ONLY renders the skeleton, nothing else + setSize(); + unfreezeContentHeight(); + (currentView.afterRender || noop)(); + + updateTitle(); + updateTodayButton(); + + trigger('viewRender', currentView, currentView, currentView.element); + currentView.trigger('viewDisplay', _element); // deprecated + + ignoreWindowResize--; + + getAndRenderEvents(); + } + + + + /* Resizing + -----------------------------------------------------------------------------*/ + + + function updateSize() { + if (elementVisible()) { + unselect(); + clearEvents(); + calcSize(); + setSize(); + renderEvents(); + } + } + + + function calcSize() { // assumes elementVisible + if (options.contentHeight) { + suggestedViewHeight = options.contentHeight; + } + else if (options.height) { + suggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content); + } + else { + suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5)); + } + } + + + function setSize() { // assumes elementVisible + + if (suggestedViewHeight === undefined) { + calcSize(); // for first time + // NOTE: we don't want to recalculate on every renderView because + // it could result in oscillating heights due to scrollbars. + } + + ignoreWindowResize++; + currentView.setHeight(suggestedViewHeight); + currentView.setWidth(content.width()); + ignoreWindowResize--; + + elementOuterWidth = element.outerWidth(); + } + + + function windowResize() { + if (!ignoreWindowResize) { + if (currentView.start) { // view has already been rendered + var uid = ++resizeUID; + setTimeout(function() { // add a delay + if (uid == resizeUID && !ignoreWindowResize && elementVisible()) { + if (elementOuterWidth != (elementOuterWidth = element.outerWidth())) { + ignoreWindowResize++; // in case the windowResize callback changes the height + updateSize(); + currentView.trigger('windowResize', _element); + ignoreWindowResize--; + } + } + }, 200); + }else{ + // calendar must have been initialized in a 0x0 iframe that has just been resized + lateRender(); + } + } + } + + + + /* Event Fetching/Rendering + -----------------------------------------------------------------------------*/ + // TODO: going forward, most of this stuff should be directly handled by the view + + + function refetchEvents() { // can be called as an API method + clearEvents(); + fetchAndRenderEvents(); + } + + + function rerenderEvents(modifiedEventID) { // can be called as an API method + clearEvents(); + renderEvents(modifiedEventID); + } + + + function renderEvents(modifiedEventID) { // TODO: remove modifiedEventID hack + if (elementVisible()) { + currentView.setEventData(events); // for View.js, TODO: unify with renderEvents + currentView.renderEvents(events, modifiedEventID); // actually render the DOM elements + currentView.trigger('eventAfterAllRender'); + } + } + + + function clearEvents() { + currentView.triggerEventDestroy(); // trigger 'eventDestroy' for each event + currentView.clearEvents(); // actually remove the DOM elements + currentView.clearEventData(); // for View.js, TODO: unify with clearEvents + } + + + function getAndRenderEvents() { + if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) { + fetchAndRenderEvents(); + } + else { + renderEvents(); + } + } + + + function fetchAndRenderEvents() { + fetchEvents(currentView.visStart, currentView.visEnd); + // ... will call reportEvents + // ... which will call renderEvents + } + + + // called when event data arrives + function reportEvents(_events) { + events = _events; + renderEvents(); + } + + + // called when a single event's data has been changed + function reportEventChange(eventID) { + rerenderEvents(eventID); + } + + + + /* Header Updating + -----------------------------------------------------------------------------*/ + + + function updateTitle() { + header.updateTitle(currentView.title); + } + + + function updateTodayButton() { + var today = new Date(); + if (today >= currentView.start && today < currentView.end) { + header.disableButton('today'); + } + else { + header.enableButton('today'); + } + } + + + + /* Selection + -----------------------------------------------------------------------------*/ + + + function select(start, end, allDay) { + currentView.select(start, end, allDay===undefined ? true : allDay); + } + + + function unselect() { // safe to be called before renderView + if (currentView) { + currentView.unselect(); + } + } + + + + /* Date + -----------------------------------------------------------------------------*/ + + + function prev() { + renderView(-1); + } + + + function next() { + renderView(1); + } + + + function prevYear() { + addYears(date, -1); + renderView(); + } + + + function nextYear() { + addYears(date, 1); + renderView(); + } + + + function today() { + date = new Date(); + renderView(); + } + + + function gotoDate(year, month, dateOfMonth) { + if (year instanceof Date) { + date = cloneDate(year); // provided 1 argument, a Date + }else{ + setYMD(date, year, month, dateOfMonth); + } + renderView(); + } + + + function incrementDate(years, months, days) { + if (years !== undefined) { + addYears(date, years); + } + if (months !== undefined) { + addMonths(date, months); + } + if (days !== undefined) { + addDays(date, days); + } + renderView(); + } + + + function getDate() { + return cloneDate(date); + } + + + + /* Height "Freezing" + -----------------------------------------------------------------------------*/ + + + function freezeContentHeight() { + content.css({ + width: '100%', + height: content.height(), + overflow: 'hidden' + }); + } + + + function unfreezeContentHeight() { + content.css({ + width: '', + height: '', + overflow: '' + }); + } + + + + /* Misc + -----------------------------------------------------------------------------*/ + + + function getView() { + return currentView; + } + + + function option(name, value) { + if (value === undefined) { + return options[name]; + } + if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') { + options[name] = value; + updateSize(); + } + } + + + function trigger(name, thisObj) { + if (options[name]) { + return options[name].apply( + thisObj || _element, + Array.prototype.slice.call(arguments, 2) + ); + } + } + + + + /* External Dragging + ------------------------------------------------------------------------*/ + + if (options.droppable) { + $(document) + .bind('dragstart', function(ev, ui) { + var _e = ev.target; + var e = $(_e); + if (!e.parents('.fc').length) { // not already inside a calendar + var accept = options.dropAccept; + if ($.isFunction(accept) ? accept.call(_e, e) : e.is(accept)) { + _dragElement = _e; + currentView.dragStart(_dragElement, ev, ui); + } + } + }) + .bind('dragstop', function(ev, ui) { + if (_dragElement) { + currentView.dragStop(_dragElement, ev, ui); + _dragElement = null; + } + }); + } + + +} + +;; + +function Header(calendar, options) { + var t = this; + + + // exports + t.render = render; + t.destroy = destroy; + t.updateTitle = updateTitle; + t.activateButton = activateButton; + t.deactivateButton = deactivateButton; + t.disableButton = disableButton; + t.enableButton = enableButton; + + + // locals + var element = $([]); + var tm; + + + + function render() { + tm = options.theme ? 'ui' : 'fc'; + var sections = options.header; + if (sections) { + element = $("") + .append( + $("") + .append(renderSection('left')) + .append(renderSection('center')) + .append(renderSection('right')) + ); + return element; + } + } + + + function destroy() { + element.remove(); + } + + + function renderSection(position) { + var e = $(""; + + if (showWeekNumbers) { + html += + ""; + } + + for (col=0; col" + + htmlEscape(formatDate(date, colFormat)) + + ""; + } + + html += ""; + + return html; + } + + + function buildBodyHTML() { + var contentClass = tm + "-widget-content"; + var html = ''; + var row; + var col; + var date; + + html += ""; + + for (row=0; row" + + "
" + + htmlEscape(formatDate(date, weekNumberFormat)) + + "
" + + ""; + } + + for (col=0; col" + + "
"; + + if (showNumbers) { + html += "
" + date.getDate() + "
"; + } + + html += + "
" + + "
 
" + + "
" + + "
" + + ""; + + return html; + } + + + + /* Dimensions + -----------------------------------------------------------*/ + + + function setHeight(height) { + viewHeight = height; + + var bodyHeight = viewHeight - head.height(); + var rowHeight; + var rowHeightLast; + var cell; + + if (opt('weekMode') == 'variable') { + rowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6)); + }else{ + rowHeight = Math.floor(bodyHeight / rowCnt); + rowHeightLast = bodyHeight - rowHeight * (rowCnt-1); + } + + bodyFirstCells.each(function(i, _cell) { + if (i < rowCnt) { + cell = $(_cell); + cell.find('> div').css( + 'min-height', + (i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell) + ); + } + }); + + } + + + function setWidth(width) { + viewWidth = width; + colPositions.clear(); + colContentPositions.clear(); + + weekNumberWidth = 0; + if (showWeekNumbers) { + weekNumberWidth = head.find('th.fc-week-number').outerWidth(); + } + + colWidth = Math.floor((viewWidth - weekNumberWidth) / colCnt); + setOuterWidth(headCells.slice(0, -1), colWidth); + } + + + + /* Day clicking and binding + -----------------------------------------------------------*/ + + + function dayBind(days) { + days.click(dayClick) + .mousedown(daySelectionMousedown); + } + + + function dayClick(ev) { + if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick + var date = parseISO8601($(this).data('date')); + trigger('dayClick', this, date, true, ev); + } + } + + + + /* Semi-transparent Overlay Helpers + ------------------------------------------------------*/ + // TODO: should be consolidated with AgendaView's methods + + + function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive + + if (refreshCoordinateGrid) { + coordinateGrid.build(); + } + + var segments = rangeToSegments(overlayStart, overlayEnd); + + for (var i=0; i") + .appendTo(element); + + if (opt('allDaySlot')) { + + daySegmentContainer = + $("
") + .appendTo(slotLayer); + + s = + "
"); + var buttonStr = options.header[position]; + if (buttonStr) { + $.each(buttonStr.split(' '), function(i) { + if (i > 0) { + e.append(""); + } + var prevButton; + $.each(this.split(','), function(j, buttonName) { + if (buttonName == 'title') { + e.append("

 

"); + if (prevButton) { + prevButton.addClass(tm + '-corner-right'); + } + prevButton = null; + }else{ + var buttonClick; + if (calendar[buttonName]) { + buttonClick = calendar[buttonName]; // calendar method + } + else if (fcViews[buttonName]) { + buttonClick = function() { + button.removeClass(tm + '-state-hover'); // forget why + calendar.changeView(buttonName); + }; + } + if (buttonClick) { + var icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null; // why are we using smartProperty here? + var text = smartProperty(options.buttonText, buttonName); // why are we using smartProperty here? + var button = $( + "" + + (icon ? + "" + + "" + + "" : + text + ) + + "" + ) + .click(function() { + if (!button.hasClass(tm + '-state-disabled')) { + buttonClick(); + } + }) + .mousedown(function() { + button + .not('.' + tm + '-state-active') + .not('.' + tm + '-state-disabled') + .addClass(tm + '-state-down'); + }) + .mouseup(function() { + button.removeClass(tm + '-state-down'); + }) + .hover( + function() { + button + .not('.' + tm + '-state-active') + .not('.' + tm + '-state-disabled') + .addClass(tm + '-state-hover'); + }, + function() { + button + .removeClass(tm + '-state-hover') + .removeClass(tm + '-state-down'); + } + ) + .appendTo(e); + disableTextSelection(button); + if (!prevButton) { + button.addClass(tm + '-corner-left'); + } + prevButton = button; + } + } + }); + if (prevButton) { + prevButton.addClass(tm + '-corner-right'); + } + }); + } + return e; + } + + + function updateTitle(html) { + element.find('h2') + .html(html); + } + + + function activateButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .addClass(tm + '-state-active'); + } + + + function deactivateButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .removeClass(tm + '-state-active'); + } + + + function disableButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .addClass(tm + '-state-disabled'); + } + + + function enableButton(buttonName) { + element.find('span.fc-button-' + buttonName) + .removeClass(tm + '-state-disabled'); + } + + +} + +;; + +fc.sourceNormalizers = []; +fc.sourceFetchers = []; + +var ajaxDefaults = { + dataType: 'json', + cache: false +}; + +var eventGUID = 1; + + +function EventManager(options, _sources) { + var t = this; + + + // exports + t.isFetchNeeded = isFetchNeeded; + t.fetchEvents = fetchEvents; + t.addEventSource = addEventSource; + t.removeEventSource = removeEventSource; + t.updateEvent = updateEvent; + t.renderEvent = renderEvent; + t.removeEvents = removeEvents; + t.clientEvents = clientEvents; + t.normalizeEvent = normalizeEvent; + + + // imports + var trigger = t.trigger; + var getView = t.getView; + var reportEvents = t.reportEvents; + + + // locals + var stickySource = { events: [] }; + var sources = [ stickySource ]; + var rangeStart, rangeEnd; + var currentFetchID = 0; + var pendingSourceCnt = 0; + var loadingLevel = 0; + var cache = []; + + + for (var i=0; i<_sources.length; i++) { + _addEventSource(_sources[i]); + } + + + + /* Fetching + -----------------------------------------------------------------------------*/ + + + function isFetchNeeded(start, end) { + return !rangeStart || start < rangeStart || end > rangeEnd; + } + + + function fetchEvents(start, end) { + rangeStart = start; + rangeEnd = end; + cache = []; + var fetchID = ++currentFetchID; + var len = sources.length; + pendingSourceCnt = len; + for (var i=0; i)), return null instead + return null; +} + + +function parseISO8601(s, ignoreTimezone) { // ignoreTimezone defaults to false + // derived from http://delete.me.uk/2005/03/iso8601.html + // TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html + var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/); + if (!m) { + return null; + } + var date = new Date(m[1], 0, 1); + if (ignoreTimezone || !m[13]) { + var check = new Date(m[1], 0, 1, 9, 0); + if (m[3]) { + date.setMonth(m[3] - 1); + check.setMonth(m[3] - 1); + } + if (m[5]) { + date.setDate(m[5]); + check.setDate(m[5]); + } + fixDate(date, check); + if (m[7]) { + date.setHours(m[7]); + } + if (m[8]) { + date.setMinutes(m[8]); + } + if (m[10]) { + date.setSeconds(m[10]); + } + if (m[12]) { + date.setMilliseconds(Number("0." + m[12]) * 1000); + } + fixDate(date, check); + }else{ + date.setUTCFullYear( + m[1], + m[3] ? m[3] - 1 : 0, + m[5] || 1 + ); + date.setUTCHours( + m[7] || 0, + m[8] || 0, + m[10] || 0, + m[12] ? Number("0." + m[12]) * 1000 : 0 + ); + if (m[14]) { + var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0); + offset *= m[15] == '-' ? 1 : -1; + date = new Date(+date + (offset * 60 * 1000)); + } + } + return date; +} + + +function parseTime(s) { // returns minutes since start of day + if (typeof s == 'number') { // an hour + return s * 60; + } + if (typeof s == 'object') { // a Date object + return s.getHours() * 60 + s.getMinutes(); + } + var m = s.match(/(\d+)(?::(\d+))?\s*(\w+)?/); + if (m) { + var h = parseInt(m[1], 10); + if (m[3]) { + h %= 12; + if (m[3].toLowerCase().charAt(0) == 'p') { + h += 12; + } + } + return h * 60 + (m[2] ? parseInt(m[2], 10) : 0); + } +} + + + +/* Date Formatting +-----------------------------------------------------------------------------*/ +// TODO: use same function formatDate(date, [date2], format, [options]) + + +function formatDate(date, format, options) { + return formatDates(date, null, format, options); +} + + +function formatDates(date1, date2, format, options) { + options = options || defaults; + var date = date1, + otherDate = date2, + i, len = format.length, c, + i2, formatter, + res = ''; + for (i=0; ii; i2--) { + if (formatter = dateFormatters[format.substring(i, i2)]) { + if (date) { + res += formatter(date, options); + } + i = i2 - 1; + break; + } + } + if (i2 == i) { + if (date) { + res += c; + } + } + } + } + return res; +}; + + +var dateFormatters = { + s : function(d) { return d.getSeconds() }, + ss : function(d) { return zeroPad(d.getSeconds()) }, + m : function(d) { return d.getMinutes() }, + mm : function(d) { return zeroPad(d.getMinutes()) }, + h : function(d) { return d.getHours() % 12 || 12 }, + hh : function(d) { return zeroPad(d.getHours() % 12 || 12) }, + H : function(d) { return d.getHours() }, + HH : function(d) { return zeroPad(d.getHours()) }, + d : function(d) { return d.getDate() }, + dd : function(d) { return zeroPad(d.getDate()) }, + ddd : function(d,o) { return o.dayNamesShort[d.getDay()] }, + dddd: function(d,o) { return o.dayNames[d.getDay()] }, + M : function(d) { return d.getMonth() + 1 }, + MM : function(d) { return zeroPad(d.getMonth() + 1) }, + MMM : function(d,o) { return o.monthNamesShort[d.getMonth()] }, + MMMM: function(d,o) { return o.monthNames[d.getMonth()] }, + yy : function(d) { return (d.getFullYear()+'').substring(2) }, + yyyy: function(d) { return d.getFullYear() }, + t : function(d) { return d.getHours() < 12 ? 'a' : 'p' }, + tt : function(d) { return d.getHours() < 12 ? 'am' : 'pm' }, + T : function(d) { return d.getHours() < 12 ? 'A' : 'P' }, + TT : function(d) { return d.getHours() < 12 ? 'AM' : 'PM' }, + u : function(d) { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'") }, + S : function(d) { + var date = d.getDate(); + if (date > 10 && date < 20) { + return 'th'; + } + return ['st', 'nd', 'rd'][date%10-1] || 'th'; + }, + w : function(d, o) { // local + return o.weekNumberCalculation(d); + }, + W : function(d) { // ISO + return iso8601Week(d); + } +}; +fc.dateFormatters = dateFormatters; + + +/* thanks jQuery UI (https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js) + * + * Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + * `date` - the date to get the week for + * `number` - the number of the week within the year that contains this date + */ +function iso8601Week(date) { + var time; + var checkDate = new Date(date.getTime()); + + // Find Thursday of this week starting on Monday + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + + time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; +} + + +;; + +fc.applyAll = applyAll; + + +/* Event Date Math +-----------------------------------------------------------------------------*/ + + +function exclEndDay(event) { + if (event.end) { + return _exclEndDay(event.end, event.allDay); + }else{ + return addDays(cloneDate(event.start), 1); + } +} + + +function _exclEndDay(end, allDay) { + end = cloneDate(end); + return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end); + // why don't we check for seconds/ms too? +} + +/* Event Element Binding +-----------------------------------------------------------------------------*/ - /* Event Fetching/Rendering - -----------------------------------------------------------------------------*/ +function lazySegBind(container, segs, bindHandlers) { + container.unbind('mouseover').mouseover(function(ev) { + var parent=ev.target, e, + i, seg; + while (parent != this) { + e = parent; + parent = parent.parentNode; + } + if ((i = e._fci) !== undefined) { + e._fci = undefined; + seg = segs[i]; + bindHandlers(seg.event, seg.element, seg); + $(ev.target).trigger(ev); + } + ev.stopPropagation(); + }); +} - // fetches events if necessary, rerenders events if necessary (or if forced) - function updateEvents(forceRender) { - if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) { - refetchEvents(); - } - else if (forceRender) { - rerenderEvents(); - } - } - function refetchEvents() { - fetchEvents(currentView.visStart, currentView.visEnd); // will call reportEvents - } +/* Element Dimensions +-----------------------------------------------------------------------------*/ - // called when event data arrives - function reportEvents(_events) { - events = _events; - rerenderEvents(); - } +function setOuterWidth(element, width, includeMargins) { + for (var i=0, e; i=0; i--) { + res = obj[parts[i].toLowerCase()]; + if (res !== undefined) { + return res; + } + } + return obj['']; +} + + +function htmlEscape(s) { + return s.replace(/&/g, '&') + .replace(//g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"') + .replace(/\n/g, '
'); +} +function disableTextSelection(element) { + element + .attr('unselectable', 'on') + .css('MozUserSelect', 'none') + .bind('selectstart.ui', function() { return false; }); +} + + +/* +function enableTextSelection(element) { + element + .attr('unselectable', 'off') + .css('MozUserSelect', '') + .unbind('selectstart.ui'); +} +*/ + + +function markFirstLast(e) { + e.children() + .removeClass('fc-first fc-last') + .filter(':first-child') + .addClass('fc-first') + .end() + .filter(':last-child') + .addClass('fc-last'); +} + + +function setDayID(cell, date) { + cell.each(function(i, _cell) { + _cell.className = _cell.className.replace(/^fc-\w*/, 'fc-' + dayIDs[date.getDay()]); + // TODO: make a way that doesn't rely on order of classes + }); +} + + +function getSkinCss(event, opt) { + var source = event.source || {}; + var eventColor = event.color; + var sourceColor = source.color; + var optionColor = opt('eventColor'); + var backgroundColor = + event.backgroundColor || + eventColor || + source.backgroundColor || + sourceColor || + opt('eventBackgroundColor') || + optionColor; + var borderColor = + event.borderColor || + eventColor || + source.borderColor || + sourceColor || + opt('eventBorderColor') || + optionColor; + var textColor = + event.textColor || + source.textColor || + opt('eventTextColor'); + var statements = []; + if (backgroundColor) { + statements.push('background-color:' + backgroundColor); + } + if (borderColor) { + statements.push('border-color:' + borderColor); + } + if (textColor) { + statements.push('color:' + textColor); + } + return statements.join(';'); +} + + +function applyAll(functions, thisObj, args) { + if ($.isFunction(functions)) { + functions = [ functions ]; + } + if (functions) { + var i; + var ret; + for (i=0; i") + .appendTo(element); + } + + + function buildTable() { + var html = buildTableHTML(); + + if (table) { + table.remove(); + } + table = $(html).appendTo(element); + + head = table.find('thead'); + headCells = head.find('.fc-day-header'); + body = table.find('tbody'); + bodyRows = body.find('tr'); + bodyCells = body.find('.fc-day'); + bodyFirstCells = bodyRows.find('td:first-child'); + + firstRowCellInners = bodyRows.eq(0).find('.fc-day > div'); + firstRowCellContentInners = bodyRows.eq(0).find('.fc-day-content > div'); + + markFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's + markFirstLast(bodyRows); // marks first+last td's + bodyRows.eq(0).addClass('fc-first'); + bodyRows.filter(':last').addClass('fc-last'); + + bodyCells.each(function(i, _cell) { + var date = cellToDate( + Math.floor(i / colCnt), + i % colCnt + ); + trigger('dayRender', t, date, $(_cell)); + }); + + dayBind(bodyCells); + } + + + + /* HTML Building + -----------------------------------------------------------*/ + + + function buildTableHTML() { + var html = + "" + + buildHeadHTML() + + buildBodyHTML() + + "
"; + + return html; + } + + + function buildHeadHTML() { + var headerClass = tm + "-widget-header"; + var html = ''; + var col; + var date; + + html += "
" + + htmlEscape(weekNumberTitle) + + "
" + + "" + + "" + + "" + + "" + + "" + + "
" + opt('allDayText') + "" + + "
" + + "
 
"; + allDayTable = $(s).appendTo(slotLayer); + allDayRow = allDayTable.find('tr'); + + dayBind(allDayRow.find('td')); + + slotLayer.append( + "
" + + "
" + + "
" + ); + + }else{ + + daySegmentContainer = $([]); // in jQuery 1.4, we can just do $() + + } + + slotScroller = + $("
") + .appendTo(slotLayer); + + slotContainer = + $("
") + .appendTo(slotScroller); + + slotSegmentContainer = + $("
") + .appendTo(slotContainer); + + s = + "" + + ""; + d = zeroDate(); + maxd = addMinutes(cloneDate(d), maxMinute); + addMinutes(d, minMinute); + slotCnt = 0; + for (i=0; d < maxd; i++) { + minutes = d.getMinutes(); + s += + "" + + "" + + "" + + ""; + addMinutes(d, opt('slotMinutes')); + slotCnt++; + } + s += + "" + + "
" + + ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') + + "" + + "
 
" + + "
"; + slotTable = $(s).appendTo(slotContainer); + + slotBind(slotTable.find('td')); + } + + + + /* Build Day Table + -----------------------------------------------------------------------*/ + + + function buildDayTable() { + var html = buildDayTableHTML(); + + if (dayTable) { + dayTable.remove(); + } + dayTable = $(html).appendTo(element); + + dayHead = dayTable.find('thead'); + dayHeadCells = dayHead.find('th').slice(1, -1); // exclude gutter + dayBody = dayTable.find('tbody'); + dayBodyCells = dayBody.find('td').slice(0, -1); // exclude gutter + dayBodyCellInners = dayBodyCells.find('> div'); + dayBodyCellContentInners = dayBodyCells.find('.fc-day-content > div'); + + dayBodyFirstCell = dayBodyCells.eq(0); + dayBodyFirstCellStretcher = dayBodyCellInners.eq(0); + + markFirstLast(dayHead.add(dayHead.find('tr'))); + markFirstLast(dayBody.add(dayBody.find('tr'))); + + // TODO: now that we rebuild the cells every time, we should call dayRender + } + + + function buildDayTableHTML() { + var html = + "" + + buildDayTableHeadHTML() + + buildDayTableBodyHTML() + + "
"; + + return html; + } + + + function buildDayTableHeadHTML() { + var headerClass = tm + "-widget-header"; + var date; + var html = ''; + var weekText; + var col; + + html += + "" + + ""; + + if (showWeekNumbers) { + date = cellToDate(0, 0); + weekText = formatDate(date, weekNumberFormat); + if (rtl) { + weekText += weekNumberTitle; + } + else { + weekText = weekNumberTitle + weekText; + } + html += + "" + + htmlEscape(weekText) + + ""; + } + else { + html += " "; + } + + for (col=0; col" + + htmlEscape(formatDate(date, colFormat)) + + ""; + } + + html += + " " + + "" + + ""; + + return html; + } + + + function buildDayTableBodyHTML() { + var headerClass = tm + "-widget-header"; // TODO: make these when updateOptions() called + var contentClass = tm + "-widget-content"; + var date; + var today = clearTime(new Date()); + var col; + var cellsHTML; + var cellHTML; + var classNames; + var html = ''; + + html += + "" + + "" + + " "; + + cellsHTML = ''; + + for (col=0; col" + + "
" + + "
" + + "
 
" + + "
" + + "
" + + ""; + + cellsHTML += cellHTML; + } + + html += cellsHTML; + html += + " " + + "" + + ""; + + return html; + } + + + // TODO: data-date on the cells + + + + /* Dimensions + -----------------------------------------------------------------------*/ + + + function setHeight(height) { + if (height === undefined) { + height = viewHeight; + } + viewHeight = height; + slotTopCache = {}; + + var headHeight = dayBody.position().top; + var allDayHeight = slotScroller.position().top; // including divider + var bodyHeight = Math.min( // total body height, including borders + height - headHeight, // when scrollbars + slotTable.height() + allDayHeight + 1 // when no scrollbars. +1 for bottom border + ); + + dayBodyFirstCellStretcher + .height(bodyHeight - vsides(dayBodyFirstCell)); + + slotLayer.css('top', headHeight); + + slotScroller.height(bodyHeight - allDayHeight - 1); + + // the stylesheet guarantees that the first row has no border. + // this allows .height() to work well cross-browser. + slotHeight = slotTable.find('tr:first').height() + 1; // +1 for bottom border + + snapRatio = opt('slotMinutes') / snapMinutes; + snapHeight = slotHeight / snapRatio; + } + + + function setWidth(width) { + viewWidth = width; + colPositions.clear(); + colContentPositions.clear(); + + var axisFirstCells = dayHead.find('th:first'); + if (allDayTable) { + axisFirstCells = axisFirstCells.add(allDayTable.find('th:first')); + } + axisFirstCells = axisFirstCells.add(slotTable.find('th:first')); + + axisWidth = 0; + setOuterWidth( + axisFirstCells + .width('') + .each(function(i, _cell) { + axisWidth = Math.max(axisWidth, $(_cell).outerWidth()); + }), + axisWidth + ); + + var gutterCells = dayTable.find('.fc-agenda-gutter'); + if (allDayTable) { + gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter')); + } + + var slotTableWidth = slotScroller[0].clientWidth; // needs to be done after axisWidth (for IE7) + + gutterWidth = slotScroller.width() - slotTableWidth; + if (gutterWidth) { + setOuterWidth(gutterCells, gutterWidth); + gutterCells + .show() + .prev() + .removeClass('fc-last'); + }else{ + gutterCells + .hide() + .prev() + .addClass('fc-last'); + } + + colWidth = Math.floor((slotTableWidth - axisWidth) / colCnt); + setOuterWidth(dayHeadCells.slice(0, -1), colWidth); + } + + + + /* Scrolling + -----------------------------------------------------------------------*/ + + + function resetScroll() { + var d0 = zeroDate(); + var scrollDate = cloneDate(d0); + scrollDate.setHours(opt('firstHour')); + var top = timePosition(d0, scrollDate) + 1; // +1 for the border + function scroll() { + slotScroller.scrollTop(top); + } + scroll(); + setTimeout(scroll, 0); // overrides any previous scroll state made by the browser + } + + + function afterRender() { // after the view has been freshly rendered and sized + resetScroll(); + } + + + + /* Slot/Day clicking and binding + -----------------------------------------------------------------------*/ + + + function dayBind(cells) { + cells.click(slotClick) + .mousedown(daySelectionMousedown); + } + + + function slotBind(cells) { + cells.click(slotClick) + .mousedown(slotSelectionMousedown); + } + + + function slotClick(ev) { + if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick + var col = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth)); + var date = cellToDate(0, col); + var rowMatch = this.parentNode.className.match(/fc-slot(\d+)/); // TODO: maybe use data + if (rowMatch) { + var mins = parseInt(rowMatch[1]) * opt('slotMinutes'); + var hours = Math.floor(mins/60); + date.setHours(hours); + date.setMinutes(mins%60 + minMinute); + trigger('dayClick', dayBodyCells[col], date, false, ev); + }else{ + trigger('dayClick', dayBodyCells[col], date, true, ev); + } + } + } + + + + /* Semi-transparent Overlay Helpers + -----------------------------------------------------*/ + // TODO: should be consolidated with BasicView's methods + + + function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive + + if (refreshCoordinateGrid) { + coordinateGrid.build(); + } + + var segments = rangeToSegments(overlayStart, overlayEnd); + + for (var i=0; i= 0) { + addMinutes(d, minMinute + slotIndex * snapMinutes); + } + return d; + } + + + // get the Y coordinate of the given time on the given day (both Date objects) + function timePosition(day, time) { // both date objects. day holds 00:00 of current day + day = cloneDate(day, true); + if (time < addMinutes(cloneDate(day), minMinute)) { + return 0; + } + if (time >= addMinutes(cloneDate(day), maxMinute)) { + return slotTable.height(); + } + var slotMinutes = opt('slotMinutes'), + minutes = time.getHours()*60 + time.getMinutes() - minMinute, + slotI = Math.floor(minutes / slotMinutes), + slotTop = slotTopCache[slotI]; + if (slotTop === undefined) { + slotTop = slotTopCache[slotI] = + slotTable.find('tr').eq(slotI).find('td div')[0].offsetTop; + // .eq() is faster than ":eq()" selector + // [0].offsetTop is faster than .position().top (do we really need this optimization?) + // a better optimization would be to cache all these divs + } + return Math.max(0, Math.round( + slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes) + )); + } + + + function getAllDayRow(index) { + return allDayRow; + } + + + function defaultEventEnd(event) { + var start = cloneDate(event.start); + if (event.allDay) { + return start; + } + return addMinutes(start, opt('defaultEventMinutes')); + } + + + + /* Selection + ---------------------------------------------------------------------------------*/ + + + function defaultSelectionEnd(startDate, allDay) { + if (allDay) { + return cloneDate(startDate); + } + return addMinutes(cloneDate(startDate), opt('slotMinutes')); + } + + + function renderSelection(startDate, endDate, allDay) { // only for all-day + if (allDay) { + if (opt('allDaySlot')) { + renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true); + } + }else{ + renderSlotSelection(startDate, endDate); + } + } + + + function renderSlotSelection(startDate, endDate) { + var helperOption = opt('selectHelper'); + coordinateGrid.build(); + if (helperOption) { + var col = dateToCell(startDate).col; + if (col >= 0 && col < colCnt) { // only works when times are on same day + var rect = coordinateGrid.rect(0, col, 0, col, slotContainer); // only for horizontal coords + var top = timePosition(startDate, startDate); + var bottom = timePosition(startDate, endDate); + if (bottom > top) { // protect against selections that are entirely before or after visible range + rect.top = top; + rect.height = bottom - top; + rect.left += 2; + rect.width -= 5; + if ($.isFunction(helperOption)) { + var helperRes = helperOption(startDate, endDate); + if (helperRes) { + rect.position = 'absolute'; + selectionHelper = $(helperRes) + .css(rect) + .appendTo(slotContainer); + } + }else{ + rect.isStart = true; // conside rect a "seg" now + rect.isEnd = true; // + selectionHelper = $(slotSegHtml( + { + title: '', + start: startDate, + end: endDate, + className: ['fc-select-helper'], + editable: false + }, + rect + )); + selectionHelper.css('opacity', opt('dragOpacity')); + } + if (selectionHelper) { + slotBind(selectionHelper); + slotContainer.append(selectionHelper); + setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended + setOuterHeight(selectionHelper, rect.height, true); + } + } + } + }else{ + renderSlotOverlay(startDate, endDate); + } + } + + + function clearSelection() { + clearOverlays(); + if (selectionHelper) { + selectionHelper.remove(); + selectionHelper = null; + } + } + + + function slotSelectionMousedown(ev) { + if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button + unselect(ev); + var dates; + hoverListener.start(function(cell, origCell) { + clearSelection(); + if (cell && cell.col == origCell.col && !getIsCellAllDay(cell)) { + var d1 = realCellToDate(origCell); + var d2 = realCellToDate(cell); + dates = [ + d1, + addMinutes(cloneDate(d1), snapMinutes), // calculate minutes depending on selection slot minutes + d2, + addMinutes(cloneDate(d2), snapMinutes) + ].sort(dateCompare); + renderSlotSelection(dates[0], dates[3]); + }else{ + dates = null; + } + }, ev); + $(document).one('mouseup', function(ev) { + hoverListener.stop(); + if (dates) { + if (+dates[0] == +dates[1]) { + reportDayClick(dates[0], false, ev); + } + reportSelection(dates[0], dates[3], false, ev); + } + }); + } + } + + + function reportDayClick(date, allDay, ev) { + trigger('dayClick', dayBodyCells[dateToCell(date).col], date, allDay, ev); + } + + + + /* External Dragging + --------------------------------------------------------------------------------*/ + + + function dragStart(_dragElement, ev, ui) { + hoverListener.start(function(cell) { + clearOverlays(); + if (cell) { + if (getIsCellAllDay(cell)) { + renderCellOverlay(cell.row, cell.col, cell.row, cell.col); + }else{ + var d1 = realCellToDate(cell); + var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes')); + renderSlotOverlay(d1, d2); + } + } + }, ev); + } + + + function dragStop(_dragElement, ev, ui) { + var cell = hoverListener.stop(); + clearOverlays(); + if (cell) { + trigger('drop', _dragElement, realCellToDate(cell), getIsCellAllDay(cell), ev, ui); + } + } + + +} + +;; + +function AgendaEventRenderer() { + var t = this; + + + // exports + t.renderEvents = renderEvents; + t.clearEvents = clearEvents; + t.slotSegHtml = slotSegHtml; + + + // imports + DayEventRenderer.call(t); + var opt = t.opt; + var trigger = t.trigger; + var isEventDraggable = t.isEventDraggable; + var isEventResizable = t.isEventResizable; + var eventEnd = t.eventEnd; + var eventElementHandlers = t.eventElementHandlers; + var setHeight = t.setHeight; + var getDaySegmentContainer = t.getDaySegmentContainer; + var getSlotSegmentContainer = t.getSlotSegmentContainer; + var getHoverListener = t.getHoverListener; + var getMaxMinute = t.getMaxMinute; + var getMinMinute = t.getMinMinute; + var timePosition = t.timePosition; + var getIsCellAllDay = t.getIsCellAllDay; + var colContentLeft = t.colContentLeft; + var colContentRight = t.colContentRight; + var cellToDate = t.cellToDate; + var getColCnt = t.getColCnt; + var getColWidth = t.getColWidth; + var getSnapHeight = t.getSnapHeight; + var getSnapMinutes = t.getSnapMinutes; + var getSlotContainer = t.getSlotContainer; + var reportEventElement = t.reportEventElement; + var showEvents = t.showEvents; + var hideEvents = t.hideEvents; + var eventDrop = t.eventDrop; + var eventResize = t.eventResize; + var renderDayOverlay = t.renderDayOverlay; + var clearOverlays = t.clearOverlays; + var renderDayEvents = t.renderDayEvents; + var calendar = t.calendar; + var formatDate = calendar.formatDate; + var formatDates = calendar.formatDates; + + + // overrides + t.draggableDayEvent = draggableDayEvent; + + + + /* Rendering + ----------------------------------------------------------------------------*/ + + + function renderEvents(events, modifiedEventId) { + var i, len=events.length, + dayEvents=[], + slotEvents=[]; + for (i=0; i start && eventStart < end) { + if (eventStart < start) { + segStart = cloneDate(start); + isStart = false; + }else{ + segStart = eventStart; + isStart = true; + } + if (eventEnd > end) { + segEnd = cloneDate(end); + isEnd = false; + }else{ + segEnd = eventEnd; + isEnd = true; + } + segs.push({ + event: event, + start: segStart, + end: segEnd, + isStart: isStart, + isEnd: isEnd + }); + } + } + return segs.sort(compareSlotSegs); + } + + + function slotEventEnd(event) { + if (event.end) { + return cloneDate(event.end); + }else{ + return addMinutes(cloneDate(event.start), opt('defaultEventMinutes')); + } + } + + + // renders events in the 'time slots' at the bottom + // TODO: when we refactor this, when user returns `false` eventRender, don't have empty space + // TODO: refactor will include using pixels to detect collisions instead of dates (handy for seg cmp) + + function renderSlotSegs(segs, modifiedEventId) { + + var i, segCnt=segs.length, seg, + event, + top, + bottom, + columnLeft, + columnRight, + columnWidth, + width, + left, + right, + html = '', + eventElements, + eventElement, + triggerRes, + titleElement, + height, + slotSegmentContainer = getSlotSegmentContainer(), + isRTL = opt('isRTL'); + + // calculate position/dimensions, create html + for (i=0; i" + + "
" + + "
" + + htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) + + "
" + + "
" + + htmlEscape(event.title || '') + + "
" + + "
" + + "
"; + if (seg.isEnd && isEventResizable(event)) { + html += + "
=
"; + } + html += + ""; + return html; + } + + + function bindSlotSeg(event, eventElement, seg) { + var timeElement = eventElement.find('div.fc-event-time'); + if (isEventDraggable(event)) { + draggableSlotEvent(event, eventElement, timeElement); + } + if (seg.isEnd && isEventResizable(event)) { + resizableSlotEvent(event, eventElement, timeElement); + } + eventElementHandlers(event, eventElement); + } + + + + /* Dragging + -----------------------------------------------------------------------------------*/ + + + // when event starts out FULL-DAY + // overrides DayEventRenderer's version because it needs to account for dragging elements + // to and from the slot area. + + function draggableDayEvent(event, eventElement, seg) { + var isStart = seg.isStart; + var origWidth; + var revert; + var allDay = true; + var dayDelta; + var hoverListener = getHoverListener(); + var colWidth = getColWidth(); + var snapHeight = getSnapHeight(); + var snapMinutes = getSnapMinutes(); + var minMinute = getMinMinute(); + eventElement.draggable({ + opacity: opt('dragOpacity', 'month'), // use whatever the month view was using + revertDuration: opt('dragRevertDuration'), + start: function(ev, ui) { + trigger('eventDragStart', eventElement, event, ev, ui); + hideEvents(event, eventElement); + origWidth = eventElement.width(); + hoverListener.start(function(cell, origCell) { + clearOverlays(); + if (cell) { + revert = false; + var origDate = cellToDate(0, origCell.col); + var date = cellToDate(0, cell.col); + dayDelta = dayDiff(date, origDate); + if (!cell.row) { + // on full-days + renderDayOverlay( + addDays(cloneDate(event.start), dayDelta), + addDays(exclEndDay(event), dayDelta) + ); + resetElement(); + }else{ + // mouse is over bottom slots + if (isStart) { + if (allDay) { + // convert event to temporary slot-event + eventElement.width(colWidth - 10); // don't use entire width + setOuterHeight( + eventElement, + snapHeight * Math.round( + (event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes')) / + snapMinutes + ) + ); + eventElement.draggable('option', 'grid', [colWidth, 1]); + allDay = false; + } + }else{ + revert = true; + } + } + revert = revert || (allDay && !dayDelta); + }else{ + resetElement(); + revert = true; + } + eventElement.draggable('option', 'revert', revert); + }, ev, 'drag'); + }, + stop: function(ev, ui) { + hoverListener.stop(); + clearOverlays(); + trigger('eventDragStop', eventElement, event, ev, ui); + if (revert) { + // hasn't moved or is out of bounds (draggable has already reverted) + resetElement(); + eventElement.css('filter', ''); // clear IE opacity side-effects + showEvents(event, eventElement); + }else{ + // changed! + var minuteDelta = 0; + if (!allDay) { + minuteDelta = Math.round((eventElement.offset().top - getSlotContainer().offset().top) / snapHeight) + * snapMinutes + + minMinute + - (event.start.getHours() * 60 + event.start.getMinutes()); + } + eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui); + } + } + }); + function resetElement() { + if (!allDay) { + eventElement + .width(origWidth) + .height('') + .draggable('option', 'grid', null); + allDay = true; + } + } + } + + + // when event starts out IN TIMESLOTS + + function draggableSlotEvent(event, eventElement, timeElement) { + var coordinateGrid = t.getCoordinateGrid(); + var colCnt = getColCnt(); + var colWidth = getColWidth(); + var snapHeight = getSnapHeight(); + var snapMinutes = getSnapMinutes(); + + // states + var origPosition; // original position of the element, not the mouse + var origCell; + var isInBounds, prevIsInBounds; + var isAllDay, prevIsAllDay; + var colDelta, prevColDelta; + var dayDelta; // derived from colDelta + var minuteDelta, prevMinuteDelta; + + eventElement.draggable({ + scroll: false, + grid: [ colWidth, snapHeight ], + axis: colCnt==1 ? 'y' : false, + opacity: opt('dragOpacity'), + revertDuration: opt('dragRevertDuration'), + start: function(ev, ui) { + + trigger('eventDragStart', eventElement, event, ev, ui); + hideEvents(event, eventElement); + + coordinateGrid.build(); + + // initialize states + origPosition = eventElement.position(); + origCell = coordinateGrid.cell(ev.pageX, ev.pageY); + isInBounds = prevIsInBounds = true; + isAllDay = prevIsAllDay = getIsCellAllDay(origCell); + colDelta = prevColDelta = 0; + dayDelta = 0; + minuteDelta = prevMinuteDelta = 0; + + }, + drag: function(ev, ui) { + + // NOTE: this `cell` value is only useful for determining in-bounds and all-day. + // Bad for anything else due to the discrepancy between the mouse position and the + // element position while snapping. (problem revealed in PR #55) + // + // PS- the problem exists for draggableDayEvent() when dragging an all-day event to a slot event. + // We should overhaul the dragging system and stop relying on jQuery UI. + var cell = coordinateGrid.cell(ev.pageX, ev.pageY); + + // update states + isInBounds = !!cell; + if (isInBounds) { + isAllDay = getIsCellAllDay(cell); + + // calculate column delta + colDelta = Math.round((ui.position.left - origPosition.left) / colWidth); + if (colDelta != prevColDelta) { + // calculate the day delta based off of the original clicked column and the column delta + var origDate = cellToDate(0, origCell.col); + var col = origCell.col + colDelta; + col = Math.max(0, col); + col = Math.min(colCnt-1, col); + var date = cellToDate(0, col); + dayDelta = dayDiff(date, origDate); + } + + // calculate minute delta (only if over slots) + if (!isAllDay) { + minuteDelta = Math.round((ui.position.top - origPosition.top) / snapHeight) * snapMinutes; + } + } + + // any state changes? + if ( + isInBounds != prevIsInBounds || + isAllDay != prevIsAllDay || + colDelta != prevColDelta || + minuteDelta != prevMinuteDelta + ) { + + updateUI(); + + // update previous states for next time + prevIsInBounds = isInBounds; + prevIsAllDay = isAllDay; + prevColDelta = colDelta; + prevMinuteDelta = minuteDelta; + } + + // if out-of-bounds, revert when done, and vice versa. + eventElement.draggable('option', 'revert', !isInBounds); + + }, + stop: function(ev, ui) { + + clearOverlays(); + trigger('eventDragStop', eventElement, event, ev, ui); + + if (isInBounds && (isAllDay || dayDelta || minuteDelta)) { // changed! + eventDrop(this, event, dayDelta, isAllDay ? 0 : minuteDelta, isAllDay, ev, ui); + } + else { // either no change or out-of-bounds (draggable has already reverted) + + // reset states for next time, and for updateUI() + isInBounds = true; + isAllDay = false; + colDelta = 0; + dayDelta = 0; + minuteDelta = 0; + + updateUI(); + eventElement.css('filter', ''); // clear IE opacity side-effects + + // sometimes fast drags make event revert to wrong position, so reset. + // also, if we dragged the element out of the area because of snapping, + // but the *mouse* is still in bounds, we need to reset the position. + eventElement.css(origPosition); + + showEvents(event, eventElement); + } + } + }); + + function updateUI() { + clearOverlays(); + if (isInBounds) { + if (isAllDay) { + timeElement.hide(); + eventElement.draggable('option', 'grid', null); // disable grid snapping + renderDayOverlay( + addDays(cloneDate(event.start), dayDelta), + addDays(exclEndDay(event), dayDelta) + ); + } + else { + updateTimeText(minuteDelta); + timeElement.css('display', ''); // show() was causing display=inline + eventElement.draggable('option', 'grid', [colWidth, snapHeight]); // re-enable grid snapping + } + } + } + + function updateTimeText(minuteDelta) { + var newStart = addMinutes(cloneDate(event.start), minuteDelta); + var newEnd; + if (event.end) { + newEnd = addMinutes(cloneDate(event.end), minuteDelta); + } + timeElement.text(formatDates(newStart, newEnd, opt('timeFormat'))); + } + + } + + + + /* Resizing + --------------------------------------------------------------------------------------*/ + + + function resizableSlotEvent(event, eventElement, timeElement) { + var snapDelta, prevSnapDelta; + var snapHeight = getSnapHeight(); + var snapMinutes = getSnapMinutes(); + eventElement.resizable({ + handles: { + s: '.ui-resizable-handle' + }, + grid: snapHeight, + start: function(ev, ui) { + snapDelta = prevSnapDelta = 0; + hideEvents(event, eventElement); + trigger('eventResizeStart', this, event, ev, ui); + }, + resize: function(ev, ui) { + // don't rely on ui.size.height, doesn't take grid into account + snapDelta = Math.round((Math.max(snapHeight, eventElement.height()) - ui.originalSize.height) / snapHeight); + if (snapDelta != prevSnapDelta) { + timeElement.text( + formatDates( + event.start, + (!snapDelta && !event.end) ? null : // no change, so don't display time range + addMinutes(eventEnd(event), snapMinutes*snapDelta), + opt('timeFormat') + ) + ); + prevSnapDelta = snapDelta; + } + }, + stop: function(ev, ui) { + trigger('eventResizeStop', this, event, ev, ui); + if (snapDelta) { + eventResize(this, event, 0, snapMinutes*snapDelta, ev, ui); + }else{ + showEvents(event, eventElement); + // BUG: if event was really short, need to put title back in span + } + } + }); + } + + +} + + + +/* Agenda Event Segment Utilities +-----------------------------------------------------------------------------*/ + + +// Sets the seg.backwardCoord and seg.forwardCoord on each segment and returns a new +// list in the order they should be placed into the DOM (an implicit z-index). +function placeSlotSegs(segs) { + var levels = buildSlotSegLevels(segs); + var level0 = levels[0]; + var i; + + computeForwardSlotSegs(levels); + + if (level0) { + + for (i=0; i") - .append( - $("") - .append(renderSection('left')) - .append(renderSection('center')) - .append(renderSection('right')) - ); - return element; - } - } - - - function destroy() { - element.remove(); - } - - - function renderSection(position) { - var e = $(""); - var buttonStr = options.header[position]; - if (buttonStr) { - $.each(buttonStr.split(' '), function(i) { - if (i > 0) { - e.append(""); - } - var prevButton; - $.each(this.split(','), function(j, buttonName) { - if (buttonName == 'title') { - e.append("

 

"); - if (prevButton) { - prevButton.addClass(tm + '-corner-right'); - } - prevButton = null; - }else{ - var buttonClick; - if (calendar[buttonName]) { - buttonClick = calendar[buttonName]; // calendar method - } - else if (fcViews[buttonName]) { - buttonClick = function() { - button.removeClass(tm + '-state-hover'); // forget why - calendar.changeView(buttonName); - }; - } - if (buttonClick) { - var icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null; // why are we using smartProperty here? - var text = smartProperty(options.buttonText, buttonName); // why are we using smartProperty here? - var button = $( - "" + - (icon ? - "" + - "" + - "" : - text - ) + - "" - ) - .click(function() { - if (!button.hasClass(tm + '-state-disabled')) { - buttonClick(); - } - }) - .mousedown(function() { - button - .not('.' + tm + '-state-active') - .not('.' + tm + '-state-disabled') - .addClass(tm + '-state-down'); - }) - .mouseup(function() { - button.removeClass(tm + '-state-down'); - }) - .hover( - function() { - button - .not('.' + tm + '-state-active') - .not('.' + tm + '-state-disabled') - .addClass(tm + '-state-hover'); - }, - function() { - button - .removeClass(tm + '-state-hover') - .removeClass(tm + '-state-down'); - } - ) - .appendTo(e); - disableTextSelection(button); - if (!prevButton) { - button.addClass(tm + '-corner-left'); - } - prevButton = button; - } - } - }); - if (prevButton) { - prevButton.addClass(tm + '-corner-right'); - } - }); - } - return e; - } - - - function updateTitle(html) { - element.find('h2') - .html(html); - } - - - function activateButton(buttonName) { - element.find('span.fc-button-' + buttonName) - .addClass(tm + '-state-active'); - } - - - function deactivateButton(buttonName) { - element.find('span.fc-button-' + buttonName) - .removeClass(tm + '-state-active'); - } - - - function disableButton(buttonName) { - element.find('span.fc-button-' + buttonName) - .addClass(tm + '-state-disabled'); - } - - - function enableButton(buttonName) { - element.find('span.fc-button-' + buttonName) - .removeClass(tm + '-state-disabled'); - } - - - } - - ;; - - fc.sourceNormalizers = []; - fc.sourceFetchers = []; - - var ajaxDefaults = { - dataType: 'json', - cache: false - }; - - var eventGUID = 1; - - - function EventManager(options, _sources) { - var t = this; - - - // exports - t.isFetchNeeded = isFetchNeeded; - t.fetchEvents = fetchEvents; - t.addEventSource = addEventSource; - t.removeEventSource = removeEventSource; - t.updateEvent = updateEvent; - t.renderEvent = renderEvent; - t.removeEvents = removeEvents; - t.clientEvents = clientEvents; - t.normalizeEvent = normalizeEvent; - - - // imports - var trigger = t.trigger; - var getView = t.getView; - var reportEvents = t.reportEvents; - - - // locals - var stickySource = { events: [] }; - var sources = [ stickySource ]; - var rangeStart, rangeEnd; - var currentFetchID = 0; - var pendingSourceCnt = 0; - var loadingLevel = 0; - var cache = []; - - - for (var i=0; i<_sources.length; i++) { - _addEventSource(_sources[i]); - } - - - - /* Fetching - -----------------------------------------------------------------------------*/ - - - function isFetchNeeded(start, end) { - return !rangeStart || start < rangeStart || end > rangeEnd; - } - - - function fetchEvents(start, end) { - rangeStart = start; - rangeEnd = end; - cache = []; - var fetchID = ++currentFetchID; - var len = sources.length; - pendingSourceCnt = len; - for (var i=0; i)), return null instead - return null; - } - - - function parseISO8601(s, ignoreTimezone) { // ignoreTimezone defaults to false - // derived from http://delete.me.uk/2005/03/iso8601.html - // TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html - var m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/); - if (!m) { - return null; - } - var date = new Date(m[1], 0, 1); - if (ignoreTimezone || !m[13]) { - var check = new Date(m[1], 0, 1, 9, 0); - if (m[3]) { - date.setMonth(m[3] - 1); - check.setMonth(m[3] - 1); - } - if (m[5]) { - date.setDate(m[5]); - check.setDate(m[5]); - } - fixDate(date, check); - if (m[7]) { - date.setHours(m[7]); - } - if (m[8]) { - date.setMinutes(m[8]); - } - if (m[10]) { - date.setSeconds(m[10]); - } - if (m[12]) { - date.setMilliseconds(Number("0." + m[12]) * 1000); - } - fixDate(date, check); - }else{ - date.setUTCFullYear( - m[1], - m[3] ? m[3] - 1 : 0, - m[5] || 1 - ); - date.setUTCHours( - m[7] || 0, - m[8] || 0, - m[10] || 0, - m[12] ? Number("0." + m[12]) * 1000 : 0 - ); - if (m[14]) { - var offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0); - offset *= m[15] == '-' ? 1 : -1; - date = new Date(+date + (offset * 60 * 1000)); - } - } - return date; - } - - - function parseTime(s) { // returns minutes since start of day - if (typeof s == 'number') { // an hour - return s * 60; - } - if (typeof s == 'object') { // a Date object - return s.getHours() * 60 + s.getMinutes(); - } - var m = s.match(/(\d+)(?::(\d+))?\s*(\w+)?/); - if (m) { - var h = parseInt(m[1], 10); - if (m[3]) { - h %= 12; - if (m[3].toLowerCase().charAt(0) == 'p') { - h += 12; - } - } - return h * 60 + (m[2] ? parseInt(m[2], 10) : 0); - } - } - - - - /* Date Formatting - -----------------------------------------------------------------------------*/ - // TODO: use same function formatDate(date, [date2], format, [options]) - - - function formatDate(date, format, options) { - return formatDates(date, null, format, options); - } - - - function formatDates(date1, date2, format, options) { - options = options || defaults; - var date = date1, - otherDate = date2, - i, len = format.length, c, - i2, formatter, - res = ''; - for (i=0; ii; i2--) { - if (formatter = dateFormatters[format.substring(i, i2)]) { - if (date) { - res += formatter(date, options); - } - i = i2 - 1; - break; - } - } - if (i2 == i) { - if (date) { - res += c; - } - } - } - } - return res; - }; - - - var dateFormatters = { - s : function(d) { return d.getSeconds() }, - ss : function(d) { return zeroPad(d.getSeconds()) }, - m : function(d) { return d.getMinutes() }, - mm : function(d) { return zeroPad(d.getMinutes()) }, - h : function(d) { return d.getHours() % 12 || 12 }, - hh : function(d) { return zeroPad(d.getHours() % 12 || 12) }, - H : function(d) { return d.getHours() }, - HH : function(d) { return zeroPad(d.getHours()) }, - d : function(d) { return d.getDate() }, - dd : function(d) { return zeroPad(d.getDate()) }, - ddd : function(d,o) { return o.dayNamesShort[d.getDay()] }, - dddd: function(d,o) { return o.dayNames[d.getDay()] }, - M : function(d) { return d.getMonth() + 1 }, - MM : function(d) { return zeroPad(d.getMonth() + 1) }, - MMM : function(d,o) { return o.monthNamesShort[d.getMonth()] }, - MMMM: function(d,o) { return o.monthNames[d.getMonth()] }, - yy : function(d) { return (d.getFullYear()+'').substring(2) }, - yyyy: function(d) { return d.getFullYear() }, - t : function(d) { return d.getHours() < 12 ? 'a' : 'p' }, - tt : function(d) { return d.getHours() < 12 ? 'am' : 'pm' }, - T : function(d) { return d.getHours() < 12 ? 'A' : 'P' }, - TT : function(d) { return d.getHours() < 12 ? 'AM' : 'PM' }, - u : function(d) { return formatDate(d, "yyyy-MM-dd'T'HH:mm:ss'Z'") }, - S : function(d) { - var date = d.getDate(); - if (date > 10 && date < 20) { - return 'th'; - } - return ['st', 'nd', 'rd'][date%10-1] || 'th'; - }, - w : function(d, o) { // local - return o.weekNumberCalculation(d); - }, - W : function(d) { // ISO - return iso8601Week(d); - } - }; - fc.dateFormatters = dateFormatters; - - - /* thanks jQuery UI (https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js) - * - * Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. - * @param date Date - the date to get the week for - * @return number - the number of the week within the year that contains this date - */ - function iso8601Week(date) { - var time; - var checkDate = new Date(date.getTime()); - - // Find Thursday of this week starting on Monday - checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); - - time = checkDate.getTime(); - checkDate.setMonth(0); // Compare with Jan 1 - checkDate.setDate(1); - return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; - } - - - ;; - - fc.applyAll = applyAll; - - - /* Event Date Math - -----------------------------------------------------------------------------*/ - - - function exclEndDay(event) { - if (event.end) { - return _exclEndDay(event.end, event.allDay); - }else{ - return addDays(cloneDate(event.start), 1); - } - } - - - function _exclEndDay(end, allDay) { - end = cloneDate(end); - return allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end); - } - - - function segCmp(a, b) { - return (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start); - } - - - function segsCollide(seg1, seg2) { - return seg1.end > seg2.start && seg1.start < seg2.end; - } - - - - /* Event Sorting - -----------------------------------------------------------------------------*/ - - - // event rendering utilities - function sliceSegs(events, visEventEnds, start, end) { - var segs = [], - i, len=events.length, event, - eventStart, eventEnd, - segStart, segEnd, - isStart, isEnd; - for (i=0; i start && eventStart < end) { - if (eventStart < start) { - segStart = cloneDate(start); - isStart = false; - }else{ - segStart = eventStart; - isStart = true; - } - if (eventEnd > end) { - segEnd = cloneDate(end); - isEnd = false; - }else{ - segEnd = eventEnd; - isEnd = true; - } - segs.push({ - event: event, - start: segStart, - end: segEnd, - isStart: isStart, - isEnd: isEnd, - msLength: segEnd - segStart - }); - } - } - return segs.sort(segCmp); - } - - - // event rendering calculation utilities - function stackSegs(segs) { - var levels = [], - i, len = segs.length, seg, - j, collide, k; - for (i=0; i=0; i--) { - res = obj[parts[i].toLowerCase()]; - if (res !== undefined) { - return res; - } - } - return obj['']; - } - - - function htmlEscape(s) { - return s.replace(/&/g, '&') - .replace(//g, '>') - .replace(/'/g, ''') - .replace(/"/g, '"') - .replace(/\n/g, '
'); - } - - - function cssKey(_element) { - return _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig, ''); - } - - - function disableTextSelection(element) { - element - .attr('unselectable', 'on') - .css('MozUserSelect', 'none') - .bind('selectstart.ui', function() { return false; }); - } - - - /* - function enableTextSelection(element) { - element - .attr('unselectable', 'off') - .css('MozUserSelect', '') - .unbind('selectstart.ui'); - } - */ - - - function markFirstLast(e) { - e.children() - .removeClass('fc-first fc-last') - .filter(':first-child') - .addClass('fc-first') - .end() - .filter(':last-child') - .addClass('fc-last'); - } - - - function setDayID(cell, date) { - cell.each(function(i, _cell) { - _cell.className = _cell.className.replace(/^fc-\w*/, 'fc-' + dayIDs[date.getDay()]); - // TODO: make a way that doesn't rely on order of classes - }); - } - - - function getSkinCss(event, opt) { - var source = event.source || {}; - var eventColor = event.color; - var sourceColor = source.color; - var optionColor = opt('eventColor'); - var backgroundColor = - event.backgroundColor || - eventColor || - source.backgroundColor || - sourceColor || - opt('eventBackgroundColor') || - optionColor; - var borderColor = - event.borderColor || - eventColor || - source.borderColor || - sourceColor || - opt('eventBorderColor') || - optionColor; - var textColor = - event.textColor || - source.textColor || - opt('eventTextColor'); - var statements = []; - if (backgroundColor) { - statements.push('background-color:' + backgroundColor); - } - if (borderColor) { - statements.push('border-color:' + borderColor); - } - if (textColor) { - statements.push('color:' + textColor); - } - return statements.join(';'); - } - - - function applyAll(functions, thisObj, args) { - if ($.isFunction(functions)) { - functions = [ functions ]; - } - if (functions) { - var i; - var ret; - for (i=0; i") - .appendTo(element); - } - - - - function buildTable(showNumbers) { - var html = ''; - var i, j; - var headerClass = tm + "-widget-header"; - var contentClass = tm + "-widget-content"; - var month = t.start.getMonth(); - var today = clearTime(new Date()); - var cellDate; // not to be confused with local function. TODO: better names - var cellClasses; - var cell; - - html += "" + - "" + - ""; - - if (showWeekNumbers) { - html += "" + - "" + - ""; - - for (i=0; i" + - "
" + - ""; - } - - for (j=0; j" + - "
"; - if (showNumbers) { - html += "
" + cellDate.getDate() + "
"; - } - html += "
" + - "
 
" + - "
" + - "
" + - ""; - } - - html += ""; - } - html += "
" + - "
"; - } - - for (i=0; i"; - } - - html += "
"; - - lockHeight(); // the unlock happens later, in setHeight()... - if (table) { - table.remove(); - } - table = $(html).appendTo(element); - - head = table.find('thead'); - headCells = head.find('.fc-day-header'); - body = table.find('tbody'); - bodyRows = body.find('tr'); - bodyCells = body.find('.fc-day'); - bodyFirstCells = bodyRows.find('td:first-child'); - bodyCellTopInners = bodyRows.eq(0).find('.fc-day-content > div'); - - markFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's - markFirstLast(bodyRows); // marks first+last td's - bodyRows.eq(0).addClass('fc-first'); - bodyRows.filter(':last').addClass('fc-last'); - - if (showWeekNumbers) { - head.find('.fc-week-number').text(weekNumberTitle); - } - - headCells.each(function(i, _cell) { - var date = indexDate(i); - $(_cell).text(formatDate(date, colFormat)); - }); - - if (showWeekNumbers) { - body.find('.fc-week-number > div').each(function(i, _cell) { - var weekStart = _cellDate(i, 0); - $(_cell).text(formatDate(weekStart, weekNumberFormat)); - }); - } - - bodyCells.each(function(i, _cell) { - var date = indexDate(i); - trigger('dayRender', t, date, $(_cell)); - }); - - dayBind(bodyCells); - } - - - - function setHeight(height) { - viewHeight = height; - - var bodyHeight = viewHeight - head.height(); - var rowHeight; - var rowHeightLast; - var cell; - - if (opt('weekMode') == 'variable') { - rowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6)); - }else{ - rowHeight = Math.floor(bodyHeight / rowCnt); - rowHeightLast = bodyHeight - rowHeight * (rowCnt-1); - } - - bodyFirstCells.each(function(i, _cell) { - if (i < rowCnt) { - cell = $(_cell); - setMinHeight( - cell.find('> div'), - (i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell) - ); - } - }); - - unlockHeight(); - } - - - function setWidth(width) { - viewWidth = width; - colContentPositions.clear(); - - weekNumberWidth = 0; - if (showWeekNumbers) { - weekNumberWidth = head.find('th.fc-week-number').outerWidth(); - } - - colWidth = Math.floor((viewWidth - weekNumberWidth) / colCnt); - setOuterWidth(headCells.slice(0, -1), colWidth); - } - - - - /* Day clicking and binding - -----------------------------------------------------------*/ - - - function dayBind(days) { - days.click(dayClick) - .mousedown(daySelectionMousedown); - } - - - function dayClick(ev) { - if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick - var date = parseISO8601($(this).data('date')); - trigger('dayClick', this, date, true, ev); - } - } - - - - /* Semi-transparent Overlay Helpers - ------------------------------------------------------*/ - - - function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive - if (refreshCoordinateGrid) { - coordinateGrid.build(); - } - var rowStart = cloneDate(t.visStart); - var rowEnd = addDays(cloneDate(rowStart), colCnt); - for (var i=0; i" + - "" + - ""; - - if (showWeekNumbers) { - s += ""; - } - else { - s += " "; - } - - for (i=0; i"; // fc- needed for setDayID - } - s += - " " + - "" + - "" + - "" + - "" + - " "; - for (i=0; i" + // fc- needed for setDayID - "
" + - "
" + - "
 
" + - "
" + - "
" + - ""; - } - s += - " " + - "" + - "" + - ""; - dayTable = $(s).appendTo(element); - dayHead = dayTable.find('thead'); - dayHeadCells = dayHead.find('th').slice(1, -1); - dayBody = dayTable.find('tbody'); - dayBodyCells = dayBody.find('td').slice(0, -1); - dayBodyCellInners = dayBodyCells.find('div.fc-day-content div'); - dayBodyFirstCell = dayBodyCells.eq(0); - dayBodyFirstCellStretcher = dayBodyFirstCell.find('> div'); - - markFirstLast(dayHead.add(dayHead.find('tr'))); - markFirstLast(dayBody.add(dayBody.find('tr'))); - - axisFirstCells = dayHead.find('th:first'); - gutterCells = dayTable.find('.fc-agenda-gutter'); - - slotLayer = - $("
") - .appendTo(element); - - if (opt('allDaySlot')) { - - daySegmentContainer = - $("
") - .appendTo(slotLayer); - - s = - "" + - "" + - "" + - "" + - "" + - "" + - "
" + opt('allDayText') + "" + - "
" + - "
 
"; - allDayTable = $(s).appendTo(slotLayer); - allDayRow = allDayTable.find('tr'); - - dayBind(allDayRow.find('td')); - - axisFirstCells = axisFirstCells.add(allDayTable.find('th:first')); - gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter')); - - slotLayer.append( - "
" + - "
" + - "
" - ); - - }else{ - - daySegmentContainer = $([]); // in jQuery 1.4, we can just do $() - - } - - slotScroller = - $("
") - .appendTo(slotLayer); - - slotContent = - $("
") - .appendTo(slotScroller); - - slotSegmentContainer = - $("
") - .appendTo(slotContent); - - s = - "" + - ""; - d = zeroDate(); - maxd = addMinutes(cloneDate(d), maxMinute); - addMinutes(d, minMinute); - slotCnt = 0; - for (i=0; d < maxd; i++) { - minutes = d.getMinutes(); - s += - "" + - "" + - "" + - ""; - addMinutes(d, opt('slotMinutes')); - slotCnt++; - } - s += - "" + - "
" + - ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') + - "" + - "
 
" + - "
"; - slotTable = $(s).appendTo(slotContent); - slotTableFirstInner = slotTable.find('div:first'); - - slotBind(slotTable.find('td')); - - axisFirstCells = axisFirstCells.add(slotTable.find('th:first')); - } - - - - function updateCells() { - var i; - var headCell; - var bodyCell; - var date; - var today = clearTime(new Date()); - - if (showWeekNumbers) { - var weekText = formatDate(colDate(0), weekNumberFormat); - if (rtl) { - weekText = weekText + weekNumberTitle; - } - else { - weekText = weekNumberTitle + weekText; - } - dayHead.find('.fc-week-number').text(weekText); - } - - for (i=0; i= 0) { - addMinutes(d, minMinute + slotIndex * snapMinutes); - } - return d; - } - - - function colDate(col) { // returns dates with 00:00:00 - return addDays(cloneDate(t.visStart), col*dis+dit); - } - - - function cellIsAllDay(cell) { - return opt('allDaySlot') && !cell.row; - } - - - function dayOfWeekCol(dayOfWeek) { - return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt)*dis+dit; - } - - - - - // get the Y coordinate of the given time on the given day (both Date objects) - function timePosition(day, time) { // both date objects. day holds 00:00 of current day - day = cloneDate(day, true); - if (time < addMinutes(cloneDate(day), minMinute)) { - return 0; - } - if (time >= addMinutes(cloneDate(day), maxMinute)) { - return slotTable.height(); - } - var slotMinutes = opt('slotMinutes'), - minutes = time.getHours()*60 + time.getMinutes() - minMinute, - slotI = Math.floor(minutes / slotMinutes), - slotTop = slotTopCache[slotI]; - if (slotTop === undefined) { - slotTop = slotTopCache[slotI] = slotTable.find('tr:eq(' + slotI + ') td div')[0].offsetTop; //.position().top; // need this optimization??? - } - return Math.max(0, Math.round( - slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes) - )); - } - - - function allDayBounds() { - return { - left: axisWidth, - right: viewWidth - gutterWidth - } - } - - - function getAllDayRow(index) { - return allDayRow; - } - - - function defaultEventEnd(event) { - var start = cloneDate(event.start); - if (event.allDay) { - return start; - } - return addMinutes(start, opt('defaultEventMinutes')); - } - - - - /* Selection - ---------------------------------------------------------------------------------*/ - - - function defaultSelectionEnd(startDate, allDay) { - if (allDay) { - return cloneDate(startDate); - } - return addMinutes(cloneDate(startDate), opt('slotMinutes')); - } - - - function renderSelection(startDate, endDate, allDay) { // only for all-day - if (allDay) { - if (opt('allDaySlot')) { - renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true); - } - }else{ - renderSlotSelection(startDate, endDate); - } - } - - - function renderSlotSelection(startDate, endDate) { - var helperOption = opt('selectHelper'); - coordinateGrid.build(); - if (helperOption) { - var col = dayDiff(startDate, t.visStart) * dis + dit; - if (col >= 0 && col < colCnt) { // only works when times are on same day - var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only for horizontal coords - var top = timePosition(startDate, startDate); - var bottom = timePosition(startDate, endDate); - if (bottom > top) { // protect against selections that are entirely before or after visible range - rect.top = top; - rect.height = bottom - top; - rect.left += 2; - rect.width -= 5; - if ($.isFunction(helperOption)) { - var helperRes = helperOption(startDate, endDate); - if (helperRes) { - rect.position = 'absolute'; - rect.zIndex = 8; - selectionHelper = $(helperRes) - .css(rect) - .appendTo(slotContent); - } - }else{ - rect.isStart = true; // conside rect a "seg" now - rect.isEnd = true; // - selectionHelper = $(slotSegHtml( - { - title: '', - start: startDate, - end: endDate, - className: ['fc-select-helper'], - editable: false - }, - rect - )); - selectionHelper.css('opacity', opt('dragOpacity')); - } - if (selectionHelper) { - slotBind(selectionHelper); - slotContent.append(selectionHelper); - setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended - setOuterHeight(selectionHelper, rect.height, true); - } - } - } - }else{ - renderSlotOverlay(startDate, endDate); - } - } - - - function clearSelection() { - clearOverlays(); - if (selectionHelper) { - selectionHelper.remove(); - selectionHelper = null; - } - } - - - function slotSelectionMousedown(ev) { - if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button - unselect(ev); - var dates; - hoverListener.start(function(cell, origCell) { - clearSelection(); - if (cell && cell.col == origCell.col && !cellIsAllDay(cell)) { - var d1 = cellDate(origCell); - var d2 = cellDate(cell); - dates = [ - d1, - addMinutes(cloneDate(d1), snapMinutes), // calculate minutes depending on selection slot minutes - d2, - addMinutes(cloneDate(d2), snapMinutes) - ].sort(cmp); - renderSlotSelection(dates[0], dates[3]); - }else{ - dates = null; - } - }, ev); - $(document).one('mouseup', function(ev) { - hoverListener.stop(); - if (dates) { - if (+dates[0] == +dates[1]) { - reportDayClick(dates[0], false, ev); - } - reportSelection(dates[0], dates[3], false, ev); - } - }); - } - } - - - function reportDayClick(date, allDay, ev) { - trigger('dayClick', dayBodyCells[dayOfWeekCol(date.getDay())], date, allDay, ev); - } - - - - /* External Dragging - --------------------------------------------------------------------------------*/ - - - function dragStart(_dragElement, ev, ui) { - hoverListener.start(function(cell) { - clearOverlays(); - if (cell) { - if (cellIsAllDay(cell)) { - renderCellOverlay(cell.row, cell.col, cell.row, cell.col); - }else{ - var d1 = cellDate(cell); - var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes')); - renderSlotOverlay(d1, d2); - } - } - }, ev); - } - - - function dragStop(_dragElement, ev, ui) { - var cell = hoverListener.stop(); - clearOverlays(); - if (cell) { - trigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui); - } - } - - - } - - ;; - - function AgendaEventRenderer() { - var t = this; - - - // exports - t.renderEvents = renderEvents; - t.compileDaySegs = compileDaySegs; // for DayEventRenderer - t.clearEvents = clearEvents; - t.slotSegHtml = slotSegHtml; - t.bindDaySeg = bindDaySeg; - - - // imports - DayEventRenderer.call(t); - var opt = t.opt; - var trigger = t.trigger; - //var setOverflowHidden = t.setOverflowHidden; - var isEventDraggable = t.isEventDraggable; - var isEventResizable = t.isEventResizable; - var eventEnd = t.eventEnd; - var reportEvents = t.reportEvents; - var reportEventClear = t.reportEventClear; - var eventElementHandlers = t.eventElementHandlers; - var setHeight = t.setHeight; - var getDaySegmentContainer = t.getDaySegmentContainer; - var getSlotSegmentContainer = t.getSlotSegmentContainer; - var getHoverListener = t.getHoverListener; - var getMaxMinute = t.getMaxMinute; - var getMinMinute = t.getMinMinute; - var timePosition = t.timePosition; - var colContentLeft = t.colContentLeft; - var colContentRight = t.colContentRight; - var renderDaySegs = t.renderDaySegs; - var resizableDayEvent = t.resizableDayEvent; // TODO: streamline binding architecture - var getColCnt = t.getColCnt; - var getColWidth = t.getColWidth; - var getSnapHeight = t.getSnapHeight; - var getSnapMinutes = t.getSnapMinutes; - var getBodyContent = t.getBodyContent; - var reportEventElement = t.reportEventElement; - var showEvents = t.showEvents; - var hideEvents = t.hideEvents; - var eventDrop = t.eventDrop; - var eventResize = t.eventResize; - var renderDayOverlay = t.renderDayOverlay; - var clearOverlays = t.clearOverlays; - var calendar = t.calendar; - var formatDate = calendar.formatDate; - var formatDates = calendar.formatDates; - - - - /* Rendering - ----------------------------------------------------------------------------*/ - - - function renderEvents(events, modifiedEventId) { - reportEvents(events); - var i, len=events.length, - dayEvents=[], - slotEvents=[]; - for (i=0; i" + - "
" + - "
" + - htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) + - "
" + - "
" + - htmlEscape(event.title) + - "
" + - "
" + - "
"; - if (seg.isEnd && isEventResizable(event)) { - html += - "
=
"; - } - html += - ""; - return html; - } - - - function bindDaySeg(event, eventElement, seg) { - if (isEventDraggable(event)) { - draggableDayEvent(event, eventElement, seg.isStart); - } - if (seg.isEnd && isEventResizable(event)) { - resizableDayEvent(event, eventElement, seg); - } - eventElementHandlers(event, eventElement); - // needs to be after, because resizableDayEvent might stopImmediatePropagation on click - } - - - function bindSlotSeg(event, eventElement, seg) { - var timeElement = eventElement.find('div.fc-event-time'); - if (isEventDraggable(event)) { - draggableSlotEvent(event, eventElement, timeElement); - } - if (seg.isEnd && isEventResizable(event)) { - resizableSlotEvent(event, eventElement, timeElement); - } - eventElementHandlers(event, eventElement); - } - - - - /* Dragging - -----------------------------------------------------------------------------------*/ - - - // when event starts out FULL-DAY - - function draggableDayEvent(event, eventElement, isStart) { - var origWidth; - var revert; - var allDay=true; - var dayDelta; - var dis = opt('isRTL') ? -1 : 1; - var hoverListener = getHoverListener(); - var colWidth = getColWidth(); - var snapHeight = getSnapHeight(); - var snapMinutes = getSnapMinutes(); - var minMinute = getMinMinute(); - eventElement.draggable({ - zIndex: 9, - opacity: opt('dragOpacity', 'month'), // use whatever the month view was using - revertDuration: opt('dragRevertDuration'), - start: function(ev, ui) { - trigger('eventDragStart', eventElement, event, ev, ui); - hideEvents(event, eventElement); - origWidth = eventElement.width(); - hoverListener.start(function(cell, origCell, rowDelta, colDelta) { - clearOverlays(); - if (cell) { - //setOverflowHidden(true); - revert = false; - dayDelta = colDelta * dis; - if (!cell.row) { - // on full-days - renderDayOverlay( - addDays(cloneDate(event.start), dayDelta), - addDays(exclEndDay(event), dayDelta) - ); - resetElement(); - }else{ - // mouse is over bottom slots - if (isStart) { - if (allDay) { - // convert event to temporary slot-event - eventElement.width(colWidth - 10); // don't use entire width - setOuterHeight( - eventElement, - snapHeight * Math.round( - (event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes')) / - snapMinutes - ) - ); - eventElement.draggable('option', 'grid', [colWidth, 1]); - allDay = false; - } - }else{ - revert = true; - } - } - revert = revert || (allDay && !dayDelta); - }else{ - resetElement(); - //setOverflowHidden(false); - revert = true; - } - eventElement.draggable('option', 'revert', revert); - }, ev, 'drag'); - }, - stop: function(ev, ui) { - hoverListener.stop(); - clearOverlays(); - trigger('eventDragStop', eventElement, event, ev, ui); - if (revert) { - // hasn't moved or is out of bounds (draggable has already reverted) - resetElement(); - eventElement.css('filter', ''); // clear IE opacity side-effects - showEvents(event, eventElement); - }else{ - // changed! - var minuteDelta = 0; - if (!allDay) { - minuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / snapHeight) - * snapMinutes - + minMinute - - (event.start.getHours() * 60 + event.start.getMinutes()); - } - eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui); - } - //setOverflowHidden(false); - } - }); - function resetElement() { - if (!allDay) { - eventElement - .width(origWidth) - .height('') - .draggable('option', 'grid', null); - allDay = true; - } - } - } - - - // when event starts out IN TIMESLOTS - - function draggableSlotEvent(event, eventElement, timeElement) { - var origPosition; - var allDay=false; - var dayDelta; - var minuteDelta; - var prevMinuteDelta; - var dis = opt('isRTL') ? -1 : 1; - var hoverListener = getHoverListener(); - var colCnt = getColCnt(); - var colWidth = getColWidth(); - var snapHeight = getSnapHeight(); - var snapMinutes = getSnapMinutes(); - eventElement.draggable({ - zIndex: 9, - scroll: false, - grid: [colWidth, snapHeight], - axis: colCnt==1 ? 'y' : false, - opacity: opt('dragOpacity'), - revertDuration: opt('dragRevertDuration'), - start: function(ev, ui) { - trigger('eventDragStart', eventElement, event, ev, ui); - hideEvents(event, eventElement); - origPosition = eventElement.position(); - minuteDelta = prevMinuteDelta = 0; - hoverListener.start(function(cell, origCell, rowDelta, colDelta) { - eventElement.draggable('option', 'revert', !cell); - clearOverlays(); - if (cell) { - dayDelta = colDelta * dis; - if (opt('allDaySlot') && !cell.row) { - // over full days - if (!allDay) { - // convert to temporary all-day event - allDay = true; - timeElement.hide(); - eventElement.draggable('option', 'grid', null); - } - renderDayOverlay( - addDays(cloneDate(event.start), dayDelta), - addDays(exclEndDay(event), dayDelta) - ); - }else{ - // on slots - resetElement(); - } - } - }, ev, 'drag'); - }, - drag: function(ev, ui) { - minuteDelta = Math.round((ui.position.top - origPosition.top) / snapHeight) * snapMinutes; - if (minuteDelta != prevMinuteDelta) { - if (!allDay) { - updateTimeText(minuteDelta); - } - prevMinuteDelta = minuteDelta; - } - }, - stop: function(ev, ui) { - var cell = hoverListener.stop(); - clearOverlays(); - trigger('eventDragStop', eventElement, event, ev, ui); - if (cell && (dayDelta || minuteDelta || allDay)) { - // changed! - eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui); - }else{ - // either no change or out-of-bounds (draggable has already reverted) - resetElement(); - eventElement.css('filter', ''); // clear IE opacity side-effects - eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position - updateTimeText(0); - showEvents(event, eventElement); - } - } - }); - function updateTimeText(minuteDelta) { - var newStart = addMinutes(cloneDate(event.start), minuteDelta); - var newEnd; - if (event.end) { - newEnd = addMinutes(cloneDate(event.end), minuteDelta); - } - timeElement.text(formatDates(newStart, newEnd, opt('timeFormat'))); - } - function resetElement() { - // convert back to original slot-event - if (allDay) { - timeElement.css('display', ''); // show() was causing display=inline - eventElement.draggable('option', 'grid', [colWidth, snapHeight]); - allDay = false; - } - } - } - - - - /* Resizing - --------------------------------------------------------------------------------------*/ - - - function resizableSlotEvent(event, eventElement, timeElement) { - var snapDelta, prevSnapDelta; - var snapHeight = getSnapHeight(); - var snapMinutes = getSnapMinutes(); - eventElement.resizable({ - handles: { - s: '.ui-resizable-handle' - }, - grid: snapHeight, - start: function(ev, ui) { - snapDelta = prevSnapDelta = 0; - hideEvents(event, eventElement); - eventElement.css('z-index', 9); - trigger('eventResizeStart', this, event, ev, ui); - }, - resize: function(ev, ui) { - // don't rely on ui.size.height, doesn't take grid into account - snapDelta = Math.round((Math.max(snapHeight, eventElement.height()) - ui.originalSize.height) / snapHeight); - if (snapDelta != prevSnapDelta) { - timeElement.text( - formatDates( - event.start, - (!snapDelta && !event.end) ? null : // no change, so don't display time range - addMinutes(eventEnd(event), snapMinutes*snapDelta), - opt('timeFormat') - ) - ); - prevSnapDelta = snapDelta; - } - }, - stop: function(ev, ui) { - trigger('eventResizeStop', this, event, ev, ui); - if (snapDelta) { - eventResize(this, event, 0, snapMinutes*snapDelta, ev, ui); - }else{ - eventElement.css('z-index', 8); - showEvents(event, eventElement); - // BUG: if event was really short, need to put title back in span - } - } - }); - } - - - } - - - function countForwardSegs(levels) { - var i, j, k, level, segForward, segBack; - for (i=levels.length-1; i>0; i--) { - level = levels[i]; - for (j=0; j"); - var elements; - var segmentContainer = getDaySegmentContainer(); - var i; - var segCnt = segs.length; - var element; - tempContainer[0].innerHTML = daySegHTML(segs); // faster than .html() - elements = tempContainer.children(); - segmentContainer.append(elements); - daySegElementResolve(segs, elements); - daySegCalcHSides(segs); - daySegSetWidths(segs); - daySegCalcHeights(segs); - daySegSetTops(segs, getRowTops(getRowDivs())); - elements = []; - for (i=0; i" + - "
"; - if (!event.allDay && seg.isStart) { - html += - "" + - htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) + - ""; - } - html += - "" + htmlEscape(event.title) + "" + - "
"; - if (seg.isEnd && isEventResizable(event)) { - html += - "
" + - "   " + // makes hit area a lot better for IE6/7 - "
"; - } - html += - ""; - seg.left = left; - seg.outerWidth = right - left; - seg.startCol = leftCol; - seg.endCol = rightCol + 1; // needs to be exclusive - } - return html; - } - - - function daySegElementResolve(segs, elements) { // sets seg.element - var i; - var segCnt = segs.length; - var seg; - var event; - var element; - var triggerRes; - for (i=0; i div'); // optimal selector? - } - return rowDivs; - } - - - function getRowTops(rowDivs) { - var i; - var rowCnt = rowDivs.length; - var tops = []; - for (i=0; i selection for IE - element - .mousedown(function(ev) { // prevent native selection for others - ev.preventDefault(); - }) - .click(function(ev) { - if (isResizing) { - ev.preventDefault(); // prevent link from being visited (only method that worked in IE6) - ev.stopImmediatePropagation(); // prevent fullcalendar eventClick handler from being called - // (eventElementHandlers needs to be bound after resizableDayEvent) - } - }); - - handle.mousedown(function(ev) { - if (ev.which != 1) { - return; // needs to be left mouse button - } - isResizing = true; - var hoverListener = t.getHoverListener(); - var rowCnt = getRowCnt(); - var colCnt = getColCnt(); - var dis = rtl ? -1 : 1; - var dit = rtl ? colCnt-1 : 0; - var elementTop = element.css('top'); - var dayDelta; - var helpers; - var eventCopy = $.extend({}, event); - var minCell = dateCell(event.start); - clearSelection(); - $('body') - .css('cursor', direction + '-resize') - .one('mouseup', mouseup); - trigger('eventResizeStart', this, event, ev); - hoverListener.start(function(cell, origCell) { - if (cell) { - var r = Math.max(minCell.row, cell.row); - var c = cell.col; - if (rowCnt == 1) { - r = 0; // hack for all-day area in agenda views - } - if (r == minCell.row) { - if (rtl) { - c = Math.min(minCell.col, c); - }else{ - c = Math.max(minCell.col, c); - } - } - dayDelta = (r*7 + c*dis+dit) - (origCell.row*7 + origCell.col*dis+dit); - var newEnd = addDays(eventEnd(event), dayDelta, true); - if (dayDelta) { - eventCopy.end = newEnd; - var oldHelpers = helpers; - helpers = renderTempDaySegs(compileDaySegs([eventCopy]), seg.row, elementTop); - helpers.find('*').css('cursor', direction + '-resize'); - if (oldHelpers) { - oldHelpers.remove(); - } - hideEvents(event); - }else{ - if (helpers) { - showEvents(event); - helpers.remove(); - helpers = null; - } - } - clearOverlays(); - renderDayOverlay(event.start, addDays(cloneDate(newEnd), 1)); // coordinate grid already rebuild at hoverListener.start - } - }, ev); - - function mouseup(ev) { - trigger('eventResizeStop', this, event, ev); - $('body').css('cursor', ''); - hoverListener.stop(); - clearOverlays(); - if (dayDelta) { - eventResize(this, event, dayDelta, 0, ev); - // event redraw will clear helpers - } - // otherwise, the drag handler already restored the old events - - setTimeout(function() { // make this happen after the element's click event - isResizing = false; - },0); - } - - }); - } - - - } - - ;; - - //BUG: unselect needs to be triggered when events are dragged+dropped - - function SelectionManager() { - var t = this; - - - // exports - t.select = select; - t.unselect = unselect; - t.reportSelection = reportSelection; - t.daySelectionMousedown = daySelectionMousedown; - - - // imports - var opt = t.opt; - var trigger = t.trigger; - var defaultSelectionEnd = t.defaultSelectionEnd; - var renderSelection = t.renderSelection; - var clearSelection = t.clearSelection; - - - // locals - var selected = false; - - - - // unselectAuto - if (opt('selectable') && opt('unselectAuto')) { - $(document).mousedown(function(ev) { - var ignore = opt('unselectCancel'); - if (ignore) { - if ($(ev.target).parents(ignore).length) { // could be optimized to stop after first match - return; - } - } - unselect(ev); - }); - } - - - function select(startDate, endDate, allDay) { - unselect(); - if (!endDate) { - endDate = defaultSelectionEnd(startDate, allDay); - } - renderSelection(startDate, endDate, allDay); - reportSelection(startDate, endDate, allDay); - } - - - function unselect(ev) { - if (selected) { - selected = false; - clearSelection(); - trigger('unselect', null, ev); - } - } - - - function reportSelection(startDate, endDate, allDay, ev) { - selected = true; - trigger('select', null, startDate, endDate, allDay, ev); - } - - - function daySelectionMousedown(ev) { // not really a generic manager method, oh well - var cellDate = t.cellDate; - var cellIsAllDay = t.cellIsAllDay; - var hoverListener = t.getHoverListener(); - var reportDayClick = t.reportDayClick; // this is hacky and sort of weird - if (ev.which == 1 && opt('selectable')) { // which==1 means left mouse button - unselect(ev); - var _mousedownElement = this; - var dates; - hoverListener.start(function(cell, origCell) { // TODO: maybe put cellDate/cellIsAllDay info in cell - clearSelection(); - if (cell && cellIsAllDay(cell)) { - dates = [ cellDate(origCell), cellDate(cell) ].sort(cmp); - renderSelection(dates[0], dates[1], true); - }else{ - dates = null; - } - }, ev); - $(document).one('mouseup', function(ev) { - hoverListener.stop(); - if (dates) { - if (+dates[0] == +dates[1]) { - reportDayClick(dates[0], true, ev); - } - reportSelection(dates[0], dates[1], true, ev); - } - }); - } - } - - - } - - ;; - - function OverlayManager() { - var t = this; - - - // exports - t.renderOverlay = renderOverlay; - t.clearOverlays = clearOverlays; - - - // locals - var usedOverlays = []; - var unusedOverlays = []; - - - function renderOverlay(rect, parent) { - var e = unusedOverlays.shift(); - if (!e) { - e = $("
"); - } - if (e[0].parentNode != parent[0]) { - e.appendTo(parent); - } - usedOverlays.push(e.css(rect).show()); - return e; - } - - - function clearOverlays() { - var e; - while (e = usedOverlays.shift()) { - unusedOverlays.push(e.hide().unbind()); - } - } - - - } - - ;; - - function CoordinateGrid(buildFunc) { - - var t = this; - var rows; - var cols; - - - t.build = function() { - rows = []; - cols = []; - buildFunc(rows, cols); - }; - - - t.cell = function(x, y) { - var rowCnt = rows.length; - var colCnt = cols.length; - var i, r=-1, c=-1; - for (i=0; i= rows[i][0] && y < rows[i][1]) { - r = i; - break; - } - } - for (i=0; i= cols[i][0] && x < cols[i][1]) { - c = i; - break; - } - } - return (r>=0 && c>=0) ? { row:r, col:c } : null; - }; - - - t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive - var origin = originElement.offset(); - return { - top: rows[row0][0] - origin.top, - left: cols[col0][0] - origin.left, - width: cols[col1][1] - cols[col0][0], - height: rows[row1][1] - rows[row0][0] - }; - }; - - } - - ;; - - function HoverListener(coordinateGrid) { - - - var t = this; - var bindType; - var change; - var firstCell; - var cell; - - - t.start = function(_change, ev, _bindType) { - change = _change; - firstCell = cell = null; - coordinateGrid.build(); - mouse(ev); - bindType = _bindType || 'mousemove'; - $(document).bind(bindType, mouse); - }; - - - function mouse(ev) { - _fixUIEvent(ev); // see below - var newCell = coordinateGrid.cell(ev.pageX, ev.pageY); - if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) { - if (newCell) { - if (!firstCell) { - firstCell = newCell; - } - change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col); - }else{ - change(newCell, firstCell); - } - cell = newCell; - } - } - - - t.stop = function() { - $(document).unbind(bindType, mouse); - return cell; - }; - - - } - - - - // this fix was only necessary for jQuery UI 1.8.16 (and jQuery 1.7 or 1.7.1) - // upgrading to jQuery UI 1.8.17 (and using either jQuery 1.7 or 1.7.1) fixed the problem - // but keep this in here for 1.8.16 users - // and maybe remove it down the line - - function _fixUIEvent(event) { // for issue 1168 - if (event.pageX === undefined) { - event.pageX = event.originalEvent.pageX; - event.pageY = event.originalEvent.pageY; - } - } - ;; - - function HorizontalPositionCache(getElement) { - - var t = this, - elements = {}, - lefts = {}, - rights = {}; - - function e(i) { - return elements[i] = elements[i] || getElement(i); - } - - t.left = function(i) { - return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i]; - }; - - t.right = function(i) { - return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i]; - }; - - t.clear = function() { - elements = {}; - lefts = {}; - rights = {}; - }; - - } - - ;; + seg.forwardPressure = forwardPressure; + } +} + + +// Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range +// from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and +// seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left. +// +// The segment might be part of a "series", which means consecutive segments with the same pressure +// who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of +// segments behind this one in the current series, and `seriesBackwardCoord` is the starting +// coordinate of the first segment in the series. +function computeSlotSegCoords(seg, seriesBackwardPressure, seriesBackwardCoord) { + var forwardSegs = seg.forwardSegs; + var i; + + if (seg.forwardCoord === undefined) { // not already computed + + if (!forwardSegs.length) { + + // if there are no forward segments, this segment should butt up against the edge + seg.forwardCoord = 1; + } + else { + + // sort highest pressure first + forwardSegs.sort(compareForwardSlotSegs); + + // this segment's forwardCoord will be calculated from the backwardCoord of the + // highest-pressure forward segment. + computeSlotSegCoords(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord); + seg.forwardCoord = forwardSegs[0].backwardCoord; + } + + // calculate the backwardCoord from the forwardCoord. consider the series + seg.backwardCoord = seg.forwardCoord - + (seg.forwardCoord - seriesBackwardCoord) / // available width for series + (seriesBackwardPressure + 1); // # of segments in the series + + // use this segment's coordinates to computed the coordinates of the less-pressurized + // forward segments + for (i=0; i seg2.start && seg1.start < seg2.end; +} + + +// A cmp function for determining which forward segment to rely on more when computing coordinates. +function compareForwardSlotSegs(seg1, seg2) { + // put higher-pressure first + return seg2.forwardPressure - seg1.forwardPressure || + // put segments that are closer to initial edge first (and favor ones with no coords yet) + (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) || + // do normal sorting... + compareSlotSegs(seg1, seg2); +} + + +// A cmp function for determining which segment should be closer to the initial edge +// (the left edge on a left-to-right calendar). +function compareSlotSegs(seg1, seg2) { + return seg1.start - seg2.start || // earlier start time goes first + (seg2.end - seg2.start) - (seg1.end - seg1.start) || // tie? longer-duration goes first + (seg1.event.title || '').localeCompare(seg2.event.title); // tie? alphabetically by title +} + + +;; + + +function View(element, calendar, viewName) { + var t = this; + + + // exports + t.element = element; + t.calendar = calendar; + t.name = viewName; + t.opt = opt; + t.trigger = trigger; + t.isEventDraggable = isEventDraggable; + t.isEventResizable = isEventResizable; + t.setEventData = setEventData; + t.clearEventData = clearEventData; + t.eventEnd = eventEnd; + t.reportEventElement = reportEventElement; + t.triggerEventDestroy = triggerEventDestroy; + t.eventElementHandlers = eventElementHandlers; + t.showEvents = showEvents; + t.hideEvents = hideEvents; + t.eventDrop = eventDrop; + t.eventResize = eventResize; + // t.title + // t.start, t.end + // t.visStart, t.visEnd + + + // imports + var defaultEventEnd = t.defaultEventEnd; + var normalizeEvent = calendar.normalizeEvent; // in EventManager + var reportEventChange = calendar.reportEventChange; + + + // locals + var eventsByID = {}; // eventID mapped to array of events (there can be multiple b/c of repeating events) + var eventElementsByID = {}; // eventID mapped to array of jQuery elements + var eventElementCouples = []; // array of objects, { event, element } // TODO: unify with segment system + var options = calendar.options; + + + + function opt(name, viewNameOverride) { + var v = options[name]; + if ($.isPlainObject(v)) { + return smartProperty(v, viewNameOverride || viewName); + } + return v; + } + + + function trigger(name, thisObj) { + return calendar.trigger.apply( + calendar, + [name, thisObj || t].concat(Array.prototype.slice.call(arguments, 2), [t]) + ); + } + + + + /* Event Editable Boolean Calculations + ------------------------------------------------------------------------------*/ + + + function isEventDraggable(event) { + var source = event.source || {}; + return firstDefined( + event.startEditable, + source.startEditable, + opt('eventStartEditable'), + event.editable, + source.editable, + opt('editable') + ) + && !opt('disableDragging'); // deprecated + } + + + function isEventResizable(event) { // but also need to make sure the seg.isEnd == true + var source = event.source || {}; + return firstDefined( + event.durationEditable, + source.durationEditable, + opt('eventDurationEditable'), + event.editable, + source.editable, + opt('editable') + ) + && !opt('disableResizing'); // deprecated + } + + + + /* Event Data + ------------------------------------------------------------------------------*/ + + + function setEventData(events) { // events are already normalized at this point + eventsByID = {}; + var i, len=events.length, event; + for (i=0; i selection for IE + element + .mousedown(function(ev) { // prevent native selection for others + ev.preventDefault(); + }) + .click(function(ev) { + if (isResizing) { + ev.preventDefault(); // prevent link from being visited (only method that worked in IE6) + ev.stopImmediatePropagation(); // prevent fullcalendar eventClick handler from being called + // (eventElementHandlers needs to be bound after resizableDayEvent) + } + }); + + handle.mousedown(function(ev) { + if (ev.which != 1) { + return; // needs to be left mouse button + } + isResizing = true; + var hoverListener = getHoverListener(); + var rowCnt = getRowCnt(); + var colCnt = getColCnt(); + var elementTop = element.css('top'); + var dayDelta; + var helpers; + var eventCopy = $.extend({}, event); + var minCellOffset = dayOffsetToCellOffset( dateToDayOffset(event.start) ); + clearSelection(); + $('body') + .css('cursor', direction + '-resize') + .one('mouseup', mouseup); + trigger('eventResizeStart', this, event, ev); + hoverListener.start(function(cell, origCell) { + if (cell) { + + var origCellOffset = cellToCellOffset(origCell); + var cellOffset = cellToCellOffset(cell); + + // don't let resizing move earlier than start date cell + cellOffset = Math.max(cellOffset, minCellOffset); + + dayDelta = + cellOffsetToDayOffset(cellOffset) - + cellOffsetToDayOffset(origCellOffset); + + if (dayDelta) { + eventCopy.end = addDays(eventEnd(event), dayDelta, true); + var oldHelpers = helpers; + + helpers = renderTempDayEvent(eventCopy, segment.row, elementTop); + helpers = $(helpers); // turn array into a jQuery object + + helpers.find('*').css('cursor', direction + '-resize'); + if (oldHelpers) { + oldHelpers.remove(); + } + + hideEvents(event); + } + else { + if (helpers) { + showEvents(event); + helpers.remove(); + helpers = null; + } + } + clearOverlays(); + renderDayOverlay( // coordinate grid already rebuilt with hoverListener.start() + event.start, + addDays( exclEndDay(event), dayDelta ) + // TODO: instead of calling renderDayOverlay() with dates, + // call _renderDayOverlay (or whatever) with cell offsets. + ); + } + }, ev); + + function mouseup(ev) { + trigger('eventResizeStop', this, event, ev); + $('body').css('cursor', ''); + hoverListener.stop(); + clearOverlays(); + if (dayDelta) { + eventResize(this, event, dayDelta, 0, ev); + // event redraw will clear helpers + } + // otherwise, the drag handler already restored the old events + + setTimeout(function() { // make this happen after the element's click event + isResizing = false; + },0); + } + }); + } + + +} + + + +/* Generalized Segment Utilities +-------------------------------------------------------------------------------------------------*/ + + +function isDaySegmentCollision(segment, otherSegments) { + for (var i=0; i= segment.leftCol + ) { + return true; + } + } + return false; +} + + +function segmentElementEach(segments, callback) { // TODO: use in AgendaView? + for (var i=0; i"); + } + if (e[0].parentNode != parent[0]) { + e.appendTo(parent); + } + usedOverlays.push(e.css(rect).show()); + return e; + } + + + function clearOverlays() { + var e; + while (e = usedOverlays.shift()) { + unusedOverlays.push(e.hide().unbind()); + } + } + + +} + +;; + +function CoordinateGrid(buildFunc) { + + var t = this; + var rows; + var cols; + + + t.build = function() { + rows = []; + cols = []; + buildFunc(rows, cols); + }; + + + t.cell = function(x, y) { + var rowCnt = rows.length; + var colCnt = cols.length; + var i, r=-1, c=-1; + for (i=0; i= rows[i][0] && y < rows[i][1]) { + r = i; + break; + } + } + for (i=0; i= cols[i][0] && x < cols[i][1]) { + c = i; + break; + } + } + return (r>=0 && c>=0) ? { row:r, col:c } : null; + }; + + + t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive + var origin = originElement.offset(); + return { + top: rows[row0][0] - origin.top, + left: cols[col0][0] - origin.left, + width: cols[col1][1] - cols[col0][0], + height: rows[row1][1] - rows[row0][0] + }; + }; + +} + +;; + +function HoverListener(coordinateGrid) { + + + var t = this; + var bindType; + var change; + var firstCell; + var cell; + + + t.start = function(_change, ev, _bindType) { + change = _change; + firstCell = cell = null; + coordinateGrid.build(); + mouse(ev); + bindType = _bindType || 'mousemove'; + $(document).bind(bindType, mouse); + }; + + + function mouse(ev) { + _fixUIEvent(ev); // see below + var newCell = coordinateGrid.cell(ev.pageX, ev.pageY); + if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) { + if (newCell) { + if (!firstCell) { + firstCell = newCell; + } + change(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col); + }else{ + change(newCell, firstCell); + } + cell = newCell; + } + } + + + t.stop = function() { + $(document).unbind(bindType, mouse); + return cell; + }; + + +} + + + +// this fix was only necessary for jQuery UI 1.8.16 (and jQuery 1.7 or 1.7.1) +// upgrading to jQuery UI 1.8.17 (and using either jQuery 1.7 or 1.7.1) fixed the problem +// but keep this in here for 1.8.16 users +// and maybe remove it down the line + +function _fixUIEvent(event) { // for issue 1168 + if (event.pageX === undefined) { + event.pageX = event.originalEvent.pageX; + event.pageY = event.originalEvent.pageY; + } +} +;; + +function HorizontalPositionCache(getElement) { + + var t = this, + elements = {}, + lefts = {}, + rights = {}; + + function e(i) { + return elements[i] = elements[i] || getElement(i); + } + + t.left = function(i) { + return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i]; + }; + + t.right = function(i) { + return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i]; + }; + + t.clear = function() { + elements = {}; + lefts = {}; + rights = {}; + }; + +} + +;; })(jQuery); diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index e25e5cd34d6..197f8ff314b 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -403,6 +403,8 @@ openerp.web_calendar = function(instance) { color_key = color_key[0]; } r.color = this.get_color(color_key); + r.backgroundColor = this.get_color(color_key); + console.log(r.backgroundColor) } return r; }, From f4e243b61d721911b412a37ccaa5aabd523f26b8 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Thu, 7 Nov 2013 15:51:34 +0100 Subject: [PATCH 04/25] [FIX] CSS z-index to avoid display bug with search drawer bzr revid: jke@openerp.com-20131107145134-3qzl4aat1frigmmb --- addons/web_calendar/static/src/css/Makefile | 4 ++++ addons/web_calendar/static/src/css/web_fullcalendar.css | 7 ++++++- addons/web_calendar/static/src/css/web_fullcalendar.sass | 7 ++++++- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100755 addons/web_calendar/static/src/css/Makefile diff --git a/addons/web_calendar/static/src/css/Makefile b/addons/web_calendar/static/src/css/Makefile new file mode 100755 index 00000000000..96eee92d6ca --- /dev/null +++ b/addons/web_calendar/static/src/css/Makefile @@ -0,0 +1,4 @@ +web_fullcalendar.css: web_fullcalendar.sass + sass --trace -t expanded web_fullcalendar.sass web_fullcalendar.css + + \ No newline at end of file diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index e2df45765d2..cb666a54a8e 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -3,6 +3,10 @@ position: relative; } +.openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer { + z-index: 10; +} + .openerp .oe_fullcalendar_widget .fc-content .fc-event .close-btn { color: white; position: absolute; @@ -18,7 +22,8 @@ padding: 1px; background-color: #b40000; box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.5); - visibility: hidden; + visibility: hidden; + z-index: 9; } .openerp .oe_fullcalendar_widget .fc-content .fc-event:hover .close-btn { visibility: visible; diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass index d1565c4860b..3a9f85460f1 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.sass +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -3,6 +3,11 @@ .openerp .oe_view_manager_view_calendar position: relative + +.openerp + .oe_searchview.oe_searchview_open_drawer + .oe_searchview_drawer + z-index: 10 .openerp .oe_fullcalendar_widget @@ -24,7 +29,7 @@ background-color: rgba(180, 0, 0, 1) box-shadow: 0px 0px 2px rgba(0, 0, 0, .5) visibility: hidden - z-index: 100 + z-index: 9 .fc-event:hover .close-btn visibility: visible From 0a7c57134c15fbc1c9e4c9c51bfbfc445a71b9c3 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Fri, 8 Nov 2013 17:07:05 +0100 Subject: [PATCH 05/25] [REF] Remove a console log bzr revid: jke@openerp.com-20131108160705-j0i13p279ukeacin --- addons/web_calendar/static/src/js/fullcalendar.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 197f8ff314b..5a9cb33e927 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -241,17 +241,16 @@ openerp.web_calendar = function(instance) { }, open_quick_create: function(data_template) { - var self = this; if (this.quick) { return this.quick.trigger('close'); } - this.quick = new (get_class(this.quick_create_class))( - this, this.dataset, true, this.options, data_template) - .on('added', this, this.proxy('quick_created')) + var QuickCreate = get_class(this.quick_create_class); + this.quick = new QuickCreate(this, this.dataset, true, this.options, data_template); + this.quick.on('added', this, this.proxy('quick_created')) .on('close', this, function() { this.quick.destroy(); delete this.quick; - self.$calendar.fullCalendar('unselect'); + this.$calendar.fullCalendar('unselect'); }); this.quick.replace($(".oe_calendar_qc_placeholder")); this.quick.focus(); @@ -403,8 +402,6 @@ openerp.web_calendar = function(instance) { color_key = color_key[0]; } r.color = this.get_color(color_key); - r.backgroundColor = this.get_color(color_key); - console.log(r.backgroundColor) } return r; }, From f8eae2f9c90c9b7f2760307adac3710a2c6dd3f2 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Wed, 13 Nov 2013 13:21:44 +0100 Subject: [PATCH 06/25] [IMP] Add button more on quick create to make a slow_create. Add mini_calendar with gmail behavior bzr revid: jke@openerp.com-20131113122144-m3qpieydlx4586vl --- .../static/src/css/web_fullcalendar.css | 4 ++ .../static/src/js/fullcalendar.js | 57 ++++++++++++++++--- .../static/src/xml/web_fullcalendar.xml | 27 ++++++--- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index cb666a54a8e..f8513983e1e 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -33,3 +33,7 @@ visibility: visible; opacity: 1; } + +td.oe_calendar_sidebar_container { + padding : 10px; +} diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 5a9cb33e927..f44bc9803c8 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -53,6 +53,8 @@ openerp.web_calendar = function(instance) { return typeof id == "string" && id.indexOf('-') >= 0; } + + instance.web.views.add('calendar', 'instance.web_calendar.FullCalendarView'); instance.web_calendar.FullCalendarView = instance.web.View.extend({ @@ -81,7 +83,7 @@ openerp.web_calendar = function(instance) { this.range_start = null; this.range_stop = null; this.selected_filters = []; - + }, set_default_options: function(options) { @@ -94,6 +96,7 @@ openerp.web_calendar = function(instance) { destroy: function() { this.$calendar.fullCalendar('destroy'); + this.$small_calendar.datepicker('destroy'); this._super.apply(this, arguments); }, @@ -103,6 +106,7 @@ openerp.web_calendar = function(instance) { this.fields_view = fv; this.$calendar = this.$el.find(".oe_fullcalendar_widget"); + this.$small_calendar = this.$el.find(".oe_calendar_mini"); this.info_fields = []; @@ -235,7 +239,25 @@ openerp.web_calendar = function(instance) { }); }, + smallCalChanged: function (context) { + return function(datum,obj) { + var curView = context.$calendar.fullCalendar( 'getView'); + var curDate = new Date(obj.currentYear , obj.currentMonth, obj.currentDay); + + if (curView.name == "agendaWeek") { + if (curDate <= curView.end && curDate >= curView.start) { + context.$calendar.fullCalendar('changeView','agendaDay'); + } + } + else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)==0)) { + context.$calendar.fullCalendar('changeView','agendaWeek'); + } + context.$calendar.fullCalendar( 'gotoDate', obj.currentYear , obj.currentMonth, obj.currentDay); + } + }, + init_fullcalendar: function() { + this.$small_calendar.datepicker({ onSelect: this.smallCalChanged(this) }); this.$calendar.fullCalendar(this.get_fc_init_options()); return $.when(); }, @@ -247,11 +269,12 @@ openerp.web_calendar = function(instance) { var QuickCreate = get_class(this.quick_create_class); this.quick = new QuickCreate(this, this.dataset, true, this.options, data_template); this.quick.on('added', this, this.proxy('quick_created')) - .on('close', this, function() { - this.quick.destroy(); - delete this.quick; - this.$calendar.fullCalendar('unselect'); - }); + .on('slowadded', this, this.proxy('slow_created')) + .on('close', this, function() { + this.quick.destroy(); + delete this.quick; + this.$calendar.fullCalendar('unselect'); + }); this.quick.replace($(".oe_calendar_qc_placeholder")); this.quick.focus(); }, @@ -415,7 +438,7 @@ openerp.web_calendar = function(instance) { var event_end = event.end; if (event.allDay) { // Sometimes fullcalendar doesn't give any event.end. - if (event_end === null || typeof evend_end === "undefined") + if (event_end === null || typeof event_end === "undefined") event_end = event.start; // Avoid inplace changes event_end = (new Date(event_end.getTime())).addDays(1); @@ -550,6 +573,11 @@ openerp.web_calendar = function(instance) { this.dataset.trigger("dataset_changed", id); this.refresh_event(id); }, + slow_created: function () { + // refresh all view, because maybe some recurrents item + var self = this; + self.$calendar.fullCalendar('refetchEvents'); + }, append_deletion_handle: function (event, element, view) { var self = this; @@ -596,7 +624,7 @@ openerp.web_calendar = function(instance) { * a "close" event. */ init: function(parent, dataset, buttons, options, data_template) { - this._super(parent); + this._super(parent); this.dataset = dataset; this._buttons = buttons || false; this.options = options; @@ -631,6 +659,10 @@ openerp.web_calendar = function(instance) { self.quick_add(); self.focus(); }); + this.$el.find(".oe_calendar_quick_create_edit").click(function () { + self.slow_add(); + self.focus(); + }); this.$el.find(".oe_calendar_quick_create_close").click(function (ev) { ev.preventDefault(); self.trigger('close'); @@ -657,6 +689,12 @@ openerp.web_calendar = function(instance) { if (/^\s*$/.test(val)) { return; } this.quick_create({'name': val}); }, + + slow_add: function() { + var val = this.$input.val(); + if (/^\s*$/.test(val)) { return; } + this.slow_create({'name': val}); + }, /** * Handles saving data coming from quick create box @@ -732,7 +770,7 @@ openerp.web_calendar = function(instance) { def.resolve(); }); pop.on('create_completed', self, function(id) { - self.trigger('added', id); + self.trigger('slowadded'); }); def.then(function() { self.trigger('close'); @@ -1071,6 +1109,7 @@ openerp.web_calendar = function(instance) { instance.web.form.widgets.add('many2many_calendar','instance.web_calendar.FieldMany2ManyCalendar'); instance.web.form.widgets.add('one2many_calendar','instance.web_calendar.FieldOne2ManyCalendar'); + }; diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index 8f867ad980d..dfd04054d39 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -1,12 +1,20 @@ From 7e1c7030b2c3d92ea32320a4d1ef2c886b1401ed Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Fri, 15 Nov 2013 17:58:26 +0100 Subject: [PATCH 07/25] bzr revid: jke@openerp.com-20131115165826-m8nzjqxmvbonx6vl --- .../static/src/js/fullcalendar.js | 230 ++++++++++++++---- .../static/src/xml/web_fullcalendar.xml | 18 +- 2 files changed, 201 insertions(+), 47 deletions(-) diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index f44bc9803c8..18fb21f632d 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -21,32 +21,18 @@ openerp.web_calendar = function(instance) { */ // Dates - monthNames: Date.CultureInfo.monthNames, monthNamesShort: Date.CultureInfo.abbreviatedMonthNames, dayNames: Date.CultureInfo.dayNames, dayNamesShort: Date.CultureInfo.abbreviatedDayNames, // Label - weekNumberTitle: _t("W"), allDayText: _t("all-day"), // Functional - firstDay: Date.CultureInfo.firstDayOfWeek, - /* XXXvlab: propose a patch to formatDate - https://github.com/arshaw/fullcalendar/blob/0c20380d6967e6669633918c16047bc23eae50f2/src/date_util.js - So as to allow overriding of formatDate function only (and not formatDates), and - use datejs formatting codes. - */ - // columnFormat: { - // month: , - // week: , - // day: , - // } - }; function is_virtual_id(id) { @@ -73,10 +59,10 @@ openerp.web_calendar = function(instance) { this.view_type = 'calendar'; - this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', + this.COLOR_PALETTE = ['#ffc900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f', '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00', - '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ]; + '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#f57900' ]; this.color_map = {}; this.last_search = []; @@ -102,11 +88,8 @@ openerp.web_calendar = function(instance) { view_loading: function (fv) { var self = this; - this.fields_view = fv; - this.$calendar = this.$el.find(".oe_fullcalendar_widget"); - this.$small_calendar = this.$el.find(".oe_calendar_mini"); this.info_fields = []; @@ -138,12 +121,17 @@ openerp.web_calendar = function(instance) { this.view_id = fv.view_id; - this.mode = attrs.mode; // one of month, week or day - this.date_start = attrs.date_start; // Field name of starting date field - this.date_delay = attrs.date_delay; // duration + this.mode = attrs.mode; // one of month, week or day + this.date_start = attrs.date_start; // Field name of starting date field + this.date_delay = attrs.date_delay; // duration this.date_stop = attrs.date_stop; - this.all_day = attrs.all_day; // boolean - + this.all_day = attrs.all_day; // boolean + this.attendee_people = attrs.attendee; + this.how_display_event = ''; + + if (typeof attrs.display !== "undefined") + this.how_display_event = attrs.display; // String with [FIELD] + this.color_field = attrs.color; this.color_string = fv.fields[this.color_field] ? fv.fields[this.color_field].string : _t("Filter"); @@ -156,21 +144,20 @@ openerp.web_calendar = function(instance) { } this.fields = fv.fields; - for (var fld = 0; fld < fv.arch.children.length; fld++) { this.info_fields.push(fv.arch.children[fld].attrs.name); } - + return (new instance.web.Model(this.dataset.model)) .call("check_access_rights", ["create", false]) .then(function (create_right) { self.create_right = create_right; - self.init_fullcalendar().then(function() { + self.init_fullcalendar().then(function() { + debugger; self.trigger('calendar_view_loaded', fv); self.ready.resolve(); }); }); - }, get_fc_init_options: function () { @@ -204,6 +191,19 @@ openerp.web_calendar = function(instance) { if (!self.options.read_only_mode) { self.append_deletion_handle(event, element, view); } + element.find('.fc-event-title').html(event.title); + if (event.attendees.indexOf(self.myPartnerID)<0) { + console.log("HIDE !!!!"); + console.log(self.myPartnerID); + console.log(event.attendees); + element.hide(); + } + else { + console.log("SHOW !!!!"); + console.log(self.myPartnerID); + console.log(event.attendees); + } + }, eventClick: function (event) { self.open_event(event._id); }, select: function (start_date, end_date, all_day, _js_event, _view) { @@ -239,7 +239,7 @@ openerp.web_calendar = function(instance) { }); }, - smallCalChanged: function (context) { + calendarMiniChanged: function (context) { return function(datum,obj) { var curView = context.$calendar.fullCalendar( 'getView'); var curDate = new Date(obj.currentYear , obj.currentMonth, obj.currentDay); @@ -252,13 +252,50 @@ openerp.web_calendar = function(instance) { else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)==0)) { context.$calendar.fullCalendar('changeView','agendaWeek'); } - context.$calendar.fullCalendar( 'gotoDate', obj.currentYear , obj.currentMonth, obj.currentDay); + context.$calendar.fullCalendar('gotoDate', obj.currentYear , obj.currentMonth, obj.currentDay); } }, init_fullcalendar: function() { - this.$small_calendar.datepicker({ onSelect: this.smallCalChanged(this) }); - this.$calendar.fullCalendar(this.get_fc_init_options()); + var self = this; + + + + new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.dataset.context.uid]]).first().then( + function(result) { + self.myPartnerID = result.partner_id[0];; + }); + + if (!this.sidebar && this.options.$sidebar) { + this.sidebar = new instance.web_calendar.Sidebar(this); + this.sidebar.appendTo(this.$el.find('.oe_calendar_sidebar_container')); + + //Initialize small calendar + this.$small_calendar = self.$el.find(".oe_calendar_mini"); + this.$small_calendar.datepicker({ onSelect: self.calendarMiniChanged(self) }); + + + var sidebar_items = {}; + + //CALENDAR_FRIENDLY ==> should be moved in WEB_CALENDAR.Friends + new instance.web.Model("calendar.friendly").query(["name","partner_id"]).filter([["user_id", "=",this.dataset.context.uid]]).all().then(function(result) { + _.each(result, function(item) { + var filter_value = item.partner_id[0]; + var filter_item = { + value: filter_value, + label: item.name, + color: self.get_color(filter_value) + }; + sidebar_items[filter_value] = filter_item ; + }); + + self.myFriends = sidebar_items; + self.sidebar.filter.events_loaded(sidebar_items); + + }); + } + self.$calendar.fullCalendar(self.get_fc_init_options()); + return $.when(); }, @@ -377,33 +414,86 @@ openerp.web_calendar = function(instance) { */ event_data_transform: function(evt) { var self = this; + var date_start = instance.web.auto_str_to_date(evt[this.date_start]), date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null, date_delay = evt[this.date_delay] || 1.0, all_day = this.all_day ? evt[this.all_day] : false, - res_text = ''; + res_computed_text = '', + the_title = '', + attendees = []; if (this.date_stop && this.fields[this.date_stop].type == 'date') { date_stop.addDay(1); } if (this.info_fields) { - res_text = _(this.info_fields) + var temp_ret = {}; + res_computed_text = this.how_display_event; + + _.each(this.info_fields, function (fieldname) { + var value = evt[fieldname]; + if (_.contains(["many2one", "one2one"], self.fields[fieldname].type)) { + if (value === false) + temp_ret[fieldname] = null; + else if (value instanceof Array) + temp_ret[fieldname] = value[1]; // Yipee, no name_get to make + else + throw new Error("Incomplete data received from dataset for record " + evt.id); + } + else if (_.contains(["one2many","many2many"], self.fields[fieldname].type)) { + if (value === false) + temp_ret[fieldname] = null; + else if (value instanceof Array) + temp_ret[fieldname] = value; // if x2many, keep all id ! + else + throw new Error("Incomplete data received from dataset for record " + evt.id); + } + else { + temp_ret[fieldname] = value; + } + res_computed_text = res_computed_text.replace("["+fieldname+"]",temp_ret[fieldname]); + }); + + + if (res_computed_text.length) { + the_title = res_computed_text; + } + else { + var res_text= []; + _.each(temp_ret, function(val,key) { res_text.push(val)} ); + the_title = res_text.join(', '); + } + + if (typeof this.attendee_people !== "undefined") { + _.each(temp_ret[this.attendee_people], + function (partner_id) { + attendees.push(partner_id); + if (partner_id in self.myFriends && partner_id != self.myPartnerID) { + the_title += '+' + } + } + ); + } + +/* res_text = _(this.info_fields) .chain() .map(function(fieldname) { var value = evt[fieldname]; - if (_.contains(["one2many", "many2one", "one2one", "many2many"], - self.fields[fieldname].type)) { + var temp_ret = {}; + if (_.contains(["one2many", "many2one", "one2one", "many2many"], self.fields[fieldname].type)) { if (value === false) return null; - if (value instanceof Array) - return value[1]; // Yipee, no name_get to make + if (value instanceof Array) { + return value[1]; // Yipee, no name_get to make + } throw new Error("Incomplete data received from dataset for record " + evt.id); } return value; }).reject(function (x) { return x === null; - }).value(); + }).value(); */ } + if (!date_stop && date_delay) { date_stop = date_start.clone().addHours(date_delay); } @@ -413,12 +503,12 @@ openerp.web_calendar = function(instance) { var r = { 'start': date_start.toString('yyyy-MM-dd HH:mm:ss'), 'end': date_stop.toString('yyyy-MM-dd HH:mm:ss'), - 'title': res_text.join(', '), - // check this with recurring data ! - 'allDay': (this.fields[this.date_start].type == 'date' || - (this.all_day && evt[this.all_day]) || false), + 'title': the_title, //res_text.join(', '), + 'allDay': (this.fields[this.date_start].type == 'date' || (this.all_day && evt[this.all_day]) || false), 'id': evt.id, + 'attendees':attendees }; + if (this.color_field && evt[this.color_field]) { var color_key = evt[this.color_field]; if (typeof color_key === "object") { @@ -428,7 +518,7 @@ openerp.web_calendar = function(instance) { } return r; }, - + /** * Transform fullcalendar event object to OpenERP Data object */ @@ -455,7 +545,6 @@ openerp.web_calendar = function(instance) { data[this.all_day] = event.allDay; } if (this.date_delay) { - // XXXvlab: what if different dates ? var diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000); data[this.date_delay] = diff_seconds / 3600; } @@ -593,7 +682,7 @@ openerp.web_calendar = function(instance) { remove_event: function(id) { var self = this; function do_it() { - return $.when(self.dataset.unlink([id])).done(function() { + return $.when(self.dataset.unlink([id])).then(function() { self.$calendar.fullCalendar('removeEvents', id); }); } @@ -980,10 +1069,13 @@ openerp.web_calendar = function(instance) { $.async_when().done(function () { self.calendar_view.appendTo(self.$el); }); + + return loaded; }, render_value: function() { + debugger; var self = this; this.dataset.set_ids(this.get("value")); this.is_loaded = this.is_loaded.then(function() { @@ -1110,6 +1202,52 @@ openerp.web_calendar = function(instance) { instance.web.form.widgets.add('many2many_calendar','instance.web_calendar.FieldMany2ManyCalendar'); instance.web.form.widgets.add('one2many_calendar','instance.web_calendar.FieldOne2ManyCalendar'); + + instance.web_calendar.Sidebar = instance.web.Widget.extend({ + template: 'CalendarView.sidebar', + + start: function() { + this._super(); + this.filter = new instance.web_calendar.SidebarFilter(this, this.getParent()); + this.filter.appendTo(this.$el.find('.oe_calendar_filter')); + } + }); + instance.web_calendar.SidebarFilter = instance.web.Widget.extend({ + events: { + 'change input:checkbox': 'filter_click' + }, + init: function(parent, view) { + this._super(parent); + this.view = view; + }, + events_loaded: function(filters) { + var selected_filters = this.view.selected_filters.slice(0); + this.$el.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters })); + this.$('div.oe_calendar_responsible input').each(function() { + if (_.indexOf(selected_filters, $(this).val()) > -1) { + $(this).click(); + } + }); + }, + filter_click: function(e) { + var self = this, + responsibles = [], + $e = $(e.target); + this.view.selected_filters = []; + this.$('div.oe_calendar_responsible input:checked').each(function() { + responsibles.push($(this).val()); + self.view.selected_filters.push($(this).val()); + }); + //scheduler.clearAll(); + if (responsibles.length) { + this.view.events_loaded(this.view.dataset_events, function(filter_value) { + return _.indexOf(responsibles, filter_value.toString()) > -1; + }, true); + } else { + this.view.events_loaded(this.view.dataset_events, false, true); + } + } + }); }; diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index dfd04054d39..8babdabbb9d 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -10,11 +10,27 @@
-
+ + + +
+
+
+

+
+
+ + +
+ + +
+
+
+ + + + My Contacts + web_calendar.contacts + + + + + + + + + Calendar Contacts + web_calendar.contacts + form + tree + + + + + \ No newline at end of file diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index f8513983e1e..d117d2504a4 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -9,10 +9,8 @@ .openerp .oe_fullcalendar_widget .fc-content .fc-event .close-btn { color: white; - position: absolute; - top: 1px; - right: 1px; - display: inline-block; + float: right; + display: none; line-height: 6px; height: 8px; width: 8px; @@ -22,18 +20,31 @@ padding: 1px; background-color: #b40000; box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.5); - visibility: hidden; z-index: 9; } .openerp .oe_fullcalendar_widget .fc-content .fc-event:hover .close-btn { - visibility: visible; + display: inline; opacity: 0.5; } .openerp .oe_fullcalendar_widget .fc-content .fc-event:hover .close-btn:hover { - visibility: visible; + display: inline; opacity: 1; } -td.oe_calendar_sidebar_container { - padding : 10px; +.openerp td.oe_calendar_sidebar_container { + padding: 10px; +} + +.bgDark { + background-color: rgba(55, 55, 55, 0.5); +} + +.bgLight { + background-color: rgba(255, 255, 255, 0.5); +} + +.attendee_head { + float: right; + margin-left: 1px; + size: 18px !important; } diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass index 3a9f85460f1..8ac427cb429 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.sass +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -15,10 +15,8 @@ .fc-event .close-btn color: white - position: absolute - top: 1px - right: 1px - display: inline-block + float: right + display: none line-height: 6px height: 8px width: 8px @@ -28,14 +26,27 @@ padding: 1px background-color: rgba(180, 0, 0, 1) box-shadow: 0px 0px 2px rgba(0, 0, 0, .5) - visibility: hidden z-index: 9 .fc-event:hover .close-btn - visibility: visible + display: inline opacity: 0.5 .fc-event:hover .close-btn:hover - visibility: visible + display: inline opacity: 1.0 +.openerp + td.oe_calendar_sidebar_container + padding: 10px + +.bgDark + background-color: rgba(55, 55, 55, 0.5) + +.bgLight + background-color: rgba(255, 255, 255, 0.5) + +.attendee_head + float: right + margin-left: 1px + size: 18px !important \ No newline at end of file diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 18fb21f632d..7d292469f43 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -15,32 +15,21 @@ openerp.web_calendar = function(instance) { } var fc_defaultOptions = { - - /* - * Internationalization - */ - - // Dates monthNames: Date.CultureInfo.monthNames, monthNamesShort: Date.CultureInfo.abbreviatedMonthNames, dayNames: Date.CultureInfo.dayNames, dayNamesShort: Date.CultureInfo.abbreviatedDayNames, - // Label weekNumberTitle: _t("W"), allDayText: _t("all-day"), - // Functional firstDay: Date.CultureInfo.firstDayOfWeek, - }; function is_virtual_id(id) { return typeof id == "string" && id.indexOf('-') >= 0; } - - instance.web.views.add('calendar', 'instance.web_calendar.FullCalendarView'); instance.web_calendar.FullCalendarView = instance.web.View.extend({ @@ -58,7 +47,6 @@ openerp.web_calendar = function(instance) { this.view_id = view_id; this.view_type = 'calendar'; - this.COLOR_PALETTE = ['#ffc900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f', '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00', @@ -128,14 +116,36 @@ openerp.web_calendar = function(instance) { this.all_day = attrs.all_day; // boolean this.attendee_people = attrs.attendee; this.how_display_event = ''; - + + if (typeof attrs.quick_create_instance !== "undefined") + self.quick_create_class = attrs.quick_create_instance; + + if (typeof attrs.quick_add !== "undefined" && attrs.quick_add == "True") + this.quick_add_pop = true; + else + this.quick_add_pop = false; + + + // The display format which will be used to display the event where fields are between "[" and "]" if (typeof attrs.display !== "undefined") this.how_display_event = attrs.display; // String with [FIELD] + + // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event + // The color is the color of the attendee, so don't need to show again that it will be present + if (typeof attrs.color_is_attendee !== "undefined" && attrs.color_is_attendee == "True") + this.colorIsAttendee = true; + else + this.colorIsAttendee = false; + + // If this field is set to true, we will use de calendar_friends model as filter and not the color field. + if (typeof attrs.use_contacts !== "undefined" && attrs.use_contacts == "True") + this.useContacts = true; + else + this.useContacts = false; this.color_field = attrs.color; - this.color_string = fv.fields[this.color_field] ? - fv.fields[this.color_field].string : _t("Filter"); + if (this.color_field && this.selected_filters.length === 0) { var default_filter; if ((default_filter = this.dataset.context['calendar_default_' + this.color_field])) { @@ -153,7 +163,6 @@ openerp.web_calendar = function(instance) { .then(function (create_right) { self.create_right = create_right; self.init_fullcalendar().then(function() { - debugger; self.trigger('calendar_view_loaded', fv); self.ready.resolve(); }); @@ -188,22 +197,10 @@ openerp.web_calendar = function(instance) { self.proxy('update_record')(event._id, data); }, eventRender: function (event, element, view) { + element.find('.fc-event-title').html(event.title); if (!self.options.read_only_mode) { self.append_deletion_handle(event, element, view); } - element.find('.fc-event-title').html(event.title); - if (event.attendees.indexOf(self.myPartnerID)<0) { - console.log("HIDE !!!!"); - console.log(self.myPartnerID); - console.log(event.attendees); - element.hide(); - } - else { - console.log("SHOW !!!!"); - console.log(self.myPartnerID); - console.log(event.attendees); - } - }, eventClick: function (event) { self.open_event(event._id); }, select: function (start_date, end_date, all_day, _js_event, _view) { @@ -213,7 +210,6 @@ openerp.web_calendar = function(instance) { allDay: all_day, }); - // Opening quick create widget self.open_quick_create(data_template); }, @@ -258,14 +254,7 @@ openerp.web_calendar = function(instance) { init_fullcalendar: function() { var self = this; - - - - new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.dataset.context.uid]]).first().then( - function(result) { - self.myPartnerID = result.partner_id[0];; - }); - + if (!this.sidebar && this.options.$sidebar) { this.sidebar = new instance.web_calendar.Sidebar(this); this.sidebar.appendTo(this.$el.find('.oe_calendar_sidebar_container')); @@ -274,27 +263,49 @@ openerp.web_calendar = function(instance) { this.$small_calendar = self.$el.find(".oe_calendar_mini"); this.$small_calendar.datepicker({ onSelect: self.calendarMiniChanged(self) }); - - var sidebar_items = {}; + if (this.useContacts) { + new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.dataset.context.uid]]).first() + .done( + function(result) { + var sidebar_items = {}; + var filter_value = result.partner_id[0]; + var filter_item = { + value: filter_value, + label: result.partner_id[1] + " [Me]", + color: self.get_color(filter_value) + }; + sidebar_items[filter_value] = filter_item ; + filter_item = { + value: -1, + label: "All partners [All]", + color: self.get_color(-1) + }; + sidebar_items[-1] = filter_item ; - //CALENDAR_FRIENDLY ==> should be moved in WEB_CALENDAR.Friends - new instance.web.Model("calendar.friendly").query(["name","partner_id"]).filter([["user_id", "=",this.dataset.context.uid]]).all().then(function(result) { - _.each(result, function(item) { - var filter_value = item.partner_id[0]; - var filter_item = { - value: filter_value, - label: item.name, - color: self.get_color(filter_value) - }; - sidebar_items[filter_value] = filter_item ; - }); - - self.myFriends = sidebar_items; - self.sidebar.filter.events_loaded(sidebar_items); - - }); + new instance.web.Model("web_calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) { + _.each(result, function(item) { + filter_value = item.partner_id[0]; + filter_item = { + value: filter_value, + label: item.partner_id[1], + color: self.get_color(filter_value) + }; + sidebar_items[filter_value] = filter_item ; + }); + + self.allFilters = sidebar_items; + self.sidebar.filter.events_loaded(sidebar_items); + self.sidebar.filter.addUpdateButton(); + }).done(function () { + self.$calendar.fullCalendar('refetchEvents'); + }); + } + ); + + } } - self.$calendar.fullCalendar(self.get_fc_init_options()); + self.$calendar.fullCalendar(self.get_fc_init_options()); + return $.when(); }, @@ -304,6 +315,8 @@ openerp.web_calendar = function(instance) { return this.quick.trigger('close'); } var QuickCreate = get_class(this.quick_create_class); + + this.options.disable_quick_create = this.options.disable_quick_create || !this.quick_add_pop; this.quick = new QuickCreate(this, this.dataset, true, this.options, data_template); this.quick.on('added', this, this.proxy('quick_created')) .on('slowadded', this, this.proxy('slow_created')) @@ -408,7 +421,25 @@ openerp.web_calendar = function(instance) { return def; }, - + + hexToRgb : function(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; + }, + + isInArray: function(array_is, array_in) { + for(var z=0; z+' + function (the_attendee_people) { + attendees.push(the_attendee_people); + if (the_attendee_people in self.allFilters && (!self.colorIsAttendee || temp_ret[self.color_field]!=the_attendee_people)) { //&& the_attendee_people != this.colorIsAttendee + /* + var color = self.get_color(the_attendee_people); + var bgcolor = 'bgLight'; + var rgbColor = self.hexToRgb(color); + if ((0.2126 * rgbColor.r + 0.7152 * rgbColor.g + 0.0722 * rgbColor.b) > 127) { + bgcolor = 'bgDark'; + } + + the_title += '+' + */ + the_title += ''; + } } - ); - } - -/* res_text = _(this.info_fields) - .chain() - .map(function(fieldname) { - var value = evt[fieldname]; - var temp_ret = {}; - if (_.contains(["one2many", "many2one", "one2one", "many2many"], self.fields[fieldname].type)) { - if (value === false) return null; - if (value instanceof Array) { - return value[1]; // Yipee, no name_get to make - } - throw new Error("Incomplete data received from dataset for record " + evt.id); - } - return value; - }).reject(function (x) { - return x === null; - }).value(); */ + ); + } } if (!date_stop && date_delay) { @@ -509,13 +537,19 @@ openerp.web_calendar = function(instance) { 'attendees':attendees }; - if (this.color_field && evt[this.color_field]) { - var color_key = evt[this.color_field]; - if (typeof color_key === "object") { - color_key = color_key[0]; + if (!self.useContacts || self.all_filters[evt[this.color_field]] != undefined) { + if (this.color_field && evt[this.color_field]) { + var color_key = evt[this.color_field]; + if (typeof color_key === "object") { + color_key = color_key[0]; + } + r.color = this.get_color(color_key); } - r.color = this.get_color(color_key); } + else { // if form all, get color -1 + r.color = self.all_filters[-1].color; + } + return r; }, @@ -569,7 +603,53 @@ openerp.web_calendar = function(instance) { } // We should make sure that *2many used in title of event have // their extended form [ID, NAME]... - + + if (!self.useContacts) { + var now_filters = {}; + var filter_value; + var filter_item; + + _.each(events, function (e) { + filter_value = e[self.color_field][0]; + filter_item = { + value: filter_value, + label: e[self.color_field][1], + color: self.get_color(filter_value) + }; + if (!now_filters[e[self.color_field][0]]) + now_filters[e[self.color_field][0]] = filter_item; + }); + + self.allFilters = now_filters; + self.sidebar.filter.events_loaded(now_filters); + + } + + events = $.map(events, function (e) { + + if (self.attendee_people != undefined) { + if (self.isInArray(self.selected_filters,e[self.attendee_people]) + || (self.selected_filters.indexOf(-1) > -1)) { + console.log(e.name + 'is show'); + console.log(self.isInArray(self.selected_filters,e[self.attendee_people])); + console.log(self.selected_filters.indexOf(-1) > -1); + + return e; + } + else { + console.log(e.name + 'is hidden'); + console.log(self.isInArray(self.selected_filters,e[self.attendee_people])); + console.log(self.selected_filters.indexOf(-1) > -1); + console.log(self.selected_filters); + return null; + } + } + else if (self.isInArray(self.selected_filters,e[self.color_field])){ + return e; + } + return null; + }); + return self.perform_necessary_name_gets(events).then(callback); }); }, @@ -675,8 +755,8 @@ openerp.web_calendar = function(instance) { self.remove_event(event.id); ev.preventDefault(); return false; - }); - element.prepend($x); + }); + element.find('.deleteMe').html($x);//prepend($x); }, remove_event: function(id) { @@ -707,11 +787,7 @@ openerp.web_calendar = function(instance) { */ instance.web_calendar.QuickCreate = instance.web.Widget.extend({ template: 'CalendarView.quick_create', - - /** - * close_btn: If true, the widget will display a "Close" button able to trigger - * a "close" event. - */ + init: function(parent, dataset, buttons, options, data_template) { this._super(parent); this.dataset = dataset; @@ -781,7 +857,6 @@ openerp.web_calendar = function(instance) { slow_add: function() { var val = this.$input.val(); - if (/^\s*$/.test(val)) { return; } this.slow_create({'name': val}); }, @@ -814,8 +889,7 @@ openerp.web_calendar = function(instance) { var pop = new instance.web.form.FormOpenPopup(this); var context = new instance.web.CompoundContext(this.dataset.context, defaults) - pop.show_element(this.dataset.model, null, context -, { + pop.show_element(this.dataset.model, null, context, { title: this.get_title(), disable_multiple_selection: true, // Ensuring we use ``self.dataset`` and DO NOT create a new one. @@ -826,7 +900,8 @@ openerp.web_calendar = function(instance) { // XXXvlab: why ``create`` does not call dataset_changed AND adds id in dataset.ids // is a mystery for me ATM. }).fail(function (r, event) { - throw new Error(r); + if (!r.data.message) //els emanage by openerp + throw new Error(r); }); }, @@ -842,7 +917,8 @@ openerp.web_calendar = function(instance) { read_function: function(id, fields, options) { return self.dataset.read_ids.apply(self.dataset, arguments).done(function() { }).fail(function (r, event) { - throw new Error(r); + if (!r.data.message) //else manage by openerp + throw new Error(r); }); }, }); @@ -1040,6 +1116,7 @@ openerp.web_calendar = function(instance) { self.is_loaded = self.is_loaded.then(function() { self.calendar_view.destroy(); return $.when(self.load_view()).done(function() { + console.log("Load view done, so we render"); self.render_value(); }); }); @@ -1075,7 +1152,7 @@ openerp.web_calendar = function(instance) { }, render_value: function() { - debugger; + console.log("In render value"); var self = this; this.dataset.set_ids(this.get("value")); this.is_loaded = this.is_loaded.then(function() { @@ -1218,34 +1295,46 @@ openerp.web_calendar = function(instance) { }, init: function(parent, view) { this._super(parent); - this.view = view; + this.view = view; }, events_loaded: function(filters) { - var selected_filters = this.view.selected_filters.slice(0); + var self = this; + self.selected_filters = []; + self.view.all_filters = filters; this.$el.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters })); - this.$('div.oe_calendar_responsible input').each(function() { - if (_.indexOf(selected_filters, $(this).val()) > -1) { - $(this).click(); - } - }); + this.filter_click(null); }, filter_click: function(e) { var self = this, - responsibles = [], - $e = $(e.target); - this.view.selected_filters = []; + responsibles = []; + //$e = $(e.target); + self.view.selected_filters = []; this.$('div.oe_calendar_responsible input:checked').each(function() { responsibles.push($(this).val()); - self.view.selected_filters.push($(this).val()); + + if (e==null && parseInt($(this).val())<0) { + $(this).prop('checked',false); +; return; + } + self.view.selected_filters.push(parseInt($(this).val())); }); - //scheduler.clearAll(); - if (responsibles.length) { - this.view.events_loaded(this.view.dataset_events, function(filter_value) { - return _.indexOf(responsibles, filter_value.toString()) > -1; - }, true); - } else { - this.view.events_loaded(this.view.dataset_events, false, true); + + if (e !== null) { //First intialize + self.view.$calendar.fullCalendar('refetchEvents'); //RERENDER ALL... } + + + }, + addUpdateButton: function() { + var self=this; + var button = ""; + this.$('div.oe_calendar_all_responsibles').append(button); + this.$(".add_contacts_link").on('click', function() { + self.rpc("/web/action/load", { + action_id: "web_calendar.action_calendar_contacts" + }).then( function(result) { return self.do_action(result); }); + }); + } }); diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index 8babdabbb9d..e2d0c9ccde0 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -25,9 +25,13 @@
-
- - +
+
+ + + , + +
@@ -45,12 +49,12 @@
- +
- - - or Cancel + + +
From a704c8433931c83494460cb7d448092ea39e7625 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Tue, 26 Nov 2013 19:02:12 +0100 Subject: [PATCH 09/25] [IMP] Add picture on event, manage name on tooltip, ... bzr revid: jke@openerp.com-20131126180212-gsmsgjlsqa7yq0u1 --- addons/web_calendar/contacts_view.xml | 10 +- .../static/src/css/web_fullcalendar.css | 32 --- .../static/src/css/web_fullcalendar.sass | 33 --- .../static/src/js/fullcalendar.js | 234 +++++++++++------- .../static/src/xml/web_fullcalendar.xml | 9 +- 5 files changed, 164 insertions(+), 154 deletions(-) diff --git a/addons/web_calendar/contacts_view.xml b/addons/web_calendar/contacts_view.xml index 6f59193be2b..e168ba08fe1 100644 --- a/addons/web_calendar/contacts_view.xml +++ b/addons/web_calendar/contacts_view.xml @@ -16,7 +16,15 @@ web_calendar.contacts form tree - + + +

+ Click to add your first contact. +

+ Add your contacts here to see the events which are created by them.
+ Each contact will have it own color on calendar, to see easily who is busy... +

+
diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index d117d2504a4..bda17c32bca 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -7,42 +7,10 @@ z-index: 10; } -.openerp .oe_fullcalendar_widget .fc-content .fc-event .close-btn { - color: white; - float: right; - display: none; - line-height: 6px; - height: 8px; - width: 8px; - border: 1px solid white; - border-radius: 3px; - text-align: center; - padding: 1px; - background-color: #b40000; - box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.5); - z-index: 9; -} -.openerp .oe_fullcalendar_widget .fc-content .fc-event:hover .close-btn { - display: inline; - opacity: 0.5; -} -.openerp .oe_fullcalendar_widget .fc-content .fc-event:hover .close-btn:hover { - display: inline; - opacity: 1; -} - .openerp td.oe_calendar_sidebar_container { padding: 10px; } -.bgDark { - background-color: rgba(55, 55, 55, 0.5); -} - -.bgLight { - background-color: rgba(255, 255, 255, 0.5); -} - .attendee_head { float: right; margin-left: 1px; diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass index 8ac427cb429..a93ae0652b6 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.sass +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -9,43 +9,10 @@ .oe_searchview_drawer z-index: 10 -.openerp - .oe_fullcalendar_widget - .fc-content - .fc-event - .close-btn - color: white - float: right - display: none - line-height: 6px - height: 8px - width: 8px - border: 1px solid white - border-radius: 3px - text-align: center - padding: 1px - background-color: rgba(180, 0, 0, 1) - box-shadow: 0px 0px 2px rgba(0, 0, 0, .5) - z-index: 9 - .fc-event:hover - .close-btn - display: inline - opacity: 0.5 - .fc-event:hover - .close-btn:hover - display: inline - opacity: 1.0 - .openerp td.oe_calendar_sidebar_container padding: 10px -.bgDark - background-color: rgba(55, 55, 55, 0.5) - -.bgLight - background-color: rgba(255, 255, 255, 0.5) - .attendee_head float: right margin-left: 1px diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 7d292469f43..cd96b838799 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -113,7 +113,7 @@ openerp.web_calendar = function(instance) { this.date_start = attrs.date_start; // Field name of starting date field this.date_delay = attrs.date_delay; // duration this.date_stop = attrs.date_stop; - this.all_day = attrs.all_day; // boolean + this.all_day = attrs.all_day; this.attendee_people = attrs.attendee; this.how_display_event = ''; @@ -130,18 +130,28 @@ openerp.web_calendar = function(instance) { if (typeof attrs.display !== "undefined") this.how_display_event = attrs.display; // String with [FIELD] - // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event - // The color is the color of the attendee, so don't need to show again that it will be present - if (typeof attrs.color_is_attendee !== "undefined" && attrs.color_is_attendee == "True") - this.colorIsAttendee = true; - else - this.colorIsAttendee = false; + // If this field is set ot true, we don't open the event in form view, but in a popup with the xml_view_id passed by this parameter + if (attrs.event_open_popup == null || attrs.event_open_popup == "False") + this.open_popup_action = false; + else { + this.open_popup_action = attrs.event_open_popup; + } + // If this field is set to true, we will use de calendar_friends model as filter and not the color field. if (typeof attrs.use_contacts !== "undefined" && attrs.use_contacts == "True") this.useContacts = true; else this.useContacts = false; + + // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event + // The color is the color of the attendee, so don't need to show again that it will be present + if (typeof attrs.color_is_attendee == null || attrs.color_is_attendee == "False") + this.colorIsAttendee = false; + else + this.colorIsAttendee = true; + + this.color_field = attrs.color; @@ -199,10 +209,10 @@ openerp.web_calendar = function(instance) { eventRender: function (event, element, view) { element.find('.fc-event-title').html(event.title); if (!self.options.read_only_mode) { - self.append_deletion_handle(event, element, view); + //self.append_deletion_handle(event, element, view); } }, - eventClick: function (event) { self.open_event(event._id); }, + eventClick: function (event) { console.log(event); self.open_event(event._id,event.title); }, select: function (start_date, end_date, all_day, _js_event, _view) { var data_template = self.get_event_data({ start: start_date, @@ -214,6 +224,9 @@ openerp.web_calendar = function(instance) { }, drop: function(start_date, all_day) { + if (this.classList.contains("ui-dialog")) { + return; //don't look click event on calendar if popup hover ! + } var data_template = self.get_event_data({ start: start_date, allDay: all_day, @@ -231,6 +244,17 @@ openerp.web_calendar = function(instance) { weekNumbers: true, snapMinutes: 15, + timeFormat : { + // for agendaWeek and agendaDay + agenda: 'h:mm{ - h:mm}', // 5:00 - 6:30 + + // for all other views + '': 'h(:mm)tt' // 7pm + }, + firstHour: 8, + weekMode : 'liquid', + + }); }, @@ -420,17 +444,7 @@ openerp.web_calendar = function(instance) { }); return def; }, - - - hexToRgb : function(hex) { - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? { - r: parseInt(result[1], 16), - g: parseInt(result[2], 16), - b: parseInt(result[3], 16) - } : null; - }, - + isInArray: function(array_is, array_in) { for(var z=0; z/g,'>'); + if (typeof this.attendee_people !== "undefined") { - if (temp_ret[this.attendee_people]) - the_title += " "; - _.each(temp_ret[this.attendee_people], function (the_attendee_people) { attendees.push(the_attendee_people); - if (the_attendee_people in self.allFilters && (!self.colorIsAttendee || temp_ret[self.color_field]!=the_attendee_people)) { //&& the_attendee_people != this.colorIsAttendee - /* - var color = self.get_color(the_attendee_people); - var bgcolor = 'bgLight'; - var rgbColor = self.hexToRgb(color); - if ((0.2126 * rgbColor.r + 0.7152 * rgbColor.g + 0.0722 * rgbColor.b) > 127) { - bgcolor = 'bgDark'; - } - - the_title += '+' - */ - the_title += ''; - - } + + style = 'style="border:2px solid '+self.get_color((the_attendee_people in self.allFilters) ? the_attendee_people : '-1')+'"'; + + // if (the_attendee_people in self.allFilters && (!self.colorIsAttendee || temp_ret[self.color_field]!=the_attendee_people)) { //&& the_attendee_people != this.colorIsAttendee + the_title += ''; } ); } @@ -601,10 +605,28 @@ openerp.web_calendar = function(instance) { console.log("Consecutive ``do_search`` called. Cancelling."); return; } - // We should make sure that *2many used in title of event have - // their extended form [ID, NAME]... + // We should make sure that *2many used in title of event have their extended form [ID, NAME]... - if (!self.useContacts) { + events = $.map(events, function (e) { + + if (self.attendee_people != undefined) { //If we filter on contacts... + if (self.isInArray(self.selected_filters,e[self.attendee_people]) || (self.selected_filters.indexOf(-1) > -1)) { + return e; + } + else { + return null; + } + } + else { //We adds all events # TO TEST ? if (self.isInArray(self.selected_filters,e[self.color_field])){ + + return e; + } + return null; + }); + + + + if (!self.useContacts) { // If we use all peoples as filter in sidebars var now_filters = {}; var filter_value; var filter_item; @@ -621,36 +643,30 @@ openerp.web_calendar = function(instance) { }); self.allFilters = now_filters; - self.sidebar.filter.events_loaded(now_filters); + self.sidebar.filter.events_loaded(now_filters); + return self.perform_necessary_name_gets(events).then(callback); + } + else { + var all_attendees = []; + + _.each(events, function (e) { + all_attendees.push(e[self.attendee_people]); + }); + + self.all_attendees = {} + + all_attendees = _.chain(all_attendees).flatten().uniq().value(); + new instance.web.Model("res.partner").query(["name"]).filter([["id", "in",all_attendees]]).all().then(function(result) { + _.each(result, function(item) { + self.all_attendees[item.id] = item.name; + }); + }).done(function() { + return self.perform_necessary_name_gets(events).then(callback); + }); } - events = $.map(events, function (e) { - - if (self.attendee_people != undefined) { - if (self.isInArray(self.selected_filters,e[self.attendee_people]) - || (self.selected_filters.indexOf(-1) > -1)) { - console.log(e.name + 'is show'); - console.log(self.isInArray(self.selected_filters,e[self.attendee_people])); - console.log(self.selected_filters.indexOf(-1) > -1); - - return e; - } - else { - console.log(e.name + 'is hidden'); - console.log(self.isInArray(self.selected_filters,e[self.attendee_people])); - console.log(self.selected_filters.indexOf(-1) > -1); - console.log(self.selected_filters); - return null; - } - } - else if (self.isInArray(self.selected_filters,e[self.color_field])){ - return e; - } - return null; - }); - - return self.perform_necessary_name_gets(events).then(callback); + }); }, eventDataTransform: function (event) { @@ -697,11 +713,63 @@ openerp.web_calendar = function(instance) { } return false; }, - open_event: function(id) { - var index = this.dataset.get_id_index(id); - this.dataset.index = index; - this.do_switch_view('form'); - return false; + open_event: function(id,title) { + if (! this.open_popup_action) { + var index = this.dataset.get_id_index(id); + this.dataset.index = index; + this.do_switch_view('form'); + } + else { + + var self = this; + + var pop = new instance.web.form.FormOpenPopup(this); + pop.show_element(this.dataset.model, id, this.dataset.get_context(), { + title: _.str.sprintf(_t("View: %s"),title), + view_id: this.open_popup_action, + res_id: id, + target: 'new', + readonly:true + }); + + var form_controller = pop.view_form; + form_controller.on("load_record", self, function(){ + button_delete = _.str.sprintf("",_t("Delete")); + button_edit = _.str.sprintf("",_t("Edit event >>")); + + + pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete) + pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit) + + $('.delme').click( + function() { + $('.oe_form_button_cancel').trigger('click'); + self.remove_event(id); + } + ); + $('.editme').click( + function() { + var action = { + type: 'ir.actions.act_window', + res_model: 'crm.meeting', + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + res_id: id, + context: {}, + }; + $('.oe_form_button_cancel').trigger('click'); + self.do_action(action); + } + ); + + + }); + + } + + return false; + }, do_show: function() { @@ -748,17 +816,6 @@ openerp.web_calendar = function(instance) { self.$calendar.fullCalendar('refetchEvents'); }, - append_deletion_handle: function (event, element, view) { - var self = this; - var $x = $("
x
") - .on('click', function(ev) { - self.remove_event(event.id); - ev.preventDefault(); - return false; - }); - element.find('.deleteMe').html($x);//prepend($x); - }, - remove_event: function(id) { var self = this; function do_it() { @@ -886,6 +943,11 @@ openerp.web_calendar = function(instance) { _.each($.extend({}, this.data_template, data), function(val, field_name) { defaults['default_' + field_name] = val; }); + + if (defaults['default_allday'] && (defaults['default_date_deadline'] || defaults['default_duration'])) { + delete defaults['default_date_deadline']; + delete defaults['default_duration']; + } var pop = new instance.web.form.FormOpenPopup(this); var context = new instance.web.CompoundContext(this.dataset.context, defaults) @@ -900,7 +962,7 @@ openerp.web_calendar = function(instance) { // XXXvlab: why ``create`` does not call dataset_changed AND adds id in dataset.ids // is a mystery for me ATM. }).fail(function (r, event) { - if (!r.data.message) //els emanage by openerp + if (!r.data.message) //else manage by openerp throw new Error(r); }); }, @@ -965,7 +1027,7 @@ openerp.web_calendar = function(instance) { var self = this; return $.when(this._super.apply(this, arguments)).then(function() { self.on('event_rendered', this, function (event, element, view) { - self.append_deletion_handle(event, element, view); + }); }); }, diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index e2d0c9ccde0..d844a8d17e6 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -28,9 +28,14 @@
- - , + + , + + + + +
From d88b0f68e7ba6387937fa40dc7cf362bcc135f7e Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Wed, 27 Nov 2013 13:34:27 +0100 Subject: [PATCH 10/25] [FIX] Big fix for calendar click event bzr revid: jke@openerp.com-20131127123427-2g5rggszx3ymznmw --- .../static/src/css/web_fullcalendar.css | 5 ++ .../static/src/js/fullcalendar.js | 65 ++++++++++++------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index bda17c32bca..f31e1b9f0a5 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -16,3 +16,8 @@ margin-left: 1px; size: 18px !important; } + +.fc-event-hori { + //border-width : 0px 0px 0px 0px; +} + diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index cd96b838799..c46327ecd39 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -47,10 +47,10 @@ openerp.web_calendar = function(instance) { this.view_id = view_id; this.view_type = 'calendar'; - this.COLOR_PALETTE = ['#ffc900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', + this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f', '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00', - '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#f57900' ]; + '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ]; this.color_map = {}; this.last_search = []; @@ -82,7 +82,6 @@ openerp.web_calendar = function(instance) { this.info_fields = []; /* buttons */ - this.$buttons = $(QWeb.render("CalendarView.buttons", {'widget': this})); if (this.options.$buttons) { this.$buttons.appendTo(this.options.$buttons); @@ -96,7 +95,6 @@ openerp.web_calendar = function(instance) { }); /* xml view calendar options */ - var attrs = fv.arch.attrs; if (!attrs.date_start) { @@ -108,7 +106,6 @@ openerp.web_calendar = function(instance) { this.name = fv.name || attrs.string; this.view_id = fv.view_id; - this.mode = attrs.mode; // one of month, week or day this.date_start = attrs.date_start; // Field name of starting date field this.date_delay = attrs.date_delay; // duration @@ -130,13 +127,12 @@ openerp.web_calendar = function(instance) { if (typeof attrs.display !== "undefined") this.how_display_event = attrs.display; // String with [FIELD] - // If this field is set ot true, we don't open the event in form view, but in a popup with the xml_view_id passed by this parameter + // If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter if (attrs.event_open_popup == null || attrs.event_open_popup == "False") this.open_popup_action = false; else { this.open_popup_action = attrs.event_open_popup; } - // If this field is set to true, we will use de calendar_friends model as filter and not the color field. if (typeof attrs.use_contacts !== "undefined" && attrs.use_contacts == "True") @@ -151,10 +147,8 @@ openerp.web_calendar = function(instance) { else this.colorIsAttendee = true; - this.color_field = attrs.color; - if (this.color_field && this.selected_filters.length === 0) { var default_filter; @@ -182,7 +176,7 @@ openerp.web_calendar = function(instance) { get_fc_init_options: function () { var self = this; return $.extend({}, fc_defaultOptions, { - + defaultView: (this.mode == "month")?"month": (this.mode == "week"?"agendaWeek": (this.mode == "day"?"agendaDay":"month")), @@ -199,6 +193,7 @@ openerp.web_calendar = function(instance) { // callbacks eventDrop: function (event, _day_delta, _minute_delta, _all_day, _revertFunc) { + debugger; var data = self.get_event_data(event); self.proxy('update_record')(event._id, data); // we don't revert the event, but update it. }, @@ -207,10 +202,15 @@ openerp.web_calendar = function(instance) { self.proxy('update_record')(event._id, data); }, eventRender: function (event, element, view) { - element.find('.fc-event-title').html(event.title); - if (!self.options.read_only_mode) { - //self.append_deletion_handle(event, element, view); - } + element.find('.fc-event-title').html(event.title); + }, + eventAfterRender: function (event, element, view) { + if ((view.name !== 'month') && (((event.end-event.start)/60000)<=30)) { + //if duration is too small, we see the html code of img + var current_title = $(element.find('.fc-event-time')).text(); + var new_title = current_title.substr(0,current_title.indexOf("0?current_title.indexOf("/g,'>'); - if (typeof this.attendee_people !== "undefined") { + var MAX_ATTENDEES = 3; + var attendee_showed = 0; + var attendee_other = ''; + _.each(temp_ret[this.attendee_people], function (the_attendee_people) { attendees.push(the_attendee_people); - - style = 'style="border:2px solid '+self.get_color((the_attendee_people in self.allFilters) ? the_attendee_people : '-1')+'"'; - + attendee_showed += 1; + //style = 'style="border:2px solid '+self.get_color((the_attendee_people in self.allFilters) ? the_attendee_people : '-1')+'"'; + if (attendee_showed<= MAX_ATTENDEES) { // if (the_attendee_people in self.allFilters && (!self.colorIsAttendee || temp_ret[self.color_field]!=the_attendee_people)) { //&& the_attendee_people != this.colorIsAttendee - the_title += ''; + the_title += ''; + } + else { + attendee_other += self.all_attendees[the_attendee_people] +", "; + } } - ); + ); + if (attendee_other.length) { + the_title += '+'; + } } } @@ -576,6 +586,12 @@ openerp.web_calendar = function(instance) { name: event.title }; data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]); + + //Bug whenmove a all_day event from week or day, we don't have a dateend or duration... + if (event_end == null) { + event_end = event.start.addHours(2); + } + if (this.date_stop) { data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]); } @@ -898,6 +914,12 @@ openerp.web_calendar = function(instance) { self.on('added', self, function() { self.trigger('close'); }); + + self.$el.on('dialogclose', self, function() { + console.log("dialogclose"); + self.trigger('close'); + }); + }, focus: function() { this.$el.find('input').focus(); @@ -1178,7 +1200,6 @@ openerp.web_calendar = function(instance) { self.is_loaded = self.is_loaded.then(function() { self.calendar_view.destroy(); return $.when(self.load_view()).done(function() { - console.log("Load view done, so we render"); self.render_value(); }); }); From dbda9a879a0f4ecc44c7e4d5ecf6807cd14c916d Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Mon, 2 Dec 2013 15:20:02 +0100 Subject: [PATCH 11/25] [REF] Manage event color by css and not inline-style bzr revid: jke@openerp.com-20131202142002-40tz3pslyxybib5q --- .../static/src/css/web_fullcalendar.css | 342 +++++++++++++++++- .../static/src/css/web_fullcalendar.sass | 316 +++++++++++++++- .../static/src/js/fullcalendar.js | 90 +++-- .../static/src/xml/web_fullcalendar.xml | 6 +- 4 files changed, 710 insertions(+), 44 deletions(-) diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index f31e1b9f0a5..b6a1f89df49 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -17,7 +17,345 @@ size: 18px !important; } -.fc-event-hori { - //border-width : 0px 0px 0px 0px; +.cal_opacity { + opacity: 0.7; } +.event_color_1 { + background-color: #a4bdfc; + color: #0d0d0d; +} + +.event_color_2 { + background-color: #7ae7bf; + color: #0d0d0d; +} + +.event_color_3 { + background-color: #dbadff; + color: #0d0d0d; +} + +.event_color_4 { + background-color: #ff887c; + color: #0d0d0d; +} + +.event_color_5 { + background-color: #fbd75b; + color: #0d0d0d; +} + +.event_color_6 { + background-color: #ffb878; + color: #0d0d0d; +} + +.event_color_7 { + background-color: #46d6db; + color: #0d0d0d; +} + +.event_color_8 { + background-color: #e1e1e1; + color: #0d0d0d; +} + +.event_color_9 { + background-color: #5484ed; + color: #0d0d0d; +} + +.event_color_10 { + background-color: #51b749; + color: #0d0d0d; +} + +.event_color_11 { + background-color: #dc2127; + color: #0d0d0d; +} + +.calendar_color_1 { + border-color: #ac725e; + background-color: #ac725e; + color: #0d0d0d; +} + +.calendar_color_2 { + border-color: #d06b64; + background-color: #d06b64; + color: #0d0d0d; +} + +.calendar_color_3 { + border-color: #f83a22; + background-color: #f83a22; + color: #0d0d0d; +} + +.calendar_color_4 { + border-color: #fa573c; + background-color: #fa573c; + color: #0d0d0d; +} + +.calendar_color_5 { + border-color: #ff7537; + background-color: #ff7537; + color: #0d0d0d; +} + +.calendar_color_6 { + border-color: #ffad46; + background-color: #ffad46; + color: #0d0d0d; +} + +.calendar_color_7 { + border-color: #42d692; + background-color: #42d692; + color: #0d0d0d; +} + +.calendar_color_8 { + border-color: #16a765; + background-color: #16a765; + color: #0d0d0d; +} + +.calendar_color_9 { + border-color: #7bd148; + background-color: #7bd148; + color: #0d0d0d; +} + +.calendar_color_10 { + border-color: #b3dc6c; + background-color: #b3dc6c; + color: #0d0d0d; +} + +.calendar_color_11 { + border-color: #fbe983; + background-color: #fbe983; + color: #0d0d0d; +} + +.calendar_color_12 { + border-color: #fad165; + background-color: #fad165; + color: #0d0d0d; +} + +.calendar_color_13 { + border-color: #92e1c0; + background-color: #92e1c0; + color: #0d0d0d; +} + +.calendar_color_14 { + border-color: #9fe1e7; + background-color: #9fe1e7; + color: #0d0d0d; +} + +.calendar_color_15 { + border-color: #9fc6e7; + background-color: #9fc6e7; + color: #0d0d0d; +} + +.calendar_color_16 { + border-color: #4986e7; + background-color: #4986e7; + color: #0d0d0d; +} + +.calendar_color_17 { + border-color: #9a9cff; + background-color: #9a9cff; + color: #0d0d0d; +} + +.calendar_color_18 { + border-color: #b99aff; + background-color: #b99aff; + color: #0d0d0d; +} + +.calendar_color_19 { + border-color: #c2c2c2; + background-color: #c2c2c2; + color: #0d0d0d; +} + +.calendar_color_20 { + border-color: #cabdbf; + background-color: #cabdbf; + color: #0d0d0d; +} + +.calendar_color_21 { + border-color: #cca6ac; + background-color: #cca6ac; + color: #0d0d0d; +} + +.calendar_color_22 { + border-color: #f691b2; + background-color: #f691b2; + color: #0d0d0d; +} + +.calendar_color_23 { + border-color: #cd74e6; + background-color: #cd74e6; + color: #0d0d0d; +} + +.calendar_color_24 { + border-color: #a47ae2; + background-color: #a47ae2; + color: #0d0d0d; +} + +.underline_ecolor_1 { + border-bottom: 4px solid #a4bdfc; +} + +.underline_ecolor_2 { + border-bottom: 4px solid #7ae7bf; +} + +.underline_ecolor_3 { + border-bottom: 4px solid #dbadff; +} + +.underline_ecolor_4 { + border-bottom: 4px solid #ff887c; +} + +.underline_ecolor_5 { + border-bottom: 4px solid #fbd75b; +} + +.underline_ecolor_6 { + border-bottom: 4px solid #ffb878; +} + +.underline_ecolor_7 { + border-bottom: 4px solid #46d6db; +} + +.underline_ecolor_8 { + border-bottom: 4px solid #e1e1e1; +} + +.underline_ecolor_9 { + border-bottom: 4px solid #5484ed; +} + +.underline_ecolor_10 { + border-bottom: 4px solid #51b749; +} + +.underline_ecolor_11 { + border-bottom: 4px solid #dc2127; +} + +.underline_color_1 { + border-bottom: 4px solid #ac725e; +} + +.underline_color_2 { + border-bottom: 4px solid #d06b64; +} + +.underline_color_3 { + border-bottom: 4px solid #f83a22; +} + +.underline_color_4 { + border-bottom: 4px solid #fa573c; +} + +.underline_color_5 { + border-bottom: 4px solid #ff7537; +} + +.underline_color_6 { + border-bottom: 4px solid #ffad46; +} + +.underline_color_7 { + border-bottom: 4px solid #42d692; +} + +.underline_color_8 { + border-bottom: 4px solid #16a765; +} + +.underline_color_9 { + border-bottom: 4px solid #7bd148; +} + +.underline_color_10 { + border-bottom: 4px solid #b3dc6c; +} + +.underline_color_11 { + border-bottom: 4px solid #fbe983; +} + +.underline_color_12 { + border-bottom: 4px solid #fad165; +} + +.underline_color_13 { + border-bottom: 4px solid #92e1c0; +} + +.underline_color_14 { + border-bottom: 4px solid #9fe1e7; +} + +.underline_color_15 { + border-bottom: 4px solid #9fc6e7; +} + +.underline_color_16 { + border-bottom: 4px solid #4986e7; +} + +.underline_color_17 { + border-bottom: 4px solid #9a9cff; +} + +.underline_color_18 { + border-bottom: 4px solid #b99aff; +} + +.underline_color_19 { + border-bottom: 4px solid #c2c2c2; +} + +.underline_color_20 { + border-bottom: 4px solid #cabdbf; +} + +.underline_color_21 { + border-bottom: 4px solid #cca6ac; +} + +.underline_color_22 { + border-bottom: 4px solid #f691b2; +} + +.underline_color_23 { + border-bottom: 4px solid #cd74e6; +} + +.underline_color_24 { + border-bottom: 4px solid #a47ae2; +} diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass index a93ae0652b6..65624a6d590 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.sass +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -1,5 +1,42 @@ @charset "utf-8" +$color1: #ac725e +$color2: #d06b64 +$color3: #f83a22 +$color4: #fa573c +$color5: #ff7537 +$color6: #ffad46 +$color7: #42d692 +$color8: #16a765 +$color9: #7bd148 +$color10: #b3dc6c +$color11: #fbe983 +$color12: #fad165 +$color13: #92e1c0 +$color14: #9fe1e7 +$color15: #9fc6e7 +$color16: #4986e7 +$color17: #9a9cff +$color18: #b99aff +$color19: #c2c2c2 +$color20: #cabdbf +$color21: #cca6ac +$color22: #f691b2 +$color23: #cd74e6 +$color24: #a47ae2 +$ecolor1: #a4bdfc +$ecolor2: #7ae7bf +$ecolor3: #dbadff +$ecolor4: #ff887c +$ecolor5: #fbd75b +$ecolor6: #ffb878 +$ecolor7: #46d6db +$ecolor8: #e1e1e1 +$ecolor9: #5484ed +$ecolor10:#51b749 +$ecolor11: #dc2127 +$fontcolor: #0d0d0d + .openerp .oe_view_manager_view_calendar position: relative @@ -16,4 +53,281 @@ .attendee_head float: right margin-left: 1px - size: 18px !important \ No newline at end of file + size: 18px !important + + +.cal_opacity + opacity: 0.7 + +.event_color_1 + background-color: $ecolor1 + color: $fontcolor + +.event_color_2 + background-color: $ecolor2 + color: $fontcolor + +.event_color_3 + background-color: $ecolor3 + color: $fontcolor + +.event_color_4 + background-color: $ecolor4 + color: $fontcolor + +.event_color_5 + background-color: $ecolor5 + color: $fontcolor + +.event_color_6 + background-color: $ecolor6 + color: $fontcolor + +.event_color_7 + background-color: $ecolor7 + color: $fontcolor + +.event_color_8 + background-color: $ecolor8 + color: $fontcolor + +.event_color_9 + background-color: $ecolor9 + color: $fontcolor + +.event_color_10 + background-color: $ecolor10 + color: $fontcolor + +.event_color_11 + background-color: $ecolor11 + color: $fontcolor + +.calendar_color_1 + border-color: $color1 + background-color: $color1 + color: $fontcolor + +.calendar_color_2 + border-color: $color2 + background-color: $color2 + color: $fontcolor + +.calendar_color_3 + border-color: $color3 + background-color: $color3 + color: $fontcolor + +.calendar_color_4 + border-color: $color4 + background-color: $color4 + color: $fontcolor + +.calendar_color_5 + border-color: $color5 + background-color: $color5 + color: $fontcolor + +.calendar_color_6 + border-color: $color6 + background-color: $color6 + color: $fontcolor + +.calendar_color_7 + border-color: $color7 + background-color: $color7 + color: $fontcolor + +.calendar_color_8 + border-color: $color8 + background-color: $color8 + color: $fontcolor + +.calendar_color_9 + border-color: $color9 + background-color: $color9 + color: $fontcolor + +.calendar_color_10 + border-color: $color10 + background-color: $color10 + color: $fontcolor + +.calendar_color_11 + border-color: $color11 + background-color: $color11 + color: $fontcolor + +.calendar_color_12 + border-color: $color12 + background-color: $color12 + color: $fontcolor + +.calendar_color_13 + border-color: $color13 + background-color: $color13 + color: $fontcolor + +.calendar_color_14 + border-color: $color14 + background-color: $color14 + color: $fontcolor + +.calendar_color_15 + border-color: $color15 + background-color: $color15 + color: $fontcolor + +.calendar_color_16 + border-color: $color16 + background-color: $color16 + color: $fontcolor + +.calendar_color_17 + border-color: $color17 + background-color: $color17 + color: $fontcolor + +.calendar_color_18 + border-color: $color18 + background-color: $color18 + color: $fontcolor + +.calendar_color_19 + border-color: $color19 + background-color: $color19 + color: $fontcolor + +.calendar_color_20 + border-color: $color20 + background-color: $color20 + color: $fontcolor + +.calendar_color_21 + border-color: $color21 + background-color: $color21 + color: $fontcolor + +.calendar_color_22 + border-color: $color22 + background-color: $color22 + color: $fontcolor + +.calendar_color_23 + border-color: $color23 + background-color: $color23 + color: $fontcolor + +.calendar_color_24 + border-color: $color24 + background-color: $color24 + color: $fontcolor + + + +.underline_ecolor_1 + border-bottom: 4px solid $ecolor1 + +.underline_ecolor_2 + border-bottom: 4px solid $ecolor2 + +.underline_ecolor_3 + border-bottom: 4px solid $ecolor3 + +.underline_ecolor_4 + border-bottom: 4px solid $ecolor4 + +.underline_ecolor_5 + border-bottom: 4px solid $ecolor5 + +.underline_ecolor_6 + border-bottom: 4px solid $ecolor6 + +.underline_ecolor_7 + border-bottom: 4px solid $ecolor7 + +.underline_ecolor_8 + border-bottom: 4px solid $ecolor8 + +.underline_ecolor_9 + border-bottom: 4px solid $ecolor9 + +.underline_ecolor_10 + border-bottom: 4px solid $ecolor10 + +.underline_ecolor_11 + border-bottom: 4px solid $ecolor11 + + +.underline_color_1 + border-bottom: 4px solid $color1 + +.underline_color_2 + border-bottom: 4px solid $color2 + +.underline_color_3 + border-bottom: 4px solid $color3 + +.underline_color_4 + border-bottom: 4px solid $color4 + +.underline_color_5 + border-bottom: 4px solid $color5 + +.underline_color_6 + border-bottom: 4px solid $color6 + +.underline_color_7 + border-bottom: 4px solid $color7 + +.underline_color_8 + border-bottom: 4px solid $color8 + +.underline_color_9 + border-bottom: 4px solid $color9 + +.underline_color_10 + border-bottom: 4px solid $color10 + +.underline_color_11 + border-bottom: 4px solid $color11 + +.underline_color_12 + border-bottom: 4px solid $color12 + +.underline_color_13 + border-bottom: 4px solid $color13 + +.underline_color_14 + border-bottom: 4px solid $color14 + +.underline_color_15 + border-bottom: 4px solid $color15 + +.underline_color_16 + border-bottom: 4px solid $color16 + +.underline_color_17 + border-bottom: 4px solid $color17 + +.underline_color_18 + border-bottom: 4px solid $color18 + +.underline_color_19 + border-bottom: 4px solid $color19 + +.underline_color_20 + border-bottom: 4px solid $color20 + +.underline_color_21 + border-bottom: 4px solid $color21 + +.underline_color_22 + border-bottom: 4px solid $color22 + +.underline_color_23 + border-bottom: 4px solid $color23 + +.underline_color_24 + border-bottom: 4px solid $color24 + \ No newline at end of file diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index c46327ecd39..ec43fdb2969 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -289,47 +289,48 @@ openerp.web_calendar = function(instance) { if (this.useContacts) { new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.dataset.context.uid]]).first() - .done( - function(result) { - var sidebar_items = {}; - var filter_value = result.partner_id[0]; - var filter_item = { + .done( + function(result) { + var sidebar_items = {}; + var filter_value = result.partner_id[0]; + var filter_item = { + value: filter_value, + label: result.partner_id[1] + " [Me]", + color: self.get_color(filter_value) + }; + sidebar_items[filter_value] = filter_item ; + filter_item = { + value: -1, + label: "All partners [All]", + color: self.get_color(-1) + }; + sidebar_items[-1] = filter_item ; + + new instance.web.Model("web_calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) { + _.each(result, function(item) { + filter_value = item.partner_id[0]; + filter_item = { value: filter_value, - label: result.partner_id[1] + " [Me]", + label: item.partner_id[1], color: self.get_color(filter_value) }; - sidebar_items[filter_value] = filter_item ; - filter_item = { - value: -1, - label: "All partners [All]", - color: self.get_color(-1) - }; - sidebar_items[-1] = filter_item ; - - new instance.web.Model("web_calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) { - _.each(result, function(item) { - filter_value = item.partner_id[0]; - filter_item = { - value: filter_value, - label: item.partner_id[1], - color: self.get_color(filter_value) - }; - sidebar_items[filter_value] = filter_item ; - }); - - self.allFilters = sidebar_items; - self.sidebar.filter.events_loaded(sidebar_items); - self.sidebar.filter.addUpdateButton(); - }).done(function () { - self.$calendar.fullCalendar('refetchEvents'); + sidebar_items[filter_value] = filter_item ; }); - } - ); - - } + + self.allFilters = sidebar_items; + self.sidebar.filter.events_loaded(sidebar_items); + self.sidebar.filter.addUpdateButton(); + }).done(function () { + self.$calendar.fullCalendar('refetchEvents'); + }); + } + ); + }; + + } self.$calendar.fullCalendar(self.get_fc_init_options()); - + return $.when(); }, @@ -389,6 +390,15 @@ openerp.web_calendar = function(instance) { }, get_color: function(key) { + if (this.color_map[key]) { + return this.color_map[key]; + } + var index = ((_.keys(this.color_map).length + 4) % 24) + 1; + this.color_map[key] = index; + return index; + }, + + old_get_color: function(key) { if (this.color_map[key]) { return this.color_map[key]; } @@ -551,17 +561,20 @@ openerp.web_calendar = function(instance) { 'attendees':attendees }; + if (!self.useContacts || self.all_filters[evt[this.color_field]] != undefined) { if (this.color_field && evt[this.color_field]) { var color_key = evt[this.color_field]; if (typeof color_key === "object") { color_key = color_key[0]; } - r.color = this.get_color(color_key); + //r.color = this.get_color(color_key); + r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key); } } else { // if form all, get color -1 - r.color = self.all_filters[-1].color; +// r.color = self.all_filters[-1].color; + r.className = 'cal_opacity calendar_color_'+ self.all_filters[-1].color; } return r; @@ -1222,6 +1235,7 @@ openerp.web_calendar = function(instance) { } var loaded = $.Deferred(); this.calendar_view.on("calendar_view_loaded", self, function() { + alert('Why never here ?'); self.initial_is_loaded.resolve(); loaded.resolve(); }); @@ -1418,7 +1432,7 @@ openerp.web_calendar = function(instance) { }).then( function(result) { return self.do_action(result); }); }); - } + }, }); }; diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index d844a8d17e6..3deb1379b64 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -11,7 +11,7 @@ - + @@ -21,7 +21,7 @@

-
+
@@ -34,7 +34,7 @@ - +
From 493a5327bb007fd86540b319d128a63631e5abae Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Tue, 10 Dec 2013 17:37:49 +0100 Subject: [PATCH 12/25] [IMP] Add compatibility on date_start and date_end of calendar to work with gmail API; Add button to synchronize calendar with google bzr revid: jke@openerp.com-20131210163749-rzchu6nkg2ere55i --- .../static/src/css/web_fullcalendar.css | 21 -------- .../static/src/js/fullcalendar.js | 49 ++++++++++++------- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index 4d2f34c7e5c..b6a1f89df49 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -359,24 +359,3 @@ .underline_color_24 { border-bottom: 4px solid #a47ae2; } - -.dhx_cal_tab { - height: 18px; -} - -.dhx_cal_tab.active { - height: 20px; -} - -.dhx_cal_today_button { - height: 20px; -} - -.dhx_cal_event .dhx_body { - width: auto !important; - height: 28px !important; -} - -.dhx_scale_hour { - height: 42px !important; -} diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index ec43fdb2969..65898c884d3 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -586,31 +586,44 @@ openerp.web_calendar = function(instance) { get_event_data: function(event) { // Normalize event_end without changing fullcalendars event. - var event_end = event.end; - if (event.allDay) { - // Sometimes fullcalendar doesn't give any event.end. - if (event_end === null || typeof event_end === "undefined") - event_end = event.start; - // Avoid inplace changes - event_end = (new Date(event_end.getTime())).addDays(1); - } - var data = { name: event.title }; - data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]); - - //Bug whenmove a all_day event from week or day, we don't have a dateend or duration... + + + var event_end = event.end; + //Bug when we move an all_day event from week or day view, we don't have a dateend or duration... if (event_end == null) { - event_end = event.start.addHours(2); + debugger; + event_end = new Date(event.start).addHours(2); + } + + + if (event.allDay) { + // Sometimes fullcalendar doesn't give any event.end. + if (event_end === null || typeof event_end === "undefined") + event_end = new Date(event.start); + // Avoid inplace changes + event_end = (new Date(event_end.getTime())).addDays(1); + + data[this.date_start] = instance.web.parse_value(new Date(event.start.setUTCHours(0,0,0,0)), this.fields[this.date_start]); + data[this.date_stop] = instance.web.parse_value(new Date(event_end.setUTCHours(0,0,0,0)), this.fields[this.date_stop]); + + } + else { + + data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]); + if (this.date_stop) { + data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]); + } + } - if (this.date_stop) { - data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]); - } + if (this.all_day) { - data[this.all_day] = event.allDay; + data[this.all_day] = event.allDay; } + if (this.date_delay) { var diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000); data[this.date_delay] = diff_seconds / 3600; @@ -1424,7 +1437,7 @@ openerp.web_calendar = function(instance) { }, addUpdateButton: function() { var self=this; - var button = ""; + var button = ""; this.$('div.oe_calendar_all_responsibles').append(button); this.$(".add_contacts_link").on('click', function() { self.rpc("/web/action/load", { From 688c5fbe1da7bbf3744f1a594334e55ffec35c58 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Wed, 11 Dec 2013 14:13:27 +0100 Subject: [PATCH 13/25] [REF] Refactoring, comment, and rmeove bug with timeZone on day event in web_calendar bzr revid: jke@openerp.com-20131211131327-6qq2nyv6gm10lc9n --- .../static/src/js/fullcalendar.js | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 65898c884d3..7717223bffc 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -46,14 +46,7 @@ openerp.web_calendar = function(instance) { this.fields_view = {}; this.view_id = view_id; this.view_type = 'calendar'; - - this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400', - '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f', - '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00', - '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ]; - this.color_map = {}; - this.last_search = []; this.range_start = null; this.range_stop = null; this.selected_filters = []; @@ -193,7 +186,6 @@ openerp.web_calendar = function(instance) { // callbacks eventDrop: function (event, _day_delta, _minute_delta, _all_day, _revertFunc) { - debugger; var data = self.get_event_data(event); self.proxy('update_record')(event._id, data); // we don't revert the event, but update it. }, @@ -212,7 +204,7 @@ openerp.web_calendar = function(instance) { element.find('.fc-event-time').html(new_title); } }, - eventClick: function (event) { console.log(event); self.open_event(event._id,event.title); }, + eventClick: function (event) { self.open_event(event._id,event.title); }, select: function (start_date, end_date, all_day, _js_event, _view) { var data_template = self.get_event_data({ start: start_date, @@ -398,15 +390,6 @@ openerp.web_calendar = function(instance) { return index; }, - old_get_color: function(key) { - if (this.color_map[key]) { - return this.color_map[key]; - } - var index = _.keys(this.color_map).length % this.COLOR_PALETTE.length; - var color = this.COLOR_PALETTE[index]; - this.color_map[key] = color; - return color; - }, /** * In o2m case, records from dataset won't have names attached to their *2o values. @@ -530,9 +513,7 @@ openerp.web_calendar = function(instance) { function (the_attendee_people) { attendees.push(the_attendee_people); attendee_showed += 1; - //style = 'style="border:2px solid '+self.get_color((the_attendee_people in self.allFilters) ? the_attendee_people : '-1')+'"'; if (attendee_showed<= MAX_ATTENDEES) { - // if (the_attendee_people in self.allFilters && (!self.colorIsAttendee || temp_ret[self.color_field]!=the_attendee_people)) { //&& the_attendee_people != this.colorIsAttendee the_title += ''; } else { @@ -540,8 +521,8 @@ openerp.web_calendar = function(instance) { } } ); - if (attendee_other.length) { - the_title += '+'; + if (attendee_other.length>2) { + the_title += '+'; } } } @@ -606,8 +587,10 @@ openerp.web_calendar = function(instance) { // Avoid inplace changes event_end = (new Date(event_end.getTime())).addDays(1); - data[this.date_start] = instance.web.parse_value(new Date(event.start.setUTCHours(0,0,0,0)), this.fields[this.date_start]); - data[this.date_stop] = instance.web.parse_value(new Date(event_end.setUTCHours(0,0,0,0)), this.fields[this.date_stop]); + date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate())) + date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate())) + data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]); + data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]); } else { From 889518d86635a5bc987d1b531ef5fd41f883b401 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Wed, 11 Dec 2013 19:55:02 +0100 Subject: [PATCH 14/25] [IMP] Add permission on web_Calendar.contacts bzr revid: jke@openerp.com-20131211185502-mmzi1nkdkdmsuuqj --- addons/web_calendar/__openerp__.py | 5 ++++- addons/web_calendar/security/ir.model.access.csv | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 addons/web_calendar/security/ir.model.access.csv diff --git a/addons/web_calendar/__openerp__.py b/addons/web_calendar/__openerp__.py index 66558794eb7..cb75471b152 100644 --- a/addons/web_calendar/__openerp__.py +++ b/addons/web_calendar/__openerp__.py @@ -8,7 +8,10 @@ OpenERP Web Calendar view. """, 'version': '2.0', 'depends': ['web'], - 'data' : ['contacts_view.xml'], + 'data' : [ + 'contacts_view.xml', + 'security/ir.model.access.csv', + ], 'js': [ 'static/lib/fullcalendar/js/fullcalendar.js', 'static/src/js/*.js' diff --git a/addons/web_calendar/security/ir.model.access.csv b/addons/web_calendar/security/ir.model.access.csv new file mode 100644 index 00000000000..0b92a94566d --- /dev/null +++ b/addons/web_calendar/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_web_calendar_contacts_all,access_web_calendar_contacts_all,web_calendar.contacts,,1,0,0,0 +access_web_calendar_contacts,access_web_calendar_contacts,web_calendar.contacts,base.group_system,1,1,1,1 From 5f4e3ea83507416ac98a26d37a04847bf5570de1 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Wed, 11 Dec 2013 20:18:31 +0100 Subject: [PATCH 15/25] [TYPO] Typo, bad security rules bzr revid: jke@openerp.com-20131211191831-r70gxot42ef2epf1 --- addons/web_calendar/security/ir.model.access.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web_calendar/security/ir.model.access.csv b/addons/web_calendar/security/ir.model.access.csv index 0b92a94566d..d616183a6cf 100644 --- a/addons/web_calendar/security/ir.model.access.csv +++ b/addons/web_calendar/security/ir.model.access.csv @@ -1,3 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_web_calendar_contacts_all,access_web_calendar_contacts_all,web_calendar.contacts,,1,0,0,0 -access_web_calendar_contacts,access_web_calendar_contacts,web_calendar.contacts,base.group_system,1,1,1,1 +access_web_calendar_contacts_all,access_web_calendar_contacts_all,model_web_calendar_contacts,,1,0,0,0 +access_web_calendar_contacts,access_web_calendar_contacts,model_web_calendar_contacts,base.group_system,1,1,1,1 From 0578ceabaad4b0b3a4b17bd66d2c96f9b97fb049 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Fri, 13 Dec 2013 17:30:05 +0100 Subject: [PATCH 16/25] [Typo] Set the avatar of calendar event, before text to always have the picture at top 0px (float right on the first line) bzr revid: jke@openerp.com-20131213163005-439v2vy300b362m1 --- addons/web_calendar/static/src/css/web_fullcalendar.css | 4 ++++ addons/web_calendar/static/src/css/web_fullcalendar.sass | 4 ++++ addons/web_calendar/static/src/js/fullcalendar.js | 9 ++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index b6a1f89df49..c721df12e68 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -2,6 +2,10 @@ .openerp .oe_view_manager_view_calendar { position: relative; } +.openerp .oe_calendar_table { + margin-top : 10px; + margin-left: 5px; +} .openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer { z-index: 10; diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass index 0e52d1a1c68..920814b4f2b 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.sass +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -41,6 +41,10 @@ $fontcolor: #0d0d0d .oe_view_manager_view_calendar position: relative + .oe_calendar_table + margin-top : 10px + margin-left: 5px + .openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 7717223bffc..2d003c6c1e1 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -385,7 +385,7 @@ openerp.web_calendar = function(instance) { if (this.color_map[key]) { return this.color_map[key]; } - var index = ((_.keys(this.color_map).length + 4) % 24) + 1; + var index = (((_.keys(this.color_map).length + 1) * 5) % 24) + 1; this.color_map[key] = index; return index; }, @@ -504,6 +504,8 @@ openerp.web_calendar = function(instance) { } the_title = the_title.replace(/&/g,'&').replace(//g,'>'); + the_title_avatar = ''; + if (typeof this.attendee_people !== "undefined") { var MAX_ATTENDEES = 3; var attendee_showed = 0; @@ -514,7 +516,7 @@ openerp.web_calendar = function(instance) { attendees.push(the_attendee_people); attendee_showed += 1; if (attendee_showed<= MAX_ATTENDEES) { - the_title += ''; + the_title_avatar += ''; } else { attendee_other += self.all_attendees[the_attendee_people] +", "; @@ -522,8 +524,9 @@ openerp.web_calendar = function(instance) { } ); if (attendee_other.length>2) { - the_title += '+'; + the_title_avatar += '+'; } + the_title = the_title_avatar + the_title; } } From 569d273f8bb80f70d6975851988bf749fb36d390 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Mon, 16 Dec 2013 17:13:36 +0100 Subject: [PATCH 17/25] [IMP] Fix bug where date_stop are computed has a required field bzr revid: jke@openerp.com-20131216161336-zwg0po61j54c2z6i --- .../static/src/css/web_fullcalendar.css | 114 +++++++++++++++++- .../static/src/css/web_fullcalendar.sass | 82 ++++++++++++- .../static/src/js/fullcalendar.js | 91 +++++++++++--- .../static/src/xml/web_fullcalendar.xml | 4 +- 4 files changed, 263 insertions(+), 28 deletions(-) diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index c721df12e68..dbaccd788ba 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -2,9 +2,9 @@ .openerp .oe_view_manager_view_calendar { position: relative; } -.openerp .oe_calendar_table { - margin-top : 10px; - margin-left: 5px; +.openerp .oe_calendar_table { + margin-top: 10px; + margin-left: 5px; } .openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer { @@ -15,14 +15,24 @@ padding: 10px; } +img.attendee_head { + height: 18px; + width: 18px; +} + .attendee_head { float: right; margin-left: 1px; size: 18px !important; } +.cal_avatar { + height: 24px; + width: 24px; +} + .cal_opacity { - opacity: 0.7; + opacity: 0.6; } .event_color_1 { @@ -363,3 +373,99 @@ .underline_color_24 { border-bottom: 4px solid #a47ae2; } + +.color_1 { + color: #ac725e; +} + +.color_2 { + color: #d06b64; +} + +.color_3 { + color: #f83a22; +} + +.color_4 { + color: #fa573c; +} + +.color_5 { + color: #ff7537; +} + +.color_6 { + color: #ffad46; +} + +.color_7 { + color: #42d692; +} + +.color_8 { + color: #16a765; +} + +.color_9 { + color: #7bd148; +} + +.color_10 { + color: #b3dc6c; +} + +.color_11 { + color: #fbe983; +} + +.color_12 { + color: #fad165; +} + +.color_13 { + color: #92e1c0; +} + +.color_14 { + color: #9fe1e7; +} + +.color_15 { + color: #9fc6e7; +} + +.color_16 { + color: #4986e7; +} + +.color_17 { + color: #9a9cff; +} + +.color_18 { + color: #b99aff; +} + +.color_19 { + color: #c2c2c2; +} + +.color_20 { + color: #cabdbf; +} + +.color_21 { + color: #cca6ac; +} + +.color_22 { + color: #f691b2; +} + +.color_23 { + color: #cd74e6; +} + +.color_24 { + color: #a47ae2; +} diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass index 920814b4f2b..460f9878db7 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.sass +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -54,14 +54,21 @@ $fontcolor: #0d0d0d td.oe_calendar_sidebar_container padding: 10px +img.attendee_head + height: 18px + width: 18px + .attendee_head float: right margin-left: 1px size: 18px !important - +.cal_avatar + height: 24px + width: 24px + .cal_opacity - opacity: 0.7 + opacity: 0.6 .event_color_1 background-color: $ecolor1 @@ -335,3 +342,74 @@ $fontcolor: #0d0d0d .underline_color_24 border-bottom: 4px solid $color24 +.color_1 + color: $color1 + +.color_2 + color: $color2 + +.color_3 + color: $color3 + +.color_4 + color: $color4 + +.color_5 + color: $color5 + +.color_6 + color: $color6 + +.color_7 + color: $color7 + +.color_8 + color: $color8 + +.color_9 + color: $color9 + +.color_10 + color: $color10 + +.color_11 + color: $color11 + +.color_12 + color: $color12 + +.color_13 + color: $color13 + +.color_14 + color: $color14 + +.color_15 + color: $color15 + +.color_16 + color: $color16 + +.color_17 + color: $color17 + +.color_18 + color: $color18 + +.color_19 + color: $color19 + +.color_20 + color: $color20 + +.color_21 + color: $color21 + +.color_22 + color: $color22 + +.color_23 + color: $color23 + +.color_24 + color: $color24 \ No newline at end of file diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 2d003c6c1e1..e5e0ad1a814 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -30,12 +30,16 @@ openerp.web_calendar = function(instance) { return typeof id == "string" && id.indexOf('-') >= 0; } + function isNull(value) { + return typeof value === "undefined" || value === null + } + instance.web.views.add('calendar', 'instance.web_calendar.FullCalendarView'); instance.web_calendar.FullCalendarView = instance.web.View.extend({ template: "FullCalendarView", display_name: _lt('Calendar'), - quick_create_class: 'instance.web_calendar.QuickCreate', + quick_create_class: 'instance.' + 'web_calendar.QuickCreate', init: function (parent, dataset, view_id, options) { this._super(parent); @@ -106,40 +110,58 @@ openerp.web_calendar = function(instance) { this.all_day = attrs.all_day; this.attendee_people = attrs.attendee; this.how_display_event = ''; + - if (typeof attrs.quick_create_instance !== "undefined") - self.quick_create_class = attrs.quick_create_instance; + if (!isNull(attrs.quick_create_instance)) + self.quick_create_class = 'instance.' + attrs.quick_create_instance; - if (typeof attrs.quick_add !== "undefined" && attrs.quick_add == "True") + if (!isNull(attrs.quick_add) && attrs.quick_add == "True") this.quick_add_pop = true; else this.quick_add_pop = false; - // The display format which will be used to display the event where fields are between "[" and "]" - if (typeof attrs.display !== "undefined") + if (!isNull(attrs.display)) this.how_display_event = attrs.display; // String with [FIELD] // If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter - if (attrs.event_open_popup == null || attrs.event_open_popup == "False") + if (isNull(attrs.event_open_popup) || attrs.event_open_popup == "False") this.open_popup_action = false; else { this.open_popup_action = attrs.event_open_popup; } // If this field is set to true, we will use de calendar_friends model as filter and not the color field. - if (typeof attrs.use_contacts !== "undefined" && attrs.use_contacts == "True") + if (!isNull(attrs.use_contacts) && attrs.use_contacts == "True") this.useContacts = true; else this.useContacts = false; // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event // The color is the color of the attendee, so don't need to show again that it will be present - if (typeof attrs.color_is_attendee == null || attrs.color_is_attendee == "False") + if (isNull(attrs.color_is_attendee) || attrs.color_is_attendee == "False") this.colorIsAttendee = false; else this.colorIsAttendee = true; - + + if (isNull(attrs.avatar_model)) { + this.avatar_model = 'res.partner'; + } + else { + if (attrs.avatar_model == 'False') { + this.avatar_model = null; + } + else { + this.avatar_model = attrs.avatar_model; + } + } + + if (isNull(attrs.avatar_title)) { + this.avatar_title = this.avatar_model; + } + else { + this.avatar_title = attrs.avatar_title; + } this.color_field = attrs.color; @@ -293,7 +315,7 @@ openerp.web_calendar = function(instance) { sidebar_items[filter_value] = filter_item ; filter_item = { value: -1, - label: "All partners [All]", + label: "All...", color: self.get_color(-1) }; sidebar_items[-1] = filter_item ; @@ -328,7 +350,7 @@ openerp.web_calendar = function(instance) { }, open_quick_create: function(data_template) { - if (this.quick) { + if (!isNull(this.quick)) { return this.quick.trigger('close'); } var QuickCreate = get_class(this.quick_create_class); @@ -515,8 +537,24 @@ openerp.web_calendar = function(instance) { function (the_attendee_people) { attendees.push(the_attendee_people); attendee_showed += 1; - if (attendee_showed<= MAX_ATTENDEES) { - the_title_avatar += ''; + if (attendee_showed<= MAX_ATTENDEES) { + if (self.avatar_model != null) { + //if (self.all_filters[the_attendee_people] != undefined) { + the_title_avatar += ''; + //} + //else { + // the_title_avatar += '' ; + //} + } + else { + if (!self.colorIsAttendee || the_attendee_people != temp_ret[self.color_field]) { + tempColor = (self.all_filters[the_attendee_people] != undefined) + ? self.all_filters[the_attendee_people].color + : self.all_filters[-1].color; + + the_title_avatar += '' + }//else don't add myself + } } else { attendee_other += self.all_attendees[the_attendee_people] +", "; @@ -593,7 +631,9 @@ openerp.web_calendar = function(instance) { date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate())) date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate())) data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]); - data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]); + if (this.date_stop) { + data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]); + } } else { @@ -685,13 +725,24 @@ openerp.web_calendar = function(instance) { self.all_attendees = {} all_attendees = _.chain(all_attendees).flatten().uniq().value(); - new instance.web.Model("res.partner").query(["name"]).filter([["id", "in",all_attendees]]).all().then(function(result) { - _.each(result, function(item) { - self.all_attendees[item.id] = item.name; + + if (self.avatar_title != null) { + new instance.web.Model(self.avatar_title).query(["name"]).filter([["id", "in",all_attendees]]).all().then(function(result) { + _.each(result, function(item) { + self.all_attendees[item.id] = item.name; + }); + }).done(function() { + return self.perform_necessary_name_gets(events).then(callback); + }); + } + else { + _.each(all_attendees,function(item){ + self.all_attendees[item] = ''; }); - }).done(function() { return self.perform_necessary_name_gets(events).then(callback); - }); + + } + } diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index 3deb1379b64..79635db0c65 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -29,10 +29,10 @@
- , + - + From e97db06cbe6f6f4c5fcd8b50743b9ba7d391c6a9 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Tue, 17 Dec 2013 13:20:38 +0100 Subject: [PATCH 18/25] [IMP] Improve the form opened by quick_create in web_calendar, add function for google calendar button, improve event on add event bzr revid: jke@openerp.com-20131217122038-rvrxp9lioa4ccw8b --- .../static/src/js/fullcalendar.js | 107 ++++++++++-------- .../static/src/xml/web_fullcalendar.xml | 7 +- 2 files changed, 64 insertions(+), 50 deletions(-) diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index e5e0ad1a814..207452e2a3a 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -340,7 +340,7 @@ openerp.web_calendar = function(instance) { } ); }; - + this.extraSideBar(); } self.$calendar.fullCalendar(self.get_fc_init_options()); @@ -348,6 +348,9 @@ openerp.web_calendar = function(instance) { return $.when(); }, + extraSideBar: function() { + console.log("In extra Side bar from fullcalendar"); + }, open_quick_create: function(data_template) { if (!isNull(this.quick)) { @@ -356,6 +359,7 @@ openerp.web_calendar = function(instance) { var QuickCreate = get_class(this.quick_create_class); this.options.disable_quick_create = this.options.disable_quick_create || !this.quick_add_pop; + this.quick = new QuickCreate(this, this.dataset, true, this.options, data_template); this.quick.on('added', this, this.proxy('quick_created')) .on('slowadded', this, this.proxy('slow_created')) @@ -366,6 +370,7 @@ openerp.web_calendar = function(instance) { }); this.quick.replace($(".oe_calendar_qc_placeholder")); this.quick.focus(); + }, /** @@ -616,20 +621,24 @@ openerp.web_calendar = function(instance) { var event_end = event.end; //Bug when we move an all_day event from week or day view, we don't have a dateend or duration... if (event_end == null) { - debugger; event_end = new Date(event.start).addHours(2); } - - + if (event.allDay) { // Sometimes fullcalendar doesn't give any event.end. if (event_end === null || typeof event_end === "undefined") event_end = new Date(event.start); // Avoid inplace changes - event_end = (new Date(event_end.getTime())).addDays(1); - date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate())) - date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate())) + if (this.all_day) { + event_end = (new Date(event_end.getTime())).addDays(1); //midnight to midnight + date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate())) + date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate())) + } + else { + date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7)) + date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19)) + } data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]); if (this.date_stop) { data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]); @@ -935,10 +944,12 @@ openerp.web_calendar = function(instance) { }, get_title: function () { var parent = this.getParent(); - var title = - (typeof parent.field_widget === "undefined") ? + if (typeof parent === 'undefined') { + return _t("Create") + } + var title = (typeof parent.field_widget === "undefined") ? (parent.string || parent.name) : - parent.field_widget.string || parent.field_widget.name || ''; + parent.field_widget.string || parent.field_widget.name || ''; return _t("Create: ") + title; }, start: function () { @@ -951,13 +962,21 @@ openerp.web_calendar = function(instance) { } self.$input = this.$el.find('input'); - self.$input.keyup(function(event) { + self.$input.keyup(function enterHandler (event) { if(event.keyCode == 13){ - self.quick_add(); + self.$input.off('keyup', enterHandler); + if (!self.quick_add()){ + self.$input.on('keyup', enterHandler); + } } }); - this.$el.find(".oe_calendar_quick_create_add").click(function () { - self.quick_add(); + + var submit = this.$el.find(".oe_calendar_quick_create_add"); + submit.click(function clickHandler() { + submit.off('click', clickHandler); + if (!self.quick_add()){ + submit.on('click', clickHandler); + } self.focus(); }); this.$el.find(".oe_calendar_quick_create_edit").click(function () { @@ -968,7 +987,7 @@ openerp.web_calendar = function(instance) { ev.preventDefault(); self.trigger('close'); }); - self.$input.keyup(function(e) { + self.$input.keyup(function enterHandler (e) { if (e.keyCode == 27 && self._buttons) { self.trigger('close'); } @@ -993,8 +1012,8 @@ openerp.web_calendar = function(instance) { */ quick_add: function() { var val = this.$input.val(); - if (/^\s*$/.test(val)) { return; } - this.quick_create({'name': val}); + if (/^\s*$/.test(val)) { return false; } + return this.quick_create({'name': val}).always(function() { return true }); }, slow_add: function() { @@ -1007,7 +1026,7 @@ openerp.web_calendar = function(instance) { */ quick_create: function(data, options) { var self = this; - this.dataset.create($.extend({}, this.data_template, data), options) + return this.dataset.create($.extend({}, this.data_template, data), options) .then(function(id) { self.trigger('added', id); self.$input.val(""); @@ -1021,6 +1040,17 @@ openerp.web_calendar = function(instance) { /** * Show full form popup */ + get_form_popup_infos: function() { + var parent = this.getParent(); + var infos = { + view_id: false, + title: this.name, + }; + if (typeof parent !== 'undefined' && typeof parent.ViewManager !== 'undefined') { + infos.view_id = parent.ViewManager.get_view_id('form'); + } + return infos; + }, slow_create: function(data) { var self = this; var def = $.Deferred(); @@ -1034,33 +1064,21 @@ openerp.web_calendar = function(instance) { delete defaults['default_duration']; } + var pop_infos = self.get_form_popup_infos(); var pop = new instance.web.form.FormOpenPopup(this); var context = new instance.web.CompoundContext(this.dataset.context, defaults) - pop.show_element(this.dataset.model, null, context, { + pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), { title: this.get_title(), disable_multiple_selection: true, + view_id: pop_infos.view_id, // Ensuring we use ``self.dataset`` and DO NOT create a new one. create_function: function(data, options) { return self.dataset.create(data, options).done(function(r) { - // Although ``self.dataset.create`` DOES not call ``dataset_changed`` in O2M - // it gets called thanks to ``create_completed`` -> ``added`` - // XXXvlab: why ``create`` does not call dataset_changed AND adds id in dataset.ids - // is a mystery for me ATM. }).fail(function (r, event) { if (!r.data.message) //else manage by openerp throw new Error(r); }); }, - - // ATM this method should not be attainable as the current pop up is - // spawned only for newly created objects. - - // write_function: function(id, data, options) { - // return self.dataset.write(id, data, options).done(function() { - // }).fail(function (r, event) { - // throw new Error(r); - // }); - // }, read_function: function(id, fields, options) { return self.dataset.read_ids.apply(self.dataset, arguments).done(function() { }).fail(function (r, event) { @@ -1070,14 +1088,9 @@ openerp.web_calendar = function(instance) { }, }); pop.on('closed', self, function() { - // Hum, this is bad trick happening: we must avoid - // calling ``self.trigger('close')`` directly because - // it would itself destroy all child element including - // the slow create popup, which would then re-trigger - // recursively the 'closed' signal. - // - // Thus, here, we use a deferred and its state to cut - // the endless recurrence. + // ``self.trigger('close')`` would itself destroy all child element including + // the slow create popup, which would then re-trigger recursively the 'closed' signal. + // Thus, here, we use a deferred and its state to cut the endless recurrence. if (def.state() === "pending") def.resolve(); }); @@ -1285,7 +1298,6 @@ openerp.web_calendar = function(instance) { } var loaded = $.Deferred(); this.calendar_view.on("calendar_view_loaded", self, function() { - alert('Why never here ?'); self.initial_is_loaded.resolve(); loaded.resolve(); }); @@ -1404,9 +1416,8 @@ openerp.web_calendar = function(instance) { init: function(field_manager, node) { this._super(field_manager, node); this.dataset.on('dataset_changed', this, function() { - // Force dirty state, as if dataset changed, then 'get_value' - // result will change because it uses directly the dataset to - // compute its result. + // Force dirty state, as if dataset changed, then 'get_value' result will change + // because it uses directly the dataset to compute its result. this.trigger('changed_value'); }); }, @@ -1454,20 +1465,19 @@ openerp.web_calendar = function(instance) { filter_click: function(e) { var self = this, responsibles = []; - //$e = $(e.target); self.view.selected_filters = []; this.$('div.oe_calendar_responsible input:checked').each(function() { responsibles.push($(this).val()); if (e==null && parseInt($(this).val())<0) { $(this).prop('checked',false); -; return; + return; } self.view.selected_filters.push(parseInt($(this).val())); }); if (e !== null) { //First intialize - self.view.$calendar.fullCalendar('refetchEvents'); //RERENDER ALL... + self.view.$calendar.fullCalendar('refetchEvents'); } @@ -1487,4 +1497,3 @@ openerp.web_calendar = function(instance) { }; -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index 79635db0c65..df838460452 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -54,7 +54,12 @@
- + +
+ + +
+
From 00d43cd601beb1927c421fca7c65df02002689ec Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Tue, 17 Dec 2013 15:07:19 +0100 Subject: [PATCH 19/25] [TYPO] Typo and go in edit mode by default and not view mode when editing an event bzr revid: jke@openerp.com-20131217140719-3nh6pmwmg716d9jh --- addons/web_calendar/static/src/js/fullcalendar.js | 15 ++++++++++++--- .../static/src/xml/web_fullcalendar.xml | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 207452e2a3a..ce03c8c63b1 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -802,10 +802,11 @@ openerp.web_calendar = function(instance) { return false; }, open_event: function(id,title) { + var self = this; if (! this.open_popup_action) { var index = this.dataset.get_id_index(id); this.dataset.index = index; - this.do_switch_view('form'); + this.do_switch_view('form', null, { mode: "edit" }); } else { @@ -823,7 +824,7 @@ openerp.web_calendar = function(instance) { var form_controller = pop.view_form; form_controller.on("load_record", self, function(){ button_delete = _.str.sprintf("",_t("Delete")); - button_edit = _.str.sprintf("",_t("Edit event >>")); + button_edit = _.str.sprintf("",_t("Edit Event")); pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete) @@ -837,6 +838,7 @@ openerp.web_calendar = function(instance) { ); $('.editme').click( function() { + /* var action = { type: 'ir.actions.act_window', res_model: 'crm.meeting', @@ -845,9 +847,16 @@ openerp.web_calendar = function(instance) { views: [[false, 'form']], res_id: id, context: {}, + mode:"edit", }; - $('.oe_form_button_cancel').trigger('click'); self.do_action(action); + */ + $('.oe_form_button_cancel').trigger('click'); + + var index = self.dataset.get_id_index(id); + self.dataset.index = index; + self.do_switch_view('form', null, { mode: "edit" }); + } ); diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index df838460452..d0c156b0133 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -63,7 +63,7 @@
- +
From b5059e1d525b0e774923fade7c1b2f183c499622 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Wed, 18 Dec 2013 10:10:20 +0100 Subject: [PATCH 20/25] [FIX] Add required on field res.partner from model Contacts to avoid the creation of empty coworkers bzr revid: jke@openerp.com-20131218091020-8upymhda9nd84fg8 --- addons/web_calendar/contacts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web_calendar/contacts.py b/addons/web_calendar/contacts.py index ddc11ab044d..854e1e7fc58 100644 --- a/addons/web_calendar/contacts.py +++ b/addons/web_calendar/contacts.py @@ -5,7 +5,7 @@ class web_calendar_contacts(osv.osv): _columns = { 'user_id': fields.many2one('res.users','Me'), - 'partner_id': fields.many2one('res.partner','Contact'), + 'partner_id': fields.many2one('res.partner','Contact',required=True), 'active':fields.boolean('active'), } _defaults = { From 698a74c0a2f4c2c7df3b6f1d268758ce4166b68d Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Fri, 20 Dec 2013 15:50:28 +0100 Subject: [PATCH 21/25] [FIX] Fixe according to aprs review bzr revid: jke@openerp.com-20131220145028-2vy4t19uxgrh9jw4 --- addons/web_calendar/contacts.py | 2 +- addons/web_calendar/contacts_view.xml | 5 ++-- .../web_calendar/security/ir.model.access.csv | 2 +- .../static/src/js/fullcalendar.js | 26 ++++++++++++++----- .../static/src/xml/web_fullcalendar.xml | 19 +++++++------- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/addons/web_calendar/contacts.py b/addons/web_calendar/contacts.py index 854e1e7fc58..32ab6df3b83 100644 --- a/addons/web_calendar/contacts.py +++ b/addons/web_calendar/contacts.py @@ -5,7 +5,7 @@ class web_calendar_contacts(osv.osv): _columns = { 'user_id': fields.many2one('res.users','Me'), - 'partner_id': fields.many2one('res.partner','Contact',required=True), + 'partner_id': fields.many2one('res.partner','Employee',required=True, domain=[('customer','=',True)]), 'active':fields.boolean('active'), } _defaults = { diff --git a/addons/web_calendar/contacts_view.xml b/addons/web_calendar/contacts_view.xml index e168ba08fe1..05642944d21 100644 --- a/addons/web_calendar/contacts_view.xml +++ b/addons/web_calendar/contacts_view.xml @@ -19,10 +19,9 @@

- Click to add your first contact. + Click on "create" to select colleagues you want to see meetings.

- Add your contacts here to see the events which are created by them.
- Each contact will have it own color on calendar, to see easily who is busy... + Your colleagues will appear in the right list to see them in the calendar view. You will easily manage collaboration and meeting with them.

diff --git a/addons/web_calendar/security/ir.model.access.csv b/addons/web_calendar/security/ir.model.access.csv index d616183a6cf..ea1b4050949 100644 --- a/addons/web_calendar/security/ir.model.access.csv +++ b/addons/web_calendar/security/ir.model.access.csv @@ -1,3 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_web_calendar_contacts_all,access_web_calendar_contacts_all,model_web_calendar_contacts,,1,0,0,0 +access_web_calendar_contacts_all,access_web_calendar_contacts_all,model_web_calendar_contacts,,1,1,1,1 access_web_calendar_contacts,access_web_calendar_contacts,model_web_calendar_contacts,base.group_system,1,1,1,1 diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index ce03c8c63b1..946b6cf0a96 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -144,6 +144,7 @@ openerp.web_calendar = function(instance) { else this.colorIsAttendee = true; +/* if (isNull(attrs.avatar_model)) { this.avatar_model = 'res.partner'; } @@ -154,7 +155,15 @@ openerp.web_calendar = function(instance) { else { this.avatar_model = attrs.avatar_model; } + } +*/ + if (isNull(attrs.avatar_model)) { + this.avatar_model = null; } + else { + this.avatar_model = attrs.avatar_model; + } + if (isNull(attrs.avatar_title)) { this.avatar_title = this.avatar_model; @@ -310,13 +319,15 @@ openerp.web_calendar = function(instance) { var filter_item = { value: filter_value, label: result.partner_id[1] + " [Me]", - color: self.get_color(filter_value) + color: self.get_color(filter_value), + avatar_model: self.avatar_model }; sidebar_items[filter_value] = filter_item ; filter_item = { value: -1, label: "All...", - color: self.get_color(-1) + color: self.get_color(-1), + avatar_model: self.avatar_model }; sidebar_items[-1] = filter_item ; @@ -326,7 +337,8 @@ openerp.web_calendar = function(instance) { filter_item = { value: filter_value, label: item.partner_id[1], - color: self.get_color(filter_value) + color: self.get_color(filter_value), + avatar_model: self.avatar_model }; sidebar_items[filter_value] = filter_item ; }); @@ -349,7 +361,6 @@ openerp.web_calendar = function(instance) { return $.when(); }, extraSideBar: function() { - console.log("In extra Side bar from fullcalendar"); }, open_quick_create: function(data_template) { @@ -713,7 +724,8 @@ openerp.web_calendar = function(instance) { filter_item = { value: filter_value, label: e[self.color_field][1], - color: self.get_color(filter_value) + color: self.get_color(filter_value), + avatar_model: self.avatar_model }; if (!now_filters[e[self.color_field][0]]) now_filters[e[self.color_field][0]] = filter_item; @@ -1493,9 +1505,9 @@ openerp.web_calendar = function(instance) { }, addUpdateButton: function() { var self=this; - var button = ""; + var button = ""; this.$('div.oe_calendar_all_responsibles').append(button); - this.$(".add_contacts_link").on('click', function() { + this.$(".add_contacts_link_btn").on('click', function() { self.rpc("/web/action/load", { action_id: "web_calendar.action_calendar_contacts" }).then( function(result) { return self.do_action(result); }); diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index d0c156b0133..4102113ebaa 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -26,16 +26,17 @@
-
- - - +
+ + + + + + + + + - - - - -
From d5f350eac71183f617f735344eb0145f7c8ffdf7 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Fri, 20 Dec 2013 17:07:41 +0100 Subject: [PATCH 22/25] [TYPO] cleaning bzr revid: jke@openerp.com-20131220160741-qg53c46autlrvn3v --- addons/web_calendar/contacts_view.xml | 2 +- .../static/src/js/fullcalendar.js | 33 +++---------------- .../static/src/xml/web_fullcalendar.xml | 3 +- 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/addons/web_calendar/contacts_view.xml b/addons/web_calendar/contacts_view.xml index 05642944d21..4977608c727 100644 --- a/addons/web_calendar/contacts_view.xml +++ b/addons/web_calendar/contacts_view.xml @@ -2,7 +2,7 @@ - My Contacts + My Coworkers web_calendar.contacts diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/fullcalendar.js index 946b6cf0a96..aac81398a6f 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/fullcalendar.js @@ -1,5 +1,3 @@ -/*globals: openerp, $, console */ - /*--------------------------------------------------------- * OpenERP web_calendar *---------------------------------------------------------*/ @@ -145,6 +143,8 @@ openerp.web_calendar = function(instance) { this.colorIsAttendee = true; /* + Will be more logic to do it in futur, but see below to stay Retro-compatible + if (isNull(attrs.avatar_model)) { this.avatar_model = 'res.partner'; } @@ -513,7 +513,7 @@ openerp.web_calendar = function(instance) { if (value === false) temp_ret[fieldname] = null; else if (value instanceof Array) - temp_ret[fieldname] = value[1]; // Yipee, no name_get to make + temp_ret[fieldname] = value[1]; // no name_get to make else throw new Error("Incomplete data received from dataset for record " + evt.id); } @@ -555,12 +555,7 @@ openerp.web_calendar = function(instance) { attendee_showed += 1; if (attendee_showed<= MAX_ATTENDEES) { if (self.avatar_model != null) { - //if (self.all_filters[the_attendee_people] != undefined) { the_title_avatar += ''; - //} - //else { - // the_title_avatar += '' ; - //} } else { if (!self.colorIsAttendee || the_attendee_people != temp_ret[self.color_field]) { @@ -606,12 +601,11 @@ openerp.web_calendar = function(instance) { if (typeof color_key === "object") { color_key = color_key[0]; } - //r.color = this.get_color(color_key); r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key); } } else { // if form all, get color -1 -// r.color = self.all_filters[-1].color; + r.className = 'cal_opacity calendar_color_'+ self.all_filters[-1].color; } @@ -705,8 +699,7 @@ openerp.web_calendar = function(instance) { return null; } } - else { //We adds all events # TO TEST ? if (self.isInArray(self.selected_filters,e[self.color_field])){ - + else { //We adds all events return e; } return null; @@ -787,9 +780,6 @@ openerp.web_calendar = function(instance) { [this.date_start, '<=', format(end.clone())]]); }, - // do_show: function () { - // this.$el.show(); - // }, /** * Updates record identified by ``id`` with values in object ``data`` @@ -850,19 +840,6 @@ openerp.web_calendar = function(instance) { ); $('.editme').click( function() { - /* - var action = { - type: 'ir.actions.act_window', - res_model: 'crm.meeting', - view_mode: 'form', - view_type: 'form', - views: [[false, 'form']], - res_id: id, - context: {}, - mode:"edit", - }; - self.do_action(action); - */ $('.oe_form_button_cancel').trigger('click'); var index = self.dataset.get_id_index(id); diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index 4102113ebaa..1d81aee1f8f 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -27,7 +27,7 @@
- + @@ -65,7 +65,6 @@
-
From 4a6d2a508ef0a5d176ff3317e6bb73d4c036fed8 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Fri, 20 Dec 2013 18:13:55 +0100 Subject: [PATCH 23/25] [IMP] Remove unused library jquery.ui.touch-punch bzr revid: jke@openerp.com-20131220171355-2t77njuxx697mjh5 --- addons/web/__openerp__.py | 1 - .../js/jquery.ui.touch-punch.js | 160 ------------------ 2 files changed, 161 deletions(-) delete mode 100644 addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index 51d433a2656..09347eea24c 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -31,7 +31,6 @@ This module provides the core of the OpenERP Web Client. "static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js", "static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js", "static/lib/jquery.ui.notify/js/jquery.notify.js", - "static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js", "static/lib/jquery.deferred-queue/jquery.deferred-queue.js", "static/lib/jquery.scrollTo/jquery.scrollTo-min.js", "static/lib/jquery.tipsy/jquery.tipsy.js", diff --git a/addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js b/addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js deleted file mode 100644 index 2766f4184d6..00000000000 --- a/addons/web/static/lib/jquery.ui.touch-punch/js/jquery.ui.touch-punch.js +++ /dev/null @@ -1,160 +0,0 @@ -/*! - * jQuery UI Touch Punch 0.2.2 - * - * Copyright 2011, Dave Furfero - * Dual licensed under the MIT or GPL Version 2 licenses. - * - * Depends: - * jquery.ui.widget.js - * jquery.ui.mouse.js - */ -(function ($) { - - // Detect touch support - $.support.touch = 'ontouchend' in document; - - // Ignore browsers without touch support - if (!$.support.touch) { - return; - } - - var mouseProto = $.ui.mouse.prototype, - _mouseInit = mouseProto._mouseInit, - touchHandled; - - /** - * Simulate a mouse event based on a corresponding touch event - * @param {Object} event A touch event - * @param {String} simulatedType The corresponding mouse event - */ - function simulateMouseEvent (event, simulatedType) { - - // Ignore multi-touch events - if (event.originalEvent.touches.length > 1) { - return; - } - - event.preventDefault(); - - var touch = event.originalEvent.changedTouches[0], - simulatedEvent = document.createEvent('MouseEvents'); - - // Initialize the simulated mouse event using the touch event's coordinates - simulatedEvent.initMouseEvent( - simulatedType, // type - true, // bubbles - true, // cancelable - window, // view - 1, // detail - touch.screenX, // screenX - touch.screenY, // screenY - touch.clientX, // clientX - touch.clientY, // clientY - false, // ctrlKey - false, // altKey - false, // shiftKey - false, // metaKey - 0, // button - null // relatedTarget - ); - - // Dispatch the simulated event to the target element - event.target.dispatchEvent(simulatedEvent); - } - - /** - * Handle the jQuery UI widget's touchstart events - * @param {Object} event The widget element's touchstart event - */ - mouseProto._touchStart = function (event) { - - var self = this; - - // Ignore the event if another widget is already being handled - if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) { - return; - } - - // Set the flag to prevent other widgets from inheriting the touch event - touchHandled = true; - - // Track movement to determine if interaction was a click - self._touchMoved = false; - - // Simulate the mouseover event - simulateMouseEvent(event, 'mouseover'); - - // Simulate the mousemove event - simulateMouseEvent(event, 'mousemove'); - - // Simulate the mousedown event - simulateMouseEvent(event, 'mousedown'); - }; - - /** - * Handle the jQuery UI widget's touchmove events - * @param {Object} event The document's touchmove event - */ - mouseProto._touchMove = function (event) { - - // Ignore event if not handled - if (!touchHandled) { - return; - } - - // Interaction was not a click - this._touchMoved = true; - - // Simulate the mousemove event - simulateMouseEvent(event, 'mousemove'); - }; - - /** - * Handle the jQuery UI widget's touchend events - * @param {Object} event The document's touchend event - */ - mouseProto._touchEnd = function (event) { - - // Ignore event if not handled - if (!touchHandled) { - return; - } - - // Simulate the mouseup event - simulateMouseEvent(event, 'mouseup'); - - // Simulate the mouseout event - simulateMouseEvent(event, 'mouseout'); - - // If the touch interaction did not move, it should trigger a click - if (!this._touchMoved) { - - // Simulate the click event - simulateMouseEvent(event, 'click'); - } - - // Unset the flag to allow other widgets to inherit the touch event - touchHandled = false; - }; - - /** - * A duck punch of the $.ui.mouse _mouseInit method to support touch events. - * This method extends the widget with bound touch event handlers that - * translate touch events to mouse events and pass them to the widget's - * original mouse event handling methods. - */ - mouseProto._mouseInit = function () { - - var self = this; - - // Delegate the touch handlers to the widget's element - self.element - .bind('touchstart', $.proxy(self, '_touchStart')) - .bind('touchmove', $.proxy(self, '_touchMove')) - .bind('touchend', $.proxy(self, '_touchEnd')); - - // Call the original $.ui.mouse init method - _mouseInit.call(self); - }; - -})(jQuery); \ No newline at end of file From 4d728f85dc36a704b740bee88de3feaf06197986 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Fri, 10 Jan 2014 18:03:33 +0100 Subject: [PATCH 24/25] [IMP] Improve according first review CHS bzr revid: jke@openerp.com-20140110170333-vkvhw7zon9h2qw6n --- addons/web_calendar/__init__.py | 1 - addons/web_calendar/__openerp__.py | 5 +- addons/web_calendar/contacts.py | 14 - addons/web_calendar/contacts_view.xml | 30 - .../web_calendar/security/ir.model.access.csv | 3 - .../static/src/css/web_fullcalendar.css | 598 +++++---------- .../static/src/css/web_fullcalendar.sass | 696 +++++++++--------- .../js/{fullcalendar.js => web_calendar.js} | 187 ++--- .../static/src/xml/web_fullcalendar.xml | 11 +- 9 files changed, 659 insertions(+), 886 deletions(-) delete mode 100644 addons/web_calendar/contacts.py delete mode 100644 addons/web_calendar/contacts_view.xml delete mode 100644 addons/web_calendar/security/ir.model.access.csv rename addons/web_calendar/static/src/js/{fullcalendar.js => web_calendar.js} (92%) diff --git a/addons/web_calendar/__init__.py b/addons/web_calendar/__init__.py index 74856718eeb..e69de29bb2d 100644 --- a/addons/web_calendar/__init__.py +++ b/addons/web_calendar/__init__.py @@ -1 +0,0 @@ -import contacts \ No newline at end of file diff --git a/addons/web_calendar/__openerp__.py b/addons/web_calendar/__openerp__.py index cb75471b152..090684a764c 100644 --- a/addons/web_calendar/__openerp__.py +++ b/addons/web_calendar/__openerp__.py @@ -8,10 +8,7 @@ OpenERP Web Calendar view. """, 'version': '2.0', 'depends': ['web'], - 'data' : [ - 'contacts_view.xml', - 'security/ir.model.access.csv', - ], + 'data' : [], 'js': [ 'static/lib/fullcalendar/js/fullcalendar.js', 'static/src/js/*.js' diff --git a/addons/web_calendar/contacts.py b/addons/web_calendar/contacts.py deleted file mode 100644 index 32ab6df3b83..00000000000 --- a/addons/web_calendar/contacts.py +++ /dev/null @@ -1,14 +0,0 @@ -from openerp.osv import fields, osv - -class web_calendar_contacts(osv.osv): - _name = 'web_calendar.contacts' - - _columns = { - 'user_id': fields.many2one('res.users','Me'), - 'partner_id': fields.many2one('res.partner','Employee',required=True, domain=[('customer','=',True)]), - 'active':fields.boolean('active'), - } - _defaults = { - 'user_id': lambda self, cr, uid, ctx: uid, - 'active' : True, - } \ No newline at end of file diff --git a/addons/web_calendar/contacts_view.xml b/addons/web_calendar/contacts_view.xml deleted file mode 100644 index 4977608c727..00000000000 --- a/addons/web_calendar/contacts_view.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - My Coworkers - web_calendar.contacts - - - - - - - - - Calendar Contacts - web_calendar.contacts - form - tree - - -

- Click on "create" to select colleagues you want to see meetings. -

- Your colleagues will appear in the right list to see them in the calendar view. You will easily manage collaboration and meeting with them. -

-
-
- -
-
\ No newline at end of file diff --git a/addons/web_calendar/security/ir.model.access.csv b/addons/web_calendar/security/ir.model.access.csv deleted file mode 100644 index ea1b4050949..00000000000 --- a/addons/web_calendar/security/ir.model.access.csv +++ /dev/null @@ -1,3 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_web_calendar_contacts_all,access_web_calendar_contacts_all,model_web_calendar_contacts,,1,1,1,1 -access_web_calendar_contacts,access_web_calendar_contacts,model_web_calendar_contacts,base.group_system,1,1,1,1 diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.css b/addons/web_calendar/static/src/css/web_fullcalendar.css index dbaccd788ba..188376f75cc 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.css +++ b/addons/web_calendar/static/src/css/web_fullcalendar.css @@ -1,471 +1,275 @@ @charset "utf-8"; .openerp .oe_view_manager_view_calendar { - position: relative; -} + position: relative; } .openerp .oe_calendar_table { margin-top: 10px; - margin-left: 5px; -} + margin-left: 5px; } .openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer { - z-index: 10; -} + z-index: 10; } .openerp td.oe_calendar_sidebar_container { - padding: 10px; -} + padding: 10px; } img.attendee_head { height: 18px; - width: 18px; -} + width: 18px; } -.attendee_head { +.openerp .oe_calendar_table .attendee_head { float: right; margin-left: 1px; - size: 18px !important; -} - -.cal_avatar { + size: 18px !important; } +.openerp .oe_calendar_table .cal_avatar { height: 24px; - width: 24px; -} - -.cal_opacity { - opacity: 0.6; -} - -.event_color_1 { + width: 24px; } +.openerp .oe_calendar_table .cal_opacity { + opacity: 0.6; } +.openerp .oe_calendar_table .event_color_1 { background-color: #a4bdfc; - color: #0d0d0d; -} - -.event_color_2 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_2 { background-color: #7ae7bf; - color: #0d0d0d; -} - -.event_color_3 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_3 { background-color: #dbadff; - color: #0d0d0d; -} - -.event_color_4 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_4 { background-color: #ff887c; - color: #0d0d0d; -} - -.event_color_5 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_5 { background-color: #fbd75b; - color: #0d0d0d; -} - -.event_color_6 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_6 { background-color: #ffb878; - color: #0d0d0d; -} - -.event_color_7 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_7 { background-color: #46d6db; - color: #0d0d0d; -} - -.event_color_8 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_8 { background-color: #e1e1e1; - color: #0d0d0d; -} - -.event_color_9 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_9 { background-color: #5484ed; - color: #0d0d0d; -} - -.event_color_10 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_10 { background-color: #51b749; - color: #0d0d0d; -} - -.event_color_11 { + color: #0d0d0d; } +.openerp .oe_calendar_table .event_color_11 { background-color: #dc2127; - color: #0d0d0d; -} - -.calendar_color_1 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_1 { border-color: #ac725e; background-color: #ac725e; - color: #0d0d0d; -} - -.calendar_color_2 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_2 { border-color: #d06b64; background-color: #d06b64; - color: #0d0d0d; -} - -.calendar_color_3 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_3 { border-color: #f83a22; background-color: #f83a22; - color: #0d0d0d; -} - -.calendar_color_4 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_4 { border-color: #fa573c; background-color: #fa573c; - color: #0d0d0d; -} - -.calendar_color_5 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_5 { border-color: #ff7537; background-color: #ff7537; - color: #0d0d0d; -} - -.calendar_color_6 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_6 { border-color: #ffad46; background-color: #ffad46; - color: #0d0d0d; -} - -.calendar_color_7 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_7 { border-color: #42d692; background-color: #42d692; - color: #0d0d0d; -} - -.calendar_color_8 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_8 { border-color: #16a765; background-color: #16a765; - color: #0d0d0d; -} - -.calendar_color_9 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_9 { border-color: #7bd148; background-color: #7bd148; - color: #0d0d0d; -} - -.calendar_color_10 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_10 { border-color: #b3dc6c; background-color: #b3dc6c; - color: #0d0d0d; -} - -.calendar_color_11 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_11 { border-color: #fbe983; background-color: #fbe983; - color: #0d0d0d; -} - -.calendar_color_12 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_12 { border-color: #fad165; background-color: #fad165; - color: #0d0d0d; -} - -.calendar_color_13 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_13 { border-color: #92e1c0; background-color: #92e1c0; - color: #0d0d0d; -} - -.calendar_color_14 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_14 { border-color: #9fe1e7; background-color: #9fe1e7; - color: #0d0d0d; -} - -.calendar_color_15 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_15 { border-color: #9fc6e7; background-color: #9fc6e7; - color: #0d0d0d; -} - -.calendar_color_16 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_16 { border-color: #4986e7; background-color: #4986e7; - color: #0d0d0d; -} - -.calendar_color_17 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_17 { border-color: #9a9cff; background-color: #9a9cff; - color: #0d0d0d; -} - -.calendar_color_18 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_18 { border-color: #b99aff; background-color: #b99aff; - color: #0d0d0d; -} - -.calendar_color_19 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_19 { border-color: #c2c2c2; background-color: #c2c2c2; - color: #0d0d0d; -} - -.calendar_color_20 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_20 { border-color: #cabdbf; background-color: #cabdbf; - color: #0d0d0d; -} - -.calendar_color_21 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_21 { border-color: #cca6ac; background-color: #cca6ac; - color: #0d0d0d; -} - -.calendar_color_22 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_22 { border-color: #f691b2; background-color: #f691b2; - color: #0d0d0d; -} - -.calendar_color_23 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_23 { border-color: #cd74e6; background-color: #cd74e6; - color: #0d0d0d; -} - -.calendar_color_24 { + color: #0d0d0d; } +.openerp .oe_calendar_table .calendar_color_24 { border-color: #a47ae2; background-color: #a47ae2; - color: #0d0d0d; -} - -.underline_ecolor_1 { - border-bottom: 4px solid #a4bdfc; -} - -.underline_ecolor_2 { - border-bottom: 4px solid #7ae7bf; -} - -.underline_ecolor_3 { - border-bottom: 4px solid #dbadff; -} - -.underline_ecolor_4 { - border-bottom: 4px solid #ff887c; -} - -.underline_ecolor_5 { - border-bottom: 4px solid #fbd75b; -} - -.underline_ecolor_6 { - border-bottom: 4px solid #ffb878; -} - -.underline_ecolor_7 { - border-bottom: 4px solid #46d6db; -} - -.underline_ecolor_8 { - border-bottom: 4px solid #e1e1e1; -} - -.underline_ecolor_9 { - border-bottom: 4px solid #5484ed; -} - -.underline_ecolor_10 { - border-bottom: 4px solid #51b749; -} - -.underline_ecolor_11 { - border-bottom: 4px solid #dc2127; -} - -.underline_color_1 { - border-bottom: 4px solid #ac725e; -} - -.underline_color_2 { - border-bottom: 4px solid #d06b64; -} - -.underline_color_3 { - border-bottom: 4px solid #f83a22; -} - -.underline_color_4 { - border-bottom: 4px solid #fa573c; -} - -.underline_color_5 { - border-bottom: 4px solid #ff7537; -} - -.underline_color_6 { - border-bottom: 4px solid #ffad46; -} - -.underline_color_7 { - border-bottom: 4px solid #42d692; -} - -.underline_color_8 { - border-bottom: 4px solid #16a765; -} - -.underline_color_9 { - border-bottom: 4px solid #7bd148; -} - -.underline_color_10 { - border-bottom: 4px solid #b3dc6c; -} - -.underline_color_11 { - border-bottom: 4px solid #fbe983; -} - -.underline_color_12 { - border-bottom: 4px solid #fad165; -} - -.underline_color_13 { - border-bottom: 4px solid #92e1c0; -} - -.underline_color_14 { - border-bottom: 4px solid #9fe1e7; -} - -.underline_color_15 { - border-bottom: 4px solid #9fc6e7; -} - -.underline_color_16 { - border-bottom: 4px solid #4986e7; -} - -.underline_color_17 { - border-bottom: 4px solid #9a9cff; -} - -.underline_color_18 { - border-bottom: 4px solid #b99aff; -} - -.underline_color_19 { - border-bottom: 4px solid #c2c2c2; -} - -.underline_color_20 { - border-bottom: 4px solid #cabdbf; -} - -.underline_color_21 { - border-bottom: 4px solid #cca6ac; -} - -.underline_color_22 { - border-bottom: 4px solid #f691b2; -} - -.underline_color_23 { - border-bottom: 4px solid #cd74e6; -} - -.underline_color_24 { - border-bottom: 4px solid #a47ae2; -} - -.color_1 { - color: #ac725e; -} - -.color_2 { - color: #d06b64; -} - -.color_3 { - color: #f83a22; -} - -.color_4 { - color: #fa573c; -} - -.color_5 { - color: #ff7537; -} - -.color_6 { - color: #ffad46; -} - -.color_7 { - color: #42d692; -} - -.color_8 { - color: #16a765; -} - -.color_9 { - color: #7bd148; -} - -.color_10 { - color: #b3dc6c; -} - -.color_11 { - color: #fbe983; -} - -.color_12 { - color: #fad165; -} - -.color_13 { - color: #92e1c0; -} - -.color_14 { - color: #9fe1e7; -} - -.color_15 { - color: #9fc6e7; -} - -.color_16 { - color: #4986e7; -} - -.color_17 { - color: #9a9cff; -} - -.color_18 { - color: #b99aff; -} - -.color_19 { - color: #c2c2c2; -} - -.color_20 { - color: #cabdbf; -} - -.color_21 { - color: #cca6ac; -} - -.color_22 { - color: #f691b2; -} - -.color_23 { - color: #cd74e6; -} - -.color_24 { - color: #a47ae2; -} + color: #0d0d0d; } +.openerp .oe_calendar_table .underline_ecolor_1 { + border-bottom: 4px solid #a4bdfc; } +.openerp .oe_calendar_table .underline_ecolor_2 { + border-bottom: 4px solid #7ae7bf; } +.openerp .oe_calendar_table .underline_ecolor_3 { + border-bottom: 4px solid #dbadff; } +.openerp .oe_calendar_table .underline_ecolor_4 { + border-bottom: 4px solid #ff887c; } +.openerp .oe_calendar_table .underline_ecolor_5 { + border-bottom: 4px solid #fbd75b; } +.openerp .oe_calendar_table .underline_ecolor_6 { + border-bottom: 4px solid #ffb878; } +.openerp .oe_calendar_table .underline_ecolor_7 { + border-bottom: 4px solid #46d6db; } +.openerp .oe_calendar_table .underline_ecolor_8 { + border-bottom: 4px solid #e1e1e1; } +.openerp .oe_calendar_table .underline_ecolor_9 { + border-bottom: 4px solid #5484ed; } +.openerp .oe_calendar_table .underline_ecolor_10 { + border-bottom: 4px solid #51b749; } +.openerp .oe_calendar_table .underline_ecolor_11 { + border-bottom: 4px solid #dc2127; } +.openerp .oe_calendar_table .underline_color_1 { + border-bottom: 4px solid #ac725e; } +.openerp .oe_calendar_table .underline_color_2 { + border-bottom: 4px solid #d06b64; } +.openerp .oe_calendar_table .underline_color_3 { + border-bottom: 4px solid #f83a22; } +.openerp .oe_calendar_table .underline_color_4 { + border-bottom: 4px solid #fa573c; } +.openerp .oe_calendar_table .underline_color_5 { + border-bottom: 4px solid #ff7537; } +.openerp .oe_calendar_table .underline_color_6 { + border-bottom: 4px solid #ffad46; } +.openerp .oe_calendar_table .underline_color_7 { + border-bottom: 4px solid #42d692; } +.openerp .oe_calendar_table .underline_color_8 { + border-bottom: 4px solid #16a765; } +.openerp .oe_calendar_table .underline_color_9 { + border-bottom: 4px solid #7bd148; } +.openerp .oe_calendar_table .underline_color_10 { + border-bottom: 4px solid #b3dc6c; } +.openerp .oe_calendar_table .underline_color_11 { + border-bottom: 4px solid #fbe983; } +.openerp .oe_calendar_table .underline_color_12 { + border-bottom: 4px solid #fad165; } +.openerp .oe_calendar_table .underline_color_13 { + border-bottom: 4px solid #92e1c0; } +.openerp .oe_calendar_table .underline_color_14 { + border-bottom: 4px solid #9fe1e7; } +.openerp .oe_calendar_table .underline_color_15 { + border-bottom: 4px solid #9fc6e7; } +.openerp .oe_calendar_table .underline_color_16 { + border-bottom: 4px solid #4986e7; } +.openerp .oe_calendar_table .underline_color_17 { + border-bottom: 4px solid #9a9cff; } +.openerp .oe_calendar_table .underline_color_18 { + border-bottom: 4px solid #b99aff; } +.openerp .oe_calendar_table .underline_color_19 { + border-bottom: 4px solid #c2c2c2; } +.openerp .oe_calendar_table .underline_color_20 { + border-bottom: 4px solid #cabdbf; } +.openerp .oe_calendar_table .underline_color_21 { + border-bottom: 4px solid #cca6ac; } +.openerp .oe_calendar_table .underline_color_22 { + border-bottom: 4px solid #f691b2; } +.openerp .oe_calendar_table .underline_color_23 { + border-bottom: 4px solid #cd74e6; } +.openerp .oe_calendar_table .underline_color_24 { + border-bottom: 4px solid #a47ae2; } +.openerp .oe_calendar_table .color_1 { + color: #ac725e; } +.openerp .oe_calendar_table .color_2 { + color: #d06b64; } +.openerp .oe_calendar_table .color_3 { + color: #f83a22; } +.openerp .oe_calendar_table .color_4 { + color: #fa573c; } +.openerp .oe_calendar_table .color_5 { + color: #ff7537; } +.openerp .oe_calendar_table .color_6 { + color: #ffad46; } +.openerp .oe_calendar_table .color_7 { + color: #42d692; } +.openerp .oe_calendar_table .color_8 { + color: #16a765; } +.openerp .oe_calendar_table .color_9 { + color: #7bd148; } +.openerp .oe_calendar_table .color_10 { + color: #b3dc6c; } +.openerp .oe_calendar_table .color_11 { + color: #fbe983; } +.openerp .oe_calendar_table .color_12 { + color: #fad165; } +.openerp .oe_calendar_table .color_13 { + color: #92e1c0; } +.openerp .oe_calendar_table .color_14 { + color: #9fe1e7; } +.openerp .oe_calendar_table .color_15 { + color: #9fc6e7; } +.openerp .oe_calendar_table .color_16 { + color: #4986e7; } +.openerp .oe_calendar_table .color_17 { + color: #9a9cff; } +.openerp .oe_calendar_table .color_18 { + color: #b99aff; } +.openerp .oe_calendar_table .color_19 { + color: #c2c2c2; } +.openerp .oe_calendar_table .color_20 { + color: #cabdbf; } +.openerp .oe_calendar_table .color_21 { + color: #cca6ac; } +.openerp .oe_calendar_table .color_22 { + color: #f691b2; } +.openerp .oe_calendar_table .color_23 { + color: #cd74e6; } +.openerp .oe_calendar_table .color_24 { + color: #a47ae2; } +.openerp .oe_calendar_table .oe_calendar_buttons_add_contact .add_contacts_link_btn { + margin-top: 10px; } diff --git a/addons/web_calendar/static/src/css/web_fullcalendar.sass b/addons/web_calendar/static/src/css/web_fullcalendar.sass index 460f9878db7..0e2ce4bb49f 100644 --- a/addons/web_calendar/static/src/css/web_fullcalendar.sass +++ b/addons/web_calendar/static/src/css/web_fullcalendar.sass @@ -1,5 +1,6 @@ @charset "utf-8" + $color1: #ac725e $color2: #d06b64 $color3: #f83a22 @@ -57,359 +58,364 @@ $fontcolor: #0d0d0d img.attendee_head height: 18px width: 18px - -.attendee_head - float: right - margin-left: 1px - size: 18px !important - -.cal_avatar - height: 24px - width: 24px - -.cal_opacity - opacity: 0.6 -.event_color_1 - background-color: $ecolor1 - color: $fontcolor - -.event_color_2 - background-color: $ecolor2 - color: $fontcolor - -.event_color_3 - background-color: $ecolor3 - color: $fontcolor - -.event_color_4 - background-color: $ecolor4 - color: $fontcolor - -.event_color_5 - background-color: $ecolor5 - color: $fontcolor - -.event_color_6 - background-color: $ecolor6 - color: $fontcolor - -.event_color_7 - background-color: $ecolor7 - color: $fontcolor - -.event_color_8 - background-color: $ecolor8 - color: $fontcolor - -.event_color_9 - background-color: $ecolor9 - color: $fontcolor - -.event_color_10 - background-color: $ecolor10 - color: $fontcolor - -.event_color_11 - background-color: $ecolor11 - color: $fontcolor - -.calendar_color_1 - border-color: $color1 - background-color: $color1 - color: $fontcolor - -.calendar_color_2 - border-color: $color2 - background-color: $color2 - color: $fontcolor - -.calendar_color_3 - border-color: $color3 - background-color: $color3 - color: $fontcolor - -.calendar_color_4 - border-color: $color4 - background-color: $color4 - color: $fontcolor - -.calendar_color_5 - border-color: $color5 - background-color: $color5 - color: $fontcolor - -.calendar_color_6 - border-color: $color6 - background-color: $color6 - color: $fontcolor - -.calendar_color_7 - border-color: $color7 - background-color: $color7 - color: $fontcolor - -.calendar_color_8 - border-color: $color8 - background-color: $color8 - color: $fontcolor - -.calendar_color_9 - border-color: $color9 - background-color: $color9 - color: $fontcolor - -.calendar_color_10 - border-color: $color10 - background-color: $color10 - color: $fontcolor - -.calendar_color_11 - border-color: $color11 - background-color: $color11 - color: $fontcolor - -.calendar_color_12 - border-color: $color12 - background-color: $color12 - color: $fontcolor - -.calendar_color_13 - border-color: $color13 - background-color: $color13 - color: $fontcolor - -.calendar_color_14 - border-color: $color14 - background-color: $color14 - color: $fontcolor - -.calendar_color_15 - border-color: $color15 - background-color: $color15 - color: $fontcolor - -.calendar_color_16 - border-color: $color16 - background-color: $color16 - color: $fontcolor - -.calendar_color_17 - border-color: $color17 - background-color: $color17 - color: $fontcolor - -.calendar_color_18 - border-color: $color18 - background-color: $color18 - color: $fontcolor - -.calendar_color_19 - border-color: $color19 - background-color: $color19 - color: $fontcolor - -.calendar_color_20 - border-color: $color20 - background-color: $color20 - color: $fontcolor - -.calendar_color_21 - border-color: $color21 - background-color: $color21 - color: $fontcolor - -.calendar_color_22 - border-color: $color22 - background-color: $color22 - color: $fontcolor - -.calendar_color_23 - border-color: $color23 - background-color: $color23 - color: $fontcolor +.openerp .oe_calendar_table + .attendee_head + float: right + margin-left: 1px + size: 18px !important -.calendar_color_24 - border-color: $color24 - background-color: $color24 - color: $fontcolor - - - -.underline_ecolor_1 - border-bottom: 4px solid $ecolor1 - -.underline_ecolor_2 - border-bottom: 4px solid $ecolor2 - -.underline_ecolor_3 - border-bottom: 4px solid $ecolor3 - -.underline_ecolor_4 - border-bottom: 4px solid $ecolor4 - -.underline_ecolor_5 - border-bottom: 4px solid $ecolor5 - -.underline_ecolor_6 - border-bottom: 4px solid $ecolor6 - -.underline_ecolor_7 - border-bottom: 4px solid $ecolor7 - -.underline_ecolor_8 - border-bottom: 4px solid $ecolor8 - -.underline_ecolor_9 - border-bottom: 4px solid $ecolor9 - -.underline_ecolor_10 - border-bottom: 4px solid $ecolor10 - -.underline_ecolor_11 - border-bottom: 4px solid $ecolor11 - + .cal_avatar + height: 24px + width: 24px -.underline_color_1 - border-bottom: 4px solid $color1 - -.underline_color_2 - border-bottom: 4px solid $color2 - -.underline_color_3 - border-bottom: 4px solid $color3 - -.underline_color_4 - border-bottom: 4px solid $color4 - -.underline_color_5 - border-bottom: 4px solid $color5 - -.underline_color_6 - border-bottom: 4px solid $color6 - -.underline_color_7 - border-bottom: 4px solid $color7 - -.underline_color_8 - border-bottom: 4px solid $color8 - -.underline_color_9 - border-bottom: 4px solid $color9 - -.underline_color_10 - border-bottom: 4px solid $color10 - -.underline_color_11 - border-bottom: 4px solid $color11 - -.underline_color_12 - border-bottom: 4px solid $color12 + .cal_opacity + opacity: 0.6 + + .event_color_1 + background-color: $ecolor1 + color: $fontcolor + + .event_color_2 + background-color: $ecolor2 + color: $fontcolor + + .event_color_3 + background-color: $ecolor3 + color: $fontcolor + + .event_color_4 + background-color: $ecolor4 + color: $fontcolor -.underline_color_13 - border-bottom: 4px solid $color13 - -.underline_color_14 - border-bottom: 4px solid $color14 - -.underline_color_15 - border-bottom: 4px solid $color15 - -.underline_color_16 - border-bottom: 4px solid $color16 - -.underline_color_17 - border-bottom: 4px solid $color17 - -.underline_color_18 - border-bottom: 4px solid $color18 - -.underline_color_19 - border-bottom: 4px solid $color19 - -.underline_color_20 - border-bottom: 4px solid $color20 - -.underline_color_21 - border-bottom: 4px solid $color21 - -.underline_color_22 - border-bottom: 4px solid $color22 - -.underline_color_23 - border-bottom: 4px solid $color23 - -.underline_color_24 - border-bottom: 4px solid $color24 - -.color_1 - color: $color1 - -.color_2 - color: $color2 - -.color_3 - color: $color3 - -.color_4 - color: $color4 - -.color_5 - color: $color5 - -.color_6 - color: $color6 - -.color_7 - color: $color7 - -.color_8 - color: $color8 - -.color_9 - color: $color9 - -.color_10 - color: $color10 - -.color_11 - color: $color11 - -.color_12 - color: $color12 + .event_color_5 + background-color: $ecolor5 + color: $fontcolor -.color_13 - color: $color13 + .event_color_6 + background-color: $ecolor6 + color: $fontcolor + + .event_color_7 + background-color: $ecolor7 + color: $fontcolor + + .event_color_8 + background-color: $ecolor8 + color: $fontcolor + + .event_color_9 + background-color: $ecolor9 + color: $fontcolor + + .event_color_10 + background-color: $ecolor10 + color: $fontcolor + + .event_color_11 + background-color: $ecolor11 + color: $fontcolor + + .calendar_color_1 + border-color: $color1 + background-color: $color1 + color: $fontcolor + + .calendar_color_2 + border-color: $color2 + background-color: $color2 + color: $fontcolor + + .calendar_color_3 + border-color: $color3 + background-color: $color3 + color: $fontcolor + + .calendar_color_4 + border-color: $color4 + background-color: $color4 + color: $fontcolor + + .calendar_color_5 + border-color: $color5 + background-color: $color5 + color: $fontcolor + + .calendar_color_6 + border-color: $color6 + background-color: $color6 + color: $fontcolor + + .calendar_color_7 + border-color: $color7 + background-color: $color7 + color: $fontcolor + + .calendar_color_8 + border-color: $color8 + background-color: $color8 + color: $fontcolor + + .calendar_color_9 + border-color: $color9 + background-color: $color9 + color: $fontcolor + + .calendar_color_10 + border-color: $color10 + background-color: $color10 + color: $fontcolor + + .calendar_color_11 + border-color: $color11 + background-color: $color11 + color: $fontcolor + + .calendar_color_12 + border-color: $color12 + background-color: $color12 + color: $fontcolor + + .calendar_color_13 + border-color: $color13 + background-color: $color13 + color: $fontcolor + + .calendar_color_14 + border-color: $color14 + background-color: $color14 + color: $fontcolor + + .calendar_color_15 + border-color: $color15 + background-color: $color15 + color: $fontcolor + + .calendar_color_16 + border-color: $color16 + background-color: $color16 + color: $fontcolor + + .calendar_color_17 + border-color: $color17 + background-color: $color17 + color: $fontcolor + + .calendar_color_18 + border-color: $color18 + background-color: $color18 + color: $fontcolor + + .calendar_color_19 + border-color: $color19 + background-color: $color19 + color: $fontcolor + + .calendar_color_20 + border-color: $color20 + background-color: $color20 + color: $fontcolor + + .calendar_color_21 + border-color: $color21 + background-color: $color21 + color: $fontcolor + + .calendar_color_22 + border-color: $color22 + background-color: $color22 + color: $fontcolor + + .calendar_color_23 + border-color: $color23 + background-color: $color23 + color: $fontcolor -.color_14 - color: $color14 + .calendar_color_24 + border-color: $color24 + background-color: $color24 + color: $fontcolor -.color_15 - color: $color15 -.color_16 - color: $color16 -.color_17 - color: $color17 + .underline_ecolor_1 + border-bottom: 4px solid $ecolor1 + + .underline_ecolor_2 + border-bottom: 4px solid $ecolor2 + + .underline_ecolor_3 + border-bottom: 4px solid $ecolor3 + + .underline_ecolor_4 + border-bottom: 4px solid $ecolor4 + + .underline_ecolor_5 + border-bottom: 4px solid $ecolor5 + + .underline_ecolor_6 + border-bottom: 4px solid $ecolor6 + + .underline_ecolor_7 + border-bottom: 4px solid $ecolor7 + + .underline_ecolor_8 + border-bottom: 4px solid $ecolor8 + + .underline_ecolor_9 + border-bottom: 4px solid $ecolor9 + + .underline_ecolor_10 + border-bottom: 4px solid $ecolor10 + + .underline_ecolor_11 + border-bottom: 4px solid $ecolor11 + + + .underline_color_1 + border-bottom: 4px solid $color1 + + .underline_color_2 + border-bottom: 4px solid $color2 + + .underline_color_3 + border-bottom: 4px solid $color3 + + .underline_color_4 + border-bottom: 4px solid $color4 + + .underline_color_5 + border-bottom: 4px solid $color5 + + .underline_color_6 + border-bottom: 4px solid $color6 + + .underline_color_7 + border-bottom: 4px solid $color7 + + .underline_color_8 + border-bottom: 4px solid $color8 + + .underline_color_9 + border-bottom: 4px solid $color9 + + .underline_color_10 + border-bottom: 4px solid $color10 + + .underline_color_11 + border-bottom: 4px solid $color11 + + .underline_color_12 + border-bottom: 4px solid $color12 + + .underline_color_13 + border-bottom: 4px solid $color13 + + .underline_color_14 + border-bottom: 4px solid $color14 + + .underline_color_15 + border-bottom: 4px solid $color15 + + .underline_color_16 + border-bottom: 4px solid $color16 + + .underline_color_17 + border-bottom: 4px solid $color17 + + .underline_color_18 + border-bottom: 4px solid $color18 + + .underline_color_19 + border-bottom: 4px solid $color19 + + .underline_color_20 + border-bottom: 4px solid $color20 + + .underline_color_21 + border-bottom: 4px solid $color21 + + .underline_color_22 + border-bottom: 4px solid $color22 + + .underline_color_23 + border-bottom: 4px solid $color23 -.color_18 - color: $color18 + .underline_color_24 + border-bottom: 4px solid $color24 + + .color_1 + color: $color1 + + .color_2 + color: $color2 + + .color_3 + color: $color3 + + .color_4 + color: $color4 + + .color_5 + color: $color5 + + .color_6 + color: $color6 + + .color_7 + color: $color7 + + .color_8 + color: $color8 + + .color_9 + color: $color9 + + .color_10 + color: $color10 + + .color_11 + color: $color11 + + .color_12 + color: $color12 + + .color_13 + color: $color13 + + .color_14 + color: $color14 + + .color_15 + color: $color15 + + .color_16 + color: $color16 + + .color_17 + color: $color17 + + .color_18 + color: $color18 + + .color_19 + color: $color19 + + .color_20 + color: $color20 + + .color_21 + color: $color21 + + .color_22 + color: $color22 + + .color_23 + color: $color23 -.color_19 - color: $color19 - -.color_20 - color: $color20 - -.color_21 - color: $color21 - -.color_22 - color: $color22 - -.color_23 - color: $color23 - -.color_24 - color: $color24 \ No newline at end of file + .color_24 + color: $color24 + + .oe_calendar_buttons_add_contact + .add_contacts_link_btn + margin-top: 10px \ No newline at end of file diff --git a/addons/web_calendar/static/src/js/fullcalendar.js b/addons/web_calendar/static/src/js/web_calendar.js similarity index 92% rename from addons/web_calendar/static/src/js/fullcalendar.js rename to addons/web_calendar/static/src/js/web_calendar.js index aac81398a6f..b051bd33a29 100644 --- a/addons/web_calendar/static/src/js/fullcalendar.js +++ b/addons/web_calendar/static/src/js/web_calendar.js @@ -28,16 +28,16 @@ openerp.web_calendar = function(instance) { return typeof id == "string" && id.indexOf('-') >= 0; } - function isNull(value) { - return typeof value === "undefined" || value === null + function isNullOrUndef(value) { + return _.isUndefined(value) || _.isNull(value) } - instance.web.views.add('calendar', 'instance.web_calendar.FullCalendarView'); + instance.web.views.add('calendar', 'instance.web_calendar.CalendarView'); - instance.web_calendar.FullCalendarView = instance.web.View.extend({ - template: "FullCalendarView", + instance.web_calendar.CalendarView = instance.web.View.extend({ + template: "CalendarView", display_name: _lt('Calendar'), - quick_create_class: 'instance.' + 'web_calendar.QuickCreate', + quick_create_instance: 'instance.web_calendar.QuickCreate', init: function (parent, dataset, view_id, options) { this._super(parent); @@ -58,7 +58,6 @@ openerp.web_calendar = function(instance) { set_default_options: function(options) { this._super(options); _.defaults(this.options, { - // All possible views options should be defaulted here confirm_on_delete: true, }); }, @@ -72,7 +71,7 @@ openerp.web_calendar = function(instance) { view_loading: function (fv) { var self = this; this.fields_view = fv; - this.$calendar = this.$el.find(".oe_fullcalendar_widget"); + this.$calendar = this.$el.find(".oe_calendar_widget"); this.info_fields = []; @@ -110,37 +109,36 @@ openerp.web_calendar = function(instance) { this.how_display_event = ''; - if (!isNull(attrs.quick_create_instance)) - self.quick_create_class = 'instance.' + attrs.quick_create_instance; + if (!isNullOrUndef(attrs.quick_create_instance)) { + self.quick_create_instance = 'instance.' + attrs.quick_create_instance; + } - if (!isNull(attrs.quick_add) && attrs.quick_add == "True") - this.quick_add_pop = true; - else - this.quick_add_pop = false; - + //if quick_add = False, we don't allow quick_add + //if quick_add = not specified in view, we use the default quick_create_instance + //if quick_add = is NOT False and IS specified in view, we this one for quick_create_instance' + this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || attrs.quick_add != "False"); + if (this.quick_add_pop && !isNullOrUndef(attrs.quick_add)) { + self.quick_create_instance = 'instance.' + attrs.quick_add; + } // The display format which will be used to display the event where fields are between "[" and "]" - if (!isNull(attrs.display)) + if (!isNullOrUndef(attrs.display)) { this.how_display_event = attrs.display; // String with [FIELD] + } // If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter - if (isNull(attrs.event_open_popup) || attrs.event_open_popup == "False") + if (isNullOrUndef(attrs.event_open_popup) || attrs.event_open_popup == "False") { this.open_popup_action = false; + } else { this.open_popup_action = attrs.event_open_popup; } // If this field is set to true, we will use de calendar_friends model as filter and not the color field. - if (!isNull(attrs.use_contacts) && attrs.use_contacts == "True") - this.useContacts = true; - else - this.useContacts = false; + this.useContacts = (!isNullOrUndef(attrs.use_contacts) && attrs.use_contacts == "True"); // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event // The color is the color of the attendee, so don't need to show again that it will be present - if (isNull(attrs.color_is_attendee) || attrs.color_is_attendee == "False") - this.colorIsAttendee = false; - else - this.colorIsAttendee = true; + this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || attrs.color_is_attendee == "False")); /* Will be more logic to do it in futur, but see below to stay Retro-compatible @@ -157,15 +155,14 @@ openerp.web_calendar = function(instance) { } } */ - if (isNull(attrs.avatar_model)) { + if (isNullOrUndef(attrs.avatar_model)) { this.avatar_model = null; } else { this.avatar_model = attrs.avatar_model; } - - if (isNull(attrs.avatar_title)) { + if (isNullOrUndef(attrs.avatar_title)) { this.avatar_title = this.avatar_model; } else { @@ -190,7 +187,7 @@ openerp.web_calendar = function(instance) { .call("check_access_rights", ["create", false]) .then(function (create_right) { self.create_right = create_right; - self.init_fullcalendar().then(function() { + self.init_calendar().then(function() { self.trigger('calendar_view_loaded', fv); self.ready.resolve(); }); @@ -198,6 +195,7 @@ openerp.web_calendar = function(instance) { }, get_fc_init_options: function () { + //Documentation here : http://arshaw.com/fullcalendar/docs/ var self = this; return $.extend({}, fc_defaultOptions, { @@ -257,8 +255,6 @@ openerp.web_calendar = function(instance) { var stored_data = $(this).data('eventDefaults'); data_template = $.extend({}, stored_data, data_template); - - // Opening quick create widget self.open_quick_create(data_template); }, unselectAuto: false, @@ -274,11 +270,8 @@ openerp.web_calendar = function(instance) { // for all other views '': 'h(:mm)tt' // 7pm }, - firstHour: 8, weekMode : 'liquid', aspectRatio: 1.8, - - }); }, @@ -299,14 +292,13 @@ openerp.web_calendar = function(instance) { } }, - init_fullcalendar: function() { + init_calendar: function() { var self = this; if (!this.sidebar && this.options.$sidebar) { this.sidebar = new instance.web_calendar.Sidebar(this); this.sidebar.appendTo(this.$el.find('.oe_calendar_sidebar_container')); - - //Initialize small calendar + this.$small_calendar = self.$el.find(".oe_calendar_mini"); this.$small_calendar.datepicker({ onSelect: self.calendarMiniChanged(self) }); @@ -318,20 +310,20 @@ openerp.web_calendar = function(instance) { var filter_value = result.partner_id[0]; var filter_item = { value: filter_value, - label: result.partner_id[1] + " [Me]", + label: result.partner_id[1] + _lt(" [Me]"), color: self.get_color(filter_value), avatar_model: self.avatar_model }; sidebar_items[filter_value] = filter_item ; filter_item = { value: -1, - label: "All...", + label: _lt("All..."), color: self.get_color(-1), avatar_model: self.avatar_model }; sidebar_items[-1] = filter_item ; - new instance.web.Model("web_calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) { + new instance.web.Model("calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) { _.each(result, function(item) { filter_value = item.partner_id[0]; filter_item = { @@ -364,16 +356,16 @@ openerp.web_calendar = function(instance) { }, open_quick_create: function(data_template) { - if (!isNull(this.quick)) { + if (!isNullOrUndef(this.quick)) { return this.quick.trigger('close'); } - var QuickCreate = get_class(this.quick_create_class); + var QuickCreate = get_class(this.quick_create_instance); this.options.disable_quick_create = this.options.disable_quick_create || !this.quick_add_pop; this.quick = new QuickCreate(this, this.dataset, true, this.options, data_template); - this.quick.on('added', this, this.proxy('quick_created')) - .on('slowadded', this, this.proxy('slow_created')) + this.quick.on('added', this, this.quick_created) + .on('slowadded', this, this.slow_created) .on('close', this, function() { this.quick.destroy(); delete this.quick; @@ -390,11 +382,12 @@ openerp.web_calendar = function(instance) { */ refresh_event: function(id) { var self = this; - if (is_virtual_id(id)) + if (is_virtual_id(id)) { // Should avoid "refreshing" a virtual ID because it can't // really be modified so it should never be refreshed. As upon // edition, a NEW event with a non-virtual id will be created. console.warn("Unwise use of refresh_event on a virtual ID."); + } this.dataset.read_ids([id], _.keys(this.fields)).done(function (incomplete_records) { self.perform_necessary_name_gets(incomplete_records).then(function(records) { // Event boundaries were already changed by fullcalendar, but we need to reload them: @@ -444,12 +437,14 @@ openerp.web_calendar = function(instance) { to_get[fieldname] = []; _(evts).each(function (evt) { var value = evt[fieldname]; - if (value === false || (value instanceof Array)) + if (value === false || (value instanceof Array)) { return; + } to_get[fieldname].push(value); }); - if (to_get[fieldname].length === 0) + if (to_get[fieldname].length === 0) { delete to_get[fieldname]; + } }); var defs = _(to_get).map(function (ids, fieldname) { return (new instance.web.Model(self.fields[fieldname].relation)) @@ -478,8 +473,9 @@ openerp.web_calendar = function(instance) { isInArray: function(array_is, array_in) { for(var z=0; z/g,'>'); + the_title = _.escape(the_title); + the_title_avatar = ''; - if (typeof this.attendee_people !== "undefined") { + if (! _.isUndefined(this.attendee_people)) { var MAX_ATTENDEES = 3; var attendee_showed = 0; var attendee_other = ''; @@ -631,12 +634,11 @@ openerp.web_calendar = function(instance) { if (event.allDay) { // Sometimes fullcalendar doesn't give any event.end. - if (event_end === null || typeof event_end === "undefined") + if (event_end === null || _.isUndefined(event_end)) { event_end = new Date(event.start); - // Avoid inplace changes - + } if (this.all_day) { - event_end = (new Date(event_end.getTime())).addDays(1); //midnight to midnight + event_end = (new Date(event_end.getTime())).addDays(1); date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate())) date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate())) } @@ -672,8 +674,9 @@ openerp.web_calendar = function(instance) { }, do_search: function(domain, context, _group_by) { var self = this; - if (typeof this.event_source !== "undefined") + if (! _.isUndefined(this.event_source)) { this.$calendar.fullCalendar('removeEventSource', this.event_source); + } this.event_source = { events: function(start, end, callback) { var current_event_source = self.event_source; @@ -683,7 +686,6 @@ openerp.web_calendar = function(instance) { context: context, }).done(function(events) { if (self.event_source !== current_event_source) { - // Event source changed while waiting for AJAX response console.log("Consecutive ``do_search`` called. Cancelling."); return; } @@ -692,7 +694,7 @@ openerp.web_calendar = function(instance) { events = $.map(events, function (e) { if (self.attendee_people != undefined) { //If we filter on contacts... - if (self.isInArray(self.selected_filters,e[self.attendee_people]) || (self.selected_filters.indexOf(-1) > -1)) { + if (_.intersection(self.selected_filters,e[self.attendee_people]).length || (self.selected_filters.indexOf(-1) > -1)) { return e; } else { @@ -705,8 +707,6 @@ openerp.web_calendar = function(instance) { return null; }); - - if (!self.useContacts) { // If we use all peoples as filter in sidebars var now_filters = {}; var filter_value; @@ -720,8 +720,9 @@ openerp.web_calendar = function(instance) { color: self.get_color(filter_value), avatar_model: self.avatar_model }; - if (!now_filters[e[self.color_field][0]]) + if (!now_filters[e[self.color_field][0]]) { now_filters[e[self.color_field][0]] = filter_item; + } }); self.allFilters = now_filters; @@ -872,8 +873,9 @@ openerp.web_calendar = function(instance) { return this._super(); }, is_action_enabled: function(action) { - if (action === 'create' && !this.options.creatable) + if (action === 'create' && !this.options.creatable) { return false; + } return this._super(action); }, @@ -892,7 +894,6 @@ openerp.web_calendar = function(instance) { * trigger action upon modification. */ this.dataset.ids = this.dataset.ids.concat([id]); - // Inform every body that dataset changed this.dataset.trigger("dataset_changed", id); this.refresh_event(id); }, @@ -942,10 +943,10 @@ openerp.web_calendar = function(instance) { }, get_title: function () { var parent = this.getParent(); - if (typeof parent === 'undefined') { + if (_.isUndefined(parent)) { return _t("Create") } - var title = (typeof parent.field_widget === "undefined") ? + var title = (_.isUndefined(parent.field_widget)) ? (parent.string || parent.name) : parent.field_widget.string || parent.field_widget.name || ''; return _t("Create: ") + title; @@ -1010,7 +1011,9 @@ openerp.web_calendar = function(instance) { */ quick_add: function() { var val = this.$input.val(); - if (/^\s*$/.test(val)) { return false; } + if (/^\s*$/.test(val)) { + return false; + } return this.quick_create({'name': val}).always(function() { return true }); }, @@ -1044,7 +1047,7 @@ openerp.web_calendar = function(instance) { view_id: false, title: this.name, }; - if (typeof parent !== 'undefined' && typeof parent.ViewManager !== 'undefined') { + if (!_.isUndefined(parent) && !(_.isUndefined(parent.ViewManager))) { infos.view_id = parent.ViewManager.get_view_id('form'); } return infos; @@ -1073,15 +1076,17 @@ openerp.web_calendar = function(instance) { create_function: function(data, options) { return self.dataset.create(data, options).done(function(r) { }).fail(function (r, event) { - if (!r.data.message) //else manage by openerp + if (!r.data.message) { //else manage by openerp throw new Error(r); + } }); }, read_function: function(id, fields, options) { return self.dataset.read_ids.apply(self.dataset, arguments).done(function() { }).fail(function (r, event) { - if (!r.data.message) //else manage by openerp + if (!r.data.message) { //else manage by openerp throw new Error(r); + } }); }, }); @@ -1089,8 +1094,9 @@ openerp.web_calendar = function(instance) { // ``self.trigger('close')`` would itself destroy all child element including // the slow create popup, which would then re-trigger recursively the 'closed' signal. // Thus, here, we use a deferred and its state to cut the endless recurrence. - if (def.state() === "pending") + if (def.state() === "pending") { def.resolve(); + } }); pop.on('create_completed', self, function(id) { self.trigger('slowadded'); @@ -1108,10 +1114,11 @@ openerp.web_calendar = function(instance) { */ function widget_calendar_lazy_init() { - if (instance.web.form.Many2ManyCalendarView) + if (instance.web.form.Many2ManyCalendarView) { return; + } - instance.web_fullcalendar.FieldFullCalendarView = instance.web_fullcalendar.FullCalendarView.extend({ + instance.web_calendar.FieldCalendarView = instance.web_calendar.CalendarView.extend({ init: function (parent) { this._super.apply(this, arguments); @@ -1131,7 +1138,7 @@ openerp.web_calendar = function(instance) { // In forms, we could be hidden in a notebook. Thus we couldn't // render correctly fullcalendar so we try to detect when we are // not visible to wait for when we will be visible. - init_fullcalendar: function() { + init_calendar: function() { if (this.$calendar.width() !== 0) { // visible return this._super(); } @@ -1166,7 +1173,7 @@ openerp.web_calendar = function(instance) { var def = $.Deferred(); var self = this; var create = this._super; - if (typeof this.required_fields === "undefined") { + if (_.isUndefined(this.required_fields)) { this.required_fields = (new instance.web.Model(this.model)) .call('fields_get').then(function (fields_def) { return _(fields_def).chain() @@ -1181,7 +1188,7 @@ openerp.web_calendar = function(instance) { } $.when(this.required_fields).then(function (required_fields) { var missing_fields = _(required_fields).filter(function (v) { - return typeof data[v] === "undefined"; + return _.isUndefined(data[v]); }); var default_get = (missing_fields.length !== 0) ? self.default_get(missing_fields) : []; @@ -1189,7 +1196,7 @@ openerp.web_calendar = function(instance) { // Remove all fields that have a default from the missing fields. missing_fields = _(missing_fields).filter(function (f) { - return typeof defaults[f] === "undefined"; + return _.isUndefined(defaults[f]); }); if (missing_fields.length !== 0) { def.reject( @@ -1238,7 +1245,7 @@ openerp.web_calendar = function(instance) { instance.web_calendar.FieldCalendar = instance.web.form.AbstractField.extend({ disable_utility_classes: true, - fullcalendar_view_class: 'instance.web_calendar.FieldFullCalendarView', + calendar_view_class: 'instance.web_calendar.FieldCalendarView', init: function(field_manager, node) { this._super(field_manager, node); @@ -1282,7 +1289,7 @@ openerp.web_calendar = function(instance) { load_view: function() { var self = this; - var calendar_view_class = get_class(this.fullcalendar_view_class); + var calendar_view_class = get_class(this.calendar_view_class); this.calendar_view = new calendar_view_class(this, this.dataset, false, $.extend({ 'create_text': _t("Add"), 'creatable': self.get("effective_readonly") ? false : true, @@ -1318,14 +1325,15 @@ openerp.web_calendar = function(instance) { }, open_popup: function(type, unused) { - if (type !== "form") - return; + if (type !== "form") { return; } if (this.dataset.index === null) { - if (typeof this.open_popup_add === "function") + if (typeof this.open_popup_add === "function") { this.open_popup_add(); + } } else { - if (typeof this.open_popup_edit === "function") + if (typeof this.open_popup_edit === "function") { this.open_popup_edit(); + } } }, open_popup_add: function() { @@ -1482,11 +1490,10 @@ openerp.web_calendar = function(instance) { }, addUpdateButton: function() { var self=this; - var button = ""; - this.$('div.oe_calendar_all_responsibles').append(button); + this.$('div.oe_calendar_all_responsibles').append(QWeb.render('CalendarView.sidebar.button_add_contact')); this.$(".add_contacts_link_btn").on('click', function() { self.rpc("/web/action/load", { - action_id: "web_calendar.action_calendar_contacts" + action_id: "calendar.action_calendar_contacts" }).then( function(result) { return self.do_action(result); }); }); diff --git a/addons/web_calendar/static/src/xml/web_fullcalendar.xml b/addons/web_calendar/static/src/xml/web_fullcalendar.xml index 1d81aee1f8f..615599781c1 100644 --- a/addons/web_calendar/static/src/xml/web_fullcalendar.xml +++ b/addons/web_calendar/static/src/xml/web_fullcalendar.xml @@ -1,10 +1,10 @@