diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 7d12473..d395abc 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,7 @@ X-editable changelog Version 1.4.4 wip ---------------------------- +[enh] update to bootstrap-datepicker 1.0.2 (vitalets) [enh] update to combodate 1.0.3 with yearDescending and roundTime options (vitalets) [enh] add 'use strict' directive (vitalets) [enh #202] allow pk=0 (mdeweerd) diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js index d5f9605..83d1018 100644 --- a/src/containers/editable-container.js +++ b/src/containers/editable-container.js @@ -54,24 +54,30 @@ Applied as jQuery method. var $target = $(e.target), i, exclude_classes = ['.editable-container', '.ui-datepicker-header', + '.datepicker', //in inline mode datepicker is rendered into body '.modal-backdrop', '.bootstrap-wysihtml5-insert-image-modal', '.bootstrap-wysihtml5-insert-link-modal' ]; + //check if element is detached. It occurs when clicking in bootstrap datepicker + if (!$.contains(document.documentElement, e.target)) { + return; + } + + //for some reason FF 20 generates extra event (click) in select2 widget with e.target = document + //we need to filter it via construction below. See https://github.com/vitalets/x-editable/issues/199 + //Possibly related to http://stackoverflow.com/questions/10119793/why-does-firefox-react-differently-from-webkit-and-ie-to-click-event-on-selec + if($target.is(document)) { + return; + } + //if click inside one of exclude classes --> no nothing for(i=0; i<exclude_classes.length; i++) { if($target.is(exclude_classes[i]) || $target.parents(exclude_classes[i]).length) { return; } } - - //for some reason FF 20 generates extra event (click) in select2 widget with e.target = document - //we need to filter it via construction below. See https://github.com/vitalets/x-editable/issues/199 - //Possibly related to http://stackoverflow.com/questions/10119793/why-does-firefox-react-differently-from-webkit-and-ie-to-click-event-on-selec - if($target.is(document)) { - return; - } //close all open containers (except one - target) Popup.prototype.closeOthers(e.target); diff --git a/src/inputs/date/bootstrap-datepicker/css/datepicker.css b/src/inputs/date/bootstrap-datepicker/css/datepicker.css index dfe9df8..5ecec5d 100644 --- a/src/inputs/date/bootstrap-datepicker/css/datepicker.css +++ b/src/inputs/date/bootstrap-datepicker/css/datepicker.css @@ -9,7 +9,6 @@ */ .datepicker { padding: 4px; - margin-top: 1px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; @@ -112,6 +111,7 @@ border-color: #fdf59a #fdf59a #fbed50; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #000 !important; } .datepicker table tr td.today:hover, .datepicker table tr td.today:hover:hover, diff --git a/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js b/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js index 3d80a50..8991aa8 100644 --- a/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js +++ b/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js @@ -41,13 +41,11 @@ this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||dates[this.language].format||'mm/dd/yyyy'); this.isInline = false; this.isInput = this.element.is('input'); - this.component = this.element.is('.date') ? this.element.find('.add-on') : false; + this.component = this.element.is('.date') ? this.element.find('.add-on, .btn') : false; this.hasInput = this.component && this.element.find('input').length; if(this.component && this.component.length === 0) this.component = false; - this._attachEvents(); - this.forceParse = true; if ('forceParse' in options) { this.forceParse = options.forceParse; @@ -55,16 +53,12 @@ this.forceParse = this.element.data('date-force-parse'); } - - this.picker = $(DPGlobal.template) - .appendTo(this.isInline ? this.element : 'body') - .on({ - click: $.proxy(this.click, this), - mousedown: $.proxy(this.mousedown, this) - }); + this.picker = $(DPGlobal.template); + this._buildEvents(); + this._attachEvents(); if(this.isInline) { - this.picker.addClass('datepicker-inline'); + this.picker.addClass('datepicker-inline').appendTo(this.element); } else { this.picker.addClass('datepicker-dropdown dropdown-menu'); } @@ -73,12 +67,6 @@ this.picker.find('.prev i, .next i') .toggleClass('icon-arrow-left icon-arrow-right'); } - $(document).on('mousedown', function (e) { - // Clicked outside the datepicker, hide it - if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) { - that.hide(); - } - }); this.autoclose = false; if ('autoclose' in options) { @@ -138,6 +126,8 @@ return parseInt(val) + 1; }); + this._allow_update = false; + this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7); this.weekEnd = ((this.weekStart + 6) % 7); this.startDate = -Infinity; @@ -148,6 +138,9 @@ this.setDaysOfWeekDisabled(options.daysOfWeekDisabled||this.element.data('date-days-of-week-disabled')); this.fillDow(); this.fillMonths(); + + this._allow_update = true; + this.update(); this.showMode(); @@ -160,8 +153,22 @@ constructor: Datepicker, _events: [], - _attachEvents: function(){ - this._detachEvents(); + _secondaryEvents: [], + _applyEvents: function(evs){ + for (var i=0, el, ev; i<evs.length; i++){ + el = evs[i][0]; + ev = evs[i][1]; + el.on(ev); + } + }, + _unapplyEvents: function(evs){ + for (var i=0, el, ev; i<evs.length; i++){ + el = evs[i][0]; + ev = evs[i][1]; + el.off(ev); + } + }, + _buildEvents: function(){ if (this.isInput) { // single input this._events = [ [this.element, { @@ -184,9 +191,9 @@ }] ]; } - else if (this.element.is('div')) { // inline datepicker - this.isInline = true; - } + else if (this.element.is('div')) { // inline datepicker + this.isInline = true; + } else { this._events = [ [this.element, { @@ -194,29 +201,47 @@ }] ]; } - for (var i=0, el, ev; i<this._events.length; i++){ - el = this._events[i][0]; - ev = this._events[i][1]; - el.on(ev); - } + + this._secondaryEvents = [ + [this.picker, { + click: $.proxy(this.click, this) + }], + [$(window), { + resize: $.proxy(this.place, this) + }], + [$(document), { + mousedown: $.proxy(function (e) { + // Clicked outside the datepicker, hide it + if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) { + this.hide(); + } + }, this) + }] + ]; + }, + _attachEvents: function(){ + this._detachEvents(); + this._applyEvents(this._events); }, _detachEvents: function(){ - for (var i=0, el, ev; i<this._events.length; i++){ - el = this._events[i][0]; - ev = this._events[i][1]; - el.off(ev); - } - this._events = []; + this._unapplyEvents(this._events); + }, + _attachSecondaryEvents: function(){ + this._detachSecondaryEvents(); + this._applyEvents(this._secondaryEvents); + }, + _detachSecondaryEvents: function(){ + this._unapplyEvents(this._secondaryEvents); }, show: function(e) { + if (!this.isInline) + this.picker.appendTo('body'); this.picker.show(); this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); - this.update(); this.place(); - $(window).on('resize', $.proxy(this.place, this)); - if (e ) { - e.stopPropagation(); + this._attachSecondaryEvents(); + if (e) { e.preventDefault(); } this.element.trigger({ @@ -228,13 +253,10 @@ hide: function(e){ if(this.isInline) return; if (!this.picker.is(':visible')) return; - this.picker.hide(); - $(window).off('resize', this.place); + this.picker.hide().detach(); + this._detachSecondaryEvents(); this.viewMode = this.startViewMode; this.showMode(); - if (!this.isInput) { - $(document).off('mousedown', this.hide); - } if ( this.forceParse && @@ -251,9 +273,14 @@ }, remove: function() { + this.hide(); this._detachEvents(); + this._detachSecondaryEvents(); this.picker.remove(); delete this.element.data().datepicker; + if (!this.isInput) { + delete this.element.data().date; + } }, getDate: function() { @@ -327,7 +354,7 @@ var zIndex = parseInt(this.element.parents().filter(function() { return $(this).css('z-index') != 'auto'; }).first().css('z-index'))+10; - var offset = this.component ? this.component.offset() : this.element.offset(); + var offset = this.component ? this.component.parent().offset() : this.element.offset(); var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(true); this.picker.css({ top: offset.top + height, @@ -336,7 +363,10 @@ }); }, + _allow_update: true, update: function(){ + if (!this._allow_update) return; + var date, fromArgs = false; if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { date = arguments[0]; @@ -491,6 +521,8 @@ }, updateNavArrows: function() { + if (!this._allow_update) return; + var d = new Date(this.viewDate), year = d.getUTCFullYear(), month = d.getUTCMonth(); @@ -524,7 +556,6 @@ }, click: function(e) { - e.stopPropagation(); e.preventDefault(); var target = $(e.target).closest('span, td, th'); if (target.length == 1) {