PageSourceSearch

https://theneomag.com/wp-content/plugins/wpc-product-options/assets/libs/wpcdpk/js/datepicker.js?ver=3.1.6

js theneomag.com collected 2026-10-04 05:26:23 UTC 88,373 bytes, 2,508 lines download raw bytes

1;(
2    function(window, $, undefined) {
3      ;
4      (
5          function() {
6            var VERSION = '2.2.3',
7                pluginName = 'wpcdpk',
8                autoInitSelector = '.wpcdpk-here',
9                $body, $wpcdpksContainer,
10                containerBuilt = false,
11                baseTemplate = '' +
12                    '<div class="wpcdpk">' +
13                    '<i class="wpcdpk--pointer"></i>' +
14                    '<nav class="wpcdpk--nav"></nav>' +
15                    '<div class="wpcdpk--content"></div>' +
16                    '</div>',
17                defaults = {
18                  classes: '',
19                  inline: false,
20                  language: 'en',
21                  startDate: new Date(),
22                  firstDay: '',
23                  weekends: [6, 0],
24                  dateFormat: '',
25                  altField: '',
26                  altFieldDateFormat: '@',
27                  toggleSelected: true,
28                  keyboardNav: true,
29
30                  position: 'bottom left',
31                  offset: 12,
32
33                  view: 'days',
34                  minView: 'days',
35
36                  showOtherMonths: true,
37                  selectOtherMonths: true,
38                  moveToOtherMonthsOnSelect: true,
39
40                  showOtherYears: true,
41                  selectOtherYears: true,
42                  moveToOtherYearsOnSelect: true,
43
44                  minDate: '',
45                  maxDate: '',
46                  disableNavWhenOutOfRange: true,
47
48                  multipleDates: false, // Boolean or Number
49                  multipleDatesSeparator: ',',
50                  range: false,
51
52                  todayButton: false,
53                  clearButton: false,
54
55                  showEvent: 'focus',
56                  autoClose: false,
57
58                  // navigation
59                  monthsField: 'monthsShort',
60                  prevHtml: '<svg><path d="M 17,12 l -5,5 l 5,5"></path></svg>',
61                  nextHtml: '<svg><path d="M 14,12 l 5,5 l -5,5"></path></svg>',
62                  navTitles: {
63                    days: 'MM, <i>yyyy</i>',
64                    months: 'yyyy',
65                    years: 'yyyy1 - yyyy2',
66                  },
67
68                  // timepicker
69                  timepicker: false,
70                  onlyTimepicker: false,
71                  dateTimeSeparator: ' ',
72                  timeFormat: '',
73                  minHours: 0,
74                  maxHours: 24,
75                  minMinutes: 0,
76                  maxMinutes: 59,
77                  hoursStep: 1,
78                  minutesStep: 1,
79
80                  // events
81                  onSelect: '',
82                  onShow: '',
83                  onHide: '',
84                  onChangeMonth: '',
85                  onChangeYear: '',
86                  onChangeDecade: '',
87                  onChangeView: '',
88                  onRenderCell: '',
89                },
90                hotKeys = {
91                  'ctrlRight': [17, 39],
92                  'ctrlUp': [17, 38],
93                  'ctrlLeft': [17, 37],
94                  'ctrlDown': [17, 40],
95                  'shiftRight': [16, 39],
96                  'shiftUp': [16, 38],
97                  'shiftLeft': [16, 37],
98                  'shiftDown': [16, 40],
99                  'altUp': [18, 38],
100                  'altRight': [18, 39],
101                  'altLeft': [18, 37],
102                  'altDown': [18, 40],
103                  'ctrlShiftUp': [16, 17, 38],
104                },
105                wpcdpk;
106
107            var Wpcdpk = function(el, options) {
108              this.el = el;
109              this.$el = $(el);
110
111              this.opts = $.extend(true, {}, defaults, options,
112                  this.$el.data());
113
114              if ($body == undefined) {
115                $body = $('body');
116              }
117
118              if (!this.opts.startDate) {
119                this.opts.startDate = new Date();
120              }
121
122              if (this.el.nodeName == 'INPUT') {
123                this.elIsInput = true;
124              }
125
126              if (this.opts.altField) {
127                this.$altField = typeof this.opts.altField == 'string' ?
128                    $(this.opts.altField) :
129                    this.opts.altField;
130              }
131
132              this.inited = false;
133              this.visible = false;
134              this.silent = false; // Need to prevent unnecessary rendering
135
136              this.currentDate = this.opts.startDate;
137              this.currentView = this.opts.view;
138              this._createShortCuts();
139              this.selectedDates = [];
140              this.views = {};
141              this.keys = [];
142              this.minRange = '';
143              this.maxRange = '';
144              this._prevOnSelectValue = '';
145
146              this.init();
147            };
148
149            wpcdpk = Wpcdpk;
150
151            wpcdpk.prototype = {
152              VERSION: VERSION,
153              viewIndexes: ['days', 'months', 'years'],
154
155              init: function() {
156                if (!containerBuilt && !this.opts.inline && this.elIsInput) {
157                  this._buildWpcdpksContainer();
158                }
159                this._buildBaseHtml();
160                this._defineLocale(this.opts.language);
161                this._syncWithMinMaxDates();
162
163                if (this.elIsInput) {
164                  if (!this.opts.inline) {
165                    // Set extra classes for proper transitions
166                    this._setPositionClasses(this.opts.position);
167                    this._bindEvents();
168                  }
169                  if (this.opts.keyboardNav && !this.opts.onlyTimepicker) {
170                    this._bindKeyboardEvents();
171                  }
172                  this.$wpcdpk.on('mousedown',
173                      this._onMouseDownWpcdpk.bind(this));
174                  this.$wpcdpk.on('mouseup',
175                      this._onMouseUpWpcdpk.bind(this));
176                }
177
178                if (this.opts.classes) {
179                  this.$wpcdpk.addClass(this.opts.classes);
180                }
181
182                if (this.opts.timepicker) {
183                  this.timepicker = new $.fn.wpcdpk.Timepicker(this, this.opts);
184                  this._bindTimepickerEvents();
185                }
186
187                if (this.opts.onlyTimepicker) {
188                  this.$wpcdpk.addClass('-only-timepicker-');
189                }
190
191                this.views[this.currentView] = new $.fn.wpcdpk.Body(this,
192                    this.currentView, this.opts);
193                this.views[this.currentView].show();
194                this.nav = new $.fn.wpcdpk.Navigation(this, this.opts);
195                this.view = this.currentView;
196
197                this.$el.on('clickCell.adp', this._onClickCell.bind(this));
198                this.$wpcdpk.on('mouseenter', '.wpcdpk--cell',
199                    this._onMouseEnterCell.bind(this));
200                this.$wpcdpk.on('mouseleave', '.wpcdpk--cell',
201                    this._onMouseLeaveCell.bind(this));
202
203                this.inited = true;
204              },
205
206              _createShortCuts: function() {
207                this.minDate = this.opts.minDate ?
208                    this.opts.minDate :
209                    new Date(-8639999913600000);
210                this.maxDate = this.opts.maxDate ?
211                    this.opts.maxDate :
212                    new Date(8639999913600000);
213              },
214
215              _bindEvents: function() {
216                this.$el.on(this.opts.showEvent + '.adp',
217                    this._onShowEvent.bind(this));
218                this.$el.on('mouseup.adp', this._onMouseUpEl.bind(this));
219                this.$el.on('blur.adp', this._onBlur.bind(this));
220                this.$el.on('keyup.adp', this._onKeyUpGeneral.bind(this));
221                $(window).on('resize.adp', this._onResize.bind(this));
222                $('body').on('mouseup.adp', this._onMouseUpBody.bind(this));
223              },
224
225              _bindKeyboardEvents: function() {
226                this.$el.on('keydown.adp', this._onKeyDown.bind(this));
227                this.$el.on('keyup.adp', this._onKeyUp.bind(this));
228                this.$el.on('hotKey.adp', this._onHotKey.bind(this));
229              },
230
231              _bindTimepickerEvents: function() {
232                this.$el.on('timeChange.adp', this._onTimeChange.bind(this));
233              },
234
235              isWeekend: function(day) {
236                return this.opts.weekends.indexOf(day) !== -1;
237              },
238
239              _defineLocale: function(lang) {
240                if (typeof lang == 'string') {
241                  this.loc = $.fn.wpcdpk.language[lang];
242                  if (!this.loc) {
243                    console.warn('Can\'t find language "' + lang +
244                        '" in Wpcdpk.language, will use "ru" instead');
245                    this.loc = $.extend(true, {}, $.fn.wpcdpk.language.ru);
246                  }
247
248                  this.loc = $.extend(true, {}, $.fn.wpcdpk.language.ru,
249                      $.fn.wpcdpk.language[lang]);
250                } else {
251                  this.loc = $.extend(true, {}, $.fn.wpcdpk.language.ru, lang);
252                }
253
254                if (this.opts.dateFormat) {
255                  this.loc.dateFormat = this.opts.dateFormat;
256                }
257
258                if (this.opts.timeFormat) {
259                  this.loc.timeFormat = this.opts.timeFormat;
260                }
261
262                if (this.opts.firstDay !== '') {
263                  this.loc.firstDay = this.opts.firstDay;
264                }
265
266                if (this.opts.timepicker) {
267                  this.loc.dateFormat = [
268                    this.loc.dateFormat,
269                    this.loc.timeFormat,
270                  ].join(this.opts.dateTimeSeparator);
271                }
272
273                if (this.opts.onlyTimepicker) {
274                  this.loc.dateFormat = this.loc.timeFormat;
275                }
276
277                var boundary = this._getWordBoundaryRegExp;
278                if (this.loc.timeFormat.match(boundary('aa')) ||
279                    this.loc.timeFormat.match(boundary('AA'))
280                ) {
281                  this.ampm = true;
282                }
283              },
284
285              _buildWpcdpksContainer: function() {
286                containerBuilt = true;
287                $body.append(
288                    '<div class="wpcdpks-container" id="wpcdpks-container"></div>');
289                $wpcdpksContainer = $('#wpcdpks-container');
290              },
291
292              _buildBaseHtml: function() {
293                var $appendTarget,
294                    $inline = $('<div class="wpcdpk-inline">');
295
296                if (this.el.nodeName == 'INPUT') {
297                  if (!this.opts.inline) {
298                    $appendTarget = $wpcdpksContainer;
299                  } else {
300                    $appendTarget = $inline.insertAfter(this.$el);
301                  }
302                } else {
303                  $appendTarget = $inline.appendTo(this.$el);
304                }
305
306                this.$wpcdpk = $(baseTemplate).appendTo($appendTarget);
307                this.$content = $('.wpcdpk--content', this.$wpcdpk);
308                this.$nav = $('.wpcdpk--nav', this.$wpcdpk);
309              },
310
311              _triggerOnChange: function() {
312                if (!this.selectedDates.length) {
313                  // Prevent from triggering multiple onSelect callback with same argument (empty string) in IE10-11
314                  if (this._prevOnSelectValue === '') {
315                    return;
316                  }
317                  this._prevOnSelectValue = '';
318                  return this.opts.onSelect('', '', this);
319                }
320
321                var selectedDates = this.selectedDates,
322                    parsedSelected = wpcdpk.getParsedDate(selectedDates[0]),
323                    formattedDates,
324                    _this = this,
325                    dates = new Date(
326                        parsedSelected.year,
327                        parsedSelected.month,
328                        parsedSelected.date,
329                        parsedSelected.hours,
330                        parsedSelected.minutes,
331                    );
332
333                formattedDates = selectedDates.map(function(date) {
334                  return _this.formatDate(_this.loc.dateFormat, date);
335                }).join(this.opts.multipleDatesSeparator);
336
337                // Create new dates array, to separate it from original selectedDates
338                if (this.opts.multipleDates || this.opts.range) {
339                  dates = selectedDates.map(function(date) {
340                    var parsedDate = wpcdpk.getParsedDate(date);
341                    return new Date(
342                        parsedDate.year,
343                        parsedDate.month,
344                        parsedDate.date,
345                        parsedDate.hours,
346                        parsedDate.minutes,
347                    );
348                  });
349                }
350
351                this._prevOnSelectValue = formattedDates;
352                this.opts.onSelect(formattedDates, dates, this);
353              },
354
355              next: function() {
356                var d = this.parsedDate,
357                    o = this.opts;
358                switch (this.view) {
359                  case 'days':
360                    this.date = new Date(d.year, d.month + 1, 1);
361                    if (o.onChangeMonth) {
362                      o.onChangeMonth(this.parsedDate.month,
363                          this.parsedDate.year);
364                    }
365                    break;
366                  case 'months':
367                    this.date = new Date(d.year + 1, d.month, 1);
368                    if (o.onChangeYear) {
369                      o.onChangeYear(this.parsedDate.year);
370                    }
371                    break;
372                  case 'years':
373                    this.date = new Date(d.year + 10, 0, 1);
374                    if (o.onChangeDecade) {
375                      o.onChangeDecade(this.curDecade);
376                    }
377                    break;
378                }
379              },
380
381              prev: function() {
382                var d = this.parsedDate,
383                    o = this.opts;
384                switch (this.view) {
385                  case 'days':
386                    this.date = new Date(d.year, d.month - 1, 1);
387                    if (o.onChangeMonth) {
388                      o.onChangeMonth(this.parsedDate.month,
389                          this.parsedDate.year);
390                    }
391                    break;
392                  case 'months':
393                    this.date = new Date(d.year - 1, d.month, 1);
394                    if (o.onChangeYear) {
395                      o.onChangeYear(this.parsedDate.year);
396                    }
397                    break;
398                  case 'years':
399                    this.date = new Date(d.year - 10, 0, 1);
400                    if (o.onChangeDecade) {
401                      o.onChangeDecade(this.curDecade);
402                    }
403                    break;
404                }
405              },
406
407              formatDate: function(string, date) {
408                date = date || this.date;
409                var result = string,
410                    boundary = this._getWordBoundaryRegExp,
411                    locale = this.loc,
412                    leadingZero = wpcdpk.getLeadingZeroNum,
413                    decade = wpcdpk.getDecade(date),
414                    d = wpcdpk.getParsedDate(date),
415                    fullHours = d.fullHours,
416                    hours = d.hours,
417                    ampm = string.match(boundary('aa')) ||
418                        string.match(boundary('AA')),
419                    dayPeriod = 'am',
420                    replacer = this._replacer,
421                    validHours;
422
423                if (this.opts.timepicker && this.timepicker && ampm) {
424                  validHours = this.timepicker._getValidHoursFromDate(date,
425                      ampm);
426                  fullHours = leadingZero(validHours.hours);
427                  hours = validHours.hours;
428                  dayPeriod = validHours.dayPeriod;
429                }
430
431                switch (true) {
432                  case /@/.test(result):
433                    result = result.replace(/@/, date.getTime());
434                  case /aa/.test(result):
435                    result = replacer(result, boundary('aa'), dayPeriod);
436                  case /AA/.test(result):
437                    result = replacer(result, boundary('AA'),
438                        dayPeriod.toUpperCase());
439                  case /dd/.test(result):
440                    result = replacer(result, boundary('dd'), d.fullDate);
441                  case /d/.test(result):
442                    result = replacer(result, boundary('d'), d.date);
443                  case /DD/.test(result):
444                    result = replacer(result, boundary('DD'),
445                        locale.days[d.day]);
446                  case /D/.test(result):
447                    result = replacer(result, boundary('D'),
448                        locale.daysShort[d.day]);
449                  case /mm/.test(result):
450                    result = replacer(result, boundary('mm'), d.fullMonth);
451                  case /m/.test(result):
452                    result = replacer(result, boundary('m'), d.month + 1);
453                  case /MM/.test(result):
454                    result = replacer(result, boundary('MM'),
455                        this.loc.months[d.month]);
456                  case /M/.test(result):
457                    result = replacer(result, boundary('M'),
458                        locale.monthsShort[d.month]);
459                  case /ii/.test(result):
460                    result = replacer(result, boundary('ii'), d.fullMinutes);
461                  case /i/.test(result):
462                    result = replacer(result, boundary('i'), d.minutes);
463                  case /hh/.test(result):
464                    result = replacer(result, boundary('hh'), fullHours);
465                  case /h/.test(result):
466                    result = replacer(result, boundary('h'), hours);
467                  case /yyyy/.test(result):
468                    result = replacer(result, boundary('yyyy'), d.year);
469                  case /yyyy1/.test(result):
470                    result = replacer(result, boundary('yyyy1'), decade[0]);
471                  case /yyyy2/.test(result):
472                    result = replacer(result, boundary('yyyy2'), decade[1]);
473                  case /yy/.test(result):
474                    result = replacer(result, boundary('yy'),
475                        d.year.toString().slice(-2));
476                }
477
478                return result;
479              },
480
481              _replacer: function(str, reg, data) {
482                return str.replace(reg, function(match, p1, p2, p3) {
483                  return p1 + data + p3;
484                });
485              },
486
487              _getWordBoundaryRegExp: function(sign) {
488                var symbols = '\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;';
489
490                return new RegExp(
491                    '(^|>|' + symbols + ')(' + sign + ')($|<|' + symbols + ')',
492                    'g');
493              },
494
495              selectDate: function(date) {
496                var _this = this,
497                    opts = _this.opts,
498                    d = _this.parsedDate,
499                    selectedDates = _this.selectedDates,
500                    len = selectedDates.length,
501                    newDate = '';
502
503                if (Array.isArray(date)) {
504                  date.forEach(function(d) {
505                    _this.selectDate(d);
506                  });
507                  return;
508                }
509
510                if (!(
511                    date instanceof Date
512                )) {
513                  return;
514                }
515
516                this.lastSelectedDate = date;
517
518                // Set new time values from Date
519                if (this.timepicker) {
520                  this.timepicker._setTime(date);
521                }
522
523                // On this step timepicker will set valid values in it's instance
524                _this._trigger('selectDate', date);
525
526                // Set correct time values after timepicker's validation
527                // Prevent from setting hours or minutes which values are lesser then `min` value or
528                // greater then `max` value
529                if (this.timepicker) {
530                  date.setHours(this.timepicker.hours);
531                  date.setMinutes(this.timepicker.minutes);
532                }
533
534                if (_this.view == 'days') {
535                  if (date.getMonth() != d.month &&
536                      opts.moveToOtherMonthsOnSelect) {
537                    newDate = new Date(date.getFullYear(), date.getMonth(), 1);
538                  }
539                }
540
541                if (_this.view == 'years') {
542                  if (date.getFullYear() != d.year &&
543                      opts.moveToOtherYearsOnSelect) {
544                    newDate = new Date(date.getFullYear(), 0, 1);
545                  }
546                }
547
548                if (newDate) {
549                  _this.silent = true;
550                  _this.date = newDate;
551                  _this.silent = false;
552                  _this.nav._render();
553                }
554
555                if (opts.multipleDates && !opts.range) { // Set priority to range functionality
556                  if (len === opts.multipleDates) {
557                    return;
558                  }
559                  if (!_this._isSelected(date)) {
560                    _this.selectedDates.push(date);
561                  }
562                } else if (opts.range) {
563                  if (len == 2) {
564                    _this.selectedDates = [date];
565                    _this.minRange = date;
566                    _this.maxRange = '';
567                  } else if (len == 1) {
568                    _this.selectedDates.push(date);
569                    if (!_this.maxRange) {
570                      _this.maxRange = date;
571                    } else {
572                      _this.minRange = date;
573                    }
574                    // Swap dates if they were selected via dp.selectDate() and second date was smaller then first
575                    if (wpcdpk.bigger(_this.maxRange, _this.minRange)) {
576                      _this.maxRange = _this.minRange;
577                      _this.minRange = date;
578                    }
579                    _this.selectedDates = [_this.minRange, _this.maxRange];
580
581                  } else {
582                    _this.selectedDates = [date];
583                    _this.minRange = date;
584                  }
585                } else {
586                  _this.selectedDates = [date];
587                }
588
589                _this._setInputValue();
590
591                if (opts.onSelect) {
592                  _this._triggerOnChange();
593                }
594
595                if (opts.autoClose && !this.timepickerIsActive) {
596                  if (!opts.multipleDates && !opts.range) {
597                    _this.hide();
598                  } else if (opts.range && _this.selectedDates.length == 2) {
599                    _this.hide();
600                  }
601                }
602
603                _this.views[this.currentView]._render();
604              },
605
606              removeDate: function(date) {
607                var selected = this.selectedDates,
608                    _this = this;
609
610                if (!(
611                    date instanceof Date
612                )) {
613                  return;
614                }
615
616                return selected.some(function(curDate, i) {
617                  if (wpcdpk.isSame(curDate, date)) {
618                    selected.splice(i, 1);
619
620                    if (!_this.selectedDates.length) {
621                      _this.minRange = '';
622                      _this.maxRange = '';
623                      _this.lastSelectedDate = '';
624                    } else {
625                      _this.lastSelectedDate = _this.selectedDates[_this.selectedDates.length -
626                      1];
627                    }
628
629                    _this.views[_this.currentView]._render();
630                    _this._setInputValue();
631
632                    if (_this.opts.onSelect) {
633                      _this._triggerOnChange();
634                    }
635
636                    return true;
637                  }
638                });
639              },
640
641              today: function() {
642                this.silent = true;
643                this.view = this.opts.minView;
644                this.silent = false;
645                this.date = new Date();
646
647                if (this.opts.todayButton instanceof Date) {
648                  this.selectDate(this.opts.todayButton);
649                }
650              },
651
652              clear: function() {
653                this.selectedDates = [];
654                this.minRange = '';
655                this.maxRange = '';
656                this.views[this.currentView]._render();
657                this._setInputValue();
658                if (this.opts.onSelect) {
659                  this._triggerOnChange();
660                }
661              },
662
663              /**
664               * Updates wpcdpk options
665               * @param {String|Object} param - parameter's name to update. If object then it will extend current options
666               * @param {String|Number|Object} [value] - new param value
667               */
668              update: function(param, value) {
669                var len = arguments.length,
670                    lastSelectedDate = this.lastSelectedDate;
671
672                if (len == 2) {
673                  this.opts[param] = value;
674                } else if (len == 1 && typeof param == 'object') {
675                  this.opts = $.extend(true, this.opts, param);
676                }
677
678                this._createShortCuts();
679                this._syncWithMinMaxDates();
680                this._defineLocale(this.opts.language);
681                this.nav._addButtonsIfNeed();
682                if (!this.opts.onlyTimepicker) {
683                  this.nav._render();
684                }
685                this.views[this.currentView]._render();
686
687                if (this.elIsInput && !this.opts.inline) {
688                  this._setPositionClasses(this.opts.position);
689                  if (this.visible) {
690                    this.setPosition(this.opts.position);
691                  }
692                }
693
694                if (this.opts.classes) {
695                  this.$wpcdpk.addClass(this.opts.classes);
696                }
697
698                if (this.opts.onlyTimepicker) {
699                  this.$wpcdpk.addClass('-only-timepicker-');
700                }
701
702                if (this.opts.timepicker) {
703                  if (lastSelectedDate) {
704                    this.timepicker._handleDate(lastSelectedDate);
705                  }
706                  this.timepicker._updateRanges();
707                  this.timepicker._updateCurrentTime();
708                  // Change hours and minutes if it's values have been changed through min/max hours/minutes
709                  if (lastSelectedDate) {
710                    lastSelectedDate.setHours(this.timepicker.hours);
711                    lastSelectedDate.setMinutes(this.timepicker.minutes);
712                  }
713                }
714
715                this._setInputValue();
716
717                return this;
718              },
719
720              _syncWithMinMaxDates: function() {
721                var curTime = this.date.getTime();
722                this.silent = true;
723                if (this.minTime > curTime) {
724                  this.date = this.minDate;
725                }
726
727                if (this.maxTime < curTime) {
728                  this.date = this.maxDate;
729                }
730                this.silent = false;
731              },
732
733              _isSelected: function(checkDate, cellType) {
734                var res = false;
735                this.selectedDates.some(function(date) {
736                  if (wpcdpk.isSame(date, checkDate, cellType)) {
737                    res = date;
738                    return true;
739                  }
740                });
741                return res;
742              },
743
744              _setInputValue: function() {
745                var _this = this,
746                    opts = _this.opts,
747                    format = _this.loc.dateFormat,
748                    altFormat = opts.altFieldDateFormat,
749                    value = _this.selectedDates.map(function(date) {
750                      return _this.formatDate(format, date);
751                    }),
752                    altValues;
753
754                if (opts.altField && _this.$altField.length) {
755                  altValues = this.selectedDates.map(function(date) {
756                    return _this.formatDate(altFormat, date);
757                  });
758                  altValues = altValues.join(this.opts.multipleDatesSeparator);
759                  this.$altField.val(altValues);
760                }
761
762                value = value.join(this.opts.multipleDatesSeparator);
763
764                this.$el.val(value);
765              },
766
767              /**
768               * Check if date is between minDate and maxDate
769               * @param date {object} - date object
770               * @param type {string} - cell type
771               * @returns {boolean}
772               * @private
773               */
774              _isInRange: function(date, type) {
775                var time = date.getTime(),
776                    d = wpcdpk.getParsedDate(date),
777                    min = wpcdpk.getParsedDate(this.minDate),
778                    max = wpcdpk.getParsedDate(this.maxDate),
779                    dMinTime = new Date(d.year, d.month, min.date).getTime(),
780                    dMaxTime = new Date(d.year, d.month, max.date).getTime(),
781                    types = {
782                      day: time >= this.minTime && time <= this.maxTime,
783                      month: dMinTime >= this.minTime && dMaxTime <=
784                          this.maxTime,
785                      year: d.year >= min.year && d.year <= max.year,
786                    };
787                return type ? types[type] : types.day;
788              },
789
790              _getDimensions: function($el) {
791                var offset = $el.offset();
792
793                return {
794                  width: $el.outerWidth(),
795                  height: $el.outerHeight(),
796                  left: offset.left,
797                  top: offset.top,
798                };
799              },
800
801              _getDateFromCell: function(cell) {
802                var curDate = this.parsedDate,
803                    year = cell.data('year') || curDate.year,
804                    month = cell.data('month') == undefined ?
805                        curDate.month :
806                        cell.data('month'),
807                    date = cell.data('date') || 1;
808
809                return new Date(year, month, date);
810              },
811
812              _setPositionClasses: function(pos) {
813                pos = pos.split(' ');
814                var main = pos[0],
815                    sec = pos[1],
816                    classes = 'wpcdpk -' + main + '-' + sec + '- -from-' +
817                        main + '-';
818
819                if (this.visible) {
820                  classes += ' active';
821                }
822
823                this.$wpcdpk.removeAttr('class').addClass(classe
823s);
824              },
825
826              setPosition: function(position) {
827                position = position || this.opts.position;
828
829                var dims = this._getDimensions(this.$el),
830                    selfDims = this._getDimensions(this.$wpcdpk),
831                    pos = position.split(' '),
832                    top, left,
833                    offset = this.opts.offset,
834                    main = pos[0],
835                    secondary = pos[1];
836
837                switch (main) {
838                  case 'top':
839                    top = dims.top - selfDims.height - offset;
840                    break;
841                  case 'right':
842                    left = dims.left + dims.width + offset;
843                    break;
844                  case 'bottom':
845                    top = dims.top + dims.height + offset;
846                    break;
847                  case 'left':
848                    left = dims.left - selfDims.width - offset;
849                    break;
850                }
851
852                switch (secondary) {
853                  case 'top':
854                    top = dims.top;
855                    break;
856                  case 'right':
857                    left = dims.left + dims.width - selfDims.width;
858                    break;
859                  case 'bottom':
860                    top = dims.top + dims.height - selfDims.height;
861                    break;
862                  case 'left':
863                    left = dims.left;
864                    break;
865                  case 'center':
866                    if (/left|right/.test(main)) {
867                      top = dims.top + dims.height / 2 - selfDims.height / 2;
868                    } else {
869                      left = dims.left + dims.width / 2 - selfDims.width / 2;
870                    }
871                }
872
873                this.$wpcdpk.css({
874                  left: left,
875                  top: top,
876                });
877              },
878
879              show: function() {
880                var onShow = this.opts.onShow;
881
882                this.setPosition(this.opts.position);
883                this.$wpcdpk.addClass('active');
884                this.visible = true;
885
886                if (onShow) {
887                  this._bindVisionEvents(onShow);
888                }
889              },
890
891              hide: function() {
892                var onHide = this.opts.onHide;
893
894                this.$wpcdpk.removeClass('active').css({
895                  left: '-100000px',
896                });
897
898                this.focused = '';
899                this.keys = [];
900
901                this.inFocus = false;
902                this.visible = false;
903                this.$el.blur();
904
905                if (onHide) {
906                  this._bindVisionEvents(onHide);
907                }
908              },
909
910              down: function(date) {
911                this._changeView(date, 'down');
912              },
913
914              up: function(date) {
915                this._changeView(date, 'up');
916              },
917
918              _bindVisionEvents: function(event) {
919                this.$wpcdpk.off('transitionend.dp');
920                event(this, false);
921                this.$wpcdpk.one('transitionend.dp',
922                    event.bind(this, this, true));
923              },
924
925              _changeView: function(date, dir) {
926                date = date || this.focused || this.date;
927
928                var nextView = dir == 'up' ?
929                    this.viewIndex + 1 :
930                    this.viewIndex - 1;
931                if (nextView > 2) {
932                  nextView = 2;
933                }
934                if (nextView < 0) {
935                  nextView = 0;
936                }
937
938                this.silent = true;
939                this.date = new Date(date.getFullYear(), date.getMonth(), 1);
940                this.silent = false;
941                this.view = this.viewIndexes[nextView];
942
943              },
944
945              _handleHotKey: function(key) {
946                var date = wpcdpk.getParsedDate(this._getFocusedDate()),
947                    focusedParsed,
948                    o = this.opts,
949                    newDate,
950                    totalDaysInNextMonth,
951                    monthChanged = false,
952                    yearChanged = false,
953                    decadeChanged = false,
954                    y = date.year,
955                    m = date.month,
956                    d = date.date;
957
958                switch (key) {
959                  case 'ctrlRight':
960                  case 'ctrlUp':
961                    m += 1;
962                    monthChanged = true;
963                    break;
964                  case 'ctrlLeft':
965                  case 'ctrlDown':
966                    m -= 1;
967                    monthChanged = true;
968                    break;
969                  case 'shiftRight':
970                  case 'shiftUp':
971                    yearChanged = true;
972                    y += 1;
973                    break;
974                  case 'shiftLeft':
975                  case 'shiftDown':
976                    yearChanged = true;
977                    y -= 1;
978                    break;
979                  case 'altRight':
980                  case 'altUp':
981                    decadeChanged = true;
982                    y += 10;
983                    break;
984                  case 'altLeft':
985                  case 'altDown':
986                    decadeChanged = true;
987                    y -= 10;
988                    break;
989                  case 'ctrlShiftUp':
990                    this.up();
991                    break;
992                }
993
994                totalDaysInNextMonth = wpcdpk.getDaysCount(new Date(y, m));
995                newDate = new Date(y, m, d);
996
997                // If next month has less days than current, set date to total days in that month
998                if (totalDaysInNextMonth < d) {
999                  d = totalDaysInNextMonth;
1000                }
1001
1002                // Check if newDate is in valid range
1003                if (newDate.getTime() < this.minTime) {
1004                  newDate = this.minDate;
1005                } else if (newDate.getTime() > this.maxTime) {
1006                  newDate = this.maxDate;
1007                }
1008
1009                this.focused = newDate;
1010
1011                focusedParsed = wpcdpk.getParsedDate(newDate);
1012                if (monthChanged && o.onChangeMonth) {
1013                  o.onChangeMonth(focusedParsed.month, focusedParsed.year);
1014                }
1015                if (yearChanged && o.onChangeYear) {
1016                  o.onChangeYear(focusedParsed.year);
1017                }
1018                if (decadeChanged && o.onChangeDecade) {
1019                  o.onChangeDecade(this.curDecade);
1020                }
1021              },
1022
1023              _registerKey: function(key) {
1024                var exists = this.keys.some(function(curKey) {
1025                  return curKey == key;
1026                });
1027
1028                if (!exists) {
1029                  this.keys.push(key);
1030                }
1031              },
1032
1033              _unRegisterKey: function(key) {
1034                var index = this.keys.indexOf(key);
1035
1036                this.keys.splice(index, 1);
1037              },
1038
1039              _isHotKeyPressed: function() {
1040                var currentHotKey,
1041                    found = false,
1042                    _this = this,
1043                    pressedKeys = this.keys.sort();
1044
1045                for (var hotKey in hotKeys) {
1046                  currentHotKey = hotKeys[hotKey];
1047                  if (pressedKeys.length != currentHotKey.length) {
1048                    continue;
1049                  }
1050
1051                  if (currentHotKey.every(function(key, i) {
1052                    return key == pressedKeys[i];
1053                  })) {
1054                    _this._trigger('hotKey', hotKey);
1055                    found = true;
1056                  }
1057                }
1058
1059                return found;
1060              },
1061
1062              _trigger: function(event, args) {
1063                this.$el.trigger(event, args);
1064              },
1065
1066              _focusNextCell: function(keyCode, type) {
1067                type = type || this.cellType;
1068
1069                var date = wpcdpk.getParsedDate(this._getFocusedDate()),
1070                    y = date.year,
1071                    m = date.month,
1072                    d = date.date;
1073
1074                if (this._isHotKeyPressed()) {
1075                  return;
1076                }
1077
1078                switch (keyCode) {
1079                  case 37: // left
1080                    type == 'day' ? (
1081                        d -= 1
1082                    ) : '';
1083                    type == 'month' ? (
1084                        m -= 1
1085                    ) : '';
1086                    type == 'year' ? (
1087                        y -= 1
1088                    ) : '';
1089                    break;
1090                  case 38: // up
1091                    type == 'day' ? (
1092                        d -= 7
1093                    ) : '';
1094                    type == 'month' ? (
1095                        m -= 3
1096                    ) : '';
1097                    type == 'year' ? (
1098                        y -= 4
1099                    ) : '';
1100                    break;
1101                  case 39: // right
1102                    type == 'day' ? (
1103                        d += 1
1104                    ) : '';
1105                    type == 'month' ? (
1106                        m += 1
1107                    ) : '';
1108                    type == 'year' ? (
1109                        y += 1
1110                    ) : '';
1111                    break;
1112                  case 40: // down
1113                    type == 'day' ? (
1114                        d += 7
1115                    ) : '';
1116                    type == 'month' ? (
1117                        m += 3
1118                    ) : '';
1119                    type == 'year' ? (
1120                        y += 4
1121                    ) : '';
1122                    break;
1123                }
1124
1125                var nd = new Date(y, m, d);
1126                if (nd.getTime() < this.minTime) {
1127                  nd = this.minDate;
1128                } else if (nd.getTime() > this.maxTime) {
1129                  nd = this.maxDate;
1130                }
1131
1132                this.focused = nd;
1133
1134              },
1135
1136              _getFocusedDate: function() {
1137                var focused = this.focused ||
1138                        this.selectedDates[this.selectedDates.length - 1],
1139                    d = this.parsedDate;
1140
1141                if (!focused) {
1142                  switch (this.view) {
1143                    case 'days':
1144                      focused = new Date(d.year, d.month, new Date().getDate());
1145                      break;
1146                    case 'months':
1147                      focused = new Date(d.year, d.month, 1);
1148                      break;
1149                    case 'years':
1150                      focused = new Date(d.year, 0, 1);
1151                      break;
1152                  }
1153                }
1154
1155                return focused;
1156              },
1157
1158              _getCell: function(date, type) {
1159                type = type || this.cellType;
1160
1161                var d = wpcdpk.getParsedDate(date),
1162                    selector = '.wpcdpk--cell[data-year="' + d.year + '"]',
1163                    $cell;
1164
1165                switch (type) {
1166                  case 'month':
1167                    selector = '[data-month="' + d.month + '"]';
1168                    break;
1169                  case 'day':
1170                    selector += '[data-month="' + d.month + '"][data-date="' +
1171                        d.date + '"]';
1172                    break;
1173                }
1174                $cell = this.views[this.currentView].$el.find(selector);
1175
1176                return $cell.length ? $cell : $('');
1177              },
1178
1179              destroy: function() {
1180                var _this = this;
1181                _this.$el.off('.adp').data('wpcdpk', '');
1182
1183                _this.selectedDates = [];
1184                _this.focused = '';
1185                _this.views = {};
1186                _this.keys = [];
1187                _this.minRange = '';
1188                _this.maxRange = '';
1189
1190                if (_this.opts.inline || !_this.elIsInput) {
1191                  _this.$wpcdpk.closest('.wpcdpk-inline').remove();
1192                } else {
1193                  _this.$wpcdpk.remove();
1194                }
1195              },
1196
1197              _handleAlreadySelectedDates: function(
1198                  alreadySelected, selectedDate) {
1199                if (this.opts.range) {
1200                  if (!this.opts.toggleSelected) {
1201                    // Add possibility to select same date when range is true
1202                    if (this.selectedDates.length != 2) {
1203                      this._trigger('clickCell', selectedDate);
1204                    }
1205                  } else {
1206                    this.removeDate(selectedDate);
1207                  }
1208                } else if (this.opts.toggleSelected) {
1209                  this.removeDate(selectedDate);
1210                }
1211
1212                // Change last selected date to be able to change time when clicking on this cell
1213                if (!this.opts.toggleSelected) {
1214                  this.lastSelectedDate = alreadySelected;
1215                  if (this.opts.timepicker) {
1216                    this.timepicker._setTime(alreadySelected);
1217                    this.timepicker.update();
1218                  }
1219                }
1220              },
1221
1222              _onShowEvent: function(e) {
1223                if (!this.visible) {
1224                  this.show();
1225                }
1226              },
1227
1228              _onBlur: function() {
1229                if (!this.inFocus && this.visible) {
1230                  this.hide();
1231                }
1232              },
1233
1234              _onMouseDownWpcdpk: function(e) {
1235                this.inFocus = true;
1236              },
1237
1238              _onMouseUpWpcdpk: function(e) {
1239                this.inFocus = false;
1240                e.originalEvent.inFocus = true;
1241                if (!e.originalEvent.timepickerFocus) {
1242                  this.$el.focus();
1243                }
1244              },
1245
1246              _onKeyUpGeneral: function(e) {
1247                var val = this.$el.val();
1248
1249                if (!val) {
1250                  this.clear();
1251                }
1252              },
1253
1254              _onResize: function() {
1255                if (this.visible) {
1256                  this.setPosition();
1257                }
1258              },
1259
1260              _onMouseUpBody: function(e) {
1261                if (e.originalEvent.inFocus) {
1262                  return;
1263                }
1264
1265                if (this.visible && !this.inFocus) {
1266                  this.hide();
1267                }
1268              },
1269
1270              _onMouseUpEl: function(e) {
1271                e.originalEvent.inFocus = true;
1272                setTimeout(this._onKeyUpGeneral.bind(this), 4);
1273              },
1274
1275              _onKeyDown: function(e) {
1276                var code = e.which;
1277                this._registerKey(code);
1278
1279                // Arrows
1280                if (code >= 37 && code <= 40) {
1281                  e.preventDefault();
1282                  this._focusNextCell(code);
1283                }
1284
1285                // Enter
1286                if (code == 13) {
1287                  if (this.focused) {
1288                    if (this._getCell(this.focused).hasClass('-disabled-')) {
1289                      return;
1290                    }
1291                    if (this.view != this.opts.minView) {
1292                      this.down();
1293                    } else {
1294                      var alreadySelected = this._isSelected(this.focused,
1295                          this.cellType);
1296
1297                      if (!alreadySelected) {
1298                        if (this.timepicker) {
1299                          this.focused.setHours(this.timepicker.hours);
1300                          this.focused.setMinutes(this.timepicker.minutes);
1301                        }
1302                        this.selectDate(this.focused);
1303                        return;
1304                      }
1305                      this._handleAlreadySelectedDates(alreadySelected,
1306                          this.focused);
1307                    }
1308                  }
1309                }
1310
1311                // Esc
1312                if (code == 27) {
1313                  this.hide();
1314                }
1315              },
1316
1317              _onKeyUp: function(e) {
1318                var code = e.which;
1319                this._unRegisterKey(code);
1320              },
1321
1322              _onHotKey: function(e, hotKey) {
1323                this._handleHotKey(hotKey);
1324              },
1325
1326              _onMouseEnterCell: function(e) {
1327                var $cell = $(e.target).closest('.wpcdpk--cell'),
1328                    date = this._getDateFromCell($cell);
1329
1330                // Prevent from unnecessary rendering and setting new currentDate
1331                this.silent = true;
1332
1333                if (this.focused) {
1334                  this.focused = '';
1335                }
1336
1337                $cell.addClass('-focus-');
1338
1339                this.focused = date;
1340                this.silent = false;
1341
1342                if (this.opts.range && this.selectedDates.length == 1) {
1343                  this.minRange = this.selectedDates[0];
1344                  this.maxRange = '';
1345                  if (wpcdpk.less(this.minRange, this.focused)) {
1346                    this.maxRange = this.minRange;
1347                    this.minRange = '';
1348                  }
1349                  this.views[this.currentView]._update();
1350                }
1351              },
1352
1353              _onMouseLeaveCell: function(e) {
1354                var $cell = $(e.target).closest('.wpcdpk--cell');
1355
1356                $cell.removeClass('-focus-');
1357
1358                this.silent = true;
1359                this.focused = '';
1360                this.silent = false;
1361              },
1362
1363              _onTimeChange: function(e, h, m) {
1364                var date = new Date(),
1365                    selectedDates = this.selectedDates,
1366                    selected = false;
1367
1368                if (selectedDates.length) {
1369                  selected = true;
1370                  date = this.lastSelectedDate;
1371                }
1372
1373                date.setHours(h);
1374                date.setMinutes(m);
1375
1376                if (!selected && !this._getCell(date).hasClass('-disabled-')) {
1377                  this.selectDate(date);
1378                } else {
1379                  this._setInputValue();
1380                  if (this.opts.onSelect) {
1381                    this._triggerOnChange();
1382                  }
1383                }
1384              },
1385
1386              _onClickCell: function(e, date) {
1387                if (this.timepicker) {
1388                  date.setHours(this.timepicker.hours);
1389                  date.setMinutes(this.timepicker.minutes);
1390                }
1391                this.selectDate(date);
1392              },
1393
1394              set focused(val) {
1395                if (!val && this.focused) {
1396                  var $cell = this._getCell(this.focused);
1397
1398                  if ($cell.length) {
1399                    $cell.removeClass('-focus-');
1400                  }
1401                }
1402                this._focused = val;
1403                if (this.opts.range && this.selectedDates.length == 1) {
1404                  this.minRange = this.selectedDates[0];
1405                  this.maxRange = '';
1406                  if (wpcdpk.less(this.minRange, this._focused)) {
1407                    this.maxRange = this.minRange;
1408                    this.minRange = '';
1409                  }
1410                }
1411                if (this.silent) {
1412                  return;
1413                }
1414                this.date = val;
1415              },
1416
1417              get focused() {
1418                return this._focused;
1419              },
1420
1421              get parsedDate() {
1422                return wpcdpk.getParsedDate(this.date);
1423              },
1424
1425              set date(val) {
1426                if (!(
1427                    val instanceof Date
1428                )) {
1429                  return;
1430                }
1431
1432                this.currentDate = val;
1433
1434                if (this.inited && !this.silent) {
1435                  this.views[this.view]._render();
1436                  this.nav._render();
1437                  if (this.visible && this.elIsInput) {
1438                    this.setPosition();
1439                  }
1440                }
1441                return val;
1442              },
1443
1444              get date() {
1445                return this.currentDate;
1446              },
1447
1448              set view(val) {
1449                this.viewIndex = this.viewIndexes.indexOf(val);
1450
1451                if (this.viewIndex < 0) {
1452                  return;
1453                }
1454
1455                this.prevView = this.currentView;
1456                this.currentView = val;
1457
1458                if (this.inited) {
1459                  if (!this.views[val]) {
1460                    this.views[val] = new $.fn.wpcdpk.Body(this, val,
1461                        this.opts);
1462                  } else {
1463                    this.views[val]._render();
1464                  }
1465
1466                  this.views[this.prevView].hide();
1467                  this.views[val].show();
1468                  this.nav._render();
1469
1470                  if (this.opts.onChangeView) {
1471                    this.opts.onChangeView(val);
1472                  }
1473                  if (this.elIsInput && this.visible) {
1474                    this.setPosition();
1475                  }
1476                }
1477
1478                return val;
1479              },
1480
1481              get view() {
1482                return this.currentView;
1483              },
1484
1485              get cellType() {
1486                return this.view.substring(0, this.view.length - 1);
1487              },
1488
1489              get minTime() {
1490                var min = wpcdpk.getParsedDate(this.minDate);
1491                return new Date(min.year, min.month, min.date).getTime();
1492              },
1493
1494              get maxTime() {
1495                var max = wpcdpk.getParsedDate(this.maxDate);
1496                return new Date(max.year, max.month, max.date).getTime();
1497              },
1498
1499              get curDecade() {
1500                return wpcdpk.getDecade(this.date);
1501              },
1502            };
1503
1504            //  Utils
1505            // -------------------------------------------------
1506
1507            wpcdpk.getDaysCount = function(date) {
1508              return new Date(date.getFullYear(), date.getMonth() + 1,
1509                  0).getDate();
1510            };
1511
1512            wpcdpk.getParsedDate = function(date) {
1513              return {
1514                year: date.getFullYear(),
1515                month: date.getMonth(),
1516                fullMonth: (
1517                    date.getMonth() + 1
1518                ) < 10 ? '0' + (
1519                    date.getMonth() + 1
1520                ) : date.getMonth() + 1, // One based
1521                date: date.getDate(),
1522                fullDate: date.getDate() < 10 ?
1523                    '0' + date.getDate() :
1524                    date.getDate(),
1525                day: date.getDay(),
1526                hours: date.getHours(),
1527                fullHours: date.getHours() < 10 ?
1528                    '0' + date.getHours() :
1529                    date.getHours(),
1530                minutes: date.getMinutes(),
1531                fullMinutes: date.getMinutes() < 10 ?
1532                    '0' + date.getMinutes() :
1533                    date.getMinutes(),
1534              };
1535            };
1536
1537            wpcdpk.getDecade = function(date) {
1538              var firstYear = Math.floor(date.getFullYear() / 10) * 10;
1539
1540              return [firstYear, firstYear + 9];
1541            };
1542
1543            wpcdpk.template = function(str, data) {
1544              return str.replace(/#\{([\w]+)\}/g, function(source, match) {
1545                if (data[match] || data[match] === 0) {
1546                  return data[match];
1547                }
1548              });
1549            };
1550
1551            wpcdpk.isSame = function(date1, date2, type) {
1552              if (!date1 || !date2) {
1553                return false;
1554              }
1555              var d1 = wpcdpk.getParsedDate(date1),
1556                  d2 = wpcdpk.getParsedDate(date2),
1557                  _type = type ? type : 'day',
1558
1559                  conditions = {
1560                    day: d1.date == d2.date && d1.month == d2.month &&
1561                        d1.year == d2.year,
1562                    month: d1.month == d2.month && d1.year == d2.year,
1563                    year: d1.year == d2.year,
1564                  };
1565
1566              return conditions[_type];
1567            };
1568
1569            wpcdpk.less = function(dateCompareTo, date, type) {
1570              if (!dateCompareTo || !date) {
1571                return false;
1572              }
1573              return date.getTime() < dateCompareTo.getTime();
1574            };
1575
1576            wpcdpk.bigger = function(dateCompareTo, date, type) {
1577              if (!dateCompareTo || !date) {
1578                return false;
1579              }
1580              return date.getTime() > dateCompareTo.getTime();
1581            };
1582
1583            wpcdpk.getLeadingZeroNum = function(num) {
1584              return parseInt(num) < 10 ? '0' + num : num;
1585            };
1586
1587            /**
1588             * Returns copy of date with hours and minutes equals to 0
1589             * @param date {Date}
1590             */
1591            wpcdpk.resetTime = function(date) {
1592              if (typeof date != 'object') {
1593                return;
1594              }
1595              date = wpcdpk.getParsedDate(date);
1596              return new Date(date.year, date.month, date.date);
1597            };
1598
1599            $.fn.wpcdpk = function(options) {
1600              return this.each(function() {
1601                if (!$.data(this, pluginName)) {
1602                  $.data(this, pluginName,
1603                      new Wpcdpk(this, options));
1604                } else {
1605                  var _this = $.data(this, pluginName);
1606
1607                  _this.opts = $.extend(true, _this.opts, options);
1608                  _this.update();
1609                }
1610              });
1611            };
1612
1613            $.fn.wpcdpk.Constructor = Wpcdpk;
1614
1615            $.fn.wpcdpk.language = {
1616              en: {
1617                days: [
1618                  'Sunday',
1619                  'Monday',
1620                  'Tuesday',
1621                  'Wednesday',
1622                  'Thursday',
1623                  'Friday',
1624                  'Saturday'],
1625                daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
1626                daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
1627                months: [
1628                  'January',
1629                  'February',
1630                  'March',
1631                  'April',
1632                  'May',
1633                  'June',
1634                  'July',
1635                  'August',
1636                  'September',
1637                  'October',
1638                  'November',
1639                  'December',
1640                ],
1641                monthsShort: [
1642                  'Jan',
1643                  'Feb',
1644                  'Mar',
1645                  'Apr',
1646                  'May',
1647                  'Jun',
1648                  'Jul',
1649                  'Aug',
1650                  'Sep',
1651                  'Oct',
1652                  'Nov',
1653                  'Dec',
1654                ],
1655                today: 'Today',
1656                clear: 'Clear',
1657                dateFormat: 'mm/dd/yyyy',
1658                timeFormat: 'hh:ii aa',
1659                firstDay: 0,
1660              },
1661            };
1662
1663            $(function() {
1664              $(autoInitSelector).wpcdpk();
1665            });
1666
1667          }
1668      )();
1669
1670      ;
1671      (
1672          function() {
1673            var templates = {
1674                  days: '' +
1675                      '<div class="wpcdpk--days wpcdpk--body">' +
1676                      '<div class="wpcdpk--days-names"></div>' +
1677                      '<div class="wpcdpk--cells wpcdpk--cells-days"></div>' +
1678                      '</div>',
1679                  months: '' +
1680                      '<div class="wpcdpk--months wpcdpk--body">' +
1681                      '<div class="wpcdpk--cells wpcdpk--cells-months"></div>' +
1682                      '</div>',
1683                  years: '' +
1684                      '<div class="wpcdpk--years wpcdpk--body">' +
1685                      '<div class="wpcdpk--cells wpcdpk--cells-years"></div>' +
1686                      '</div>',
1687                },
1688                wpcdpk = $.fn.wpcdpk,
1689                dp = wpcdpk.Constructor;
1690
1691            wpcdpk.Body = function(d, type, opts) {
1692              this.d = d;
1693              this.type = type;
1694              this.opts = opts;
1695              this.$el = $('');
1696
1697              if (this.opts.onlyTimepicker) {
1698                return;
1699              }
1700              this.init();
1701            };
1702
1703            wpcdpk.Body.prototype = {
1704              init: function() {
1705                this._buildBaseHtml();
1706                this._render();
1707
1708                this._bindEvents();
1709              },
1710
1711              _bindEvents: function() {
1712                this.$el.on('click', '.wpcdpk--cell',
1713                    $.proxy(this._onClickCell, this));
1714              },
1715
1716              _buildBaseHtml: function() {
1717                this.$el = $(templates[this.type]).appendTo(this.d.$content);
1718                this.$names = $('.wpcdpk--days-names', this.$el);
1719                this.$cells = $('.wpcdpk--cells', this.$el);
1720              },
1721
1722              _getDayNamesHtml: function(firstDay, curDay, html, i) {
1723                curDay = curDay != undefined ? curDay : firstDay;
1724                html = html ? html : '';
1725                i = i != undefined ? i : 0;
1726
1727                if (i > 7) {
1728                  return html;
1729                }
1730                if (curDay == 7) {
1731                  return this._getDayNamesHtml(firstDay, 0, html, ++i);
1732                }
1733
1734                html += '<div class="wpcdpk--day-name' + (
1735                    this.d.isWeekend(curDay) ? ' -weekend-' : ''
1736                ) + '">' + this.d.loc.daysMin[curDay] + '</div>';
1737
1738                return this._getDayNamesHtml(firstDay, ++curDay, html, ++i);
1739              },
1740
1741              _getCellContents: function(date, type) {
1742                var classes = 'wpcdpk--cell wpcdpk--cell-' + type,
1743                    currentDate = new Date(),
1744                    parent = this.d,
1745                    minRange = dp.resetTime(parent.minRange),
1746                    maxRange = dp.resetTime(parent.maxRange),
1747                    opts = parent.opts,
1748                    d = dp.getParsedDate(date),
1749                    render = {},
1750                    html = d.date;
1751
1752                switch (type) {
1753                  case 'day':
1754                    if (parent.isWeekend(d.day)) {
1755                      classes += ' -weekend-';
1756                    }
1757                    if (d.month != this.d.parsedDate.month) {
1758                      classes += ' -other-month-';
1759                      if (!opts.selectOtherMonths) {
1760                        classes += ' -disabled-';
1761                      }
1762                      if (!opts.showOtherMonths) {
1763                        html = '';
1764                      }
1765                    }
1766                    break;
1767                  case 'month':
1768                    html = parent.loc[parent.opts.monthsField][d.month];
1769                    break;
1770                  case 'year':
1771                    var decade = parent.curDecade;
1772                    html = d.year;
1773                    if (d.year < decade[0] || d.year > decade[1]) {
1774                      classes += ' -other-decade-';
1775                      if (!opts.selectOtherYears) {
1776                        classes += ' -disabled-';
1777                      }
1778                      if (!opts.showOtherYears) {
1779                        html = '';
1780                      }
1781                    }
1782                    break;
1783                }
1784
1785                if (opts.onRenderCell) {
1786                  render = opts.onRenderCell(date, type) || {};
1787                  html = render.html ? render.html : html;
1788                  classes += render.classes ? ' ' + render.classes : '';
1789                }
1790
1791                if (opts.range) {
1792                  if (dp.isSame(minRange, date, type)) {
1793                    classes += ' -range-from-';
1794                  }
1795                  if (dp.isSame(maxRange, date, type)) {
1796                    classes += ' -range-to-';
1797                  }
1798
1799                  if (parent.selectedDates.length == 1 && parent.focused) {
1800                    if (
1801                        (
1802                            dp.bigger(minRange, date) &&
1803                            dp.less(parent.focused, date)
1804                        ) ||
1805                        (
1806                            dp.less(maxRange, date) &&
1807                            dp.bigger(parent.focused, date)
1808                        )) {
1809                      classes += ' -in-range-';
1810                    }
1811
1812                    if (dp.less(maxRange, date) &&
1813                        dp.isSame(parent.focused, date)) {
1814                      classes += ' -range-from-';
1815                    }
1816                    if (dp.bigger(minRange, date) &&
1817                        dp.isSame(parent.focused, date)) {
1818                      classes += ' -range-to-';
1819                    }
1820
1821                  } else if (parent.selectedDates.length == 2) {
1822                    if (dp.bigger(minRange, date) && dp.less(maxRange, date)) {
1823                      classes += ' -in-range-';
1824                    }
1825                  }
1826                }
1827
1828                if (dp.isSame(currentDate, date, type)) {
1829                  classes += ' -current-';
1830                }
1831                if (parent.focused && dp.isSame(date, parent.focused, type)) {
1832                  classes += ' -focus-';
1833                }
1834                if (parent._isSelected(date, type)) {
1835                  classes += ' -selected-';
1836                }
1837                if (!parent._isInRange(date, type) || render.disabled) {
1838                  classes += ' -disabled-';
1839                }
1840
1841                return {
1842                  html: html,
1843                  classes: classes,
1844                };
1845              },
1846
1847              /**
1848               * Calculates days number to render. Generates days html and returns it.
1849               * @param {object} date - Date object
1850               * @returns {string}
1851               * @private
1852               */
1853              _getDaysHtml: function(date) {
1854                var totalMonthDays = dp.getDaysCount(date),
1855                    firstMonthDay = new Date(date.getFullYear(),
1856                        date.getMonth(), 1).getDay(),
1857                    lastMonthDay = new Date(date.getFullYear(), date.getMonth(),
1858                        totalMonthDays).getDay(),
1859                    daysFromPevMonth = firstMonthDay - this.d.loc.firstDay,
1860                    daysFromNextMonth = 6 - lastMonthDay + this.d.loc.firstDay;
1861
1862                daysFromPevMonth = daysFromPevMonth < 0 ?
1863                    daysFromPevMonth + 7 :
1864                    daysFromPevMonth;
1865                daysFromNextMonth = daysFromNextMonth > 6 ?
1866                    daysFromNextMonth - 7 :
1867                    daysFromNextMonth;
1868
1869                var startDayIndex = -daysFromPevMonth + 1,
1870                    m, y,
1871                    html = '';
1872
1873                for (var i = startDayIndex, max = totalMonthDays +
1874                    daysFromNextMonth; i <= max; i++) {
1875                  y = date.getFullYear();
1876                  m = date.getMonth();
1877
1878                  html += this._getDayHtml(new Date(y, m, i));
1879                }
1880
1881                return html;
1882              },
1883
1884              _getDayHtml: function(date) {
1885                var content = this._getCellContents(date, 'day');
1886
1887                return '<div class="' + content.classes + '" ' +
1888                    'data-date="' + date.getDate() + '" ' +
1889                    'data-month="' + date.getMonth() + '" ' +
1890                    'data-year="' + date.getFullYear() + '">' + content.html +
1891                    '</div>';
1892              },
1893
1894              /**
1895               * Generates months html
1896               * @param {object} date - date instance
1897               * @returns {string}
1898               * @private
1899               */
1900              _getMonthsHtml: function(date) {
1901                var html = '',
1902                    d = dp.getParsedDate(date),
1903                    i = 0;
1904
1905                while (i < 12) {
1906                  html += this._getMonthHtml(new Date(d.year, i));
1907                  i++;
1908                }
1909
1910                return html;
1911              },
1912
1913              _getMonthHtml: function(date) {
1914                var content = this._getCellContents(date, 'month');
1915
1916                return '<div class="' + content.classes + '" data-month="' +
1917                    date.getMonth() + '">' + content.html + '</div>';
1918              },
1919
1920              _getYearsHtml: function(date) {
1921                var d = dp.getParsedDate(date),
1922                    decade = dp.getDecade(date),
1923                    firstYear = decade[0] - 1,
1924                    html = '',
1925                    i = firstYear;
1926
1927                for (i; i <= decade[1] + 1; i++) {
1928                  html += this._getYearHtml(new Date(i, 0));
1929                }
1930
1931                return html;
1932              },
1933
1934              _getYearHtml: function(date) {
1935                var content = this._getCellContents(date, 'year');
1936
1937                return '<div class="' + content.classes + '" data-year="' +
1938                    date.getFullYear() + '">' + content.html + '</div>';
1939              },
1940
1941              _renderTypes: {
1942                days: function() {
1943                  var dayNames = this._getDayNamesHtml(this.d.loc.firstDay),
1944                      days = this._getDaysHtml(this.d.currentDate);
1945
1946                  this.$cells.html(days);
1947                  this.$names.html(dayNames);
1948                },
1949                months: function() {
1950                  var html = this._getMonthsHtml(this.d.currentDate);
1951
1952                  this.$cells.html(html);
1953                },
1954                years: function() {
1955                  var html = this._getYearsHtml(this.d.currentDate);
1956
1957                  this.$cells.html(html);
1958                },
1959              },
1960
1961              _render: function() {
1962                if (this.opts.onlyTimepicker) {
1963                  return;
1964                }
1965                this._renderTypes[this.type].bind(this)();
1966              },
1967
1968              _update: function() {
1969                var $cells = $('.wpcdpk--cell', this.$cells),
1970                    _this = this,
1971                    classes,
1972                    $cell,
1973                    date;
1974                $cells.each(function(cell, i) {
1975                  $cell = $(this);
1976                  date = _this.d._getDateFromCell($(this));
1977                  classes = _this._getCellContents(date, _this.d.cellType);
1978                  $cell.attr('class', classes.classes);
1979                });
1980              },
1981
1982              show: function() {
1983                if (this.opts.onlyTimepicker) {
1984                  return;
1985                }
1986                this.$el.addClass('active');
1987                this.acitve = true;
1988              },
1989
1990              hide: function() {
1991                this.$el.removeClass('active');
1992                this.active = false;
1993              },
1994
1995              //  Events
1996              // -------------------------------------------------
1997
1998              _handleClick: function(el) {
1999                var date = el.data('date') || 1,
2000                    month = el.data('month') || 0,
2001                    year = el.data('year') || this.d.parsedDate.year,
2002                    dp = this.d;
2003                // Change view if min view does not reach yet
2004                if (dp.view != this.opts.minView) {
2005                  dp.down(new Date(year, month, date));
2006                  return;
2007                }
2008                // Select date if min view is reached
2009                var selectedDate = new Date(year, month, date),
2010                    alreadySelected = this.d._isSelected(selectedDate,
2011                        this.d.cellType);
2012
2013                if (!alreadySelected) {
2014                  dp._trigger('clickCell', selectedDate);
2015                  return;
2016                }
2017
2018                dp._handleAlreadySelectedDates.bind(dp, alreadySelected,
2019                    selectedDate)();
2020
2021              },
2022
2023              _onClickCell: function(e) {
2024                var $el = $(e.target).closest('.wpcdpk--cell');
2025
2026                if ($el.hasClass('-disabled-')) {
2027                  return;
2028                }
2029
2030                this._handleClick.bind(this)($el);
2031              },
2032            };
2033          }
2034      )();
2035
2036      ;
2037      (
2038          function() {
2039            var template = '' +
2040                    '<div class="wpcdpk--nav-action" data-action="prev">#{prevHtml}</div>' +
2041                    '<div class="wpcdpk--nav-title">#{title}</div>' +
2042                    '<div class="wpcdpk--nav-action" data-action="next">#{nextHtml}</div>',
2043                buttonsContainerTemplate = '<div class="wpcdpk--buttons"></div>',
2044                button = '<span class="wpcdpk--button" data-action="#{action}">#{label}</span>',
2045                wpcdpk = $.fn.wpcdpk,
2046                dp = wpcdpk.Constructor;
2047
2048            wpcdpk.Navigation = function(d, opts) {
2049              this.d = d;
2050              this.opts = opts;
2051
2052              this.$buttonsContainer = '';
2053
2054              this.init();
2055            };
2056
2057            wpcdpk.Navigation.prototype = {
2058              init: function() {
2059                this._buildBaseHtml();
2060                this._bindEvents();
2061              },
2062
2063              _bindEvents: function() {
2064                this.d.$nav.on('click', '.wpcdpk--nav-action',
2065                    $.proxy(this._onClickNavButton, this));
2066                this.d.$nav.on('click', '.wpcdpk--nav-title',
2067                    $.proxy(this._onClickNavTitle, this));
2068                this.d.$wpcdpk.on('click', '.wpcdpk--button',
2069                    $.proxy(this._onClickNavButton, this));
2070              },
2071
2072              _buildBaseHtml: function() {
2073                if (!this.opts.onlyTimepicker) {
2074                  this._render();
2075                }
2076                this._addButtonsIfNeed();
2077              },
2078
2079              _addButtonsIfNeed: function() {
2080                if (this.opts.todayButton) {
2081                  this._addButton('today');
2082                }
2083                if (this.opts.clearButton) {
2084                  this._addButton('clear');
2085                }
2086              },
2087
2088              _render: function() {
2089                var title = this._getTitle(this.d.currentDate),
2090                    html = dp.template(template,
2091                        $.extend({title: title}, this.opts));
2092                this.d.$nav.html(html);
2093                if (this.d.view == 'years') {
2094                  $('.wpcdpk--nav-title', this.d.$nav).addClass('-disabled-');
2095                }
2096                this.setNavStatus();
2097              },
2098
2099              _getTitle: function(date) {
2100                return this.d.formatDate(this.opts.navTitles[this.d.view],
2101                    date);
2102              },
2103
2104              _addButton: function(type) {
2105                if (!this.$buttonsContainer.length) {
2106                  this._addButtonsContainer();
2107                }
2108
2109                var data = {
2110                      action: type,
2111                      label: this.d.loc[type],
2112                    },
2113                    html = dp.template(button, data);
2114
2115                if ($('[data-action=' + type + ']',
2116                    this.$buttonsContainer).length) {
2117                  return;
2118                }
2119                this.$buttonsContainer.append(html);
2120              },
2121
2122              _addButtonsContainer: function() {
2123                this.d.$wpcdpk.append(buttonsContainerTemplate);
2124                this.$buttonsContainer = $('.wpcdpk--buttons', this.d.$wpcdpk);
2125              },
2126
2127              setNavStatus: function() {
2128                if (!(
2129                    this.opts.minDate || this.opts.maxDate
2130                ) || !this.opts.disableNavWhenOutOfRange) {
2131                  return;
2132                }
2133
2134                var date = this.d.parsedDate,
2135                    m = date.month,
2136                    y = date.year,
2137                    d = date.date;
2138
2139                switch (this.d.view) {
2140                  case 'days':
2141                    if (!this.d._isInRange(new Date(y, m - 1, 1), 'month')) {
2142                      this._disableNav('prev');
2143                    }
2144                    if (!this.d._isInRange(new Date(y, m + 1, 1), 'month')) {
2145                      this._disableNav('next');
2146                    }
2147                    break;
2148                  case 'months':
2149                    if (!this.d._isInRange(new Date(y - 1, m, d), 'year')) {
2150                      this._disableNav('prev');
2151                    }
2152                    if (!this.d._isInRange(new Date(y + 1, m, d), 'year')) {
2153                      this._disableNav('next');
2154                    }
2155                    break;
2156                  case 'years':
2157                    var decade = dp.getDecade(this.d.date);
2158                    if (!this.d._isInRange(new Date(decade[0] - 1, 0, 1),
2159                        'year')) {
2160                      this._disableNav('prev');
2161                    }
2162                    if (!this.d._isInRange(new Date(decade[1] + 1, 0, 1),
2163                        'year')) {
2164                      this._disableNav('next');
2165                    }
2166                    break;
2167                }
2168              },
2169
2170              _disableNav: function(nav) {
2171                $('[data-action="' + nav + '"]', this.d.$nav).
2172                    addClass('-disabled-');
2173              },
2174
2175              _activateNav: function(nav) {
2176                $('[data-action="' + nav + '"]', this.d.$nav).
2177                    removeClass('-disabled-');
2178              },
2179
2180              _onClickNavButton: function(e) {
2181                var $el = $(e.target).closest('[data-action]'),
2182                    action = $el.data('action');
2183
2184                this.d[action]();
2185              },
2186
2187              _onClickNavTitle: function(e) {
2188                if ($(e.target).hasClass('-disabled-')) {
2189                  return;
2190                }
2191
2192                if (this.d.view == 'days') {
2193                  return this.d.view = 'months';
2194                }
2195
2196                this.d.view = 'years';
2197              },
2198            };
2199
2200          }
2201      )();
2202
2203      ;
2204      (
2205          function() {
2206            var template = '<div class="wpcdpk--time">' +
2207                    '<div class="wpcdpk--time-current">' +
2208                    '   <span class="wpcdpk--time-current-hours">#{hourVisible}</span>' +
2209                    '   <span class="wpcdpk--time-current-colon">:</span>' +
2210                    '   <span class="wpcdpk--time-current-minutes">#{minValue}</span>' +
2211                    '</div>' +
2212                    '<div class="wpcdpk--time-sliders">' +
2213                    '   <div class="wpcdpk--time-row">' +
2214                    '      <input type="range" name="hours" value="#{hourValue}" min="#{hourMin}" max="#{hourMax}" step="#{hourStep}"/>' +
2215                    '   </div>' +
2216                    '   <div class="wpcdpk--time-row">' +
2217                    '      <input type="range" name="minutes" value="#{minValue}" min="#{minMin}" max="#{minMax}" step="#{minStep}"/>' +
2218                    '   </div>' +
2219                    '</div>' +
2220                    '</div>',
2221                wpcdpk = $.fn.wpcdpk,
2222                dp = wpcdpk.Constructor;
2223
2224            wpcdpk.Timepicker = function(inst, opts) {
2225              this.d = inst;
2226              this.opts = opts;
2227
2228              this.init();
2229            };
2230
2231            wpcdpk.Timepicker.prototype = {
2232              init: function() {
2233                var input = 'input';
2234                this._setTime(this.d.date);
2235                this._buildHTML();
2236
2237                if (navigator.userAgent.match(/trident/gi)) {
2238                  input = 'change';
2239                }
2240
2241                this.d.$el.on('selectDate', this._onSelectDate.bind(this));
2242                this.$ranges.on(input, this._onChangeRange.bind(this));
2243                this.$ranges.on('mouseup', this._onMouseUpRange.bind(this));
2244                this.$ranges.on('mousemove focus ',
2245                    this._onMouseEnterRange.bind(this));
2246                this.$ranges.on('mouseout blur',
2247                    this._onMouseOutRange.bind(this));
2248              },
2249
2250              _setTime: function(date) {
2251                var _date = dp.getParsedDate(date);
2252
2253                this._handleDate(date);
2254                this.hours = _date.hours < this.minHours ?
2255                    this.minHours :
2256                    _date.hours;
2257                this.minutes = _date.minutes < this.minMinutes ?
2258                    this.minMinutes :
2259                    _date.minutes;
2260              },
2261
2262              /**
2263               * Sets minHours and minMinutes from date (usually it's a minDate)
2264               * Also changes minMinutes if current hours are bigger then @date hours
2265               * @param date {Date}
2266               * @private
2267               */
2268              _setMinTimeFromDate: function(date) {
2269                this.minHours = date.getHours();
2270                this.minMinutes = date.getMinutes();
2271
2272                // If, for example, min hours are 10, and current hours are 12,
2273                // update minMinutes to default value, to be able to choose whole range of values
2274                if (this.d.lastSelectedDate) {
2275                  if (this.d.lastSelectedDate.getHours() > date.getHours()) {
2276                    this.minMinutes = this.opts.minMinutes;
2277                  }
2278                }
2279              },
2280
2281              _setMaxTimeFromDate: function(date) {
2282                this.maxHours = date.getHours();
2283                this.maxMinutes = date.getMinutes();
2284
2285                if (this.d.lastSelectedDate) {
2286                  if (this.d.lastSelectedDate.getHours() < date.getHours()) {
2287                    this.maxMinutes = this.opts.maxMinutes;
2288                  }
2289                }
2290              },
2291
2292              _setDefaultMinMaxTime: function() {
2293                var maxHours = 23,
2294                    maxMinutes = 59,
2295                    opts = this.opts;
2296
2297                this.minHours = opts.minHours < 0 || opts.minHours > maxHours ?
2298                    0 :
2299                    opts.minHours;
2300                this.minMinutes = opts.minMinutes < 0 || opts.minMinutes >
2301                maxMinutes ? 0 : opts.minMinutes;
2302                this.maxHours = opts.maxHours < 0 || opts.maxHours > maxHours ?
2303                    maxHours :
2304                    opts.maxHours;
2305                this.maxMinutes = opts.maxMinutes < 0 || opts.maxMinutes >
2306                maxMinutes ? maxMinutes : opts.maxMinutes;
2307              },
2308
2309              /**
2310               * Looks for min/max hours/minutes and if current values
2311               * are out of range sets valid values.
2312               * @private
2313               */
2314              _validateHoursMinutes: function(date) {
2315                if (this.hours < this.minHours) {
2316                  this.hours = this.minHours;
2317                } else if (this.hours > this.maxHours) {
2318                  this.hours = this.maxHours;
2319                }
2320
2321                if (this.minutes < this.minMinutes) {
2322                  this.minutes = this.minMinutes;
2323                } else if (this.minutes > this.maxMinutes) {
2324                  this.minutes = this.maxMinutes;
2325                }
2326              },
2327
2328              _buildHTML: function() {
2329                var lz = dp.getLeadingZeroNum,
2330                    data = {
2331                      hourMin: this.minHours,
2332                      hourMax: lz(this.maxHours),
2333                      hourStep: this.opts.hoursStep,
2334                      hourValue: this.hours,
2335                      hourVisible: lz(this.displayHours),
2336                      minMin: this.minMinutes,
2337                      minMax: lz(this.maxMinutes),
2338                      minStep: this.opts.minutesStep,
2339                      minValue: lz(this.minutes),
2340                    },
2341                    _template = dp.template(template, data);
2342
2343                this.$timepicker = $(_template).appendTo(this.d.$wpcdpk);
2344                this.$ranges = $('[type="range"]', this.$timepicker);
2345                this.$hours = $('[name="hours"]', this.$timepicker);
2346                this.$minutes = $('[name="minutes"]', this.$timepicker);
2347                this.$hoursText = $('.wpcdpk--time-current-hours',
2348                    this.$timepicker);
2349                this.$minutesText = $('.wpcdpk--time-current-minutes',
2350                    this.$timepicker);
2351
2352                if (this.d.ampm) {
2353                  this.$ampm = $('<span class="wpcdpk--time-current-ampm">').
2354                      appendTo($('.wpcdpk--time-current', this.$timepicker)).
2355                      html(this.dayPeriod);
2356
2357                  this.$timepicker.addClass('-am-pm-');
2358                }
2359              },
2360
2361              _updateCurrentTime: function() {
2362                var h = dp.getLeadingZeroNum(this.displayHours),
2363                    m = dp.getLeadingZeroNum(this.minutes);
2364
2365                this.$hoursText.html(h);
2366                this.$minutesText.html(m);
2367
2368                if (this.d.ampm) {
2369                  this.$ampm.html(this.dayPeriod);
2370                }
2371              },
2372
2373              _updateRanges: function() {
2374                this.$hours.attr({
2375                  min: this.minHours,
2376                  max: this.maxHours,
2377                }).val(this.hours);
2378
2379                this.$minutes.attr({
2380                  min: this.minMinutes,
2381                  max: this.maxMinutes,
2382                }).val(this.minutes);
2383              },
2384
2385              /**
2386               * Sets minHours, minMinutes etc. from date. If date is not passed, than sets
2387               * values from options
2388               * @param [date] {object} - Date object, to get values from
2389               * @private
2390               */
2391              _handleDate: function(date) {
2392                this._setDefaultMinMaxTime();
2393                if (date) {
2394                  if (dp.isSame(date, this.d.opts.minDate)) {
2395                    this._setMinTimeFromDate(this.d.opts.minDate);
2396                  } else if (dp.isSame(date, this.d.opts.maxDate)) {
2397                    this._setMaxTimeFromDate(this.d.opts.maxDate);
2398                  }
2399                }
2400
2401                this._validateHoursMinutes(date);
2402              },
2403
2404              update: function() {
2405                this._updateRanges();
2406                this._updateCurrentTime();
2407              },
2408
2409              /**
2410               * Calculates valid hour value to display in text input and wpcdpk's body.
2411               * @param date {Date|Number} - date or hours
2412               * @param [ampm] {Boolean} - 12 hours mode
2413               * @returns {{hours: *, dayPeriod: string}}
2414               * @private
2415               */
2416              _getValidHoursFromDate: function(date, ampm) {
2417                var d = date,
2418                    hours = date;
2419
2420                if (date instanceof Date) {
2421                  d = dp.getParsedDate(date);
2422                  hours = d.hours;
2423                }
2424
2425                var _ampm = ampm || this.d.ampm,
2426                    dayPeriod = 'am';
2427
2428                if (_ampm) {
2429                  switch (true) {
2430                    case hours == 0:
2431                      hours = 12;
2432                      break;
2433                    case hours == 12:
2434                      dayPeriod = 'pm';
2435                      break;
2436                    case hours > 11:
2437                      hours = hours - 12;
2438                      dayPeriod = 'pm';
2439                      break;
2440                    default:
2441                      break;
2442                  }
2443                }
2444
2445                return {
2446                  hours: hours,
2447                  dayPeriod: dayPeriod,
2448                };
2449              },
2450
2451              set hours(val) {
2452                this._hours = val;
2453
2454                var displayHours = this._getValidHoursFromDate(val);
2455
2456                this.displayHours = displayHours.hours;
2457                this.dayPeriod = displayHours.dayPeriod;
2458              },
2459
2460              get hours() {
2461                return this._hours;
2462              },
2463
2464              //  Events
2465              // -------------------------------------------------
2466
2467              _onChangeRange: function(e) {
2468                var $target = $(e.target),
2469                    name = $target.attr('name');
2470
2471                this.d.timepickerIsActive = true;
2472
2473                this[name] = $target.val();
2474                this._updateCurrentTime();
2475                this.d._trigger('timeChange', [this.hours, this.minutes]);
2476
2477                this._handleDate(this.d.lastSelectedDate);
2478                this.update();
2479              },
2480
2481              _onSelectDate: function(e, data) {
2482                this._handleDate(data);
2483                this.update();
2484              },
2485
2486              _onMouseEnterRange: function(e) {
2487                var name = $(e.target).attr('name');
2488                $('.wpcdpk--time-current-' + name, this.$timepicker).
2489                    addClass('-focus-');
2490              },
2491
2492              _onMouseOutRange: function(e) {
2493                var name = $(e.target).attr('name');
2494                if (this.d.inFocus) {
2495                  return;
2496                } // Prevent removing focus when mouse out of range slider
2497                $('.wpcdpk--time-current-' + name, this.$timepicker).
2498                    removeClass('-focus-');
2499              },
2500
2501              _onMouseUpRange: function(e) {
2502                this.d.timepickerIsActive = false;
2503              },
2504            };
2505          }
2506      )();
2507    }
2508)(window, jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.