|
133 | 133 | * |
134 | 134 | ********************************************************************************/ |
135 | 135 | getMoment = function (d) { |
136 | | - var tzEnabled = false, |
137 | | - returnMoment, |
138 | | - currentZoneOffset, |
139 | | - incomingZoneOffset, |
140 | | - timeZoneIndicator, |
141 | | - dateWithTimeZoneInfo; |
| 136 | + var returnMoment; |
142 | 137 |
|
143 | | - if (moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '') { |
144 | | - tzEnabled = true; |
145 | | - } |
146 | 138 | if (d === undefined || d === null) { |
147 | | - if (tzEnabled) { |
148 | | - returnMoment = moment().tz(options.timeZone); |
149 | | - } else { |
150 | | - returnMoment = moment(); //TODO should this use format? and locale? |
151 | | - } |
| 139 | + returnMoment = moment(); //TODO should this use format? and locale? |
| 140 | + } else if (hasTimeZone()) { // There is a string to parse and a default time zone |
| 141 | + // parse with the tz function which takes a default time zone if it is not in the format string |
| 142 | + returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone); |
152 | 143 | } else { |
153 | | - if (tzEnabled) { |
154 | | - currentZoneOffset = moment().tz(options.timeZone).utcOffset(); |
155 | | - incomingZoneOffset = moment(d, parseFormats, options.useStrict).utcOffset(); |
156 | | - if (incomingZoneOffset !== currentZoneOffset) { |
157 | | - timeZoneIndicator = moment().tz(options.timeZone).format('Z'); |
158 | | - dateWithTimeZoneInfo = moment(d, parseFormats, options.useStrict).format('YYYY-MM-DD[T]HH:mm:ss') + timeZoneIndicator; |
159 | | - returnMoment = moment(dateWithTimeZoneInfo, parseFormats, options.useStrict).tz(options.timeZone); |
160 | | - } else { |
161 | | - returnMoment = moment(d, parseFormats, options.useStrict).tz(options.timeZone); |
162 | | - } |
163 | | - } else { |
164 | | - returnMoment = moment(d, parseFormats, options.useStrict); |
165 | | - } |
| 144 | + returnMoment = moment(d, parseFormats, options.useStrict); |
| 145 | + } |
| 146 | + |
| 147 | + if (hasTimeZone()) { |
| 148 | + returnMoment.tz(options.timeZone); |
166 | 149 | } |
| 150 | + |
167 | 151 | return returnMoment; |
168 | 152 | }, |
169 | 153 |
|
|
194 | 178 | return (isEnabled('h') || isEnabled('m') || isEnabled('s')); |
195 | 179 | }, |
196 | 180 |
|
| 181 | + hasTimeZone = function () { |
| 182 | + return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== ''; |
| 183 | + }, |
| 184 | + |
197 | 185 | hasDate = function () { |
198 | 186 | return (isEnabled('y') || isEnabled('M') || isEnabled('d')); |
199 | 187 | }, |
|
474 | 462 |
|
475 | 463 | widget.css({ |
476 | 464 | top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(), |
477 | | - bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto', |
| 465 | + bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto', |
478 | 466 | left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto', |
479 | 467 | right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left) |
480 | 468 | }); |
|
659 | 647 | startDecade = moment({y: viewDate.year() - (viewDate.year() % 100) - 1}), |
660 | 648 | endDecade = startDecade.clone().add(100, 'y'), |
661 | 649 | startedAt = startDecade.clone(), |
| 650 | + minDateDecade = false, |
| 651 | + maxDateDecade = false, |
| 652 | + endDecadeYear, |
662 | 653 | html = ''; |
663 | 654 |
|
664 | 655 | decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury); |
|
677 | 668 | } |
678 | 669 |
|
679 | 670 | while (!startDecade.isAfter(endDecade, 'y')) { |
680 | | - html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') + |
681 | | - (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>'; |
| 671 | + endDecadeYear = startDecade.year() + 12; |
| 672 | + minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear; |
| 673 | + maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear; |
| 674 | + html += '<span data-action="selectDecade" class="decade' + (date.isAfter(startDecade) && date.year() <= endDecadeYear ? ' active' : '') + |
| 675 | + (!isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>'; |
682 | 676 | startDecade.add(12, 'y'); |
683 | 677 | } |
684 | 678 | html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even |
|
863 | 857 |
|
864 | 858 | targetMoment = targetMoment.clone().locale(options.locale); |
865 | 859 |
|
| 860 | + if (hasTimeZone()) { |
| 861 | + targetMoment.tz(options.timeZone); |
| 862 | + } |
| 863 | + |
866 | 864 | if (options.stepping !== 1) { |
867 | | - targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0); |
| 865 | + targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0); |
868 | 866 | } |
869 | 867 |
|
870 | 868 | if (isValid(targetMoment)) { |
|
882 | 880 | } else { |
883 | 881 | if (!options.keepInvalid) { |
884 | 882 | input.val(unset ? '' : date.format(actualFormat)); |
| 883 | + } else { |
| 884 | + notifyEvent({ |
| 885 | + type: 'dp.change', |
| 886 | + date: targetMoment, |
| 887 | + oldDate: oldDate |
| 888 | + }); |
885 | 889 | } |
886 | 890 | notifyEvent({ |
887 | 891 | type: 'dp.error', |
888 | | - date: targetMoment |
| 892 | + date: targetMoment, |
| 893 | + oldDate: oldDate |
889 | 894 | }); |
890 | 895 | } |
891 | 896 | }, |
|
1520 | 1525 | } |
1521 | 1526 |
|
1522 | 1527 | if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) { |
1523 | | - throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat); |
| 1528 | + throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat); |
1524 | 1529 | } |
1525 | 1530 |
|
1526 | 1531 | options.format = newFormat; |
|
2097 | 2102 | }; |
2098 | 2103 |
|
2099 | 2104 | picker.keyBinds = function (keyBinds) { |
| 2105 | + if (arguments.length === 0) { |
| 2106 | + return options.keyBinds; |
| 2107 | + } |
| 2108 | + |
2100 | 2109 | options.keyBinds = keyBinds; |
2101 | 2110 | return picker; |
2102 | 2111 | }; |
|
2312 | 2321 | input = element; |
2313 | 2322 | } else { |
2314 | 2323 | input = element.find(options.datepickerInput); |
2315 | | - if (input.size() === 0) { |
| 2324 | + if (input.length === 0) { |
2316 | 2325 | input = element.find('input'); |
2317 | 2326 | } else if (!input.is('input')) { |
2318 | 2327 | throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element'); |
|
2321 | 2330 |
|
2322 | 2331 | if (element.hasClass('input-group')) { |
2323 | 2332 | // in case there is more then one 'input-group-addon' Issue #48 |
2324 | | - if (element.find('.datepickerbutton').size() === 0) { |
| 2333 | + if (element.find('.datepickerbutton').length === 0) { |
2325 | 2334 | component = element.find('.input-group-addon'); |
2326 | 2335 | } else { |
2327 | 2336 | component = element.find('.datepickerbutton'); |
|
2388 | 2397 | * @memberOf jQuery.fn |
2389 | 2398 | */ |
2390 | 2399 | $.fn.datetimepicker = function (options) { |
2391 | | - return this.each(function () { |
2392 | | - var $this = $(this); |
2393 | | - if (!$this.data('DateTimePicker')) { |
2394 | | - // create a private copy of the defaults object |
2395 | | - options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); |
2396 | | - $this.data('DateTimePicker', dateTimePicker($this, options)); |
2397 | | - } |
2398 | | - }); |
| 2400 | + options = options || {}; |
| 2401 | + |
| 2402 | + var args = Array.prototype.slice.call(arguments, 1), |
| 2403 | + isInstance = true, |
| 2404 | + thisMethods = ['destroy', 'hide', 'show', 'toggle'], |
| 2405 | + returnValue; |
| 2406 | + |
| 2407 | + if (typeof options === 'object') { |
| 2408 | + return this.each(function () { |
| 2409 | + var $this = $(this); |
| 2410 | + if (!$this.data('DateTimePicker')) { |
| 2411 | + // create a private copy of the defaults object |
| 2412 | + options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); |
| 2413 | + $this.data('DateTimePicker', dateTimePicker($this, options)); |
| 2414 | + } |
| 2415 | + }); |
| 2416 | + } else if (typeof options === 'string') { |
| 2417 | + this.each(function () { |
| 2418 | + var $this = $(this), |
| 2419 | + instance = $this.data('DateTimePicker'); |
| 2420 | + if (!instance) { |
| 2421 | + throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker'); |
| 2422 | + } |
| 2423 | + |
| 2424 | + returnValue = instance[options].apply(instance, args); |
| 2425 | + isInstance = returnValue === instance; |
| 2426 | + }); |
| 2427 | + |
| 2428 | + if (isInstance || $.inArray(options, thisMethods) > -1) { |
| 2429 | + return this; |
| 2430 | + } |
| 2431 | + |
| 2432 | + return returnValue; |
| 2433 | + } |
| 2434 | + |
| 2435 | + throw new TypeError('Invalid arguments for DateTimePicker: ' + options); |
2399 | 2436 | }; |
2400 | 2437 |
|
2401 | 2438 | $.fn.datetimepicker.defaults = { |
|
2581 | 2618 | enabledHours: false, |
2582 | 2619 | viewDate: false |
2583 | 2620 | }; |
| 2621 | + if (typeof module !== 'undefined') { |
| 2622 | + module.exports = $.fn.datetimepicker; |
| 2623 | + } |
2584 | 2624 | })); |
0 commit comments