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.