Skip to content

Commit fa38a54

Browse files
committed
Fixed picker transition bug
This bug happened when the widget was in the middle of a transition. It was solved by ignoring hide invocations while transitioning.
1 parent e0ab0c1 commit fa38a54

File tree

1 file changed

+53
-27
lines changed

1 file changed

+53
-27
lines changed

src/js/bootstrap-datetimepicker.js

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,30 @@
3737
constructor: DateTimePicker,
3838

3939
init: function(element, options) {
40+
var icon;
4041
if (!(options.pickTime || options.pickDate))
4142
throw new Error('Must choose at least one picker');
4243
this.$element = $(element);
43-
this.format = options.format || this.$element.data('date-format') || 'mm/dd/yyyy';
44+
this.format = options.format || this.$element.data('date-format') || 'MM/dd/yyyy';
4445
this._compileFormat();
4546
this.language = options.language in dates ? options.language : 'en'
46-
this.picker = $(getTemplate(this.id, options.pickDate, options.pickTime)).appendTo('body');
47-
if (options.pickDate && options.pickTime) {
48-
this.picker.on('click', '.accordion-toggle', function(e) {
49-
e.stopPropagation();
50-
var $this = $(this);
51-
var $parent = $this.closest('ul');
52-
var expanded = $parent.find('.collapse.in');
53-
var closed = $parent.find('.collapse:not(.in)');
54-
55-
if (expanded && expanded.length) {
56-
var hasData = expanded.data('collapse');
57-
if (hasData && hasData.transitioning) return;
58-
expanded.collapse('hide');
59-
closed.collapse('show')
60-
$this.find('i').toggleClass('icon-chevron-down icon-chevron-up');
61-
}
62-
});
63-
}
47+
this.pickDate = options.pickDate;
48+
this.pickTime = options.pickTime;
6449
this.isInput = this.$element.is('input');
6550
this.component = this.$element.is('.date') ? this.$element.find('.add-on') : false;
66-
51+
if (this.component) {
52+
icon = this.component.find('i');
53+
}
54+
if (this.pickTime) {
55+
this.timeIcon = icon.data('time-icon') || 'icon-time';
56+
icon.addClass(this.timeIcon);
57+
}
58+
if (this.pickDate) {
59+
this.dateIcon = icon.data('date-icon') || 'icon-calendar';
60+
icon.removeClass(this.timeIcon);
61+
icon.addClass(this.dateIcon);
62+
}
63+
this.picker = $(getTemplate(this.timeIcon, options.pickDate, options.pickTime)).appendTo('body');
6764
this.minViewMode = options.minViewMode||this.$element.data('date-minviewmode')||0;
6865
if (typeof this.minViewMode === 'string') {
6966
switch (this.minViewMode) {
@@ -110,14 +107,21 @@
110107
type: 'show',
111108
date: this.date
112109
});
113-
this._attachDatePickerWidgetEvents();
110+
this._attachDatePickerGlobalEvents();
114111
if (e) {
115112
e.stopPropagation();
116113
e.preventDefault();
117114
}
118115
},
119116

120117
hide: function() {
118+
// Ignore event if in the middle of a picker transition
119+
var collapse = this.picker.find('.collapse')
120+
for (var i = 0; i < collapse.length; i++) {
121+
var collapseData = collapse.eq(i).data('collapse');
122+
if (collapseData && collapseData.transitioning)
123+
return;
124+
}
121125
this.picker.hide();
122126
this.viewMode = this.startViewMode;
123127
this.showMode();
@@ -126,7 +130,7 @@
126130
type: 'hide',
127131
date: this.date
128132
});
129-
this._detachDatePickerWidgetEvents();
133+
this._detachDatePickerGlobalEvents();
130134
},
131135

132136
set: function() {
@@ -332,7 +336,7 @@
332336

333337
destroy: function() {
334338
this._detachDatePickerEvents();
335-
this._detachDatePickerWidgetEvents();
339+
this._detachDatePickerGlobalEvents();
336340
this.picker.remove();
337341
this.$element.removeData('datetimepicker');
338342
this.component.removeData('datetimepicker');
@@ -384,10 +388,29 @@
384388
},
385389

386390
_attachDatePickerEvents: function() {
391+
var self = this;
387392
this.picker.on({
388393
click: $.proxy(this.click, this),
389394
mousedown: $.proxy(this.mousedown, this)
390395
});
396+
if (this.pickDate && this.pickTime) {
397+
this.picker.on('click.togglePicker', '.accordion-toggle', function(e) {
398+
e.stopPropagation();
399+
var $this = $(this);
400+
var $parent = $this.closest('ul');
401+
var expanded = $parent.find('.collapse.in');
402+
var closed = $parent.find('.collapse:not(.in)');
403+
404+
if (expanded && expanded.length) {
405+
var collapseData = expanded.data('collapse');
406+
if (collapseData && collapseData.transitioning) return;
407+
expanded.collapse('hide');
408+
closed.collapse('show')
409+
$this.find('i').toggleClass(self.timeIcon + ' ' + self.dateIcon);
410+
self.$element.find('.add-on i').toggleClass(self.timeIcon + ' ' + self.dateIcon);
411+
}
412+
});
413+
}
391414
if (this.isInput) {
392415
this.$element.on({
393416
focus: $.proxy(this.show, this),
@@ -403,7 +426,7 @@
403426
}
404427
},
405428

406-
_attachDatePickerWidgetEvents: function() {
429+
_attachDatePickerGlobalEvents: function() {
407430
$(window).on('resize.datetimepicker' + this.id, $.proxy(this.place, this));
408431
if (!this.isInput) {
409432
$(document).on('mousedown.datetimepicker' + this.id, $.proxy(this.hide, this));
@@ -415,6 +438,9 @@
415438
click: this.click,
416439
mousedown: this.mousedown
417440
});
441+
if (this.pickDate && this.pickTime) {
442+
this.picker.off('click.togglePicker');
443+
}
418444
if (this.isInput) {
419445
this.$element.off({
420446
focus: this.show,
@@ -430,7 +456,7 @@
430456
}
431457
},
432458

433-
_detachDatePickerWidgetEvents: function () {
459+
_detachDatePickerGlobalEvents: function () {
434460
$(window).off('resize.datetimepicker' + this.id);
435461
if (!this.isInput) {
436462
$(document).off('mousedown.datetimepicker' + this.id);
@@ -507,7 +533,7 @@
507533
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
508534
}
509535

510-
function getTemplate(id, pickDate, pickTime) {
536+
function getTemplate(timeIcon, pickDate, pickTime) {
511537
if (pickDate && pickTime) {
512538
return (
513539
'<ul class="datetimepicker dropdown-menu">' +
@@ -516,7 +542,7 @@
516542
DPGlobal.template +
517543
'</div>' +
518544
'</li>' +
519-
'<li class="picker-switch"><a class="accordion-toggle"><i class="icon-chevron-down"></i></a></li>' +
545+
'<li class="picker-switch"><a class="accordion-toggle"><i class="' + timeIcon + '"></i></a></li>' +
520546
'<li class="collapse">' +
521547
'<div class="timepicker">' +
522548
TPGlobal.template +

0 commit comments

Comments
 (0)