bootstrap3-datetimepicker-rails 2.1.30 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -13,8 +13,8 @@ actively maintained and works with [Bootstrap3](http://getbootstrap.com).
13
13
 
14
14
  Add these lines to your application's Gemfile:
15
15
  ```
16
- gem 'momentjs-rails', '~> '2.5.0'
17
- gem 'bootstrap3-datetimepicker-rails', '~> 2.1.30'
16
+ gem 'momentjs-rails', '~> 2.5.0'
17
+ gem 'bootstrap3-datetimepicker-rails', '~> 3.0.0'
18
18
  ```
19
19
 
20
20
  And then execute:
@@ -39,7 +39,7 @@ Add the following to your Javascript manifest file (`application.js`):
39
39
  If you want to include a localization, also add:
40
40
  ```js
41
41
  //= require moment/<locale>
42
- //= require locales/bootstrap-datetimepicker.<locale>
42
+ //= require locales/bootstrap-datetimepicker.<locale>.js
43
43
  ```
44
44
 
45
45
  Add the following to your stylesheet file:
@@ -1,5 +1,5 @@
1
1
  module Bootstrap3Datetimepicker
2
2
  module Rails
3
- VERSION = '2.1.30'
3
+ VERSION = '3.0.0'
4
4
  end
5
5
  end
@@ -1,41 +1,42 @@
1
- /**
2
- * version 2.1.30
3
- * @license
4
- * =========================================================
5
- * bootstrap-datetimepicker.js
6
- * http://www.eyecon.ro/bootstrap-datepicker
7
- * =========================================================
8
- * Copyright 2012 Stefan Petre
9
- *
10
- * Contributions:
11
- * - updated for Bootstrap v3 by Jonathan Peterson (@Eonasdan) and (almost)
12
- * completely rewritten to use Momentjs
13
- * - based on tarruda's bootstrap-datepicker
14
- *
15
- * Licensed under the Apache License, Version 2.0 (the "License");
16
- * you may not use this file except in compliance with the License.
17
- * You may obtain a copy of the License at
18
- *
19
- * http://www.apache.org/licenses/LICENSE-2.0
20
- *
21
- * Unless required by applicable law or agreed to in writing, software
22
- * distributed under the License is distributed on an "AS IS" BASIS,
23
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
- * See the License for the specific language governing permissions and
25
- * limitations under the License.
26
- * =========================================================
27
- */
1
+ /*
2
+ Version 3.0.0
3
+ =========================================================
4
+ bootstrap-datetimepicker.js
5
+ https://github.com/Eonasdan/bootstrap-datetimepicker
6
+ =========================================================
7
+ The MIT License (MIT)
8
+
9
+ Copyright (c) 2014 Jonathan Peterson
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ THE SOFTWARE.
28
+ */
28
29
  ; (function (factory) {
29
30
  if (typeof define === 'function' && define.amd) {
30
- // AMD is used - Register as an anonymous module.
31
+ // AMD is used - Register as an anonymous module.
31
32
  define(['jquery', 'moment'], factory);
32
33
  } else {
33
34
  // AMD is not used - Attempt to fetch dependencies from scope.
34
- if(!jQuery){
35
+ if (!jQuery) {
35
36
  throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
36
- }else if(!moment) {
37
+ } else if (!moment) {
37
38
  throw 'bootstrap-datetimepicker requires moment.js to be loaded first';
38
- }else{
39
+ } else {
39
40
  factory(jQuery, moment);
40
41
  }
41
42
  }
@@ -58,17 +59,21 @@
58
59
  pickTime: true,
59
60
  useMinutes: true,
60
61
  useSeconds: false,
62
+ useCurrent: true,
61
63
  minuteStepping: 1,
62
- startDate: new pMoment({ y: 1970 }),
63
- endDate: new pMoment().add(50, "y"),
64
+ minDate: new pMoment({ y: 1900 }),
65
+ maxDate: new pMoment().add(100, "y"),
66
+ showToday: true,
64
67
  collapse: true,
65
- language: pMoment.lang(),
68
+ language: "en",
66
69
  defaultDate: "",
67
- disabledDates: [],
70
+ disabledDates: false,
68
71
  enabledDates: false,
69
72
  icons: {},
70
73
  useStrict: false,
71
- direction: "auto"
74
+ direction: "auto",
75
+ sideBySide: false,
76
+ daysOfWeekDisabled: false
72
77
  },
73
78
 
74
79
  icons = {
@@ -101,7 +106,7 @@
101
106
  picker.component = false;
102
107
 
103
108
  if (picker.element.hasClass('input-group')) {
104
- if (picker.element.find('.datepickerbutton').size() == 0) {//in case there is more then one 'input-group-addon` #48
109
+ if (picker.element.find('.datepickerbutton').size() == 0) {//in case there is more then one 'input-group-addon' Issue #48
105
110
  picker.component = picker.element.find("[class^='input-group-']");
106
111
  }
107
112
  else {
@@ -113,24 +118,19 @@
113
118
  longDateFormat = pMoment()._lang._longDateFormat;
114
119
 
115
120
  if (!picker.format) {
116
- if (picker.isInput) picker.format = picker.element.data('format');
117
- else picker.format = picker.element.find('input').data('format');
118
- if (!picker.format) {
119
- picker.format = (picker.options.pickDate ? longDateFormat.L : '');
120
- if (picker.options.pickDate && picker.options.pickTime) picker.format += ' ';
121
- picker.format += (picker.options.pickTime ? longDateFormat.LT : '');
122
- if (picker.options.useSeconds) {
123
- if (~longDateFormat.LT.indexOf(' A')) {
124
- picker.format = picker.format.split(" A")[0] + ":ss A";
125
- }
126
- else {
127
- picker.format += ':ss';
128
- }
121
+ picker.format = (picker.options.pickDate ? longDateFormat.L : '');
122
+ if (picker.options.pickDate && picker.options.pickTime) picker.format += ' ';
123
+ picker.format += (picker.options.pickTime ? longDateFormat.LT : '');
124
+ if (picker.options.useSeconds) {
125
+ if (~longDateFormat.LT.indexOf(' A')) {
126
+ picker.format = picker.format.split(" A")[0] + ":ss A";
127
+ }
128
+ else {
129
+ picker.format += ':ss';
129
130
  }
130
131
  }
131
132
  }
132
-
133
- picker.options.use24hours = picker.format.toLowerCase().indexOf("a") < 1;
133
+ picker.use24hours = picker.format.toLowerCase().indexOf("a") < 1;
134
134
 
135
135
  if (picker.component) icon = picker.component.find('span');
136
136
 
@@ -144,8 +144,13 @@
144
144
  }
145
145
  }
146
146
 
147
- picker.widget = $(getTemplate(picker.options.pickDate, picker.options.pickTime, picker.options.collapse)).appendTo('body');
148
- picker.minViewMode = picker.options.minViewMode || picker.element.data('date-minviewmode') || 0;
147
+ picker.widget = $(getTemplate()).appendTo('body');
148
+
149
+ if (picker.options.useSeconds && !picker.use24hours) {
150
+ picker.widget.width(300);
151
+ }
152
+
153
+ picker.minViewMode = picker.options.minViewMode || 0;
149
154
  if (typeof picker.minViewMode === 'string') {
150
155
  switch (picker.minViewMode) {
151
156
  case 'months':
@@ -159,7 +164,7 @@
159
164
  break;
160
165
  }
161
166
  }
162
- picker.viewMode = picker.options.viewMode || picker.element.data('date-viewmode') || 0;
167
+ picker.viewMode = picker.options.viewMode || 0;
163
168
  if (typeof picker.viewMode === 'string') {
164
169
  switch (picker.viewMode) {
165
170
  case 'months':
@@ -174,51 +179,64 @@
174
179
  }
175
180
  }
176
181
 
177
- for (i = 0; i < picker.options.disabledDates.length; i++) {
178
- dDate = picker.options.disabledDates[i];
179
- dDate = pMoment(dDate);
180
- //if this is not a valid date then set it to the startdate -1 day so it's disabled.
181
- if (!dDate.isValid()) dDate = pMoment(picker.options.startDate).subtract(1, "day");
182
- picker.options.disabledDates[i] = dDate.format("L");
183
- }
182
+ picker.options.disabledDates = indexGivenDates(picker.options.disabledDates);
183
+ picker.options.enabledDates = indexGivenDates(picker.options.enabledDates);
184
184
 
185
- for (i = 0; i < picker.options.enabledDates.length; i++) {
186
- dDate = picker.options.enabledDates[i];
187
- dDate = pMoment(dDate);
188
- //if this is not a valid date then set it to the startdate -1 day so it's disabled.
189
- if (!dDate.isValid()) dDate = pMoment(picker.options.startDate).subtract(1, "day");
190
- picker.options.enabledDates[i] = dDate.format("L");
191
- }
192
185
  picker.startViewMode = picker.viewMode;
193
- picker.setStartDate(picker.options.startDate || picker.element.data('date-startdate'));
194
- picker.setEndDate(picker.options.endDate || picker.element.data('date-enddate'));
186
+ picker.setMinDate(picker.options.minDate);
187
+ picker.setMaxDate(picker.options.maxDate);
195
188
  fillDow();
196
189
  fillMonths();
197
190
  fillHours();
198
191
  fillMinutes();
199
- fillSeconds();
192
+ fillSeconds();
200
193
  update();
201
194
  showMode();
202
195
  attachDatePickerEvents();
203
- if (picker.options.defaultDate !== "") picker.setValue(picker.options.defaultDate);
196
+ if (picker.options.defaultDate !== "" && getPickerInput().val() == "") picker.setValue(picker.options.defaultDate);
197
+ if (picker.options.minuteStepping !== 1) {
198
+ var rMinutes = picker.date.minutes();
199
+ var rInterval = picker.options.minuteStepping;
200
+ picker.date.minutes((Math.round(rMinutes / rInterval) * rInterval) % 60)
201
+ .seconds(0);
202
+ }
203
+ },
204
+
205
+ getPickerInput = function () {
206
+ if (picker.isInput) {
207
+ return picker.element;
208
+ } else {
209
+ return dateStr = picker.element.find('input');
210
+ }
204
211
  },
205
212
 
206
213
  dataToOptions = function () {
207
- var eData = picker.element.data();
208
- if (eData.pickdate !== undefined) picker.options.pickDate = eData.pickdate;
209
- if (eData.picktime !== undefined) picker.options.pickTime = eData.picktime;
210
- if (eData.useminutes !== undefined) picker.options.useMinutes = eData.useminutes;
211
- if (eData.useseconds !== undefined) picker.options.useSeconds = eData.useseconds;
212
- if (eData.minutestepping !== undefined) picker.options.minuteStepping = eData.minutestepping;
213
- if (eData.startdate !== undefined) picker.options.startDate = eData.startdate;
214
- if (eData.enddate !== undefined) picker.options.endDate = eData.enddate;
215
- if (eData.collapse !== undefined) picker.options.collapse = eData.collapse;
216
- if (eData.language !== undefined) picker.options.language = eData.language;
217
- if (eData.defaultdate !== undefined) picker.options.defaultDate = eData.defaultdate;
218
- if (eData.disableddates !== undefined) picker.options.disabledDates = eData.disableddates;
219
- if (eData.enableddates !== undefined) picker.options.enabledDates = eData.enableddates;
220
- if (eData.icons !== undefined) picker.options.icons = eData.icons;
221
- if (eData.usestrict !== undefined) picker.options.useStrict = eData.usestrict;
214
+ var eData
215
+ if (picker.element.is('input')) {
216
+ eData = picker.element.data();
217
+ }
218
+ else {
219
+ eData = picker.element.data();
220
+ }
221
+ if (eData.dateFormat !== undefined) picker.options.format = eData.dateFormat;
222
+ if (eData.datePickdate !== undefined) picker.options.pickDate = eData.datePickdate;
223
+ if (eData.datePicktime !== undefined) picker.options.pickTime = eData.datePicktime;
224
+ if (eData.dateUseminutes !== undefined) picker.options.useMinutes = eData.dateUseminutes;
225
+ if (eData.dateUseseconds !== undefined) picker.options.useSeconds = eData.dateUseseconds;
226
+ if (eData.dateUsecurrent !== undefined) picker.options.useCurrent = eData.dateUsecurrent;
227
+ if (eData.dateMinutestepping !== undefined) picker.options.minuteStepping = eData.dateMinutestepping;
228
+ if (eData.dateMindate !== undefined) picker.options.minDate = eData.dateMindate;
229
+ if (eData.dateMaxdate !== undefined) picker.options.maxDate = eData.dateMaxdate;
230
+ if (eData.dateShowtoday !== undefined) picker.options.showToday = eData.dateShowtoday;
231
+ if (eData.dateCollapse !== undefined) picker.options.collapse = eData.dateCollapse;
232
+ if (eData.dateLanguage !== undefined) picker.options.language = eData.dateLanguage;
233
+ if (eData.dateDefaultdate !== undefined) picker.options.defaultDate = eData.dateDefaultdate;
234
+ if (eData.dateDisableddates !== undefined) picker.options.disabledDates = eData.dateDisableddates;
235
+ if (eData.dateEnableddates !== undefined) picker.options.enabledDates = eData.dateEnableddates;
236
+ if (eData.dateIcons !== undefined) picker.options.icons = eData.dateIcons;
237
+ if (eData.dateUsestrict !== undefined) picker.options.useStrict = eData.dateUsestrict;
238
+ if (eData.dateDirection !== undefined) picker.options.direction = eData.dateDirection;
239
+ if (eData.dateSidebyside !== undefined) picker.options.sideBySide = eData.dateSidebyside;
222
240
  },
223
241
 
224
242
  place = function () {
@@ -226,14 +244,26 @@
226
244
  offset = picker.component ? picker.component.offset() : picker.element.offset(), $window = $(window);
227
245
  picker.width = picker.component ? picker.component.outerWidth() : picker.element.outerWidth();
228
246
  offset.top = offset.top + picker.element.outerHeight();
229
-
230
- // if (picker.options.direction === 'up' || picker.options.direction === 'auto' && offset.top + picker.widget.height() > $window.height()) {
231
- // offset.top -= picker.widget.height() + picker.element.outerHeight();
232
- // picker.widget.addClass('up');
233
- // } else if (picker.options.direction === 'down' || picker.options.direction === 'auto' && offset.top + picker.widget.height() <= $window.height()) {
234
- // offset.top += picker.element.outerHeight();
235
- // picker.widget.addClass('down');
236
- // }
247
+
248
+ var placePosition;
249
+ if (picker.options.direction === 'up') {
250
+ placePosition = 'top'
251
+ } else if (picker.options.direction === 'bottom') {
252
+ placePosition = 'bottom'
253
+ } else if (picker.options.direction === 'auto') {
254
+ if (offset.top + picker.widget.height() > $window.height() + $window.scrollTop() && picker.widget.height() + picker.element.outerHeight() < offset.top) {
255
+ placePosition = 'top';
256
+ } else {
257
+ placePosition = 'bottom';
258
+ }
259
+ };
260
+ if (placePosition === 'top') {
261
+ offset.top -= picker.widget.height() + picker.element.outerHeight() + 15;
262
+ picker.widget.addClass('top').removeClass('bottom');
263
+ } else {
264
+ offset.top += 1;
265
+ picker.widget.addClass('bottom').removeClass('top');
266
+ }
237
267
 
238
268
  if (picker.options.width !== undefined) {
239
269
  picker.widget.width(picker.options.width);
@@ -268,8 +298,9 @@
268
298
  },
269
299
 
270
300
  notifyChange = function (oldDate, eventType) {
301
+ if (pMoment(picker.date).isSame(pMoment(oldDate))) return;
271
302
  picker.element.trigger({
272
- type: 'change.dp',
303
+ type: 'dp.change',
273
304
  date: pMoment(picker.date),
274
305
  oldDate: pMoment(oldDate)
275
306
  });
@@ -280,7 +311,7 @@
280
311
 
281
312
  notifyError = function (date) {
282
313
  picker.element.trigger({
283
- type: 'error.dp',
314
+ type: 'dp.error',
284
315
  date: pMoment(date)
285
316
  });
286
317
  },
@@ -289,11 +320,7 @@
289
320
  pMoment.lang(picker.options.language);
290
321
  var dateStr = newDate;
291
322
  if (!dateStr) {
292
- if (picker.isInput) {
293
- dateStr = picker.element.val();
294
- } else {
295
- dateStr = picker.element.find('input').val();
296
- }
323
+ dateStr = getPickerInput().val()
297
324
  if (dateStr) picker.date = pMoment(dateStr, picker.format, picker.options.useStrict);
298
325
  if (!picker.date) picker.date = pMoment();
299
326
  }
@@ -306,7 +333,7 @@
306
333
  pMoment.lang(picker.options.language);
307
334
  var html = $('<tr>'), weekdaysMin = pMoment.weekdaysMin(), i;
308
335
  if (pMoment()._lang._week.dow == 0) { // starts on Sunday
309
- for(i = 0; i < 7; i++) {
336
+ for (i = 0; i < 7; i++) {
310
337
  html.append('<th class="dow">' + weekdaysMin[i] + '</th>');
311
338
  }
312
339
  } else {
@@ -334,10 +361,10 @@
334
361
  pMoment.lang(picker.options.language);
335
362
  var year = picker.viewDate.year(),
336
363
  month = picker.viewDate.month(),
337
- startYear = picker.options.startDate.year(),
338
- startMonth = picker.options.startDate.month(),
339
- endYear = picker.options.endDate.year(),
340
- endMonth = picker.options.endDate.month(),
364
+ startYear = picker.options.minDate.year(),
365
+ startMonth = picker.options.minDate.month(),
366
+ endYear = picker.options.maxDate.year(),
367
+ endMonth = picker.options.maxDate.month(),
341
368
  prevMonth, nextMonth, html = [], row, clsName, i, days, yearCont, currentYear, months = pMoment.months();
342
369
 
343
370
  picker.widget.find('.datepicker-days').find('.disabled').removeClass('disabled');
@@ -375,14 +402,27 @@
375
402
  if (isInDisableDates(prevMonth) || !isInEnableDates(prevMonth)) {
376
403
  clsName += ' disabled';
377
404
  }
405
+ if (picker.options.showToday === true) {
406
+ if (prevMonth.isSame(pMoment(), 'day')) {
407
+ clsName += ' today';
408
+ }
409
+ }
410
+ if (picker.options.daysOfWeekDisabled) {
411
+ for (i in picker.options.daysOfWeekDisabled) {
412
+ if (prevMonth.day() == picker.options.daysOfWeekDisabled[i]) {
413
+ clsName += ' disabled';
414
+ break;
415
+ }
416
+ }
417
+ }
378
418
  row.append('<td class="day' + clsName + '">' + prevMonth.date() + '</td>');
379
419
  prevMonth.add(1, "d");
380
420
  }
381
421
  picker.widget.find('.datepicker-days tbody').empty().append(html);
382
- currentYear = pMoment().year(), months = picker.widget.find('.datepicker-months')
422
+ currentYear = picker.date.year(), months = picker.widget.find('.datepicker-months')
383
423
  .find('th:eq(1)').text(year).end().find('span').removeClass('active');
384
424
  if (currentYear === year) {
385
- months.eq(pMoment().month()).addClass('active');
425
+ months.eq(picker.date.month()).addClass('active');
386
426
  }
387
427
  if (currentYear - 1 < startYear) {
388
428
  picker.widget.find('.datepicker-months th:eq(0)').addClass('disabled');
@@ -421,7 +461,7 @@
421
461
  pMoment.lang(picker.options.language);
422
462
  var table = picker.widget.find('.timepicker .timepicker-hours table'), html = '', current, i, j;
423
463
  table.parent().hide();
424
- if (picker.options.use24hours) {
464
+ if (picker.use24hours) {
425
465
  current = 0;
426
466
  for (i = 0; i < 6; i += 1) {
427
467
  html += '<tr>';
@@ -447,13 +487,18 @@
447
487
  },
448
488
 
449
489
  fillMinutes = function () {
450
- var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j;
490
+ var table = picker.widget.find('.timepicker .timepicker-minutes table'), html = '', current = 0, i, j, step = picker.options.minuteStepping;
451
491
  table.parent().hide();
452
- for (i = 0; i < 5; i++) {
492
+ if (step = 1) step = 5;
493
+ for (i = 0; i < Math.ceil(60 / step / 4) ; i++) {
453
494
  html += '<tr>';
454
495
  for (j = 0; j < 4; j += 1) {
455
- html += '<td class="minute">' + padLeft(current.toString()) + '</td>';
456
- current += 3;
496
+ if (current < 60) {
497
+ html += '<td class="minute">' + padLeft(current.toString()) + '</td>';
498
+ current += step;
499
+ } else {
500
+ html += '<td></td>';
501
+ }
457
502
  }
458
503
  html += '</tr>';
459
504
  }
@@ -463,11 +508,11 @@
463
508
  fillSeconds = function () {
464
509
  var table = picker.widget.find('.timepicker .timepicker-seconds table'), html = '', current = 0, i, j;
465
510
  table.parent().hide();
466
- for (i = 0; i < 5; i++) {
511
+ for (i = 0; i < 3; i++) {
467
512
  html += '<tr>';
468
513
  for (j = 0; j < 4; j += 1) {
469
- html += '<td class="second">' + padLeft(current.toString()) + '</td>';
470
- current += 3;
514
+ html += '<td class="second">' + padLeft(current.toString()) + '</td>';
515
+ current += 5;
471
516
  }
472
517
  html += '</tr>';
473
518
  }
@@ -479,7 +524,7 @@
479
524
  var timeComponents = picker.widget.find('.timepicker span[data-time-component]'),
480
525
  hour = picker.date.hours(),
481
526
  period = 'AM';
482
- if (!picker.options.use24hours) {
527
+ if (!picker.use24hours) {
483
528
  if (hour >= 12) period = 'PM';
484
529
  if (hour === 0) hour = 12;
485
530
  else if (hour != 12) hour = hour % 12;
@@ -520,15 +565,17 @@
520
565
  year = parseInt(target.text(), 10) || 0;
521
566
  picker.viewDate.year(year);
522
567
  }
523
- if (picker.viewMode !== 0) {
568
+ if (picker.viewMode === picker.minViewMode) {
524
569
  picker.date = pMoment({
525
570
  y: picker.viewDate.year(),
526
571
  M: picker.viewDate.month(),
527
572
  d: picker.viewDate.date(),
528
573
  h: picker.date.hours(),
529
- m: picker.date.minutes()
574
+ m: picker.date.minutes(),
575
+ s: picker.date.seconds()
530
576
  });
531
577
  notifyChange(oldDate, e.type);
578
+ set();
532
579
  }
533
580
  showMode(-1);
534
581
  fillDate();
@@ -558,7 +605,8 @@
558
605
  M: month,
559
606
  d: day,
560
607
  h: picker.date.hours(),
561
- m: picker.date.minutes()
608
+ m: picker.date.minutes(),
609
+ s: picker.date.seconds()
562
610
  }
563
611
  );
564
612
  picker.viewDate = pMoment({
@@ -627,7 +675,9 @@
627
675
  },
628
676
 
629
677
  selectHour: function (e) {
630
- picker.date.hours(parseInt($(e.target).text(), 10));
678
+ var period = picker.widget.find('.timepicker [data-action=togglePeriod]').text(), hour = parseInt($(e.target).text(), 10);
679
+ if (period == "PM") hour += 12
680
+ picker.date.hours(hour);
631
681
  actions.showPicker.call(picker);
632
682
  },
633
683
 
@@ -668,8 +718,6 @@
668
718
  }
669
719
  else {
670
720
  picker.viewDate = oldDate;
671
- input.val(pMoment(oldDate).format(picker.format));
672
- //picker.setValue(""); // unset the date when the input is erased
673
721
  notifyChange(oldDate, e.type);
674
722
  notifyError(newDate);
675
723
  picker.unset = true;
@@ -680,7 +728,7 @@
680
728
  if (dir) {
681
729
  picker.viewMode = Math.max(picker.minViewMode, Math.min(2, picker.viewMode + dir));
682
730
  }
683
-
731
+ var f = dpGlobal.modes[picker.viewMode].clsName;
684
732
  picker.widget.find('.datepicker > div').hide().filter('.datepicker-' + dpGlobal.modes[picker.viewMode].clsName).show();
685
733
  },
686
734
 
@@ -699,7 +747,7 @@
699
747
 
700
748
  if (expanded && expanded.length) {
701
749
  collapseData = expanded.data('collapse');
702
- if (collapseData && collapseData.transitioning) return;
750
+ if (collapseData && collapseData.date - transitioning) return;
703
751
  expanded.collapse('hide');
704
752
  closed.collapse('show');
705
753
  $this.find('span').toggleClass(picker.options.icons.time + ' ' + picker.options.icons.date);
@@ -785,15 +833,8 @@
785
833
  pMoment.lang(picker.options.language);
786
834
  var formatted = '', input;
787
835
  if (!picker.unset) formatted = pMoment(picker.date).format(picker.format);
788
- if (!picker.isInput) {
789
- if (picker.component) {
790
- input = picker.element.find('input');
791
- input.val(formatted);
792
- }
793
- picker.element.data('date', formatted);
794
- } else {
795
- picker.element.val(formatted);
796
- }
836
+ getPickerInput().val(formatted);
837
+ picker.element.data('date', formatted);
797
838
  if (!picker.options.pickTime) picker.hide();
798
839
  },
799
840
 
@@ -819,56 +860,73 @@
819
860
  else {
820
861
  picker.date.subtract(amount, unit);
821
862
  }
822
- picker.unset = false;
823
- },
824
-
825
- isInDisableDates = function (date) {
826
- pMoment.lang(picker.options.language);
827
- if (date.isAfter(picker.options.endDate) || date.isBefore(picker.options.startDate)) return true;
828
- var disabled = picker.options.disabledDates, i;
829
- for (i in disabled) {
830
- if (disabled[i] == pMoment(date).format("L")) {
831
- return true;
832
- }
833
- }
834
- return false;
863
+ picker.unset = false;
835
864
  },
836
865
 
866
+ isInDisableDates = function (date) {
867
+ pMoment.lang(picker.options.language);
868
+ if (date.isAfter(picker.options.maxDate) || date.isBefore(picker.options.minDate)) return true;
869
+ if (picker.options.disabledDates === false) {
870
+ return false;
871
+ }
872
+ return picker.options.disabledDates[pMoment(date).format("YYYY-MM-DD")] === true;
873
+ },
837
874
  isInEnableDates = function (date) {
838
875
  pMoment.lang(picker.options.language);
839
- var enabled = picker.options.enabledDates, i;
840
- if (enabled.length) {
841
- for (i in enabled) {
842
- if (enabled[i] == pMoment(date).format("L")) {
843
- return true;
844
- }
876
+ if (picker.options.enabledDates === false) {
877
+ return true;
878
+ }
879
+ return picker.options.enabledDates[pMoment(date).format("YYYY-MM-DD")] === true;
880
+ },
881
+
882
+ indexGivenDates = function (givenDatesArray) {
883
+ // Store given enabledDates and disabledDates as keys.
884
+ // This way we can check their existence in O(1) time instead of looping through whole array.
885
+ // (for example: picker.options.enabledDates['2014-02-27'] === true)
886
+ var givenDatesIndexed = {};
887
+ var givenDatesCount = 0;
888
+ for (i = 0; i < givenDatesArray.length; i++) {
889
+ dDate = pMoment(givenDatesArray[i]);
890
+ if (dDate.isValid()) {
891
+ givenDatesIndexed[dDate.format("YYYY-MM-DD")] = true;
892
+ givenDatesCount++;
845
893
  }
846
- return false;
847
894
  }
848
- return enabled === false ? true : false;
895
+ if (givenDatesCount > 0) {
896
+ return givenDatesIndexed;
897
+ }
898
+ return false;
849
899
  },
900
+
850
901
  padLeft = function (string) {
851
902
  string = string.toString();
852
903
  if (string.length >= 2) return string;
853
904
  else return '0' + string;
854
905
  },
855
906
 
856
- getTemplate = function (pickDate, pickTime, collapse) {
857
- if (pickDate && pickTime) {
858
- return (
859
- '<div class="bootstrap-datetimepicker-widget dropdown-menu" style="z-index:9999 !important;">' +
860
- '<ul class="list-unstyled">' +
861
- '<li' + (collapse ? ' class="collapse in"' : '') + '>' +
862
- '<div class="datepicker">' + dpGlobal.template + '</div>' +
863
- '</li>' +
864
- '<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="' + picker.options.icons.time + '"></span></a></li>' +
865
- '<li' + (collapse ? ' class="collapse"' : '') + '>' +
866
- '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
867
- '</li>' +
868
- '</ul>' +
869
- '</div>'
870
- );
871
- } else if (pickTime) {
907
+ getTemplate = function () {
908
+ if (picker.options.pickDate && picker.options.pickTime) {
909
+ var ret = '';
910
+ ret = '<div class="bootstrap-datetimepicker-widget' + (picker.options.sideBySide ? ' timepicker-sbs' : '') + ' dropdown-menu" style="z-index:9999 !important;">';
911
+ if (picker.options.sideBySide) {
912
+ ret += '<div class="row">' +
913
+ '<div class="col-sm-6 datepicker">' + dpGlobal.template + '</div>' +
914
+ '<div class="col-sm-6 timepicker">' + tpGlobal.getTemplate() + '</div>' +
915
+ '</div>';
916
+ } else {
917
+ ret += '<ul class="list-unstyled">' +
918
+ '<li' + (picker.options.collapse ? ' class="collapse in"' : '') + '>' +
919
+ '<div class="datepicker">' + dpGlobal.template + '</div>' +
920
+ '</li>' +
921
+ '<li class="picker-switch accordion-toggle"><a class="btn" style="width:100%"><span class="' + picker.options.icons.time + '"></span></a></li>' +
922
+ '<li' + (picker.options.collapse ? ' class="collapse"' : '') + '>' +
923
+ '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
924
+ '</li>' +
925
+ '</ul>';
926
+ }
927
+ ret += '</div>';
928
+ return ret;
929
+ } else if (picker.options.pickTime) {
872
930
  return (
873
931
  '<div class="bootstrap-datetimepicker-widget dropdown-menu">' +
874
932
  '<div class="timepicker">' + tpGlobal.getTemplate() + '</div>' +
@@ -911,9 +969,9 @@
911
969
  },
912
970
 
913
971
  tpGlobal = {
914
- hourTemplate: '<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',
972
+ hourTemplate: '<span data-action="showHours" data-time-component="hours" class="timepicker-hour"></span>',
915
973
  minuteTemplate: '<span data-action="showMinutes" data-time-component="minutes" class="timepicker-minute"></span>',
916
- secondTemplate: '<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>'
974
+ secondTemplate: '<span data-action="showSeconds" data-time-component="seconds" class="timepicker-second"></span>'
917
975
  };
918
976
 
919
977
  dpGlobal.template =
@@ -937,7 +995,7 @@
937
995
  '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="incrementMinutes"><span class="' + picker.options.icons.up + '"></span></a>' : '') + '</td>' +
938
996
  (picker.options.useSeconds ?
939
997
  '<td class="separator"></td><td><a href="#" class="btn" data-action="incrementSeconds"><span class="' + picker.options.icons.up + '"></span></a></td>' : '') +
940
- (picker.options.use24hours ? '' : '<td class="separator"></td>') +
998
+ (picker.use24hours ? '' : '<td class="separator"></td>') +
941
999
  '</tr>' +
942
1000
  '<tr>' +
943
1001
  '<td>' + tpGlobal.hourTemplate + '</td> ' +
@@ -945,7 +1003,7 @@
945
1003
  '<td>' + (picker.options.useMinutes ? tpGlobal.minuteTemplate : '<span class="timepicker-minute">00</span>') + '</td> ' +
946
1004
  (picker.options.useSeconds ?
947
1005
  '<td class="separator">:</td><td>' + tpGlobal.secondTemplate + '</td>' : '') +
948
- (picker.options.use24hours ? '' : '<td class="separator"></td>' +
1006
+ (picker.use24hours ? '' : '<td class="separator"></td>' +
949
1007
  '<td><button type="button" class="btn btn-primary" data-action="togglePeriod"></button></td>') +
950
1008
  '</tr>' +
951
1009
  '<tr>' +
@@ -954,7 +1012,7 @@
954
1012
  '<td>' + (picker.options.useMinutes ? '<a href="#" class="btn" data-action="decrementMinutes"><span class="' + picker.options.icons.down + '"></span></a>' : '') + '</td>' +
955
1013
  (picker.options.useSeconds ?
956
1014
  '<td class="separator"></td><td><a href="#" class="btn" data-action="decrementSeconds"><span class="' + picker.options.icons.down + '"></span></a></td>' : '') +
957
- (picker.options.use24hours ? '' : '<td class="separator"></td>') +
1015
+ (picker.use24hours ? '' : '<td class="separator"></td>') +
958
1016
  '</tr>' +
959
1017
  '</table>' +
960
1018
  '</div>' +
@@ -979,11 +1037,16 @@
979
1037
  };
980
1038
 
981
1039
  picker.show = function (e) {
1040
+ if (picker.options.useCurrent === true) {
1041
+ if (getPickerInput().val() == '') {
1042
+ picker.setValue(pMoment().format(picker.format))
1043
+ };
1044
+ }
982
1045
  picker.widget.show();
983
1046
  picker.height = picker.component ? picker.component.outerHeight() : picker.element.outerHeight();
984
1047
  place();
985
1048
  picker.element.trigger({
986
- type: 'show.dp',
1049
+ type: 'dp.show',
987
1050
  date: pMoment(picker.date)
988
1051
  });
989
1052
  attachDatePickerGlobalEvents();
@@ -994,7 +1057,7 @@
994
1057
 
995
1058
  picker.disable = function () {
996
1059
  var input = picker.element.find('input');
997
- if(input.prop('disabled')) return;
1060
+ if (input.prop('disabled')) return;
998
1061
 
999
1062
  input.prop('disabled', true);
1000
1063
  detachDatePickerEvents();
@@ -1002,7 +1065,7 @@
1002
1065
 
1003
1066
  picker.enable = function () {
1004
1067
  var input = picker.element.find('input');
1005
- if(!input.prop('disabled')) return;
1068
+ if (!input.prop('disabled')) return;
1006
1069
 
1007
1070
  input.prop('disabled', false);
1008
1071
  attachDatePickerEvents();
@@ -1015,14 +1078,14 @@
1015
1078
  var collapse = picker.widget.find('.collapse'), i, collapseData;
1016
1079
  for (i = 0; i < collapse.length; i++) {
1017
1080
  collapseData = collapse.eq(i).data('collapse');
1018
- if (collapseData && collapseData.transitioning)
1081
+ if (collapseData && collapseData.date - transitioning)
1019
1082
  return;
1020
1083
  }
1021
1084
  picker.widget.hide();
1022
1085
  picker.viewMode = picker.startViewMode;
1023
1086
  showMode();
1024
1087
  picker.element.trigger({
1025
- type: 'hide.dp',
1088
+ type: 'dp.hide',
1026
1089
  date: pMoment(picker.date)
1027
1090
  });
1028
1091
  detachDatePickerGlobalEvents();
@@ -1032,6 +1095,7 @@
1032
1095
  pMoment.lang(picker.options.language);
1033
1096
  if (!newDate) {
1034
1097
  picker.unset = true;
1098
+ set();
1035
1099
  } else {
1036
1100
  picker.unset = false;
1037
1101
  }
@@ -1054,26 +1118,33 @@
1054
1118
  },
1055
1119
 
1056
1120
  picker.setDate = function (date) {
1057
- date = pMoment(date);
1058
- if (!date) picker.setValue(null);
1059
- else picker.setValue(date);
1121
+ var oldDate = pMoment(picker.date);
1122
+ if (!date) {
1123
+ picker.setValue(null);
1124
+ } else {
1125
+ picker.setValue(date);
1126
+ }
1127
+ notifyChange(oldDate, "function");
1060
1128
  },
1061
1129
 
1130
+ picker.setDisabledDates = function (dates) {
1131
+ picker.options.disabledDates = indexGivenDates(dates);
1132
+ if (picker.viewDate) update();
1133
+ },
1062
1134
  picker.setEnabledDates = function (dates) {
1063
- if (!dates) picker.options.enabledDates = false;
1064
- else picker.options.enabledDates = dates;
1135
+ picker.options.enabledDates = indexGivenDates(dates);
1065
1136
  if (picker.viewDate) update();
1066
1137
  },
1067
1138
 
1068
- picker.setEndDate = function (date) {
1139
+ picker.setMaxDate = function (date) {
1069
1140
  if (date == undefined) return;
1070
- picker.options.endDate = pMoment(date);
1141
+ picker.options.maxDate = pMoment(date);
1071
1142
  if (picker.viewDate) update();
1072
1143
  },
1073
1144
 
1074
- picker.setStartDate = function (date) {
1145
+ picker.setMinDate = function (date) {
1075
1146
  if (date == undefined) return;
1076
- picker.options.startDate = pMoment(date);
1147
+ picker.options.minDate = pMoment(date);
1077
1148
  if (picker.viewDate) update();
1078
1149
  };
1079
1150
 
@@ -1086,4 +1157,4 @@
1086
1157
  if (!data) $this.data('DateTimePicker', new DateTimePicker(this, options));
1087
1158
  });
1088
1159
  };
1089
- }));
1160
+ }));