JAVASCRIPT   92

datepicker.js

Guest on 19th August 2021 04:32:32 PM

  1. /* =========================================================
  2.  * bootstrap-datepicker.js
  3.  * Repo: https://github.com/eternicode/bootstrap-datepicker/
  4.  * Demo: http://eternicode.github.io/bootstrap-datepicker/
  5.  * Docs: http://bootstrap-datepicker.readthedocs.org/
  6.  * Forked from http://www.eyecon.ro/bootstrap-datepicker
  7.  * =========================================================
  8.  * Started by Stefan Petre; improvements by Andrew Rowls + contributors
  9.  *
  10.  * Licensed under the Apache License, Version 2.0 (the "License");
  11.  * you may not use this file except in compliance with the License.
  12.  * You may obtain a copy of the License at
  13.  *
  14.  * http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * Unless required by applicable law or agreed to in writing, software
  17.  * distributed under the License is distributed on an "AS IS" BASIS,
  18.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19.  * See the License for the specific language governing permissions and
  20.  * limitations under the License.
  21.  * ========================================================= */
  22.  
  23. (function($, undefined){
  24.  
  25.         function UTCDate(){
  26.                 return new Date(Date.UTC.apply(Date, arguments));
  27.         }
  28.         function UTCToday(){
  29.                 var today = new Date();
  30.                 return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
  31.         }
  32.         function isUTCEquals(date1, date2) {
  33.                 return (
  34.                         date1.getUTCFullYear() === date2.getUTCFullYear() &&
  35.                         date1.getUTCMonth() === date2.getUTCMonth() &&
  36.                         date1.getUTCDate() === date2.getUTCDate()
  37.                 );
  38.         }
  39.         function alias(method){
  40.                 return function(){
  41.                         return this[method].apply(this, arguments);
  42.                 };
  43.         }
  44.  
  45.         var DateArray = (function(){
  46.                 var extras = {
  47.                         get: function(i){
  48.                                 return this.slice(i)[0];
  49.                         },
  50.                         contains: function(d){
  51.                                 // Array.indexOf is not cross-browser;
  52.                                 // $.inArray doesn't work with Dates
  53.                                 var val = d && d.valueOf();
  54.                                 for (var i=0, l=this.length; i < l; i++)
  55.                                         if (this[i].valueOf() === val)
  56.                                                 return i;
  57.                                 return -1;
  58.                         },
  59.                         remove: function(i){
  60.                                 this.splice(i,1);
  61.                         },
  62.                         replace: function(new_array){
  63.                                 if (!new_array)
  64.                                         return;
  65.                                 if (!$.isArray(new_array))
  66.                                         new_array = [new_array];
  67.                                 this.clear();
  68.                                 this.push.apply(this, new_array);
  69.                         },
  70.                         clear: function(){
  71.                                 this.length = 0;
  72.                         },
  73.                         copy: function(){
  74.                                 var a = new DateArray();
  75.                                 a.replace(this);
  76.                                 return a;
  77.                         }
  78.                 };
  79.  
  80.                 return function(){
  81.                         var a = [];
  82.                         a.push.apply(a, arguments);
  83.                         $.extend(a, extras);
  84.                         return a;
  85.                 };
  86.         })();
  87.  
  88.  
  89.         // Picker object
  90.  
  91.         var Datepicker = function(element, options){
  92.                 this._process_options(options);
  93.  
  94.                 this.dates = new DateArray();
  95.                 this.viewDate = this.o.defaultViewDate;
  96.                 this.focusDate = null;
  97.  
  98.                 this.element = $(element);
  99.                 this.isInline = false;
  100.                 this.isInput = this.element.is('input');
  101.                 this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
  102.                 this.hasInput = this.component && this.element.find('input').length;
  103.                 if (this.component && this.component.length === 0)
  104.                         this.component = false;
  105.  
  106.                 this.picker = $(DPGlobal.template);
  107.                 this._buildEvents();
  108.                 this._attachEvents();
  109.  
  110.                 if (this.isInline){
  111.                         this.picker.addClass('datepicker-inline').appendTo(this.element);
  112.                 }
  113.                 else {
  114.                         this.picker.addClass('datepicker-dropdown dropdown-menu');
  115.                 }
  116.  
  117.                 if (this.o.rtl){
  118.                         this.picker.addClass('datepicker-rtl');
  119.                 }
  120.  
  121.                 this.viewMode = this.o.startView;
  122.  
  123.                 if (this.o.calendarWeeks)
  124.                         this.picker.find('tfoot .today, tfoot .clear')
  125.                                                 .attr('colspan', function(i, val){
  126.                                                         return parseInt(val) + 1;
  127.                                                 });
  128.  
  129.                 this._allow_update = false;
  130.  
  131.                 this.setStartDate(this._o.startDate);
  132.                 this.setEndDate(this._o.endDate);
  133.                 this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
  134.                 this.setDatesDisabled(this.o.datesDisabled);
  135.  
  136.                 this.fillDow();
  137.                 this.fillMonths();
  138.  
  139.                 this._allow_update = true;
  140.  
  141.                 this.update();
  142.                 this.showMode();
  143.  
  144.                 if (this.isInline){
  145.                         this.show();
  146.                 }
  147.         };
  148.  
  149.         Datepicker.prototype = {
  150.                 constructor: Datepicker,
  151.  
  152.                 _process_options: function(opts){
  153.                         // Store raw options for reference
  154.                         this._o = $.extend({}, this._o, opts);
  155.                         // Processed options
  156.                         var o = this.o = $.extend({}, this._o);
  157.  
  158.                         // Check if "de-DE" style date is available, if not language should
  159.                         // fallback to 2 letter code eg "de"
  160.                         var lang = o.language;
  161.                         if (!dates[lang]){
  162.                                 lang = lang.split('-')[0];
  163.                                 if (!dates[lang])
  164.                                         lang = defaults.language;
  165.                         }
  166.                         o.language = lang;
  167.  
  168.                         switch (o.startView){
  169.                                 case 2:
  170.                                 case 'decade':
  171.                                         o.startView = 2;
  172.                                         break;
  173.                                 case 1:
  174.                                 case 'year':
  175.                                         o.startView = 1;
  176.                                         break;
  177.                                 default:
  178.                                         o.startView = 0;
  179.                         }
  180.  
  181.                         switch (o.minViewMode){
  182.                                 case 1:
  183.                                 case 'months':
  184.                                         o.minViewMode = 1;
  185.                                         break;
  186.                                 case 2:
  187.                                 case 'years':
  188.                                         o.minViewMode = 2;
  189.                                         break;
  190.                                 default:
  191.                                         o.minViewMode = 0;
  192.                         }
  193.  
  194.                         o.startView = Math.max(o.startView, o.minViewMode);
  195.  
  196.                         // true, false, or Number > 0
  197.                         if (o.multidate !== true){
  198.                                 o.multidate = Number(o.multidate) || false;
  199.                                 if (o.multidate !== false)
  200.                                         o.multidate = Math.max(0, o.multidate);
  201.                         }
  202.                         o.multidateSeparator = String(o.multidateSeparator);
  203.  
  204.                         o.weekStart %= 7;
  205.                         o.weekEnd = ((o.weekStart + 6) % 7);
  206.  
  207.                         var format = DPGlobal.parseFormat(o.format);
  208.                         if (o.startDate !== -Infinity){
  209.                                 if (!!o.startDate){
  210.                                         if (o.startDate instanceof Date)
  211.                                                 o.startDate = this._local_to_utc(this._zero_time(o.startDate));
  212.                                         else
  213.                                                 o.startDate = DPGlobal.parseDate(o.startDate, format, o.language);
  214.                                 }
  215.                                 else {
  216.                                         o.startDate = -Infinity;
  217.                                 }
  218.                         }
  219.                         if (o.endDate !== Infinity){
  220.                                 if (!!o.endDate){
  221.                                         if (o.endDate instanceof Date)
  222.                                                 o.endDate = this._local_to_utc(this._zero_time(o.endDate));
  223.                                         else
  224.                                                 o.endDate = DPGlobal.parseDate(o.endDate, format, o.language);
  225.                                 }
  226.                                 else {
  227.                                         o.endDate = Infinity;
  228.                                 }
  229.                         }
  230.  
  231.                         o.daysOfWeekDisabled = o.daysOfWeekDisabled||[];
  232.                         if (!$.isArray(o.daysOfWeekDisabled))
  233.                                 o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/);
  234.                         o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){
  235.                                 return parseInt(d, 10);
  236.                         });
  237.  
  238.                         o.datesDisabled = o.datesDisabled||[];
  239.                         if (!$.isArray(o.datesDisabled)) {
  240.                                 var datesDisabled = [];
  241.                                 datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language));
  242.                                 o.datesDisabled = datesDisabled;
  243.                         }
  244.                         o.datesDisabled = $.map(o.datesDisabled,function(d){
  245.                                 return DPGlobal.parseDate(d, format, o.language);
  246.                         });
  247.  
  248.                         var plc = String(o.orientation).toLowerCase().split(/\s+/g),
  249.                                 _plc = o.orientation.toLowerCase();
  250.                         plc = $.grep(plc, function(word){
  251.                                 return /^auto|left|right|top|bottom$/.test(word);
  252.                         });
  253.                         o.orientation = {x: 'auto', y: 'auto'};
  254.                         if (!_plc || _plc === 'auto')
  255.                                 ; // no action
  256.                         else if (plc.length === 1){
  257.                                 switch (plc[0]){
  258.                                         case 'top':
  259.                                         case 'bottom':
  260.                                                 o.orientation.y = plc[0];
  261.                                                 break;
  262.                                         case 'left':
  263.                                         case 'right':
  264.                                                 o.orientation.x = plc[0];
  265.                                                 break;
  266.                                 }
  267.                         }
  268.                         else {
  269.                                 _plc = $.grep(plc, function(word){
  270.                                         return /^left|right$/.test(word);
  271.                                 });
  272.                                 o.orientation.x = _plc[0] || 'auto';
  273.  
  274.                                 _plc = $.grep(plc, function(word){
  275.                                         return /^top|bottom$/.test(word);
  276.                                 });
  277.                                 o.orientation.y = _plc[0] || 'auto';
  278.                         }
  279.                         if (o.defaultViewDate) {
  280.                                 var year = o.defaultViewDate.year || new Date().getFullYear();
  281.                                 var month = o.defaultViewDate.month || 0;
  282.                                 var day = o.defaultViewDate.day || 1;
  283.                                 o.defaultViewDate = UTCDate(year, month, day);
  284.                         } else {
  285.                                 o.defaultViewDate = UTCToday();
  286.                         }
  287.                         o.showOnFocus = o.showOnFocus !== undefined ? o.showOnFocus : true;
  288.                 },
  289.                 _events: [],
  290.                 _secondaryEvents: [],
  291.                 _applyEvents: function(evs){
  292.                         for (var i=0, el, ch, ev; i < evs.length; i++){
  293.                                 el = evs[i][0];
  294.                                 if (evs[i].length === 2){
  295.                                         ch = undefined;
  296.                                         ev = evs[i][1];
  297.                                 }
  298.                                 else if (evs[i].length === 3){
  299.                                         ch = evs[i][1];
  300.                                         ev = evs[i][2];
  301.                                 }
  302.                                 el.on(ev, ch);
  303.                         }
  304.                 },
  305.                 _unapplyEvents: function(evs){
  306.                         for (var i=0, el, ev, ch; i < evs.length; i++){
  307.                                 el = evs[i][0];
  308.                                 if (evs[i].length === 2){
  309.                                         ch = undefined;
  310.                                         ev = evs[i][1];
  311.                                 }
  312.                                 else if (evs[i].length === 3){
  313.                                         ch = evs[i][1];
  314.                                         ev = evs[i][2];
  315.                                 }
  316.                                 el.off(ev, ch);
  317.                         }
  318.                 },
  319.                 _buildEvents: function(){
  320.             var events = {
  321.                 keyup: $.proxy(function(e){
  322.                     if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
  323.                         this.update();
  324.                 }, this),
  325.                 keydown: $.proxy(this.keydown, this)
  326.             };
  327.  
  328.             if (this.o.showOnFocus === true) {
  329.                 events.focus = $.proxy(this.show, this);
  330.             }
  331.  
  332.             if (this.isInput) { // single input
  333.                 this._events = [
  334.                     [this.element, events]
  335.                 ];
  336.             }
  337.             else if (this.component && this.hasInput) { // component: input + button
  338.                 this._events = [
  339.                     // For components that are not readonly, allow keyboard nav
  340.                     [this.element.find('input'), events],
  341.                     [this.component, {
  342.                         click: $.proxy(this.show, this)
  343.                     }]
  344.                 ];
  345.             }
  346.                         else if (this.element.is('div')){  // inline datepicker
  347.                                 this.isInline = true;
  348.                         }
  349.                         else {
  350.                                 this._events = [
  351.                                         [this.element, {
  352.                                                 click: $.proxy(this.show, this)
  353.                                         }]
  354.                                 ];
  355.                         }
  356.                         this._events.push(
  357.                                 // Component: listen for blur on element descendants
  358.                                 [this.element, '*', {
  359.                                         blur: $.proxy(function(e){
  360.                                                 this._focused_from = e.target;
  361.                                         }, this)
  362.                                 }],
  363.                                 // Input: listen for blur on element
  364.                                 [this.element, {
  365.                                         blur: $.proxy(function(e){
  366.                                                 this._focused_from = e.target;
  367.                                         }, this)
  368.                                 }]
  369.                         );
  370.  
  371.                         this._secondaryEvents = [
  372.                                 [this.picker, {
  373.                                         click: $.proxy(this.click, this)
  374.                                 }],
  375.                                 [$(window), {
  376.                                         resize: $.proxy(this.place, this)
  377.                                 }],
  378.                                 [$(document), {
  379.                                         'mousedown touchstart': $.proxy(function(e){
  380.                                                 // Clicked outside the datepicker, hide it
  381.                                                 if (!(
  382.                                                         this.element.is(e.target) ||
  383.                                                         this.element.find(e.target).length ||
  384.                                                         this.picker.is(e.target) ||
  385.                                                         this.picker.find(e.target).length
  386.                                                 )){
  387.                                                         this.hide();
  388.                                                 }
  389.                                         }, this)
  390.                                 }]
  391.                         ];
  392.                 },
  393.                 _attachEvents: function(){
  394.                         this._detachEvents();
  395.                         this._applyEvents(this._events);
  396.                 },
  397.                 _detachEvents: function(){
  398.                         this._unapplyEvents(this._events);
  399.                 },
  400.                 _attachSecondaryEvents: function(){
  401.                         this._detachSecondaryEvents();
  402.                         this._applyEvents(this._secondaryEvents);
  403.                 },
  404.                 _detachSecondaryEvents: function(){
  405.                         this._unapplyEvents(this._secondaryEvents);
  406.                 },
  407.                 _trigger: function(event, altdate){
  408.                         var date = altdate || this.dates.get(-1),
  409.                                 local_date = this._utc_to_local(date);
  410.  
  411.                         this.element.trigger({
  412.                                 type: event,
  413.                                 date: local_date,
  414.                                 dates: $.map(this.dates, this._utc_to_local),
  415.                                 format: $.proxy(function(ix, format){
  416.                                         if (arguments.length === 0){
  417.                                                 ix = this.dates.length - 1;
  418.                                                 format = this.o.format;
  419.                                         }
  420.                                         else if (typeof ix === 'string'){
  421.                                                 format = ix;
  422.                                                 ix = this.dates.length - 1;
  423.                                         }
  424.                                         format = format || this.o.format;
  425.                                         var date = this.dates.get(ix);
  426.                                         return DPGlobal.formatDate(date, format, this.o.language);
  427.                                 }, this)
  428.                         });
  429.                 },
  430.  
  431.                 show: function(){
  432.                         if (this.element.attr('readonly'))
  433.                                 return;
  434.                         if (!this.isInline)
  435.                                 this.picker.appendTo(this.o.container);
  436.                         this.place();
  437.                         this.picker.show();
  438.                         this._attachSecondaryEvents();
  439.                         this._trigger('show');
  440.                         if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
  441.                                 $(this.element).blur();
  442.                         }
  443.                         return this;
  444.                 },
  445.  
  446.                 hide: function(){
  447.                         if (this.isInline)
  448.                                 return this;
  449.                         if (!this.picker.is(':visible'))
  450.                                 return this;
  451.                         this.focusDate = null;
  452.                         this.picker.hide().detach();
  453.                         this._detachSecondaryEvents();
  454.                         this.viewMode = this.o.startView;
  455.                         this.showMode();
  456.  
  457.                         if (
  458.                                 this.o.forceParse &&
  459.                                 (
  460.                                         this.isInput && this.element.val() ||
  461.                                         this.hasInput && this.element.find('input').val()
  462.                                 )
  463.                         )
  464.                                 this.setValue();
  465.                         this._trigger('hide');
  466.                         return this;
  467.                 },
  468.  
  469.                 remove: function(){
  470.                         this.hide();
  471.                         this._detachEvents();
  472.                         this._detachSecondaryEvents();
  473.                         this.picker.remove();
  474.                         delete this.element.data().datepicker;
  475.                         if (!this.isInput){
  476.                                 delete this.element.data().date;
  477.                         }
  478.                         return this;
  479.                 },
  480.  
  481.                 _utc_to_local: function(utc){
  482.                         return utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000));
  483.                 },
  484.                 _local_to_utc: function(local){
  485.                         return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
  486.                 },
  487.                 _zero_time: function(local){
  488.                         return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
  489.                 },
  490.                 _zero_utc_time: function(utc){
  491.                         return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()));
  492.                 },
  493.  
  494.                 getDates: function(){
  495.                         return $.map(this.dates, this._utc_to_local);
  496.                 },
  497.  
  498.                 getUTCDates: function(){
  499.                         return $.map(this.dates, function(d){
  500.                                 return new Date(d);
  501.                         });
  502.                 },
  503.  
  504.                 getDate: function(){
  505.                         return this._utc_to_local(this.getUTCDate());
  506.                 },
  507.  
  508.                 getUTCDate: function(){
  509.                         var selected_date = this.dates.get(-1);
  510.                         if (typeof selected_date !== 'undefined') {
  511.                                 return new Date(selected_date);
  512.                         } else {
  513.                                 return null;
  514.                         }
  515.                 },
  516.  
  517.                 clearDates: function(){
  518.                         var element;
  519.                         if (this.isInput) {
  520.                                 element = this.element;
  521.                         } else if (this.component) {
  522.                                 element = this.element.find('input');
  523.                         }
  524.  
  525.                         if (element) {
  526.                                 element.val('').change();
  527.                         }
  528.  
  529.                         this.update();
  530.                         this._trigger('changeDate');
  531.  
  532.                         if (this.o.autoclose) {
  533.                                 this.hide();
  534.                         }
  535.                 },
  536.                 setDates: function(){
  537.                         var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
  538.                         this.update.apply(this, args);
  539.                         this._trigger('changeDate');
  540.                         this.setValue();
  541.                         return this;
  542.                 },
  543.  
  544.                 setUTCDates: function(){
  545.                         var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
  546.                         this.update.apply(this, $.map(args, this._utc_to_local));
  547.                         this._trigger('changeDate');
  548.                         this.setValue();
  549.                         return this;
  550.                 },
  551.  
  552.                 setDate: alias('setDates'),
  553.                 setUTCDate: alias('setUTCDates'),
  554.  
  555.                 setValue: function(){
  556.                         var formatted = this.getFormattedDate();
  557.                         if (!this.isInput){
  558.                                 if (this.component){
  559.                                         this.element.find('input').val(formatted).change();
  560.                                 }
  561.                         }
  562.                         else {
  563.                                 this.element.val(formatted).change();
  564.                         }
  565.                         return this;
  566.                 },
  567.  
  568.                 getFormattedDate: function(format){
  569.                         if (format === undefined)
  570.                                 format = this.o.format;
  571.  
  572.                         var lang = this.o.language;
  573.                         return $.map(this.dates, function(d){
  574.                                 return DPGlobal.formatDate(d, format, lang);
  575.                         }).join(this.o.multidateSeparator);
  576.                 },
  577.  
  578.                 setStartDate: function(startDate){
  579.                         this._process_options({startDate: startDate});
  580.                         this.update();
  581.                         this.updateNavArrows();
  582.                         return this;
  583.                 },
  584.  
  585.                 setEndDate: function(endDate){
  586.                         this._process_options({endDate: endDate});
  587.                         this.update();
  588.                         this.updateNavArrows();
  589.                         return this;
  590.                 },
  591.  
  592.                 setDaysOfWeekDisabled: function(daysOfWeekDisabled){
  593.                         this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
  594.                         this.update();
  595.                         this.updateNavArrows();
  596.                         return this;
  597.                 },
  598.  
  599.                 setDatesDisabled: function(datesDisabled){
  600.                         this._process_options({datesDisabled: datesDisabled});
  601.                         this.update();
  602.                         this.updateNavArrows();
  603.                 },
  604.  
  605.                 place: function(){
  606.                         if (this.isInline)
  607.                                 return this;
  608.                         var calendarWidth = this.picker.outerWidth(),
  609.                                 calendarHeight = this.picker.outerHeight(),
  610.                                 visualPadding = 10,
  611.                                 windowWidth = $(this.o.container).width(),
  612.                                 windowHeight = $(this.o.container).height(),
  613.                                 scrollTop = $(this.o.container).scrollTop(),
  614.                                 appendOffset = $(this.o.container).offset();
  615.  
  616.                         var parentsZindex = [];
  617.                         this.element.parents().each(function(){
  618.                                 var itemZIndex = $(this).css('z-index');
  619.                                 if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex));
  620.                         });
  621.                         var zIndex = Math.max.apply(Math, parentsZindex) + 10;
  622.                         var offset = this.component ? this.component.parent().offset() : this.element.offset();
  623.                         var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
  624.                         var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
  625.                         var left = offset.left - appendOffset.left,
  626.                                 top = offset.top - appendOffset.top;
  627.  
  628.                         this.picker.removeClass(
  629.                                 'datepicker-orient-top datepicker-orient-bottom '+
  630.                                 'datepicker-orient-right datepicker-orient-left'
  631.                         );
  632.  
  633.                         if (this.o.orientation.x !== 'auto'){
  634.                                 this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
  635.                                 if (this.o.orientation.x === 'right')
  636.                                         left -= calendarWidth - width;
  637.                         }
  638.                         // auto x orientation is best-placement: if it crosses a window
  639.                         // edge, fudge it sideways
  640.                         else {
  641.                                 if (offset.left < 0) {
  642.                                         // component is outside the window on the left side. Move it into visible range
  643.                                         this.picker.addClass('datepicker-orient-left');
  644.                                         left -= offset.left - visualPadding;
  645.                                 } else if (left + calendarWidth > windowWidth) {
  646.                                         // the calendar passes the widow right edge. Align it to component right side
  647.                                         this.picker.addClass('datepicker-orient-right');
  648.                                         left = offset.left + width - calendarWidth;
  649.                                 } else {
  650.                                         // Default to left
  651.                                         this.picker.addClass('datepicker-orient-left');
  652.                                 }
  653.                         }
  654.  
  655.                         // auto y orientation is best-situation: top or bottom, no fudging,
  656.                         // decision based on which shows more of the calendar
  657.                         var yorient = this.o.orientation.y,
  658.                                 top_overflow, bottom_overflow;
  659.                         if (yorient === 'auto'){
  660.                                 top_overflow = -scrollTop + top - calendarHeight;
  661.                                 bottom_overflow = scrollTop + windowHeight - (top + height + calendarHeight);
  662.                                 if (Math.max(top_overflow, bottom_overflow) === bottom_overflow)
  663.                                         yorient = 'top';
  664.                                 else
  665.                                         yorient = 'bottom';
  666.                         }
  667.                         this.picker.addClass('datepicker-orient-' + yorient);
  668.                         if (yorient === 'top')
  669.                                 top += height;
  670.                         else
  671.                                 top -= calendarHeight + parseInt(this.picker.css('padding-top'));
  672.  
  673.                         if (this.o.rtl) {
  674.                                 var right = windowWidth - (left + width);
  675.                                 this.picker.css({
  676.                                         top: top,
  677.                                         right: right,
  678.                                         zIndex: zIndex
  679.                                 });
  680.                         } else {
  681.                                 this.picker.css({
  682.                                         top: top,
  683.                                         left: left,
  684.                                         zIndex: zIndex
  685.                                 });
  686.                         }
  687.                         return this;
  688.                 },
  689.  
  690.                 _allow_update: true,
  691.                 update: function(){
  692.                         if (!this._allow_update)
  693.                                 return this;
  694.  
  695.                         var oldDates = this.dates.copy(),
  696.                                 dates = [],
  697.                                 fromArgs = false;
  698.                         if (arguments.length){
  699.                                 $.each(arguments, $.proxy(function(i, date){
  700.                                         if (date instanceof Date)
  701.                                                 date = this._local_to_utc(date);
  702.                                         dates.push(date);
  703.                                 }, this));
  704.                                 fromArgs = true;
  705.                         }
  706.                         else {
  707.                                 dates = this.isInput
  708.                                                 ? this.element.val()
  709.                                                 : this.element.data('date') || this.element.find('input').val();
  710.                                 if (dates && this.o.multidate)
  711.                                         dates = dates.split(this.o.multidateSeparator);
  712.                                 else
  713.                                         dates = [dates];
  714.                                 delete this.element.data().date;
  715.                         }
  716.  
  717.                         dates = $.map(dates, $.proxy(function(date){
  718.                                 return DPGlobal.parseDate(date, this.o.format, this.o.language);
  719.                         }, this));
  720.                         dates = $.grep(dates, $.proxy(function(date){
  721.                                 return (
  722.                                         date < this.o.startDate ||
  723.                                         date > this.o.endDate ||
  724.                                         !date
  725.                                 );
  726.                         }, this), true);
  727.                         this.dates.replace(dates);
  728.  
  729.                         if (this.dates.length)
  730.                                 this.viewDate = new Date(this.dates.get(-1));
  731.                         else if (this.viewDate < this.o.startDate)
  732.                                 this.viewDate = new Date(this.o.startDate);
  733.                         else if (this.viewDate > this.o.endDate)
  734.                                 this.viewDate = new Date(this.o.endDate);
  735.  
  736.                         if (fromArgs){
  737.                                 // setting date by clicking
  738.                                 this.setValue();
  739.                         }
  740.                         else if (dates.length){
  741.                                 // setting date by typing
  742.                                 if (String(oldDates) !== String(this.dates))
  743.                                         this._trigger('changeDate');
  744.                         }
  745.                         if (!this.dates.length && oldDates.length)
  746.                                 this._trigger('clearDate');
  747.  
  748.                         this.fill();
  749.                         return this;
  750.                 },
  751.  
  752.                 fillDow: function(){
  753.                         var dowCnt = this.o.weekStart,
  754.                                 html = '<tr>';
  755.                         if (this.o.calendarWeeks){
  756.                                 this.picker.find('.datepicker-days thead tr:first-child .datepicker-switch')
  757.                                         .attr('colspan', function(i, val){
  758.                                                 return parseInt(val) + 1;
  759.                                         });
  760.                                 var cell = '<th class="cw">&#160;</th>';
  761.                                 html += cell;
  762.                         }
  763.                         while (dowCnt < this.o.weekStart + 7){
  764.                                 html += '<th class="dow">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
  765.                         }
  766.                         html += '</tr>';
  767.                         this.picker.find('.datepicker-days thead').append(html);
  768.                 },
  769.  
  770.                 fillMonths: function(){
  771.                         var html = '',
  772.                         i = 0;
  773.                         while (i < 12){
  774.                                 html += '<span class="month">'+dates[this.o.language].monthsShort[i++]+'</span>';
  775.                         }
  776.                         this.picker.find('.datepicker-months td').html(html);
  777.                 },
  778.  
  779.                 setRange: function(range){
  780.                         if (!range || !range.length)
  781.                                 delete this.range;
  782.                         else
  783.                                 this.range = $.map(range, function(d){
  784.                                         return d.valueOf();
  785.                                 });
  786.                         this.fill();
  787.                 },
  788.  
  789.                 getClassNames: function(date){
  790.                         var cls = [],
  791.                                 year = this.viewDate.getUTCFullYear(),
  792.                                 month = this.viewDate.getUTCMonth(),
  793.                                 today = new Date();
  794.                         if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
  795.                                 cls.push('old');
  796.                         }
  797.                         else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
  798.                                 cls.push('new');
  799.                         }
  800.                         if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
  801.                                 cls.push('focused');
  802.                         // Compare internal UTC date with local today, not UTC today
  803.                         if (this.o.todayHighlight &&
  804.                                 date.getUTCFullYear() === today.getFullYear() &&
  805.                                 date.getUTCMonth() === today.getMonth() &&
  806.                                 date.getUTCDate() === today.getDate()){
  807.                                 cls.push('today');
  808.                         }
  809.                         if (this.dates.contains(date) !== -1)
  810.                                 cls.push('active');
  811.                         if (date.valueOf() < this.o.startDate || date.valueOf() > this.o.endDate ||
  812.                                 $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1){
  813.                                 cls.push('disabled');
  814.                         }
  815.                         if (this.o.datesDisabled.length > 0 &&
  816.                                 $.grep(this.o.datesDisabled, function(d){
  817.                                         return isUTCEquals(date, d); }).length > 0) {
  818.                                 cls.push('disabled', 'disabled-date');
  819.                         }
  820.  
  821.                         if (this.range){
  822.                                 if (date > this.range[0] && date < this.range[this.range.length-1]){
  823.                                         cls.push('range');
  824.                                 }
  825.                                 if ($.inArray(date.valueOf(), this.range) !== -1){
  826.                                         cls.push('selected');
  827.                                 }
  828.                         }
  829.                         return cls;
  830.                 },
  831.  
  832.                 fill: function(){
  833.                         var d = new Date(this.viewDate),
  834.                                 year = d.getUTCFullYear(),
  835.                                 month = d.getUTCMonth(),
  836.                                 startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
  837.                                 startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
  838.                                 endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
  839.                                 endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
  840.                                 todaytxt = dates[this.o.language].today || dates['en'].today || '',
  841.                                 cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
  842.                                 tooltip;
  843.                         if (isNaN(year) || isNaN(month))
  844.                                 return;
  845.                         this.picker.find('.datepicker-days thead .datepicker-switch')
  846.                                                 .text(dates[this.o.language].months[month]+' '+year);
  847.                         this.picker.find('tfoot .today')
  848.                                                 .text(todaytxt)
  849.                                                 .toggle(this.o.todayBtn !== false);
  850.                         this.picker.find('tfoot .clear')
  851.                                                 .text(cleartxt)
  852.                                                 .toggle(this.o.clearBtn !== false);
  853.                         this.updateNavArrows();
  854.                         this.fillMonths();
  855.                         var prevMonth = UTCDate(year, month-1, 28),
  856.                                 day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());
  857.                         prevMonth.setUTCDate(day);
  858.                         prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
  859.                         var nextMonth = new Date(prevMonth);
  860.                         nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
  861.                         nextMonth = nextMonth.valueOf();
  862.                         var html = [];
  863.                         var clsName;
  864.                         while (prevMonth.valueOf() < nextMonth){
  865.                                 if (prevMonth.getUTCDay() === this.o.weekStart){
  866.                                         html.push('<tr>');
  867.                                         if (this.o.calendarWeeks){
  868.                                                 // ISO 8601: First week contains first thursday.
  869.                                                 // ISO also states week starts on Monday, but we can be more abstract here.
  870.                                                 var
  871.                                                         // Start of current week: based on weekstart/current date
  872.                                                         ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
  873.                                                         // Thursday of this week
  874.                                                         th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
  875.                                                         // First Thursday of year, year from thursday
  876.                                                         yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
  877.                                                         // Calendar week: ms between thursdays, div ms per day, div 7 days
  878.                                                         calWeek =  (th - yth) / 864e5 / 7 + 1;
  879.                                                 html.push('<td class="cw">'+ calWeek +'</td>');
  880.  
  881.                                         }
  882.                                 }
  883.                                 clsName = this.getClassNames(prevMonth);
  884.                                 clsName.push('day');
  885.  
  886.                                 if (this.o.beforeShowDay !== $.noop){
  887.                                         var before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
  888.                                         if (before === undefined)
  889.                                                 before = {};
  890.                                         else if (typeof(before) === 'boolean')
  891.                                                 before = {enabled: before};
  892.                                         else if (typeof(before) === 'string')
  893.                                                 before = {classes: before};
  894.                                         if (before.enabled === false)
  895.                                                 clsName.push('disabled');
  896.                                         if (before.classes)
  897.                                                 clsName = clsName.concat(before.classes.split(/\s+/));
  898.                                         if (before.tooltip)
  899.                                                 tooltip = before.tooltip;
  900.                                 }
  901.  
  902.                                 clsName = $.unique(clsName);
  903.                                 html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>'+prevMonth.getUTCDate() + '</td>');
  904.                                 tooltip = null;
  905.                                 if (prevMonth.getUTCDay() === this.o.weekEnd){
  906.                                         html.push('</tr>');
  907.                                 }
  908.                                 prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
  909.                         }
  910.                         this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
  911.  
  912.                         var months = this.picker.find('.datepicker-months')
  913.                                                 .find('th:eq(1)')
  914.                                                         .text(year)
  915.                                                         .end()
  916.                                                 .find('span').removeClass('active');
  917.  
  918.                         $.each(this.dates, function(i, d){
  919.                                 if (d.getUTCFullYear() === year)
  920.                                         months.eq(d.getUTCMonth()).addClass('active');
  921.                         });
  922.  
  923.                         if (year < startYear || year > endYear){
  924.                                 months.addClass('disabled');
  925.                         }
  926.                         if (year === startYear){
  927.                                 months.slice(0, startMonth).addClass('disabled');
  928.                         }
  929.                         if (year === endYear){
  930.                                 months.slice(endMonth+1).addClass('disabled');
  931.                         }
  932.  
  933.                         if (this.o.beforeShowMonth !== $.noop){
  934.                                 var that = this;
  935.                                 $.each(months, function(i, month){
  936.                                         if (!$(month).hasClass('disabled')) {
  937.                                                 var moDate = new Date(year, i, 1);
  938.                                                 var before = that.o.beforeShowMonth(moDate);
  939.                                                 if (before === false)
  940.                                                         $(month).addClass('disabled');
  941.                                         }
  942.                                 });
  943.                         }
  944.  
  945.                         html = '';
  946.                         year = parseInt(year/10, 10) * 10;
  947.                         var yearCont = this.picker.find('.datepicker-years')
  948.                                                                 .find('th:eq(1)')
  949.                                                                         .text(year + '-' + (year + 9))
  950.                                                                         .end()
  951.                                                                 .find('td');
  952.                         year -= 1;
  953.                         var years = $.map(this.dates, function(d){
  954.                                         return d.getUTCFullYear();
  955.                                 }),
  956.                                 classes;
  957.                         for (var i = -1; i < 11; i++){
  958.                                 classes = ['year'];
  959.                                 if (i === -1)
  960.                                         classes.push('old');
  961.                                 else if (i === 10)
  962.                                         classes.push('new');
  963.                                 if ($.inArray(year, years) !== -1)
  964.                                         classes.push('active');
  965.                                 if (year < startYear || year > endYear)
  966.                                         classes.push('disabled');
  967.                                 html += '<span class="' + classes.join(' ') + '">' + year + '</span>';
  968.                                 year += 1;
  969.                         }
  970.                         yearCont.html(html);
  971.                 },
  972.  
  973.                 updateNavArrows: function(){
  974.                         if (!this._allow_update)
  975.                                 return;
  976.  
  977.                         var d = new Date(this.viewDate),
  978.                                 year = d.getUTCFullYear(),
  979.                                 month = d.getUTCMonth();
  980.                         switch (this.viewMode){
  981.                                 case 0:
  982.                                         if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){
  983.                                                 this.picker.find('.prev').css({visibility: 'hidden'});
  984.                                         }
  985.                                         else {
  986.                                                 this.picker.find('.prev').css({visibility: 'visible'});
  987.                                         }
  988.                                         if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){
  989.                                                 this.picker.find('.next').css({visibility: 'hidden'});
  990.                                         }
  991.                                         else {
  992.                                                 this.picker.find('.next').css({visibility: 'visible'});
  993.                                         }
  994.                                         break;
  995.                                 case 1:
  996.                                 case 2:
  997.                                         if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear()){
  998.                                                 this.picker.find('.prev').css({visibility: 'hidden'});
  999.                                         }
  1000.                                         else {
  1001.                                                 this.picker.find('.prev').css({visibility: 'visible'});
  1002.                                         }
  1003.                                         if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear()){
  1004.                                                 this.picker.find('.next').css({visibility: 'hidden'});
  1005.                                         }
  1006.                                         else {
  1007.                                                 this.picker.find('.next').css({visibility: 'visible'});
  1008.                                         }
  1009.                                         break;
  1010.                         }
  1011.                 },
  1012.  
  1013.                 click: function(e){
  1014.                         e.preventDefault();
  1015.                         var target = $(e.target).closest('span, td, th'),
  1016.                                 year, month, day;
  1017.                         if (target.length === 1){
  1018.                                 switch (target[0].nodeName.toLowerCase()){
  1019.                                         case 'th':
  1020.                                                 switch (target[0].className){
  1021.                                                         case 'datepicker-switch':
  1022.                                                                 this.showMode(1);
  1023.                                                                 break;
  1024.                                                         case 'prev':
  1025.                                                         case 'next':
  1026.                                                                 var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1);
  1027.                                                                 switch (this.viewMode){
  1028.                                                                         case 0:
  1029.                                                                                 this.viewDate = this.moveMonth(this.viewDate, dir);
  1030.                                                                                 this._trigger('changeMonth', this.viewDate);
  1031.                                                                                 break;
  1032.                                                                         case 1:
  1033.                                                                         case 2:
  1034.                                                                                 this.viewDate = this.moveYear(this.viewDate, dir);
  1035.                                                                                 if (this.viewMode === 1)
  1036.                                                                                         this._trigger('changeYear', this.viewDate);
  1037.                                                                                 break;
  1038.                                                                 }
  1039.                                                                 this.fill();
  1040.                                                                 break;
  1041.                                                         case 'today':
  1042.                                                                 var date = new Date();
  1043.                                                                 date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
  1044.  
  1045.                                                                 this.showMode(-2);
  1046.                                                                 var which = this.o.todayBtn === 'linked' ? null : 'view';
  1047.                                                                 this._setDate(date, which);
  1048.                                                                 break;
  1049.                                                         case 'clear':
  1050.                                                                 this.clearDates();
  1051.                                                                 break;
  1052.                                                 }
  1053.                                                 break;
  1054.                                         case 'span':
  1055.                                                 if (!target.hasClass('disabled')){
  1056.                                                         this.viewDate.setUTCDate(1);
  1057.                                                         if (target.hasClass('month')){
  1058.                                                                 day = 1;
  1059.                                                                 month = target.parent().find('span').index(target);
  1060.                                                                 year = this.viewDate.getUTCFullYear();
  1061.                                                                 this.viewDate.setUTCMonth(month);
  1062.                                                                 this._trigger('changeMonth', this.viewDate);
  1063.                                                                 if (this.o.minViewMode === 1){
  1064.                                                                         this._setDate(UTCDate(year, month, day));
  1065.                                                                 }
  1066.                                                         }
  1067.                                                         else {
  1068.                                                                 day = 1;
  1069.                                                                 month = 0;
  1070.                                                                 year = parseInt(target.text(), 10)||0;
  1071.                                                                 this.viewDate.setUTCFullYear(year);
  1072.                                                                 this._trigger('changeYear', this.viewDate);
  1073.                                                                 if (this.o.minViewMode === 2){
  1074.                                                                         this._setDate(UTCDate(year, month, day));
  1075.                                                                 }
  1076.                                                         }
  1077.                                                         this.showMode(-1);
  1078.                                                         this.fill();
  1079.                                                 }
  1080.                                                 break;
  1081.                                         case 'td':
  1082.                                                 if (target.hasClass('day') && !target.hasClass('disabled')){
  1083.                                                         day = parseInt(target.text(), 10)||1;
  1084.                                                         year = this.viewDate.getUTCFullYear();
  1085.                                                         month = this.viewDate.getUTCMonth();
  1086.                                                         if (target.hasClass('old')){
  1087.                                                                 if (month === 0){
  1088.                                                                         month = 11;
  1089.                                                                         year -= 1;
  1090.                                                                 }
  1091.                                                                 else {
  1092.                                                                         month -= 1;
  1093.                                                                 }
  1094.                                                         }
  1095.                                                         else if (target.hasClass('new')){
  1096.                                                                 if (month === 11){
  1097.                                                                         month = 0;
  1098.                                                                         year += 1;
  1099.                                                                 }
  1100.                                                                 else {
  1101.                                                                         month += 1;
  1102.                                                                 }
  1103.                                                         }
  1104.                                                         this._setDate(UTCDate(year, month, day));
  1105.                                                 }
  1106.                                                 break;
  1107.                                 }
  1108.                         }
  1109.                         if (this.picker.is(':visible') && this._focused_from){
  1110.                                 $(this._focused_from).focus();
  1111.                         }
  1112.                         delete this._focused_from;
  1113.                 },
  1114.  
  1115.                 _toggle_multidate: function(date){
  1116.                         var ix = this.dates.contains(date);
  1117.                         if (!date){
  1118.                                 this.dates.clear();
  1119.                         }
  1120.  
  1121.                         if (ix !== -1){
  1122.                                 if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
  1123.                                         this.dates.remove(ix);
  1124.                                 }
  1125.                         } else if (this.o.multidate === false) {
  1126.                                 this.dates.clear();
  1127.                                 this.dates.push(date);
  1128.                         }
  1129.                         else {
  1130.                                 this.dates.push(date);
  1131.                         }
  1132.  
  1133.                         if (typeof this.o.multidate === 'number')
  1134.                                 while (this.dates.length > this.o.multidate)
  1135.                                         this.dates.remove(0);
  1136.                 },
  1137.  
  1138.                 _setDate: function(date, which){
  1139.                         if (!which || which === 'date')
  1140.                                 this._toggle_multidate(date && new Date(date));
  1141.                         if (!which || which  === 'view')
  1142.                                 this.viewDate = date && new Date(date);
  1143.  
  1144.                         this.fill();
  1145.                         this.setValue();
  1146.                         if (!which || which  !== 'view') {
  1147.                                 this._trigger('changeDate');
  1148.                         }
  1149.                         var element;
  1150.                         if (this.isInput){
  1151.                                 element = this.element;
  1152.                         }
  1153.                         else if (this.component){
  1154.                                 element = this.element.find('input');
  1155.                         }
  1156.                         if (element){
  1157.                                 element.change();
  1158.                         }
  1159.                         if (this.o.autoclose && (!which || which === 'date')){
  1160.                                 this.hide();
  1161.                         }
  1162.                 },
  1163.  
  1164.                 moveMonth: function(date, dir){
  1165.                         if (!date)
  1166.                                 return undefined;
  1167.                         if (!dir)
  1168.                                 return date;
  1169.                         var new_date = new Date(date.valueOf()),
  1170.                                 day = new_date.getUTCDate(),
  1171.                                 month = new_date.getUTCMonth(),
  1172.                                 mag = Math.abs(dir),
  1173.                                 new_month, test;
  1174.                         dir = dir > 0 ? 1 : -1;
  1175.                         if (mag === 1){
  1176.                                 test = dir === -1
  1177.                                         // If going back one month, make sure month is not current month
  1178.                                         // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
  1179.                                         ? function(){
  1180.                                                 return new_date.getUTCMonth() === month;
  1181.                                         }
  1182.                                         // If going forward one month, make sure month is as expected
  1183.                                         // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
  1184.                                         : function(){
  1185.                                                 return new_date.getUTCMonth() !== new_month;
  1186.                                         };
  1187.                                 new_month = month + dir;
  1188.                                 new_date.setUTCMonth(new_month);
  1189.                                 // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
  1190.                                 if (new_month < 0 || new_month > 11)
  1191.                                         new_month = (new_month + 12) % 12;
  1192.                         }
  1193.                         else {
  1194.                                 // For magnitudes >1, move one month at a time...
  1195.                                 for (var i=0; i < mag; i++)
  1196.                                         // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
  1197.                                         new_date = this.moveMonth(new_date, dir);
  1198.                                 // ...then reset the day, keeping it in the new month
  1199.                                 new_month = new_date.getUTCMonth();
  1200.                                 new_date.setUTCDate(day);
  1201.                                 test = function(){
  1202.                                         return new_month !== new_date.getUTCMonth();
  1203.                                 };
  1204.                         }
  1205.                         // Common date-resetting loop -- if date is beyond end of month, make it
  1206.                         // end of month
  1207.                         while (test()){
  1208.                                 new_date.setUTCDate(--day);
  1209.                                 new_date.setUTCMonth(new_month);
  1210.                         }
  1211.                         return new_date;
  1212.                 },
  1213.  
  1214.                 moveYear: function(date, dir){
  1215.                         return this.moveMonth(date, dir*12);
  1216.                 },
  1217.  
  1218.                 dateWithinRange: function(date){
  1219.                         return date >= this.o.startDate && date <= this.o.endDate;
  1220.                 },
  1221.  
  1222.                 keydown: function(e){
  1223.                         if (!this.picker.is(':visible')){
  1224.                                 if (e.keyCode === 27) // allow escape to hide and re-show picker
  1225.                                         this.show();
  1226.                                 return;
  1227.                         }
  1228.                         var dateChanged = false,
  1229.                                 dir, newDate, newViewDate,
  1230.                                 focusDate = this.focusDate || this.viewDate;
  1231.                         switch (e.keyCode){
  1232.                                 case 27: // escape
  1233.                                         if (this.focusDate){
  1234.                                                 this.focusDate = null;
  1235.                                                 this.viewDate = this.dates.get(-1) || this.viewDate;
  1236.                                                 this.fill();
  1237.                                         }
  1238.                                         else
  1239.                                                 this.hide();
  1240.                                         e.preventDefault();
  1241.                                         break;
  1242.                                 case 37: // left
  1243.                                 case 39: // right
  1244.                                         if (!this.o.keyboardNavigation)
  1245.                                                 break;
  1246.                                         dir = e.keyCode === 37 ? -1 : 1;
  1247.                                         if (e.ctrlKey){
  1248.                                                 newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);
  1249.                                                 newViewDate = this.moveYear(focusDate, dir);
  1250.                                                 this._trigger('changeYear', this.viewDate);
  1251.                                         }
  1252.                                         else if (e.shiftKey){
  1253.                                                 newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);
  1254.                                                 newViewDate = this.moveMonth(focusDate, dir);
  1255.                                                 this._trigger('changeMonth', this.viewDate);
  1256.                                         }
  1257.                                         else {
  1258.                                                 newDate = new Date(this.dates.get(-1) || UTCToday());
  1259.                                                 newDate.setUTCDate(newDate.getUTCDate() + dir);
  1260.                                                 newViewDate = new Date(focusDate);
  1261.                                                 newViewDate.setUTCDate(focusDate.getUTCDate() + dir);
  1262.                                         }
  1263.                                         if (this.dateWithinRange(newViewDate)){
  1264.                                                 this.focusDate = this.viewDate = newViewDate;
  1265.                                                 this.setValue();
  1266.                                                 this.fill();
  1267.                                                 e.preventDefault();
  1268.                                         }
  1269.                                         break;
  1270.                                 case 38: // up
  1271.                                 case 40: // down
  1272.                                         if (!this.o.keyboardNavigation)
  1273.                                                 break;
  1274.                                         dir = e.keyCode === 38 ? -1 : 1;
  1275.                                         if (e.ctrlKey){
  1276.                                                 newDate = this.moveYear(this.dates.get(-1) || UTCToday(), dir);
  1277.                                                 newViewDate = this.moveYear(focusDate, dir);
  1278.                                                 this._trigger('changeYear', this.viewDate);
  1279.                                         }
  1280.                                         else if (e.shiftKey){
  1281.                                                 newDate = this.moveMonth(this.dates.get(-1) || UTCToday(), dir);
  1282.                                                 newViewDate = this.moveMonth(focusDate, dir);
  1283.                                                 this._trigger('changeMonth', this.viewDate);
  1284.                                         }
  1285.                                         else {
  1286.                                                 newDate = new Date(this.dates.get(-1) || UTCToday());
  1287.                                                 newDate.setUTCDate(newDate.getUTCDate() + dir * 7);
  1288.                                                 newViewDate = new Date(focusDate);
  1289.                                                 newViewDate.setUTCDate(focusDate.getUTCDate() + dir * 7);
  1290.                                         }
  1291.                                         if (this.dateWithinRange(newViewDate)){
  1292.                                                 this.focusDate = this.viewDate = newViewDate;
  1293.                                                 this.setValue();
  1294.                                                 this.fill();
  1295.                                                 e.preventDefault();
  1296.                                         }
  1297.                                         break;
  1298.                                 case 32: // spacebar
  1299.                                         // Spacebar is used in manually typing dates in some formats.
  1300.                                         // As such, its behavior should not be hijacked.
  1301.                                         break;
  1302.                                 case 13: // enter
  1303.                                         focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
  1304.                                         if (this.o.keyboardNavigation) {
  1305.                                                 this._toggle_multidate(focusDate);
  1306.                                                 dateChanged = true;
  1307.                                         }
  1308.                                         this.focusDate = null;
  1309.                                         this.viewDate = this.dates.get(-1) || this.viewDate;
  1310.                                         this.setValue();
  1311.                                         this.fill();
  1312.                                         if (this.picker.is(':visible')){
  1313.                                                 e.preventDefault();
  1314.                                                 if (typeof e.stopPropagation === 'function') {
  1315.                                                         e.stopPropagation(); // All modern browsers, IE9+
  1316.                                                 } else {
  1317.                                                         e.cancelBubble = true; // IE6,7,8 ignore "stopPropagation"
  1318.                                                 }
  1319.                                                 if (this.o.autoclose)
  1320.                                                         this.hide();
  1321.                                         }
  1322.                                         break;
  1323.                                 case 9: // tab
  1324.                                         this.focusDate = null;
  1325.                                         this.viewDate = this.dates.get(-1) || this.viewDate;
  1326.                                         this.fill();
  1327.                                         this.hide();
  1328.                                         break;
  1329.                         }
  1330.                         if (dateChanged){
  1331.                                 if (this.dates.length)
  1332.                                         this._trigger('changeDate');
  1333.                                 else
  1334.                                         this._trigger('clearDate');
  1335.                                 var element;
  1336.                                 if (this.isInput){
  1337.                                         element = this.element;
  1338.                                 }
  1339.                                 else if (this.component){
  1340.                                         element = this.element.find('input');
  1341.                                 }
  1342.                                 if (element){
  1343.                                         element.change();
  1344.                                 }
  1345.                         }
  1346.                 },
  1347.  
  1348.                 showMode: function(dir){
  1349.                         if (dir){
  1350.                                 this.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir));
  1351.                         }
  1352.                         this.picker
  1353.                                 .children('div')
  1354.                                 .hide()
  1355.                                 .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
  1356.                                         .css('display', 'block');
  1357.                         this.updateNavArrows();
  1358.                 }
  1359.         };
  1360.  
  1361.         var DateRangePicker = function(element, options){
  1362.                 this.element = $(element);
  1363.                 this.inputs = $.map(options.inputs, function(i){
  1364.                         return i.jquery ? i[0] : i;
  1365.                 });
  1366.                 delete options.inputs;
  1367.  
  1368.                 datepickerPlugin.call($(this.inputs), options)
  1369.                         .bind('changeDate', $.proxy(this.dateUpdated, this));
  1370.  
  1371.                 this.pickers = $.map(this.inputs, function(i){
  1372.                         return $(i).data('datepicker');
  1373.                 });
  1374.                 this.updateDates();
  1375.         };
  1376.         DateRangePicker.prototype = {
  1377.                 updateDates: function(){
  1378.                         this.dates = $.map(this.pickers, function(i){
  1379.                                 return i.getUTCDate();
  1380.                         });
  1381.                         this.updateRanges();
  1382.                 },
  1383.                 updateRanges: function(){
  1384.                         var range = $.map(this.dates, function(d){
  1385.                                 return d.valueOf();
  1386.                         });
  1387.                         $.each(this.pickers, function(i, p){
  1388.                                 p.setRange(range);
  1389.                         });
  1390.                 },
  1391.                 dateUpdated: function(e){
  1392.                         // `this.updating` is a workaround for preventing infinite recursion
  1393.                         // between `changeDate` triggering and `setUTCDate` calling.  Until
  1394.                         // there is a better mechanism.
  1395.                         if (this.updating)
  1396.                                 return;
  1397.                         this.updating = true;
  1398.  
  1399.                         var dp = $(e.target).data('datepicker'),
  1400.                                 new_date = dp.getUTCDate(),
  1401.                                 i = $.inArray(e.target, this.inputs),
  1402.                                 j = i - 1,
  1403.                                 k = i + 1,
  1404.                                 l = this.inputs.length;
  1405.                         if (i === -1)
  1406.                                 return;
  1407.  
  1408.                         $.each(this.pickers, function(i, p){
  1409.                                 if (!p.getUTCDate())
  1410.                                         p.setUTCDate(new_date);
  1411.                         });
  1412.  
  1413.                         if (new_date < this.dates[j]){
  1414.                                 // Date being moved earlier/left
  1415.                                 while (j >= 0 && new_date < this.dates[j]){
  1416.                                         this.pickers[j--].setUTCDate(new_date);
  1417.                                 }
  1418.                         }
  1419.                         else if (new_date > this.dates[k]){
  1420.                                 // Date being moved later/right
  1421.                                 while (k < l && new_date > this.dates[k]){
  1422.                                         this.pickers[k++].setUTCDate(new_date);
  1423.                                 }
  1424.                         }
  1425.                         this.updateDates();
  1426.  
  1427.                         delete this.updating;
  1428.                 },
  1429.                 remove: function(){
  1430.                         $.map(this.pickers, function(p){ p.remove(); });
  1431.                         delete this.element.data().datepicker;
  1432.                 }
  1433.         };
  1434.  
  1435.         function opts_from_el(el, prefix){
  1436.                 // Derive options from element data-attrs
  1437.                 var data = $(el).data(),
  1438.                         out = {}, inkey,
  1439.                         replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
  1440.                 prefix = new RegExp('^' + prefix.toLowerCase());
  1441.                 function re_lower(_,a){
  1442.                         return a.toLowerCase();
  1443.                 }
  1444.                 for (var key in data)
  1445.                         if (prefix.test(key)){
  1446.                                 inkey = key.replace(replace, re_lower);
  1447.                                 out[inkey] = data[key];
  1448.                         }
  1449.                 return out;
  1450.         }
  1451.  
  1452.         function opts_from_locale(lang){
  1453.                 // Derive options from locale plugins
  1454.                 var out = {};
  1455.                 // Check if "de-DE" style date is available, if not language should
  1456.                 // fallback to 2 letter code eg "de"
  1457.                 if (!dates[lang]){
  1458.                         lang = lang.split('-')[0];
  1459.                         if (!dates[lang])
  1460.                                 return;
  1461.                 }
  1462.                 var d = dates[lang];
  1463.                 $.each(locale_opts, function(i,k){
  1464.                         if (k in d)
  1465.                                 out[k] = d[k];
  1466.                 });
  1467.                 return out;
  1468.         }
  1469.  
  1470.         var old = $.fn.datepicker;
  1471.         var datepickerPlugin = function(option){
  1472.                 var args = Array.apply(null, arguments);
  1473.                 args.shift();
  1474.                 var internal_return;
  1475.                 this.each(function(){
  1476.                         var $this = $(this),
  1477.                                 data = $this.data('datepicker'),
  1478.                                 options = typeof option === 'object' && option;
  1479.                         if (!data){
  1480.                                 var elopts = opts_from_el(this, 'date'),
  1481.                                         // Preliminary otions
  1482.                                         xopts = $.extend({}, defaults, elopts, options),
  1483.                                         locopts = opts_from_locale(xopts.language),
  1484.                                         // Options priority: js args, data-attrs, locales, defaults
  1485.                                         opts = $.extend({}, defaults, locopts, elopts, options);
  1486.                                 if ($this.hasClass('input-daterange') || opts.inputs){
  1487.                                         var ropts = {
  1488.                                                 inputs: opts.inputs || $this.find('input').toArray()
  1489.                                         };
  1490.                                         $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, ropts))));
  1491.                                 }
  1492.                                 else {
  1493.                                         $this.data('datepicker', (data = new Datepicker(this, opts)));
  1494.                                 }
  1495.                         }
  1496.                         if (typeof option === 'string' && typeof data[option] === 'function'){
  1497.                                 internal_return = data[option].apply(data, args);
  1498.                                 if (internal_return !== undefined)
  1499.                                         return false;
  1500.                         }
  1501.                 });
  1502.                 if (internal_return !== undefined)
  1503.                         return internal_return;
  1504.                 else
  1505.                         return this;
  1506.         };
  1507.         $.fn.datepicker = datepickerPlugin;
  1508.  
  1509.         var defaults = $.fn.datepicker.defaults = {
  1510.                 autoclose: false,
  1511.                 beforeShowDay: $.noop,
  1512.                 beforeShowMonth: $.noop,
  1513.                 calendarWeeks: false,
  1514.                 clearBtn: false,
  1515.                 toggleActive: false,
  1516.                 daysOfWeekDisabled: [],
  1517.                 datesDisabled: [],
  1518.                 endDate: Infinity,
  1519.                 forceParse: true,
  1520.                 format: 'mm/dd/yyyy',
  1521.                 keyboardNavigation: true,
  1522.                 language: 'en',
  1523.                 minViewMode: 0,
  1524.                 multidate: false,
  1525.                 multidateSeparator: ',',
  1526.                 orientation: "auto",
  1527.                 rtl: false,
  1528.                 startDate: -Infinity,
  1529.                 startView: 0,
  1530.                 todayBtn: false,
  1531.                 todayHighlight: false,
  1532.                 weekStart: 0,
  1533.                 disableTouchKeyboard: false,
  1534.                 container: 'body'
  1535.         };
  1536.         var locale_opts = $.fn.datepicker.locale_opts = [
  1537.                 'format',
  1538.                 'rtl',
  1539.                 'weekStart'
  1540.         ];
  1541.         $.fn.datepicker.Constructor = Datepicker;
  1542.         var dates = $.fn.datepicker.dates = {
  1543.                 en: {
  1544.                         days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
  1545.                         daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
  1546.                         daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
  1547.                         months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  1548.                         monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
  1549.                         today: "Today",
  1550.                         clear: "Clear"
  1551.                 }
  1552.         };
  1553.  
  1554.         var DPGlobal = {
  1555.                 modes: [
  1556.                         {
  1557.                                 clsName: 'days',
  1558.                                 navFnc: 'Month',
  1559.                                 navStep: 1
  1560.                         },
  1561.                         {
  1562.                                 clsName: 'months',
  1563.                                 navFnc: 'FullYear',
  1564.                                 navStep: 1
  1565.                         },
  1566.                         {
  1567.                                 clsName: 'years',
  1568.                                 navFnc: 'FullYear',
  1569.                                 navStep: 10
  1570.                 }],
  1571.                 isLeapYear: function(year){
  1572.                         return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
  1573.                 },
  1574.                 getDaysInMonth: function(year, month){
  1575.                         return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
  1576.                 },
  1577.                 validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
  1578.                 nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,
  1579.                 parseFormat: function(format){
  1580.                         // IE treats \0 as a string end in inputs (truncating the value),
  1581.                         // so it's a bad format delimiter, anyway
  1582.                         var separators = format.replace(this.validParts, '\0').split('\0'),
  1583.                                 parts = format.match(this.validParts);
  1584.                         if (!separators || !separators.length || !parts || parts.length === 0){
  1585.                                 throw new Error("Invalid date format.");
  1586.                         }
  1587.                         return {separators: separators, parts: parts};
  1588.                 },
  1589.                 parseDate: function(date, format, language){
  1590.                         if (!date)
  1591.                                 return undefined;
  1592.                         if (date instanceof Date)
  1593.                                 return date;
  1594.                         if (typeof format === 'string')
  1595.                                 format = DPGlobal.parseFormat(format);
  1596.                         var part_re = /([\-+]\d+)([dmwy])/,
  1597.                                 parts = date.match(/([\-+]\d+)([dmwy])/g),
  1598.                                 part, dir, i;
  1599.                         if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){
  1600.                                 date = new Date();
  1601.                                 for (i=0; i < parts.length; i++){
  1602.                                         part = part_re.exec(parts[i]);
  1603.                                         dir = parseInt(part[1]);
  1604.                                         switch (part[2]){
  1605.                                                 case 'd':
  1606.                                                         date.setUTCDate(date.getUTCDate() + dir);
  1607.                                                         break;
  1608.                                                 case 'm':
  1609.                                                         date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir);
  1610.                                                         break;
  1611.                                                 case 'w':
  1612.                                                         date.setUTCDate(date.getUTCDate() + dir * 7);
  1613.                                                         break;
  1614.                                                 case 'y':
  1615.                                                         date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir);
  1616.                                                         break;
  1617.                                         }
  1618.                                 }
  1619.                                 return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
  1620.                         }
  1621.                         parts = date && date.match(this.nonpunctuation) || [];
  1622.                         date = new Date();
  1623.                         var parsed = {},
  1624.                                 setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
  1625.                                 setters_map = {
  1626.                                         yyyy: function(d,v){
  1627.                                                 return d.setUTCFullYear(v);
  1628.                                         },
  1629.                                         yy: function(d,v){
  1630.                                                 return d.setUTCFullYear(2000+v);
  1631.                                         },
  1632.                                         m: function(d,v){
  1633.                                                 if (isNaN(d))
  1634.                                                         return d;
  1635.                                                 v -= 1;
  1636.                                                 while (v < 0) v += 12;
  1637.                                                 v %= 12;
  1638.                                                 d.setUTCMonth(v);
  1639.                                                 while (d.getUTCMonth() !== v)
  1640.                                                         d.setUTCDate(d.getUTCDate()-1);
  1641.                                                 return d;
  1642.                                         },
  1643.                                         d: function(d,v){
  1644.                                                 return d.setUTCDate(v);
  1645.                                         }
  1646.                                 },
  1647.                                 val, filtered;
  1648.                         setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
  1649.                         setters_map['dd'] = setters_map['d'];
  1650.                         date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
  1651.                         var fparts = format.parts.slice();
  1652.                         // Remove noop parts
  1653.                         if (parts.length !== fparts.length){
  1654.                                 fparts = $(fparts).filter(function(i,p){
  1655.                                         return $.inArray(p, setters_order) !== -1;
  1656.                                 }).toArray();
  1657.                         }
  1658.                         // Process remainder
  1659.                         function match_part(){
  1660.                                 var m = this.slice(0, parts[i].length),
  1661.                                         p = parts[i].slice(0, m.length);
  1662.                                 return m.toLowerCase() === p.toLowerCase();
  1663.                         }
  1664.                         if (parts.length === fparts.length){
  1665.                                 var cnt;
  1666.                                 for (i=0, cnt = fparts.length; i < cnt; i++){
  1667.                                         val = parseInt(parts[i], 10);
  1668.                                         part = fparts[i];
  1669.                                         if (isNaN(val)){
  1670.                                                 switch (part){
  1671.                                                         case 'MM':
  1672.                                                                 filtered = $(dates[language].months).filter(match_part);
  1673.                                                                 val = $.inArray(filtered[0], dates[language].months) + 1;
  1674.                                                                 break;
  1675.                                                         case 'M':
  1676.                                                                 filtered = $(dates[language].monthsShort).filter(match_part);
  1677.                                                                 val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
  1678.                                                                 break;
  1679.                                                 }
  1680.                                         }
  1681.                                         parsed[part] = val;
  1682.                                 }
  1683.                                 var _date, s;
  1684.                                 for (i=0; i < setters_order.length; i++){
  1685.                                         s = setters_order[i];
  1686.                                         if (s in parsed && !isNaN(parsed[s])){
  1687.                                                 _date = new Date(date);
  1688.                                                 setters_map[s](_date, parsed[s]);
  1689.                                                 if (!isNaN(_date))
  1690.                                                         date = _date;
  1691.                                         }
  1692.                                 }
  1693.                         }
  1694.                         return date;
  1695.                 },
  1696.                 formatDate: function(date, format, language){
  1697.                         if (!date)
  1698.                                 return '';
  1699.                         if (typeof format === 'string')
  1700.                                 format = DPGlobal.parseFormat(format);
  1701.                         var val = {
  1702.                                 d: date.getUTCDate(),
  1703.                                 D: dates[language].daysShort[date.getUTCDay()],
  1704.                                 DD: dates[language].days[date.getUTCDay()],
  1705.                                 m: date.getUTCMonth() + 1,
  1706.                                 M: dates[language].monthsShort[date.getUTCMonth()],
  1707.                                 MM: dates[language].months[date.getUTCMonth()],
  1708.                                 yy: date.getUTCFullYear().toString().substring(2),
  1709.                                 yyyy: date.getUTCFullYear()
  1710.                         };
  1711.                         val.dd = (val.d < 10 ? '0' : '') + val.d;
  1712.                         val.mm = (val.m < 10 ? '0' : '') + val.m;
  1713.                         date = [];
  1714.                         var seps = $.extend([], format.separators);
  1715.                         for (var i=0, cnt = format.parts.length; i <= cnt; i++){
  1716.                                 if (seps.length)
  1717.                                         date.push(seps.shift());
  1718.                                 date.push(val[format.parts[i]]);
  1719.                         }
  1720.                         return date.join('');
  1721.                 },
  1722.                 headTemplate: '<thead>'+
  1723.                                                         '<tr>'+
  1724.                                                                 '<th class="prev">&#171;</th>'+
  1725.                                                                 '<th colspan="5" class="datepicker-switch"></th>'+
  1726.                                                                 '<th class="next">&#187;</th>'+
  1727.                                                         '</tr>'+
  1728.                                                 '</thead>',
  1729.                 contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
  1730.                 footTemplate: '<tfoot>'+
  1731.                                                         '<tr>'+
  1732.                                                                 '<th colspan="7" class="today"></th>'+
  1733.                                                         '</tr>'+
  1734.                                                         '<tr>'+
  1735.                                                                 '<th colspan="7" class="clear"></th>'+
  1736.                                                         '</tr>'+
  1737.                                                 '</tfoot>'
  1738.         };
  1739.         DPGlobal.template = '<div class="datepicker">'+
  1740.                                                         '<div class="datepicker-days">'+
  1741.                                                                 '<table class=" table-condensed">'+
  1742.                                                                         DPGlobal.headTemplate+
  1743.                                                                         '<tbody></tbody>'+
  1744.                                                                         DPGlobal.footTemplate+
  1745.                                                                 '</table>'+
  1746.                                                         '</div>'+
  1747.                                                         '<div class="datepicker-months">'+
  1748.                                                                 '<table class="table-condensed">'+
  1749.                                                                         DPGlobal.headTemplate+
  1750.                                                                         DPGlobal.contTemplate+
  1751.                                                                         DPGlobal.footTemplate+
  1752.                                                                 '</table>'+
  1753.                                                         '</div>'+
  1754.                                                         '<div class="datepicker-years">'+
  1755.                                                                 '<table class="table-condensed">'+
  1756.                                                                         DPGlobal.headTemplate+
  1757.                                                                         DPGlobal.contTemplate+
  1758.                                                                         DPGlobal.footTemplate+
  1759.                                                                 '</table>'+
  1760.                                                         '</div>'+
  1761.                                                 '</div>';
  1762.  
  1763.         $.fn.datepicker.DPGlobal = DPGlobal;
  1764.  
  1765.  
  1766.         /* DATEPICKER NO CONFLICT
  1767.         * =================== */
  1768.  
  1769.         $.fn.datepicker.noConflict = function(){
  1770.                 $.fn.datepicker = old;
  1771.                 return this;
  1772.         };
  1773.  
  1774.  
  1775.         /* DATEPICKER DATA-API
  1776.         * ================== */
  1777.  
  1778.         $(document).on(
  1779.                 'focus.datepicker.data-api click.datepicker.data-api',
  1780.                 '[data-provide="datepicker"]',
  1781.                 function(e){
  1782.                         var $this = $(this);
  1783.                         if ($this.data('datepicker'))
  1784.                                 return;
  1785.                         e.preventDefault();
  1786.                         // component click requires us to explicitly show it
  1787.                         datepickerPlugin.call($this, 'show');
  1788.                 }
  1789.         );
  1790.         $(function(){
  1791.                 datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
  1792.         });
  1793.  
  1794. }(window.jQuery));

Raw Paste


Login or Register to edit or fork this paste. It's free.