Skip to content

Commit c307ead

Browse files
committed
Merge branch 'master' of git://github.com/eternicode/bootstrap-datepicker into develop
* 'master' of git://github.com/eternicode/bootstrap-datepicker: this fixes an issue with IE7 that causes a Expected identifier, string or numbererror in said browser. Impact on other browsers is 0. Remove extra comma Fix whitespace Document remove function Detach events and remove Datepicker object in remove function Extract event handler manip to separate functions Make force-parsing optional Force-parse invalid dates into valid input values when picker is hidden Use local date parts when building the default UTC date Remove debugging cruft >_< Actually, there's a better solution to that Prevent infinite loop with invalid values Prevent infinite loop on invalid month (fixes uxsolutions#224) Fix for uxsolutions#214: javascript error for ms locale in IE8 Add a remove function to the datepicker object
2 parents 9013d4a + 557debd commit c307ead

File tree

8 files changed

+123
-45
lines changed

8 files changed

+123
-45
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ String. Default: 'en'
170170

171171
The two-letter code of the language to use for month and day names. These will also be used as the input's value (and subsequently sent to the server in the case of form submissions). Currently ships with English ('en'), German ('de'), Brazilian ('br'), and Spanish ('es') translations, but others can be added (see I18N below). If an unknown language code is given, English will be used.
172172

173+
### forceParse
174+
175+
Boolean. Default: true
176+
177+
Whether or not to force parsing of the input value when the picker is closed. That is, when an invalid date is left in the input field by the user, the picker will forcibly parse that value, and set the input's value to the new, valid date, conforming to the given `format`.
178+
173179
## Markup
174180

175181
Format a component.
@@ -185,6 +191,15 @@ Format a component.
185191

186192
Initializes an datepicker.
187193

194+
### remove
195+
196+
Arguments: None
197+
198+
Remove the datepicker. Removes attached events, internal attached objects, and
199+
added HTML elements.
200+
201+
$('#datepicker').datepicker('remove');
202+
188203
### show
189204

190205
Arguments: None

js/bootstrap-datepicker.js

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,13 @@
4848
if(this.component && this.component.length === 0)
4949
this.component = false;
5050

51-
if (this.isInput) {
52-
this.element.on({
53-
focus: $.proxy(this.show, this),
54-
keyup: $.proxy(this.update, this),
55-
keydown: $.proxy(this.keydown, this)
56-
});
57-
} else {
58-
if (this.component && this.hasInput){
59-
// For components that are not readonly, allow keyboard nav
60-
this.element.find('input').on({
61-
focus: $.proxy(this.show, this),
62-
keyup: $.proxy(this.update, this),
63-
keydown: $.proxy(this.keydown, this)
64-
});
51+
this._attachEvents();
6552

66-
this.component.on('click', $.proxy(this.show, this));
67-
} else {
68-
this.element.on('click', $.proxy(this.show, this));
69-
}
53+
this.forceParse = true;
54+
if ('forceParse' in options) {
55+
this.forceParse = options.forceParse;
56+
} else if ('dateForceParse' in this.element.data()) {
57+
this.forceParse = this.element.data('date-force-parse');
7058
}
7159

7260
$(document).on('mousedown', function (e) {
@@ -126,6 +114,53 @@
126114
Datepicker.prototype = {
127115
constructor: Datepicker,
128116

117+
_events: [],
118+
_attachEvents: function(){
119+
this._detachEvents();
120+
if (this.isInput) {
121+
this._events = [
122+
[this.element, {
123+
focus: $.proxy(this.show, this),
124+
keyup: $.proxy(this.update, this),
125+
keydown: $.proxy(this.keydown, this)
126+
}]
127+
];
128+
}
129+
else if (this.component && this.hasInput){
130+
this._events = [
131+
// For components that are not readonly, allow keyboard nav
132+
[this.element.find('input'), {
133+
focus: $.proxy(this.show, this),
134+
keyup: $.proxy(this.update, this),
135+
keydown: $.proxy(this.keydown, this)
136+
}],
137+
[this.component, {
138+
click: $.proxy(this.show, this)
139+
}]
140+
];
141+
}
142+
else {
143+
this._events = [
144+
[this.element, {
145+
click: $.proxy(this.show, this)
146+
}]
147+
];
148+
}
149+
for (var i=0, el, ev; i<this._events.length; i++){
150+
el = this._events[i][0];
151+
ev = this._events[i][1];
152+
el.on(ev);
153+
}
154+
},
155+
_detachEvents: function(){
156+
for (var i=0, el, ev; i<this._events.length; i++){
157+
el = this._events[i][0];
158+
ev = this._events[i][1];
159+
el.off(ev);
160+
}
161+
this._events = [];
162+
},
163+
129164
show: function(e) {
130165
this.picker.show();
131166
this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
@@ -150,14 +185,27 @@
150185
if (!this.isInput) {
151186
$(document).off('mousedown', this.hide);
152187
}
153-
if (e && e.currentTarget.value)
188+
189+
if (
190+
this.forceParse &&
191+
(
192+
this.isInput && this.element.val() ||
193+
this.hasInput && this.element.find('input').val()
194+
)
195+
)
154196
this.setValue();
155197
this.element.trigger({
156198
type: 'hide',
157199
date: this.date
158200
});
159201
},
160202

203+
remove: function() {
204+
this._detachEvents();
205+
this.picker.remove();
206+
delete this.element.data().datepicker;
207+
},
208+
161209
getDate: function() {
162210
var d = this.getUTCDate();
163211
return new Date(d.getTime() + (d.getTimezoneOffset()*60000))
@@ -760,7 +808,7 @@
760808
val, filtered, part;
761809
setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
762810
setters_map['dd'] = setters_map['d'];
763-
date = UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
811+
date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
764812
if (parts.length == format.parts.length) {
765813
for (var i=0, cnt = format.parts.length; i < cnt; i++) {
766814
val = parseInt(parts[i], 10);
@@ -789,7 +837,7 @@
789837
}
790838
for (var i=0, s; i<setters_order.length; i++){
791839
s = setters_order[i];
792-
if (s in parsed)
840+
if (s in parsed && !isNaN(parsed[s]))
793841
setters_map[s](date, parsed[s])
794842
}
795843
}

js/locales/bootstrap-datepicker.bg.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
/**
2-
* Bulgarian translation for bootstrap-datepicker
3-
* Apostol Apostolov <apostol.s.apostolov@gmail.com>
4-
*/
5-
;(function($){
6-
$.fn.datepicker.dates['bg'] = {
7-
days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя"],
8-
daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб", "Нед"],
9-
daysMin: ["Н", "П", "В", "С", "Ч", "П", "С", "Н"],
10-
months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"],
11-
monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"],
12-
today: "днес"
13-
};
14-
}(jQuery));
1+
/**
2+
* Bulgarian translation for bootstrap-datepicker
3+
* Apostol Apostolov <apostol.s.apostolov@gmail.com>
4+
*/
5+
;(function($){
6+
$.fn.datepicker.dates['bg'] = {
7+
days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя"],
8+
daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб", "Нед"],
9+
daysMin: ["Н", "П", "В", "С", "Ч", "П", "С", "Н"],
10+
months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"],
11+
monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"],
12+
today: "днес"
13+
};
14+
}(jQuery));

js/locales/bootstrap-datepicker.kr.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
daysShort: ["일", "월", "화", "수", "목", "금", "토", "일"],
99
daysMin: ["일", "월", "화", "수", "목", "금", "토", "일"],
1010
months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
11-
monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"],
11+
monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"]
1212
};
1313
}(jQuery));

js/locales/bootstrap-datepicker.ms.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab", "Aha"],
99
daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa", "Ah"],
1010
months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"],
11-
monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"]
11+
monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"],
1212
today: "Hari Ini"
1313
};
1414
}(jQuery));

tests/suites/formats.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,18 @@ test('Regression: End-of-month bug', patch_date(function(Date){
193193
.datepicker('setValue');
194194
equal(this.input.val(), '29-02-2012');
195195
}));
196+
197+
test('Invalid formats are force-parsed into a valid date on tab', patch_date(function(Date){
198+
Date.now = UTCDate(2012, 4, 31);
199+
this.input
200+
.val('44-44-4444')
201+
.datepicker({format: 'yyyy-MM-dd'})
202+
.focus();
203+
204+
this.input.trigger({
205+
type: 'keydown',
206+
keyCode: 9
207+
});
208+
209+
equal(this.input.val(), '56-September-30');
210+
}));

tests/suites/keyboard_navigation/all.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test('TAB hides picker', function(){
1616
var target;
1717

1818
ok(this.picker.is(':visible'), 'Picker is visible');
19-
19+
2020
this.input.trigger({
2121
type: 'keydown',
2222
keyCode: 9

tests/suites/mouse_navigation/all.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@ module('Mouse Navigation (All)', {
1313
});
1414

1515
test('Clicking datepicker does not hide datepicker', function(){
16-
ok(this.picker.is(':visible'), 'Picker is visible');
16+
ok(this.picker.is(':visible'), 'Picker is visible');
1717
this.picker.trigger('mousedown');
1818
ok(this.picker.is(':visible'), 'Picker is still visible');
1919
});
2020

21-
test('Clicking outside datepicker hides datepicker', function(){
21+
test('Clicking outside datepicker hides datepicker', function(){
2222
var $otherelement = $('<div />');
23-
$('body').append($otherelement);
23+
$('body').append($otherelement);
2424

25-
ok(this.picker.is(':visible'), 'Picker is visible');
26-
this.input.trigger('click');
27-
ok(this.picker.is(':visible'), 'Picker is still visible');
25+
ok(this.picker.is(':visible'), 'Picker is visible');
26+
this.input.trigger('click');
27+
ok(this.picker.is(':visible'), 'Picker is still visible');
2828

2929
$otherelement.trigger('mousedown');
3030
ok(this.picker.is(':not(:visible)'), 'Picker is hidden');
3131

3232
$otherelement.remove();
33-
});
33+
});

0 commit comments

Comments
 (0)