| /*! version : 4.14.30 |
| ========================================================= |
| bootstrap-datetimejs |
| https://github.com/Eonasdan/bootstrap-datetimepicker |
| Copyright (c) 2015 Jonathan Peterson |
| ========================================================= |
| */ |
| /* |
| The MIT License (MIT) |
| |
| Copyright (c) 2015 Jonathan Peterson |
| |
| Permission is hereby granted, free of charge, to any person obtaining a copy |
| of this software and associated documentation files (the "Software"), to deal |
| in the Software without restriction, including without limitation the rights |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| copies of the Software, and to permit persons to whom the Software is |
| furnished to do so, subject to the following conditions: |
| |
| The above copyright notice and this permission notice shall be included in |
| all copies or substantial portions of the Software. |
| |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| THE SOFTWARE. |
| */ |
| /*global define:false */ |
| /*global exports:false */ |
| /*global require:false */ |
| /*global jQuery:false */ |
| /*global moment:false */ |
| (function (factory) { |
| 'use strict'; |
| if (typeof define === 'function' && define.amd) { |
| // AMD is used - Register as an anonymous module. |
| define(['jquery', 'moment'], factory); |
| } else if (typeof exports === 'object') { |
| factory(require('jquery'), require('moment')); |
| } else { |
| // Neither AMD nor CommonJS used. Use global variables. |
| if (typeof jQuery === 'undefined') { |
| throw 'bootstrap-datetimepicker requires jQuery to be loaded first'; |
| } |
| if (typeof moment === 'undefined') { |
| throw 'bootstrap-datetimepicker requires Moment.js to be loaded first'; |
| } |
| factory(jQuery, moment); |
| } |
| }(function ($, moment) { |
| 'use strict'; |
| if (!moment) { |
| throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first'); |
| } |
| |
| var dateTimePicker = function (element, options) { |
| var picker = {}, |
| date = moment().startOf('d'), |
| viewDate = date.clone(), |
| unset = true, |
| input, |
| component = false, |
| widget = false, |
| use24Hours, |
| minViewModeNumber = 0, |
| actualFormat, |
| parseFormats, |
| currentViewMode, |
| datePickerModes = [ |
| { |
| clsName: 'days', |
| navFnc: 'M', |
| navStep: 1 |
| }, |
| { |
| clsName: 'months', |
| navFnc: 'y', |
| navStep: 1 |
| }, |
| { |
| clsName: 'years', |
| navFnc: 'y', |
| navStep: 10 |
| }, |
| { |
| clsName: 'decades', |
| navFnc: 'y', |
| navStep: 100 |
| } |
| ], |
| viewModes = ['days', 'months', 'years', 'decades'], |
| verticalModes = ['top', 'bottom', 'auto'], |
| horizontalModes = ['left', 'right', 'auto'], |
| toolbarPlacements = ['default', 'top', 'bottom'], |
| keyMap = { |
| 'up': 38, |
| 38: 'up', |
| 'down': 40, |
| 40: 'down', |
| 'left': 37, |
| 37: 'left', |
| 'right': 39, |
| 39: 'right', |
| 'tab': 9, |
| 9: 'tab', |
| 'escape': 27, |
| 27: 'escape', |
| 'enter': 13, |
| 13: 'enter', |
| 'pageUp': 33, |
| 33: 'pageUp', |
| 'pageDown': 34, |
| 34: 'pageDown', |
| 'shift': 16, |
| 16: 'shift', |
| 'control': 17, |
| 17: 'control', |
| 'space': 32, |
| 32: 'space', |
| 't': 84, |
| 84: 't', |
| 'delete': 46, |
| 46: 'delete' |
| }, |
| keyState = {}, |
| |
| /******************************************************************************** |
| * |
| * Private functions |
| * |
| ********************************************************************************/ |
| isEnabled = function (granularity) { |
| if (typeof granularity !== 'string' || granularity.length > 1) { |
| throw new TypeError('isEnabled expects a single character string parameter'); |
| } |
| switch (granularity) { |
| case 'y': |
| return actualFormat.indexOf('Y') !== -1; |
| case 'M': |
| return actualFormat.indexOf('M') !== -1; |
| case 'd': |
| return actualFormat.toLowerCase().indexOf('d') !== -1; |
| case 'h': |
| case 'H': |
| return actualFormat.toLowerCase().indexOf('h') !== -1; |
| case 'm': |
| return actualFormat.indexOf('m') !== -1; |
| case 's': |
| return actualFormat.indexOf('s') !== -1; |
| default: |
| return false; |
| } |
| }, |
| hasTime = function () { |
| return (isEnabled('h') || isEnabled('m') || isEnabled('s')); |
| }, |
| |
| hasDate = function () { |
| return (isEnabled('y') || isEnabled('M') || isEnabled('d')); |
| }, |
| |
| getDatePickerTemplate = function () { |
| var headTemplate = $('<thead>') |
| .append($('<tr>') |
| .append($('<th>').addClass('prev').attr('data-action', 'previous') |
| .append($('<span>').addClass(options.icons.previous)) |
| ) |
| .append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5'))) |
| .append($('<th>').addClass('next').attr('data-action', 'next') |
| .append($('<span>').addClass(options.icons.next)) |
| ) |
| ), |
| contTemplate = $('<tbody>') |
| .append($('<tr>') |
| .append($('<td>').attr('colspan', (options.calendarWeeks ? '8' : '7'))) |
| ); |
| |
| return [ |
| $('<div>').addClass('datepicker-days') |
| .append($('<table>').addClass('table-condensed') |
| .append(headTemplate) |
| .append($('<tbody>')) |
| ), |
| $('<div>').addClass('datepicker-months') |
| .append($('<table>').addClass('table-condensed') |
| .append(headTemplate.clone()) |
| .append(contTemplate.clone()) |
| ), |
| $('<div>').addClass('datepicker-years') |
| .append($('<table>').addClass('table-condensed') |
| .append(headTemplate.clone()) |
| .append(contTemplate.clone()) |
| ), |
| $('<div>').addClass('datepicker-decades') |
| .append($('<table>').addClass('table-condensed') |
| .append(headTemplate.clone()) |
| .append(contTemplate.clone()) |
| ) |
| ]; |
| }, |
| |
| getTimePickerMainTemplate = function () { |
| var topRow = $('<tr>'), |
| middleRow = $('<tr>'), |
| bottomRow = $('<tr>'); |
| |
| if (isEnabled('h')) { |
| topRow.append($('<td>') |
| .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Hour'}).addClass('btn').attr('data-action', 'incrementHours') |
| .append($('<span>').addClass(options.icons.up)))); |
| middleRow.append($('<td>') |
| .append($('<span>').addClass('timepicker-hour').attr({'data-time-component':'hours', 'title':'Pick Hour'}).attr('data-action', 'showHours'))); |
| bottomRow.append($('<td>') |
| .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Hour'}).addClass('btn').attr('data-action', 'decrementHours') |
| .append($('<span>').addClass(options.icons.down)))); |
| } |
| if (isEnabled('m')) { |
| if (isEnabled('h')) { |
| topRow.append($('<td>').addClass('separator')); |
| middleRow.append($('<td>').addClass('separator').html(':')); |
| bottomRow.append($('<td>').addClass('separator')); |
| } |
| topRow.append($('<td>') |
| .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Minute'}).addClass('btn').attr('data-action', 'incrementMinutes') |
| .append($('<span>').addClass(options.icons.up)))); |
| middleRow.append($('<td>') |
| .append($('<span>').addClass('timepicker-minute').attr({'data-time-component': 'minutes', 'title':'Pick Minute'}).attr('data-action', 'showMinutes'))); |
| bottomRow.append($('<td>') |
| .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Minute'}).addClass('btn').attr('data-action', 'decrementMinutes') |
| .append($('<span>').addClass(options.icons.down)))); |
| } |
| if (isEnabled('s')) { |
| if (isEnabled('m')) { |
| topRow.append($('<td>').addClass('separator')); |
| middleRow.append($('<td>').addClass('separator').html(':')); |
| bottomRow.append($('<td>').addClass('separator')); |
| } |
| topRow.append($('<td>') |
| .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Increment Second'}).addClass('btn').attr('data-action', 'incrementSeconds') |
| .append($('<span>').addClass(options.icons.up)))); |
| middleRow.append($('<td>') |
| .append($('<span>').addClass('timepicker-second').attr({'data-time-component': 'seconds', 'title':'Pick Second'}).attr('data-action', 'showSeconds'))); |
| bottomRow.append($('<td>') |
| .append($('<a>').attr({href: '#', tabindex: '-1', 'title':'Decrement Second'}).addClass('btn').attr('data-action', 'decrementSeconds') |
| .append($('<span>').addClass(options.icons.down)))); |
| } |
| |
| if (!use24Hours) { |
| topRow.append($('<td>').addClass('separator')); |
| middleRow.append($('<td>') |
| .append($('<button>').addClass('btn btn-primary').attr({'data-action': 'togglePeriod', tabindex: '-1', 'title':'Toggle Period'}))); |
| bottomRow.append($('<td>').addClass('separator')); |
| } |
| |
| return $('<div>').addClass('timepicker-picker') |
| .append($('<table>').addClass('table-condensed') |
| .append([topRow, middleRow, bottomRow])); |
| }, |
| |
| getTimePickerTemplate = function () { |
| var hoursView = $('<div>').addClass('timepicker-hours') |
| .append($('<table>').addClass('table-condensed')), |
| minutesView = $('<div>').addClass('timepicker-minutes') |
| .append($('<table>').addClass('table-condensed')), |
| secondsView = $('<div>').addClass('timepicker-seconds') |
| .append($('<table>').addClass('table-condensed')), |
| ret = [getTimePickerMainTemplate()]; |
| |
| if (isEnabled('h')) { |
| ret.push(hoursView); |
| } |
| if (isEnabled('m')) { |
| ret.push(minutesView); |
| } |
| if (isEnabled('s')) { |
| ret.push(secondsView); |
| } |
| |
| return ret; |
| }, |
| |
| getToolbar = function () { |
| var row = []; |
| if (options.showTodayButton) { |
| row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title':'Go to today'}).append($('<span>').addClass(options.icons.today)))); |
| } |
| if (!options.sideBySide && hasDate() && hasTime()) { |
| row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title':'Select Time'}).append($('<span>').addClass(options.icons.time)))); |
| } |
| if (options.showClear) { |
| row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title':'Clear selection'}).append($('<span>').addClass(options.icons.clear)))); |
| } |
| if (options.showClose) { |
| row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title':'Close the picker'}).append($('<span>').addClass(options.icons.close)))); |
| } |
| return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row))); |
| }, |
| |
| getTemplate = function () { |
| var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'), |
| dateView = $('<div>').addClass('datepicker').append(getDatePickerTemplate()), |
| timeView = $('<div>').addClass('timepicker').append(getTimePickerTemplate()), |
| content = $('<ul>').addClass('list-unstyled'), |
| toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar()); |
| |
| if (options.inline) { |
| template.removeClass('dropdown-menu'); |
| } |
| |
| if (use24Hours) { |
| template.addClass('usetwentyfour'); |
| } |
| if (isEnabled('s') && !use24Hours) { |
| template.addClass('wider'); |
| } |
| if (options.sideBySide && hasDate() && hasTime()) { |
| template.addClass('timepicker-sbs'); |
| template.append( |
| $('<div>').addClass('row') |
| .append(dateView.addClass('col-sm-6')) |
| .append(timeView.addClass('col-sm-6')) |
| ); |
| template.append(toolbar); |
| return template; |
| } |
| |
| if (options.toolbarPlacement === 'top') { |
| content.append(toolbar); |
| } |
| if (hasDate()) { |
| content.append($('<li>').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView)); |
| } |
| if (options.toolbarPlacement === 'default') { |
| content.append(toolbar); |
| } |
| if (hasTime()) { |
| content.append($('<li>').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView)); |
| } |
| if (options.toolbarPlacement === 'bottom') { |
| content.append(toolbar); |
| } |
| return template.append(content); |
| }, |
| |
| dataToOptions = function () { |
| var eData, |
| dataOptions = {}; |
| |
| if (element.is('input') || options.inline) { |
| eData = element.data(); |
| } else { |
| eData = element.find('input').data(); |
| } |
| |
| if (eData.dateOptions && eData.dateOptions instanceof Object) { |
| dataOptions = $.extend(true, dataOptions, eData.dateOptions); |
| } |
| |
| $.each(options, function (key) { |
| var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1); |
| if (eData[attributeName] !== undefined) { |
| dataOptions[key] = eData[attributeName]; |
| } |
| }); |
| return dataOptions; |
| }, |
| |
| place = function () { |
| var position = (component || element).position(), |
| offset = (component || element).offset(), |
| vertical = options.widgetPositioning.vertical, |
| horizontal = options.widgetPositioning.horizontal, |
| parent; |
| |
| if (options.widgetParent) { |
| parent = options.widgetParent.append(widget); |
| } else if (element.is('input')) { |
| parent = element.after(widget).parent(); |
| } else if (options.inline) { |
| parent = element.append(widget); |
| return; |
| } else { |
| parent = element; |
| element.children().first().after(widget); |
| } |
| |
| // Top and bottom logic |
| if (vertical === 'auto') { |
| if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() && |
| widget.height() + element.outerHeight() < offset.top) { |
| vertical = 'top'; |
| } else { |
| vertical = 'bottom'; |
| } |
| } |
| |
| // Left and right logic |
| if (horizontal === 'auto') { |
| if (parent.width() < offset.left + widget.outerWidth() / 2 && |
| offset.left + widget.outerWidth() > $(window).width()) { |
| horizontal = 'right'; |
| } else { |
| horizontal = 'left'; |
| } |
| } |
| |
| if (vertical === 'top') { |
| widget.addClass('top').removeClass('bottom'); |
| } else { |
| widget.addClass('bottom').removeClass('top'); |
| } |
| |
| if (horizontal === 'right') { |
| widget.addClass('pull-right'); |
| } else { |
| widget.removeClass('pull-right'); |
| } |
| |
| // find the first parent element that has a relative css positioning |
| if (parent.css('position') !== 'relative') { |
| parent = parent.parents().filter(function () { |
| return $(this).css('position') === 'relative'; |
| }).first(); |
| } |
| |
| if (parent.length === 0) { |
| throw new Error('datetimepicker component should be placed within a relative positioned container'); |
| } |
| |
| widget.css({ |
| top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(), |
| bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto', |
| left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto', |
| right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left) |
| }); |
| }, |
| |
| notifyEvent = function (e) { |
| if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) { |
| return; |
| } |
| element.trigger(e); |
| }, |
| |
| viewUpdate = function (e) { |
| if (e === 'y') { |
| e = 'YYYY'; |
| } |
| notifyEvent({ |
| type: 'dp.update', |
| change: e, |
| viewDate: viewDate.clone() |
| }); |
| }, |
| |
| showMode = function (dir) { |
| if (!widget) { |
| return; |
| } |
| if (dir) { |
| currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir)); |
| } |
| widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show(); |
| }, |
| |
| fillDow = function () { |
| var row = $('<tr>'), |
| currentDate = viewDate.clone().startOf('w').startOf('d'); |
| |
| if (options.calendarWeeks === true) { |
| row.append($('<th>').addClass('cw').text('#')); |
| } |
| |
| while (currentDate.isBefore(viewDate.clone().endOf('w'))) { |
| row.append($('<th>').addClass('dow').text(currentDate.format('dd'))); |
| currentDate.add(1, 'd'); |
| } |
| widget.find('.datepicker-days thead').append(row); |
| }, |
| |
| isInDisabledDates = function (testDate) { |
| return options.disabledDates[testDate.format('YYYY-MM-DD')] === true; |
| }, |
| |
| isInEnabledDates = function (testDate) { |
| return options.enabledDates[testDate.format('YYYY-MM-DD')] === true; |
| }, |
| |
| isInDisabledHours = function (testDate) { |
| return options.disabledHours[testDate.format('H')] === true; |
| }, |
| |
| isInEnabledHours = function (testDate) { |
| return options.enabledHours[testDate.format('H')] === true; |
| }, |
| |
| isValid = function (targetMoment, granularity) { |
| if (!targetMoment.isValid()) { |
| return false; |
| } |
| if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) { |
| return false; |
| } |
| if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) { |
| return false; |
| } |
| if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) { |
| return false; |
| } |
| if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) { |
| return false; |
| } |
| if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) { |
| return false; |
| } |
| if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) { |
| return false; |
| } |
| if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) { |
| return false; |
| } |
| if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) { |
| var found = false; |
| $.each(options.disabledTimeIntervals, function () { |
| if (targetMoment.isBetween(this[0], this[1])) { |
| found = true; |
| return false; |
| } |
| }); |
| if (found) { |
| return false; |
| } |
| } |
| return true; |
| }, |
| |
| fillMonths = function () { |
| var spans = [], |
| monthsShort = viewDate.clone().startOf('y').startOf('d'); |
| while (monthsShort.isSame(viewDate, 'y')) { |
| spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM'))); |
| monthsShort.add(1, 'M'); |
| } |
| widget.find('.datepicker-months td').empty().append(spans); |
| }, |
| |
| updateMonths = function () { |
| var monthsView = widget.find('.datepicker-months'), |
| monthsViewHeader = monthsView.find('th'), |
| months = monthsView.find('tbody').find('span'); |
| |
| monthsViewHeader.eq(0).find('span').attr('title', 'Previous Year'); |
| monthsViewHeader.eq(1).attr('title', 'Select Year'); |
| monthsViewHeader.eq(2).find('span').attr('title', 'Next Year'); |
| |
| monthsView.find('.disabled').removeClass('disabled'); |
| |
| if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) { |
| monthsViewHeader.eq(0).addClass('disabled'); |
| } |
| |
| monthsViewHeader.eq(1).text(viewDate.year()); |
| |
| if (!isValid(viewDate.clone().add(1, 'y'), 'y')) { |
| monthsViewHeader.eq(2).addClass('disabled'); |
| } |
| |
| months.removeClass('active'); |
| if (date.isSame(viewDate, 'y') && !unset) { |
| months.eq(date.month()).addClass('active'); |
| } |
| |
| months.each(function (index) { |
| if (!isValid(viewDate.clone().month(index), 'M')) { |
| $(this).addClass('disabled'); |
| } |
| }); |
| }, |
| |
| updateYears = function () { |
| var yearsView = widget.find('.datepicker-years'), |
| yearsViewHeader = yearsView.find('th'), |
| startYear = viewDate.clone().subtract(5, 'y'), |
| endYear = viewDate.clone().add(6, 'y'), |
| html = ''; |
| |
| yearsViewHeader.eq(0).find('span').attr('title', 'Previous Decade'); |
| yearsViewHeader.eq(1).attr('title', 'Select Decade'); |
| yearsViewHeader.eq(2).find('span').attr('title', 'Next Decade'); |
| |
| yearsView.find('.disabled').removeClass('disabled'); |
| |
| if (options.minDate && options.minDate.isAfter(startYear, 'y')) { |
| yearsViewHeader.eq(0).addClass('disabled'); |
| } |
| |
| yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year()); |
| |
| if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) { |
| yearsViewHeader.eq(2).addClass('disabled'); |
| } |
| |
| while (!startYear.isAfter(endYear, 'y')) { |
| html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>'; |
| startYear.add(1, 'y'); |
| } |
| |
| yearsView.find('td').html(html); |
| }, |
| |
| updateDecades = function () { |
| var decadesView = widget.find('.datepicker-decades'), |
| decadesViewHeader = decadesView.find('th'), |
| startDecade = viewDate.isBefore(moment({y: 1999})) ? moment({y: 1899}) : moment({y: 1999}), |
| endDecade = startDecade.clone().add(100, 'y'), |
| html = ''; |
| |
| decadesViewHeader.eq(0).find('span').attr('title', 'Previous Century'); |
| decadesViewHeader.eq(2).find('span').attr('title', 'Next Century'); |
| |
| decadesView.find('.disabled').removeClass('disabled'); |
| |
| if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) { |
| decadesViewHeader.eq(0).addClass('disabled'); |
| } |
| |
| decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year()); |
| |
| if (startDecade.isSame(moment({y: 2000})) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) { |
| decadesViewHeader.eq(2).addClass('disabled'); |
| } |
| |
| while (!startDecade.isAfter(endDecade, 'y')) { |
| html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') + |
| (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>'; |
| startDecade.add(12, 'y'); |
| } |
| html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even |
| |
| decadesView.find('td').html(html); |
| }, |
| |
| fillDate = function () { |
| var daysView = widget.find('.datepicker-days'), |
| daysViewHeader = daysView.find('th'), |
| currentDate, |
| html = [], |
| row, |
| clsName, |
| i; |
| |
| if (!hasDate()) { |
| return; |
| } |
| |
| daysViewHeader.eq(0).find('span').attr('title', 'Previous Month'); |
| daysViewHeader.eq(1).attr('title', 'Select Month'); |
| daysViewHeader.eq(2).find('span').attr('title', 'Next Month'); |
| |
| daysView.find('.disabled').removeClass('disabled'); |
| daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat)); |
| |
| if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) { |
| daysViewHeader.eq(0).addClass('disabled'); |
| } |
| if (!isValid(viewDate.clone().add(1, 'M'), 'M')) { |
| daysViewHeader.eq(2).addClass('disabled'); |
| } |
| |
| currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d'); |
| |
| for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks) |
| if (currentDate.weekday() === 0) { |
| row = $('<tr>'); |
| if (options.calendarWeeks) { |
| row.append('<td class="cw">' + currentDate.week() + '</td>'); |
| } |
| html.push(row); |
| } |
| clsName = ''; |
| if (currentDate.isBefore(viewDate, 'M')) { |
| clsName += ' old'; |
| } |
| if (currentDate.isAfter(viewDate, 'M')) { |
| clsName += ' new'; |
| } |
| if (currentDate.isSame(date, 'd') && !unset) { |
| clsName += ' active'; |
| } |
| if (!isValid(currentDate, 'd')) { |
| clsName += ' disabled'; |
| } |
| if (currentDate.isSame(moment(), 'd')) { |
| clsName += ' today'; |
| } |
| if (currentDate.day() === 0 || currentDate.day() === 6) { |
| clsName += ' weekend'; |
| } |
| row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="day' + clsName + '">' + currentDate.date() + '</td>'); |
| currentDate.add(1, 'd'); |
| } |
| |
| daysView.find('tbody').empty().append(html); |
| |
| updateMonths(); |
| |
| updateYears(); |
| |
| updateDecades(); |
| }, |
| |
| fillHours = function () { |
| var table = widget.find('.timepicker-hours table'), |
| currentHour = viewDate.clone().startOf('d'), |
| html = [], |
| row = $('<tr>'); |
| |
| if (viewDate.hour() > 11 && !use24Hours) { |
| currentHour.hour(12); |
| } |
| while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) { |
| if (currentHour.hour() % 4 === 0) { |
| row = $('<tr>'); |
| html.push(row); |
| } |
| row.append('<td data-action="selectHour" class="hour' + (!isValid(currentHour, 'h') ? ' disabled' : '') + '">' + currentHour.format(use24Hours ? 'HH' : 'hh') + '</td>'); |
| currentHour.add(1, 'h'); |
| } |
| table.empty().append(html); |
| }, |
| |
| fillMinutes = function () { |
| var table = widget.find('.timepicker-minutes table'), |
| currentMinute = viewDate.clone().startOf('h'), |
| html = [], |
| row = $('<tr>'), |
| step = options.stepping === 1 ? 5 : options.stepping; |
| |
| while (viewDate.isSame(currentMinute, 'h')) { |
| if (currentMinute.minute() % (step * 4) === 0) { |
| row = $('<tr>'); |
| html.push(row); |
| } |
| row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>'); |
| currentMinute.add(step, 'm'); |
| } |
| table.empty().append(html); |
| }, |
| |
| fillSeconds = function () { |
| var table = widget.find('.timepicker-seconds table'), |
| currentSecond = viewDate.clone().startOf('m'), |
| html = [], |
| row = $('<tr>'); |
| |
| while (viewDate.isSame(currentSecond, 'm')) { |
| if (currentSecond.second() % 20 === 0) { |
| row = $('<tr>'); |
| html.push(row); |
| } |
| row.append('<td data-action="selectSecond" class="second' + (!isValid(currentSecond, 's') ? ' disabled' : '') + '">' + currentSecond.format('ss') + '</td>'); |
| currentSecond.add(5, 's'); |
| } |
| |
| table.empty().append(html); |
| }, |
| |
| fillTime = function () { |
| var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]'); |
| |
| if (!use24Hours) { |
| toggle = widget.find('.timepicker [data-action=togglePeriod]'); |
| newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'); |
| |
| toggle.text(date.format('A')); |
| |
| if (isValid(newDate, 'h')) { |
| toggle.removeClass('disabled'); |
| } else { |
| toggle.addClass('disabled'); |
| } |
| } |
| timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh')); |
| timeComponents.filter('[data-time-component=minutes]').text(date.format('mm')); |
| timeComponents.filter('[data-time-component=seconds]').text(date.format('ss')); |
| |
| fillHours(); |
| fillMinutes(); |
| fillSeconds(); |
| }, |
| |
| update = function () { |
| if (!widget) { |
| return; |
| } |
| fillDate(); |
| fillTime(); |
| }, |
| |
| setValue = function (targetMoment) { |
| var oldDate = unset ? null : date; |
| |
| // case of calling setValue(null or false) |
| if (!targetMoment) { |
| unset = true; |
| input.val(''); |
| element.data('date', ''); |
| notifyEvent({ |
| type: 'dp.change', |
| date: false, |
| oldDate: oldDate |
| }); |
| update(); |
| return; |
| } |
| |
| targetMoment = targetMoment.clone().locale(options.locale); |
| |
| if (options.stepping !== 1) { |
| targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0); |
| } |
| |
| if (isValid(targetMoment)) { |
| date = targetMoment; |
| viewDate = date.clone(); |
| input.val(date.format(actualFormat)); |
| element.data('date', date.format(actualFormat)); |
| unset = false; |
| update(); |
| notifyEvent({ |
| type: 'dp.change', |
| date: date.clone(), |
| oldDate: oldDate |
| }); |
| } else { |
| if (!options.keepInvalid) { |
| input.val(unset ? '' : date.format(actualFormat)); |
| } |
| notifyEvent({ |
| type: 'dp.error', |
| date: targetMoment |
| }); |
| } |
| }, |
| |
| hide = function () { |
| ///<summary>Hides the widget. Possibly will emit dp.hide</summary> |
| var transitioning = false; |
| if (!widget) { |
| return picker; |
| } |
| // Ignore event if in the middle of a picker transition |
| widget.find('.collapse').each(function () { |
| var collapseData = $(this).data('collapse'); |
| if (collapseData && collapseData.transitioning) { |
| transitioning = true; |
| return false; |
| } |
| return true; |
| }); |
| if (transitioning) { |
| return picker; |
| } |
| if (component && component.hasClass('btn')) { |
| component.toggleClass('active'); |
| } |
| widget.hide(); |
| |
| $(window).off('resize', place); |
| widget.off('click', '[data-action]'); |
| widget.off('mousedown', false); |
| |
| widget.remove(); |
| widget = false; |
| |
| notifyEvent({ |
| type: 'dp.hide', |
| date: date.clone() |
| }); |
| return picker; |
| }, |
| |
| clear = function () { |
| setValue(null); |
| }, |
| |
| /******************************************************************************** |
| * |
| * Widget UI interaction functions |
| * |
| ********************************************************************************/ |
| actions = { |
| next: function () { |
| var navFnc = datePickerModes[currentViewMode].navFnc; |
| viewDate.add(datePickerModes[currentViewMode].navStep, navFnc); |
| fillDate(); |
| viewUpdate(navFnc); |
| }, |
| |
| previous: function () { |
| var navFnc = datePickerModes[currentViewMode].navFnc; |
| viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc); |
| fillDate(); |
| viewUpdate(navFnc); |
| }, |
| |
| pickerSwitch: function () { |
| showMode(1); |
| }, |
| |
| selectMonth: function (e) { |
| var month = $(e.target).closest('tbody').find('span').index($(e.target)); |
| viewDate.month(month); |
| if (currentViewMode === minViewModeNumber) { |
| setValue(date.clone().year(viewDate.year()).month(viewDate.month())); |
| if (!options.inline) { |
| hide(); |
| } |
| } else { |
| showMode(-1); |
| fillDate(); |
| } |
| viewUpdate('M'); |
| }, |
| |
| selectYear: function (e) { |
| var year = parseInt($(e.target).text(), 10) || 0; |
| viewDate.year(year); |
| if (currentViewMode === minViewModeNumber) { |
| setValue(date.clone().year(viewDate.year())); |
| if (!options.inline) { |
| hide(); |
| } |
| } else { |
| showMode(-1); |
| fillDate(); |
| } |
| viewUpdate('YYYY'); |
| }, |
| |
| selectDecade: function (e) { |
| var year = parseInt($(e.target).data('selection'), 10) || 0; |
| viewDate.year(year); |
| if (currentViewMode === minViewModeNumber) { |
| setValue(date.clone().year(viewDate.year())); |
| if (!options.inline) { |
| hide(); |
| } |
| } else { |
| showMode(-1); |
| fillDate(); |
| } |
| viewUpdate('YYYY'); |
| }, |
| |
| selectDay: function (e) { |
| var day = viewDate.clone(); |
| if ($(e.target).is('.old')) { |
| day.subtract(1, 'M'); |
| } |
| if ($(e.target).is('.new')) { |
| day.add(1, 'M'); |
| } |
| setValue(day.date(parseInt($(e.target).text(), 10))); |
| if (!hasTime() && !options.keepOpen && !options.inline) { |
| hide(); |
| } |
| }, |
| |
| incrementHours: function () { |
| var newDate = date.clone().add(1, 'h'); |
| if (isValid(newDate, 'h')) { |
| setValue(newDate); |
| } |
| }, |
| |
| incrementMinutes: function () { |
| var newDate = date.clone().add(options.stepping, 'm'); |
| if (isValid(newDate, 'm')) { |
| setValue(newDate); |
| } |
| }, |
| |
| incrementSeconds: function () { |
| var newDate = date.clone().add(1, 's'); |
| if (isValid(newDate, 's')) { |
| setValue(newDate); |
| } |
| }, |
| |
| decrementHours: function () { |
| var newDate = date.clone().subtract(1, 'h'); |
| if (isValid(newDate, 'h')) { |
| setValue(newDate); |
| } |
| }, |
| |
| decrementMinutes: function () { |
| var newDate = date.clone().subtract(options.stepping, 'm'); |
| if (isValid(newDate, 'm')) { |
| setValue(newDate); |
| } |
| }, |
| |
| decrementSeconds: function () { |
| var newDate = date.clone().subtract(1, 's'); |
| if (isValid(newDate, 's')) { |
| setValue(newDate); |
| } |
| }, |
| |
| togglePeriod: function () { |
| setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h')); |
| }, |
| |
| togglePicker: function (e) { |
| var $this = $(e.target), |
| $parent = $this.closest('ul'), |
| expanded = $parent.find('.in'), |
| closed = $parent.find('.collapse:not(.in)'), |
| collapseData; |
| |
| if (expanded && expanded.length) { |
| collapseData = expanded.data('collapse'); |
| if (collapseData && collapseData.transitioning) { |
| return; |
| } |
| if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it |
| expanded.collapse('hide'); |
| closed.collapse('show'); |
| } else { // otherwise just toggle in class on the two views |
| expanded.removeClass('in'); |
| closed.addClass('in'); |
| } |
| if ($this.is('span')) { |
| $this.toggleClass(options.icons.time + ' ' + options.icons.date); |
| } else { |
| $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); |
| } |
| |
| // NOTE: uncomment if toggled state will be restored in show() |
| //if (component) { |
| // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date); |
| //} |
| } |
| }, |
| |
| showPicker: function () { |
| widget.find('.timepicker > div:not(.timepicker-picker)').hide(); |
| widget.find('.timepicker .timepicker-picker').show(); |
| }, |
| |
| showHours: function () { |
| widget.find('.timepicker .timepicker-picker').hide(); |
| widget.find('.timepicker .timepicker-hours').show(); |
| }, |
| |
| showMinutes: function () { |
| widget.find('.timepicker .timepicker-picker').hide(); |
| widget.find('.timepicker .timepicker-minutes').show(); |
| }, |
| |
| showSeconds: function () { |
| widget.find('.timepicker .timepicker-picker').hide(); |
| widget.find('.timepicker .timepicker-seconds').show(); |
| }, |
| |
| selectHour: function (e) { |
| var hour = parseInt($(e.target).text(), 10); |
| |
| if (!use24Hours) { |
| if (date.hours() >= 12) { |
| if (hour !== 12) { |
| hour += 12; |
| } |
| } else { |
| if (hour === 12) { |
| hour = 0; |
| } |
| } |
| } |
| setValue(date.clone().hours(hour)); |
| actions.showPicker.call(picker); |
| }, |
| |
| selectMinute: function (e) { |
| setValue(date.clone().minutes(parseInt($(e.target).text(), 10))); |
| actions.showPicker.call(picker); |
| }, |
| |
| selectSecond: function (e) { |
| setValue(date.clone().seconds(parseInt($(e.target).text(), 10))); |
| actions.showPicker.call(picker); |
| }, |
| |
| clear: clear, |
| |
| today: function () { |
| if (isValid(moment(), 'd')) { |
| setValue(moment()); |
| } |
| }, |
| |
| close: hide |
| }, |
| |
| doAction = function (e) { |
| if ($(e.currentTarget).is('.disabled')) { |
| return false; |
| } |
| actions[$(e.currentTarget).data('action')].apply(picker, arguments); |
| return false; |
| }, |
| |
| show = function () { |
| ///<summary>Shows the widget. Possibly will emit dp.show and dp.change</summary> |
| var currentMoment, |
| useCurrentGranularity = { |
| 'year': function (m) { |
| return m.month(0).date(1).hours(0).seconds(0).minutes(0); |
| }, |
| 'month': function (m) { |
| return m.date(1).hours(0).seconds(0).minutes(0); |
| }, |
| 'day': function (m) { |
| return m.hours(0).seconds(0).minutes(0); |
| }, |
| 'hour': function (m) { |
| return m.seconds(0).minutes(0); |
| }, |
| 'minute': function (m) { |
| return m.seconds(0); |
| } |
| }; |
| |
| if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) { |
| return picker; |
| } |
| if (input.val() !== undefined && input.val().trim().length !== 0) { |
| setValue(parseInputDate(input.val().trim())); |
| } else if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) { |
| currentMoment = moment(); |
| if (typeof options.useCurrent === 'string') { |
| currentMoment = useCurrentGranularity[options.useCurrent](currentMoment); |
| } |
| setValue(currentMoment); |
| } |
| |
| widget = getTemplate(); |
| |
| fillDow(); |
| fillMonths(); |
| |
| widget.find('.timepicker-hours').hide(); |
| widget.find('.timepicker-minutes').hide(); |
| widget.find('.timepicker-seconds').hide(); |
| |
| update(); |
| showMode(); |
| |
| $(window).on('resize', place); |
| widget.on('click', '[data-action]', doAction); // this handles clicks on the widget |
| widget.on('mousedown', false); |
| |
| if (component && component.hasClass('btn')) { |
| component.toggleClass('active'); |
| } |
| widget.show(); |
| place(); |
| |
| if (options.focusOnShow && !input.is(':focus')) { |
| input.focus(); |
| } |
| |
| notifyEvent({ |
| type: 'dp.show' |
| }); |
| return picker; |
| }, |
| |
| toggle = function () { |
| /// <summary>Shows or hides the widget</summary> |
| return (widget ? hide() : show()); |
| }, |
| |
| parseInputDate = function (inputDate) { |
| if (options.parseInputDate === undefined) { |
| if (moment.isMoment(inputDate) || inputDate instanceof Date) { |
| inputDate = moment(inputDate); |
| } else { |
| inputDate = moment(inputDate, parseFormats, options.useStrict); |
| } |
| } else { |
| inputDate = options.parseInputDate(inputDate); |
| } |
| inputDate.locale(options.locale); |
| return inputDate; |
| }, |
| |
| keydown = function (e) { |
| var handler = null, |
| index, |
| index2, |
| pressedKeys = [], |
| pressedModifiers = {}, |
| currentKey = e.which, |
| keyBindKeys, |
| allModifiersPressed, |
| pressed = 'p'; |
| |
| keyState[currentKey] = pressed; |
| |
| for (index in keyState) { |
| if (keyState.hasOwnProperty(index) && keyState[index] === pressed) { |
| pressedKeys.push(index); |
| if (parseInt(index, 10) !== currentKey) { |
| pressedModifiers[index] = true; |
| } |
| } |
| } |
| |
| for (index in options.keyBinds) { |
| if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') { |
| keyBindKeys = index.split(' '); |
| if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) { |
| allModifiersPressed = true; |
| for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) { |
| if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) { |
| allModifiersPressed = false; |
| break; |
| } |
| } |
| if (allModifiersPressed) { |
| handler = options.keyBinds[index]; |
| break; |
| } |
| } |
| } |
| } |
| |
| if (handler) { |
| handler.call(picker, widget); |
| e.stopPropagation(); |
| e.preventDefault(); |
| } |
| }, |
| |
| keyup = function (e) { |
| keyState[e.which] = 'r'; |
| e.stopPropagation(); |
| e.preventDefault(); |
| }, |
| |
| change = function (e) { |
| var val = $(e.target).val().trim(), |
| parsedDate = val ? parseInputDate(val) : null; |
| setValue(parsedDate); |
| e.stopImmediatePropagation(); |
| return false; |
| }, |
| |
| attachDatePickerElementEvents = function () { |
| input.on({ |
| 'change': change, |
| 'blur': options.debug ? '' : hide, |
| 'keydown': keydown, |
| 'keyup': keyup, |
| 'focus': options.allowInputToggle ? show : '' |
| }); |
| |
| if (element.is('input')) { |
| input.on({ |
| 'focus': show |
| }); |
| } else if (component) { |
| component.on('click', toggle); |
| component.on('mousedown', false); |
| } |
| }, |
| |
| detachDatePickerElementEvents = function () { |
| input.off({ |
| 'change': change, |
| 'blur': hide, |
| 'keydown': keydown, |
| 'keyup': keyup, |
| 'focus': options.allowInputToggle ? hide : '' |
| }); |
| |
| if (element.is('input')) { |
| input.off({ |
| 'focus': show |
| }); |
| } else if (component) { |
| component.off('click', toggle); |
| component.off('mousedown', false); |
| } |
| }, |
| |
| indexGivenDates = function (givenDatesArray) { |
| // Store given enabledDates and disabledDates as keys. |
| // This way we can check their existence in O(1) time instead of looping through whole array. |
| // (for example: options.enabledDates['2014-02-27'] === true) |
| var givenDatesIndexed = {}; |
| $.each(givenDatesArray, function () { |
| var dDate = parseInputDate(this); |
| if (dDate.isValid()) { |
| givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true; |
| } |
| }); |
| return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false; |
| }, |
| |
| indexGivenHours = function (givenHoursArray) { |
| // Store given enabledHours and disabledHours as keys. |
| // This way we can check their existence in O(1) time instead of looping through whole array. |
| // (for example: options.enabledHours['2014-02-27'] === true) |
| var givenHoursIndexed = {}; |
| $.each(givenHoursArray, function () { |
| givenHoursIndexed[this] = true; |
| }); |
| return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false; |
| }, |
| |
| initFormatting = function () { |
| var format = options.format || 'L LT'; |
| |
| actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) { |
| var newinput = date.localeData().longDateFormat(formatInput) || formatInput; |
| return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740 |
| return date.localeData().longDateFormat(formatInput2) || formatInput2; |
| }); |
| }); |
| |
| |
| parseFormats = options.extraFormats ? options.extraFormats.slice() : []; |
| if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) { |
| parseFormats.push(actualFormat); |
| } |
| |
| use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1); |
| |
| if (isEnabled('y')) { |
| minViewModeNumber = 2; |
| } |
| if (isEnabled('M')) { |
| minViewModeNumber = 1; |
| } |
| if (isEnabled('d')) { |
| minViewModeNumber = 0; |
| } |
| |
| currentViewMode = Math.max(minViewModeNumber, currentViewMode); |
| |
| if (!unset) { |
| setValue(date); |
| } |
| }; |
| |
| /******************************************************************************** |
| * |
| * Public API functions |
| * ===================== |
| * |
| * Important: Do not expose direct references to private objects or the options |
| * object to the outer world. Always return a clone when returning values or make |
| * a clone when setting a private variable. |
| * |
| ********************************************************************************/ |
| picker.destroy = function () { |
| ///<summary>Destroys the widget and removes all attached event listeners</summary> |
| hide(); |
| detachDatePickerElementEvents(); |
| element.removeData('DateTimePicker'); |
| element.removeData('date'); |
| }; |
| |
| picker.toggle = toggle; |
| |
| picker.show = show; |
| |
| picker.hide = hide; |
| |
| picker.disable = function () { |
| ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it. |
| ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary> |
| hide(); |
| if (component && component.hasClass('btn')) { |
| component.addClass('disabled'); |
| } |
| input.prop('disabled', true); |
| return picker; |
| }; |
| |
| picker.enable = function () { |
| ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary> |
| if (component && component.hasClass('btn')) { |
| component.removeClass('disabled'); |
| } |
| input.prop('disabled', false); |
| return picker; |
| }; |
| |
| picker.ignoreReadonly = function (ignoreReadonly) { |
| if (arguments.length === 0) { |
| return options.ignoreReadonly; |
| } |
| if (typeof ignoreReadonly !== 'boolean') { |
| throw new TypeError('ignoreReadonly () expects a boolean parameter'); |
| } |
| options.ignoreReadonly = ignoreReadonly; |
| return picker; |
| }; |
| |
| picker.options = function (newOptions) { |
| if (arguments.length === 0) { |
| return $.extend(true, {}, options); |
| } |
| |
| if (!(newOptions instanceof Object)) { |
| throw new TypeError('options() options parameter should be an object'); |
| } |
| $.extend(true, options, newOptions); |
| $.each(options, function (key, value) { |
| if (picker[key] !== undefined) { |
| picker[key](value); |
| } else { |
| throw new TypeError('option ' + key + ' is not recognized!'); |
| } |
| }); |
| return picker; |
| }; |
| |
| picker.date = function (newDate) { |
| ///<signature helpKeyword="$.fn.datetimepicker.date"> |
| ///<summary>Returns the component's model current date, a moment object or null if not set.</summary> |
| ///<returns type="Moment">date.clone()</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary> |
| ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| if (unset) { |
| return null; |
| } |
| return date.clone(); |
| } |
| |
| if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { |
| throw new TypeError('date() parameter must be one of [null, string, moment or Date]'); |
| } |
| |
| setValue(newDate === null ? null : parseInputDate(newDate)); |
| return picker; |
| }; |
| |
| picker.format = function (newFormat) { |
| ///<summary>test su</summary> |
| ///<param name="newFormat">info about para</param> |
| ///<returns type="string|boolean">returns foo</returns> |
| if (arguments.length === 0) { |
| return options.format; |
| } |
| |
| if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) { |
| throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat); |
| } |
| |
| options.format = newFormat; |
| if (actualFormat) { |
| initFormatting(); // reinit formatting |
| } |
| return picker; |
| }; |
| |
| picker.dayViewHeaderFormat = function (newFormat) { |
| if (arguments.length === 0) { |
| return options.dayViewHeaderFormat; |
| } |
| |
| if (typeof newFormat !== 'string') { |
| throw new TypeError('dayViewHeaderFormat() expects a string parameter'); |
| } |
| |
| options.dayViewHeaderFormat = newFormat; |
| return picker; |
| }; |
| |
| picker.extraFormats = function (formats) { |
| if (arguments.length === 0) { |
| return options.extraFormats; |
| } |
| |
| if (formats !== false && !(formats instanceof Array)) { |
| throw new TypeError('extraFormats() expects an array or false parameter'); |
| } |
| |
| options.extraFormats = formats; |
| if (parseFormats) { |
| initFormatting(); // reinit formatting |
| } |
| return picker; |
| }; |
| |
| picker.disabledDates = function (dates) { |
| ///<signature helpKeyword="$.fn.datetimepicker.disabledDates"> |
| ///<summary>Returns an array with the currently set disabled dates on the component.</summary> |
| ///<returns type="array">options.disabledDates</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of |
| ///options.enabledDates if such exist.</summary> |
| ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates); |
| } |
| |
| if (!dates) { |
| options.disabledDates = false; |
| update(); |
| return picker; |
| } |
| if (!(dates instanceof Array)) { |
| throw new TypeError('disabledDates() expects an array parameter'); |
| } |
| options.disabledDates = indexGivenDates(dates); |
| options.enabledDates = false; |
| update(); |
| return picker; |
| }; |
| |
| picker.enabledDates = function (dates) { |
| ///<signature helpKeyword="$.fn.datetimepicker.enabledDates"> |
| ///<summary>Returns an array with the currently set enabled dates on the component.</summary> |
| ///<returns type="array">options.enabledDates</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary> |
| ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates); |
| } |
| |
| if (!dates) { |
| options.enabledDates = false; |
| update(); |
| return picker; |
| } |
| if (!(dates instanceof Array)) { |
| throw new TypeError('enabledDates() expects an array parameter'); |
| } |
| options.enabledDates = indexGivenDates(dates); |
| options.disabledDates = false; |
| update(); |
| return picker; |
| }; |
| |
| picker.daysOfWeekDisabled = function (daysOfWeekDisabled) { |
| if (arguments.length === 0) { |
| return options.daysOfWeekDisabled.splice(0); |
| } |
| |
| if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) { |
| options.daysOfWeekDisabled = false; |
| update(); |
| return picker; |
| } |
| |
| if (!(daysOfWeekDisabled instanceof Array)) { |
| throw new TypeError('daysOfWeekDisabled() expects an array parameter'); |
| } |
| options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) { |
| currentValue = parseInt(currentValue, 10); |
| if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) { |
| return previousValue; |
| } |
| if (previousValue.indexOf(currentValue) === -1) { |
| previousValue.push(currentValue); |
| } |
| return previousValue; |
| }, []).sort(); |
| if (options.useCurrent && !options.keepInvalid) { |
| var tries = 0; |
| while (!isValid(date, 'd')) { |
| date.add(1, 'd'); |
| if (tries === 7) { |
| throw 'Tried 7 times to find a valid date'; |
| } |
| tries++; |
| } |
| setValue(date); |
| } |
| update(); |
| return picker; |
| }; |
| |
| picker.maxDate = function (maxDate) { |
| if (arguments.length === 0) { |
| return options.maxDate ? options.maxDate.clone() : options.maxDate; |
| } |
| |
| if ((typeof maxDate === 'boolean') && maxDate === false) { |
| options.maxDate = false; |
| update(); |
| return picker; |
| } |
| |
| if (typeof maxDate === 'string') { |
| if (maxDate === 'now' || maxDate === 'moment') { |
| maxDate = moment(); |
| } |
| } |
| |
| var parsedDate = parseInputDate(maxDate); |
| |
| if (!parsedDate.isValid()) { |
| throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate); |
| } |
| if (options.minDate && parsedDate.isBefore(options.minDate)) { |
| throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat)); |
| } |
| options.maxDate = parsedDate; |
| if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) { |
| setValue(options.maxDate); |
| } |
| if (viewDate.isAfter(parsedDate)) { |
| viewDate = parsedDate.clone(); |
| } |
| update(); |
| return picker; |
| }; |
| |
| picker.minDate = function (minDate) { |
| if (arguments.length === 0) { |
| return options.minDate ? options.minDate.clone() : options.minDate; |
| } |
| |
| if ((typeof minDate === 'boolean') && minDate === false) { |
| options.minDate = false; |
| update(); |
| return picker; |
| } |
| |
| if (typeof minDate === 'string') { |
| if (minDate === 'now' || minDate === 'moment') { |
| minDate = moment(); |
| } |
| } |
| |
| var parsedDate = parseInputDate(minDate); |
| |
| if (!parsedDate.isValid()) { |
| throw new TypeError('minDate() Could not parse date parameter: ' + minDate); |
| } |
| if (options.maxDate && parsedDate.isAfter(options.maxDate)) { |
| throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat)); |
| } |
| options.minDate = parsedDate; |
| if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) { |
| setValue(options.minDate); |
| } |
| if (viewDate.isBefore(parsedDate)) { |
| viewDate = parsedDate.clone(); |
| } |
| update(); |
| return picker; |
| }; |
| |
| picker.defaultDate = function (defaultDate) { |
| ///<signature helpKeyword="$.fn.datetimepicker.defaultDate"> |
| ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary> |
| ///<returns type="Moment">date.clone()</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary> |
| ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| return options.defaultDate ? options.defaultDate.clone() : options.defaultDate; |
| } |
| if (!defaultDate) { |
| options.defaultDate = false; |
| return picker; |
| } |
| |
| if (typeof defaultDate === 'string') { |
| if (defaultDate === 'now' || defaultDate === 'moment') { |
| defaultDate = moment(); |
| } |
| } |
| |
| var parsedDate = parseInputDate(defaultDate); |
| if (!parsedDate.isValid()) { |
| throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate); |
| } |
| if (!isValid(parsedDate)) { |
| throw new TypeError('defaultDate() date passed is invalid according to component setup validations'); |
| } |
| |
| options.defaultDate = parsedDate; |
| |
| if (options.defaultDate && options.inline || (input.val().trim() === '' && input.attr('placeholder') === undefined)) { |
| setValue(options.defaultDate); |
| } |
| return picker; |
| }; |
| |
| picker.locale = function (locale) { |
| if (arguments.length === 0) { |
| return options.locale; |
| } |
| |
| if (!moment.localeData(locale)) { |
| throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!'); |
| } |
| |
| options.locale = locale; |
| date.locale(options.locale); |
| viewDate.locale(options.locale); |
| |
| if (actualFormat) { |
| initFormatting(); // reinit formatting |
| } |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.stepping = function (stepping) { |
| if (arguments.length === 0) { |
| return options.stepping; |
| } |
| |
| stepping = parseInt(stepping, 10); |
| if (isNaN(stepping) || stepping < 1) { |
| stepping = 1; |
| } |
| options.stepping = stepping; |
| return picker; |
| }; |
| |
| picker.useCurrent = function (useCurrent) { |
| var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute']; |
| if (arguments.length === 0) { |
| return options.useCurrent; |
| } |
| |
| if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) { |
| throw new TypeError('useCurrent() expects a boolean or string parameter'); |
| } |
| if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) { |
| throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', ')); |
| } |
| options.useCurrent = useCurrent; |
| return picker; |
| }; |
| |
| picker.collapse = function (collapse) { |
| if (arguments.length === 0) { |
| return options.collapse; |
| } |
| |
| if (typeof collapse !== 'boolean') { |
| throw new TypeError('collapse() expects a boolean parameter'); |
| } |
| if (options.collapse === collapse) { |
| return picker; |
| } |
| options.collapse = collapse; |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.icons = function (icons) { |
| if (arguments.length === 0) { |
| return $.extend({}, options.icons); |
| } |
| |
| if (!(icons instanceof Object)) { |
| throw new TypeError('icons() expects parameter to be an Object'); |
| } |
| $.extend(options.icons, icons); |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.useStrict = function (useStrict) { |
| if (arguments.length === 0) { |
| return options.useStrict; |
| } |
| |
| if (typeof useStrict !== 'boolean') { |
| throw new TypeError('useStrict() expects a boolean parameter'); |
| } |
| options.useStrict = useStrict; |
| return picker; |
| }; |
| |
| picker.sideBySide = function (sideBySide) { |
| if (arguments.length === 0) { |
| return options.sideBySide; |
| } |
| |
| if (typeof sideBySide !== 'boolean') { |
| throw new TypeError('sideBySide() expects a boolean parameter'); |
| } |
| options.sideBySide = sideBySide; |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.viewMode = function (viewMode) { |
| if (arguments.length === 0) { |
| return options.viewMode; |
| } |
| |
| if (typeof viewMode !== 'string') { |
| throw new TypeError('viewMode() expects a string parameter'); |
| } |
| |
| if (viewModes.indexOf(viewMode) === -1) { |
| throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value'); |
| } |
| |
| options.viewMode = viewMode; |
| currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber); |
| |
| showMode(); |
| return picker; |
| }; |
| |
| picker.toolbarPlacement = function (toolbarPlacement) { |
| if (arguments.length === 0) { |
| return options.toolbarPlacement; |
| } |
| |
| if (typeof toolbarPlacement !== 'string') { |
| throw new TypeError('toolbarPlacement() expects a string parameter'); |
| } |
| if (toolbarPlacements.indexOf(toolbarPlacement) === -1) { |
| throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value'); |
| } |
| options.toolbarPlacement = toolbarPlacement; |
| |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.widgetPositioning = function (widgetPositioning) { |
| if (arguments.length === 0) { |
| return $.extend({}, options.widgetPositioning); |
| } |
| |
| if (({}).toString.call(widgetPositioning) !== '[object Object]') { |
| throw new TypeError('widgetPositioning() expects an object variable'); |
| } |
| if (widgetPositioning.horizontal) { |
| if (typeof widgetPositioning.horizontal !== 'string') { |
| throw new TypeError('widgetPositioning() horizontal variable must be a string'); |
| } |
| widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase(); |
| if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) { |
| throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')'); |
| } |
| options.widgetPositioning.horizontal = widgetPositioning.horizontal; |
| } |
| if (widgetPositioning.vertical) { |
| if (typeof widgetPositioning.vertical !== 'string') { |
| throw new TypeError('widgetPositioning() vertical variable must be a string'); |
| } |
| widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase(); |
| if (verticalModes.indexOf(widgetPositioning.vertical) === -1) { |
| throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')'); |
| } |
| options.widgetPositioning.vertical = widgetPositioning.vertical; |
| } |
| update(); |
| return picker; |
| }; |
| |
| picker.calendarWeeks = function (calendarWeeks) { |
| if (arguments.length === 0) { |
| return options.calendarWeeks; |
| } |
| |
| if (typeof calendarWeeks !== 'boolean') { |
| throw new TypeError('calendarWeeks() expects parameter to be a boolean value'); |
| } |
| |
| options.calendarWeeks = calendarWeeks; |
| update(); |
| return picker; |
| }; |
| |
| picker.showTodayButton = function (showTodayButton) { |
| if (arguments.length === 0) { |
| return options.showTodayButton; |
| } |
| |
| if (typeof showTodayButton !== 'boolean') { |
| throw new TypeError('showTodayButton() expects a boolean parameter'); |
| } |
| |
| options.showTodayButton = showTodayButton; |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.showClear = function (showClear) { |
| if (arguments.length === 0) { |
| return options.showClear; |
| } |
| |
| if (typeof showClear !== 'boolean') { |
| throw new TypeError('showClear() expects a boolean parameter'); |
| } |
| |
| options.showClear = showClear; |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.widgetParent = function (widgetParent) { |
| if (arguments.length === 0) { |
| return options.widgetParent; |
| } |
| |
| if (typeof widgetParent === 'string') { |
| widgetParent = $(widgetParent); |
| } |
| |
| if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) { |
| throw new TypeError('widgetParent() expects a string or a jQuery object parameter'); |
| } |
| |
| options.widgetParent = widgetParent; |
| if (widget) { |
| hide(); |
| show(); |
| } |
| return picker; |
| }; |
| |
| picker.keepOpen = function (keepOpen) { |
| if (arguments.length === 0) { |
| return options.keepOpen; |
| } |
| |
| if (typeof keepOpen !== 'boolean') { |
| throw new TypeError('keepOpen() expects a boolean parameter'); |
| } |
| |
| options.keepOpen = keepOpen; |
| return picker; |
| }; |
| |
| picker.focusOnShow = function (focusOnShow) { |
| if (arguments.length === 0) { |
| return options.focusOnShow; |
| } |
| |
| if (typeof focusOnShow !== 'boolean') { |
| throw new TypeError('focusOnShow() expects a boolean parameter'); |
| } |
| |
| options.focusOnShow = focusOnShow; |
| return picker; |
| }; |
| |
| picker.inline = function (inline) { |
| if (arguments.length === 0) { |
| return options.inline; |
| } |
| |
| if (typeof inline !== 'boolean') { |
| throw new TypeError('inline() expects a boolean parameter'); |
| } |
| |
| options.inline = inline; |
| return picker; |
| }; |
| |
| picker.clear = function () { |
| clear(); |
| return picker; |
| }; |
| |
| picker.keyBinds = function (keyBinds) { |
| options.keyBinds = keyBinds; |
| return picker; |
| }; |
| |
| picker.debug = function (debug) { |
| if (typeof debug !== 'boolean') { |
| throw new TypeError('debug() expects a boolean parameter'); |
| } |
| |
| options.debug = debug; |
| return picker; |
| }; |
| |
| picker.allowInputToggle = function (allowInputToggle) { |
| if (arguments.length === 0) { |
| return options.allowInputToggle; |
| } |
| |
| if (typeof allowInputToggle !== 'boolean') { |
| throw new TypeError('allowInputToggle() expects a boolean parameter'); |
| } |
| |
| options.allowInputToggle = allowInputToggle; |
| return picker; |
| }; |
| |
| picker.showClose = function (showClose) { |
| if (arguments.length === 0) { |
| return options.showClose; |
| } |
| |
| if (typeof showClose !== 'boolean') { |
| throw new TypeError('showClose() expects a boolean parameter'); |
| } |
| |
| options.showClose = showClose; |
| return picker; |
| }; |
| |
| picker.keepInvalid = function (keepInvalid) { |
| if (arguments.length === 0) { |
| return options.keepInvalid; |
| } |
| |
| if (typeof keepInvalid !== 'boolean') { |
| throw new TypeError('keepInvalid() expects a boolean parameter'); |
| } |
| options.keepInvalid = keepInvalid; |
| return picker; |
| }; |
| |
| picker.datepickerInput = function (datepickerInput) { |
| if (arguments.length === 0) { |
| return options.datepickerInput; |
| } |
| |
| if (typeof datepickerInput !== 'string') { |
| throw new TypeError('datepickerInput() expects a string parameter'); |
| } |
| |
| options.datepickerInput = datepickerInput; |
| return picker; |
| }; |
| |
| picker.parseInputDate = function (parseInputDate) { |
| if (arguments.length === 0) { |
| return options.parseInputDate; |
| } |
| |
| if (typeof parseInputDate !== 'function') { |
| throw new TypeError('parseInputDate() sholud be as function'); |
| } |
| |
| options.parseInputDate = parseInputDate; |
| |
| return picker; |
| }; |
| |
| picker.disabledTimeIntervals = function (disabledTimeIntervals) { |
| ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals"> |
| ///<summary>Returns an array with the currently set disabled dates on the component.</summary> |
| ///<returns type="array">options.disabledTimeIntervals</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of |
| ///options.enabledDates if such exist.</summary> |
| ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals); |
| } |
| |
| if (!disabledTimeIntervals) { |
| options.disabledTimeIntervals = false; |
| update(); |
| return picker; |
| } |
| if (!(disabledTimeIntervals instanceof Array)) { |
| throw new TypeError('disabledTimeIntervals() expects an array parameter'); |
| } |
| options.disabledTimeIntervals = disabledTimeIntervals; |
| update(); |
| return picker; |
| }; |
| |
| picker.disabledHours = function (hours) { |
| ///<signature helpKeyword="$.fn.datetimepicker.disabledHours"> |
| ///<summary>Returns an array with the currently set disabled hours on the component.</summary> |
| ///<returns type="array">options.disabledHours</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of |
| ///options.enabledHours if such exist.</summary> |
| ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours); |
| } |
| |
| if (!hours) { |
| options.disabledHours = false; |
| update(); |
| return picker; |
| } |
| if (!(hours instanceof Array)) { |
| throw new TypeError('disabledHours() expects an array parameter'); |
| } |
| options.disabledHours = indexGivenHours(hours); |
| options.enabledHours = false; |
| if (options.useCurrent && !options.keepInvalid) { |
| var tries = 0; |
| while (!isValid(date, 'h')) { |
| date.add(1, 'h'); |
| if (tries === 24) { |
| throw 'Tried 24 times to find a valid date'; |
| } |
| tries++; |
| } |
| setValue(date); |
| } |
| update(); |
| return picker; |
| }; |
| |
| picker.enabledHours = function (hours) { |
| ///<signature helpKeyword="$.fn.datetimepicker.enabledHours"> |
| ///<summary>Returns an array with the currently set enabled hours on the component.</summary> |
| ///<returns type="array">options.enabledHours</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary> |
| ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours); |
| } |
| |
| if (!hours) { |
| options.enabledHours = false; |
| update(); |
| return picker; |
| } |
| if (!(hours instanceof Array)) { |
| throw new TypeError('enabledHours() expects an array parameter'); |
| } |
| options.enabledHours = indexGivenHours(hours); |
| options.disabledHours = false; |
| if (options.useCurrent && !options.keepInvalid) { |
| var tries = 0; |
| while (!isValid(date, 'h')) { |
| date.add(1, 'h'); |
| if (tries === 24) { |
| throw 'Tried 24 times to find a valid date'; |
| } |
| tries++; |
| } |
| setValue(date); |
| } |
| update(); |
| return picker; |
| }; |
| |
| picker.viewDate = function (newDate) { |
| ///<signature helpKeyword="$.fn.datetimepicker.viewDate"> |
| ///<summary>Returns the component's model current viewDate, a moment object or null if not set.</summary> |
| ///<returns type="Moment">viewDate.clone()</returns> |
| ///</signature> |
| ///<signature> |
| ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary> |
| ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, viewDate, moment, null parameter.</param> |
| ///</signature> |
| if (arguments.length === 0) { |
| return viewDate.clone(); |
| } |
| |
| if (!newDate) { |
| viewDate = date.clone(); |
| return picker; |
| } |
| |
| if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) { |
| throw new TypeError('viewDate() parameter must be one of [string, moment or Date]'); |
| } |
| |
| viewDate = parseInputDate(newDate); |
| viewUpdate(); |
| return picker; |
| }; |
| |
| // initializing element and component attributes |
| if (element.is('input')) { |
| input = element; |
| } else { |
| input = element.find(options.datepickerInput); |
| if (input.size() === 0) { |
| input = element.find('input'); |
| } else if (!input.is('input')) { |
| throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element'); |
| } |
| } |
| |
| if (element.hasClass('input-group')) { |
| // in case there is more then one 'input-group-addon' Issue #48 |
| if (element.find('.datepickerbutton').size() === 0) { |
| component = element.find('[class^="input-group-"]'); |
| } else { |
| component = element.find('.datepickerbutton'); |
| } |
| } |
| |
| if (!options.inline && !input.is('input')) { |
| throw new Error('Could not initialize DateTimePicker without an input element'); |
| } |
| |
| $.extend(true, options, dataToOptions()); |
| |
| picker.options(options); |
| |
| initFormatting(); |
| |
| attachDatePickerElementEvents(); |
| |
| if (input.prop('disabled')) { |
| picker.disable(); |
| } |
| if (input.is('input') && input.val().trim().length !== 0) { |
| setValue(parseInputDate(input.val().trim())); |
| } |
| else if (options.defaultDate && input.attr('placeholder') === undefined) { |
| setValue(options.defaultDate); |
| } |
| if (options.inline) { |
| show(); |
| } |
| return picker; |
| }; |
| |
| /******************************************************************************** |
| * |
| * jQuery plugin constructor and defaults object |
| * |
| ********************************************************************************/ |
| |
| $.fn.datetimepicker = function (options) { |
| return this.each(function () { |
| var $this = $(this); |
| if (!$this.data('DateTimePicker')) { |
| // create a private copy of the defaults object |
| options = $.extend(true, {}, $.fn.datetimepicker.defaults, options); |
| $this.data('DateTimePicker', dateTimePicker($this, options)); |
| } |
| }); |
| }; |
| |
| $.fn.datetimepicker.defaults = { |
| format: false, |
| dayViewHeaderFormat: 'MMMM YYYY', |
| extraFormats: false, |
| stepping: 1, |
| minDate: false, |
| maxDate: false, |
| useCurrent: true, |
| collapse: true, |
| locale: moment.locale(), |
| defaultDate: false, |
| disabledDates: false, |
| enabledDates: false, |
| icons: { |
| time: 'glyphicon glyphicon-time', |
| date: 'glyphicon glyphicon-calendar', |
| up: 'glyphicon glyphicon-chevron-up', |
| down: 'glyphicon glyphicon-chevron-down', |
| previous: 'glyphicon glyphicon-chevron-left', |
| next: 'glyphicon glyphicon-chevron-right', |
| today: 'glyphicon glyphicon-screenshot', |
| clear: 'glyphicon glyphicon-trash', |
| close: 'glyphicon glyphicon-remove' |
| }, |
| useStrict: false, |
| sideBySide: false, |
| daysOfWeekDisabled: false, |
| calendarWeeks: false, |
| viewMode: 'days', |
| toolbarPlacement: 'default', |
| showTodayButton: false, |
| showClear: false, |
| showClose: false, |
| widgetPositioning: { |
| horizontal: 'auto', |
| vertical: 'auto' |
| }, |
| widgetParent: null, |
| ignoreReadonly: false, |
| keepOpen: false, |
| focusOnShow: true, |
| inline: false, |
| keepInvalid: false, |
| datepickerInput: '.datepickerinput', |
| keyBinds: { |
| up: function (widget) { |
| if (!widget) { |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().subtract(7, 'd')); |
| } else { |
| this.date(d.clone().add(1, 'm')); |
| } |
| }, |
| down: function (widget) { |
| if (!widget) { |
| this.show(); |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().add(7, 'd')); |
| } else { |
| this.date(d.clone().subtract(1, 'm')); |
| } |
| }, |
| 'control up': function (widget) { |
| if (!widget) { |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().subtract(1, 'y')); |
| } else { |
| this.date(d.clone().add(1, 'h')); |
| } |
| }, |
| 'control down': function (widget) { |
| if (!widget) { |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().add(1, 'y')); |
| } else { |
| this.date(d.clone().subtract(1, 'h')); |
| } |
| }, |
| left: function (widget) { |
| if (!widget) { |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().subtract(1, 'd')); |
| } |
| }, |
| right: function (widget) { |
| if (!widget) { |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().add(1, 'd')); |
| } |
| }, |
| pageUp: function (widget) { |
| if (!widget) { |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().subtract(1, 'M')); |
| } |
| }, |
| pageDown: function (widget) { |
| if (!widget) { |
| return; |
| } |
| var d = this.date() || moment(); |
| if (widget.find('.datepicker').is(':visible')) { |
| this.date(d.clone().add(1, 'M')); |
| } |
| }, |
| enter: function () { |
| this.hide(); |
| }, |
| escape: function () { |
| this.hide(); |
| }, |
| //tab: function (widget) { //this break the flow of the form. disabling for now |
| // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]'); |
| // if(toggle.length > 0) toggle.click(); |
| //}, |
| 'control space': function (widget) { |
| if (widget.find('.timepicker').is(':visible')) { |
| widget.find('.btn[data-action="togglePeriod"]').click(); |
| } |
| }, |
| t: function () { |
| this.date(moment()); |
| }, |
| 'delete': function () { |
| this.clear(); |
| } |
| }, |
| debug: false, |
| allowInputToggle: false, |
| disabledTimeIntervals: false, |
| disabledHours: false, |
| enabledHours: false, |
| viewDate: false |
| }; |
| })); |