vendor: 29,274 bytes, lines 1-918
1/*! 2 * Pikaday 3 * 4 * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday 5 */ 6 7(function (root, factory) 8{ 9 'use strict'; 10 11 var moment; 12 if (typeof exports === 'object') { 13 // CommonJS module 14 // Load moment.js as an optional dependency 15 try { moment = require('moment'); } catch (e) {} 16 module.exports = factory(moment); 17 } else if (typeof define === 'function' && define.amd) { 18 // AMD. Register as an anonymous module. 19 define(function (req) 20 { 21 // Load moment.js as an optional dependency 22 var id = 'moment'; 23 try { moment = req(id); } catch (e) {} 24 return factory(moment); 25 }); 26 } else { 27 root.Pikaday = factory(root.moment); 28 } 29}(this, function (moment) 30{ 31 'use strict'; 32 33 /** 34 * feature detection and helper functions 35 */ 36 var hasMoment = typeof moment === 'function', 37 38 hasEventListeners = !!window.addEventListener, 39 40 document = window.document, 41 42 sto = window.setTimeout, 43 44 addEvent = function(el, e, callback, capture) 45 { 46 if (hasEventListeners) { 47 el.addEventListener(e, callback, !!capture); 48 } else { 49 el.attachEvent('on' + e, callback); 50 } 51 }, 52 53 removeEvent = function(el, e, callback, capture) 54 { 55 if (hasEventListeners) { 56 el.removeEventListener(e, callback, !!capture); 57 } else { 58 el.detachEvent('on' + e, callback); 59 } 60 }, 61 62 fireEvent = function(el, eventName, data) 63 { 64 var ev; 65 66 if (document.createEvent) { 67 ev = document.createEvent('HTMLEvents'); 68 ev.initEvent(eventName, true, false); 69 ev = extend(ev, data); 70 el.dispatchEvent(ev); 71 } else if (document.createEventObject) { 72 ev = document.createEventObject(); 73 ev = extend(ev, data); 74 el.fireEvent('on' + eventName, ev); 75 } 76 }, 77 78 trim = function(str) 79 { 80 return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,''); 81 }, 82 83 hasClass = function(el, cn) 84 { 85 return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1; 86 }, 87 88 addClass = function(el, cn) 89 { 90 if (!hasClass(el, cn)) { 91 el.className = (el.className === '') ? cn : el.className + ' ' + cn; 92 } 93 }, 94 95 removeClass = function(el, cn) 96 { 97 el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' ')); 98 }, 99 100 isArray = function(obj) 101 { 102 return (/Array/).test(Object.prototype.toString.call(obj)); 103 }, 104 105 isDate = function(obj) 106 { 107 return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime()); 108 }, 109 110 isWeekend = function(date) 111 { 112 var day = date.getDay(); 113 return day === 0 || day === 6; 114 }, 115 116 isLeapYear = function(year) 117 { 118 // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951 119 return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; 120 }, 121 122 getDaysInMonth = function(year, month) 123 { 124 return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; 125 }, 126 127 setToStartOfDay = function(date) 128 { 129 if (isDate(date)) date.setHours(0,0,0,0); 130 }, 131 132 compareDates = function(a,b) 133 { 134 // weak date comparison (use setToStartOfDay(date) to ensure correct result) 135 return a.getTime() === b.getTime(); 136 }, 137 138 extend = function(to, from, overwrite) 139 { 140 var prop, hasProp; 141 for (prop in from) { 142 hasProp = to[prop] !== undefined; 143 if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) { 144 if (isDate(from[prop])) { 145 if (overwrite) { 146 to[prop] = new Date(from[prop].getTime()); 147 } 148 } 149 else if (isArray(from[prop])) { 150 if (overwrite) { 151 to[prop] = from[prop].slice(0); 152 } 153 } else { 154 to[prop] = extend({}, from[prop], overwrite); 155 } 156 } else if (overwrite || !hasProp) { 157 to[prop] = from[prop]; 158 } 159 } 160 return to; 161 }, 162 163 adjustCalendar = function(calendar) { 164 if (calendar.month < 0) { 165 calendar.year -= Math.ceil(Math.abs(calendar.month)/12); 166 calendar.month += 12; 167 } 168 if (calendar.month > 11) { 169 calendar.year += Math.floor(Math.abs(calendar.month)/12); 170 calendar.month -= 12; 171 } 172 return calendar; 173 }, 174 175 /** 176 * defaults and localisation 177 */ 178 defaults = { 179 180 // bind the picker to a form field 181 field: null, 182 183 // automatically show/hide the picker on `field` focus (default `true` if `field` is set) 184 bound: undefined, 185 186 // position of the datepicker, relative to the field (default to bottom & left) 187 // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position) 188 position: 'bottom left', 189 190 // automatically fit in the viewport even if it means repositioning from the position option 191 reposition: true, 192 193 // the default output format for `.toString()` and `field` value 194 format: 'YYYY-MM-DD', 195 196 // the initial date to view when first opened 197 defaultDate: null, 198 199 // make the `defaultDate` the initial selected value 200 setDefaultDate: false, 201 202 // first day of week (0: Sunday, 1: Monday etc) 203 firstDay: 0, 204 205 // the minimum/earliest date that can be selected 206 minDate: null, 207 // the maximum/latest date that can be selected 208 maxDate: null, 209 210 // number of years either side, or array of upper/lower range 211 yearRange: 10, 212 213 // show week numbers at head of row 214 showWeekNumber: false, 215 216 // used internally (don't config outside) 217 minYear: 0, 218 maxYear: 9999, 219 minMonth: undefined, 220 maxMonth: undefined, 221 222 startRange: null, 223 endRange: null, 224 225 isRTL: false, 226 227 // Additional text to append to the year in the calendar title 228 yearSuffix: '', 229 230 // Render the month after year in the calendar title 231 showMonthAfterYear: false, 232 233 // how many months are visible 234 numberOfMonths: 1, 235 236 // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`) 237 // only used for the first display or when a selected date is not visible 238 mainCalendar: 'left', 239 240 // Specify a DOM element to render the calendar in 241 container: undefined, 242 243 // internationalization 244 i18n: { 245 previousMonth : 'Previous Month', 246 nextMonth : 'Next Month', 247 months : ['January','February','March','April','May','June','July','August','September','October','November','December'], 248 weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], 249 weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'] 250 }, 251 252 // Theme Classname 253 theme: null, 254 255 // callback function 256 onSelect: null, 257 onOpen: null, 258 onClose: null, 259 onDraw: null 260 }, 261 262 263 /** 264 * templating functions to abstract HTML rendering 265 */ 266 renderDayName = function(opts, day, abbr) 267 { 268 day += opts.firstDay; 269 while (day >= 7) { 270 day -= 7; 271 } 272 return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day]; 273 }, 274 275 renderDay = function(opts) 276 { 277 if (opts.isEmpty) { 278 return '<td class="is-empty"></td>'; 279 } 280 var arr = []; 281 if (opts.isDisabled) { 282 arr.push('is-disabled'); 283 } 284 if (opts.isToday) { 285 arr.push('is-today'); 286 } 287 if (opts.isSelected) { 288 arr.push('is-selected'); 289 } 290 if (opts.isInRange) { 291 arr.push('is-inrange'); 292 } 293 if (opts.isStartRange) { 294 arr.push('is-startrange'); 295 } 296 if (opts.isEndRange) { 297 arr.push('is-endrange'); 298 } 299 return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '">' + 300 '<button class="pika-button pika-day" type="button" ' + 301 'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' + 302 opts.day + 303 '</button>' + 304 '</td>'; 305 }, 306 307 renderWeek = function (d, m, y) { 308 // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified. 309 var onejan = new Date(y, 0, 1), 310 weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7); 311 return '<td class="pika-week">' + weekNum + '</td>'; 312 }, 313 314 renderRow = function(days, isRTL) 315 { 316 return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>'; 317 }, 318 319 renderBody = function(rows) 320 { 321 return '<tbody>' + rows.join('') + '</tbody>'; 322 }, 323 324 renderHead = function(opts) 325 { 326 var i, arr = []; 327 if (opts.showWeekNumber) { 328 arr.push('<th></th>'); 329 } 330 for (i = 0; i < 7; i++) { 331 arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>'); 332 } 333 return '<thead>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</thead>'; 334 }, 335 336 renderTitle = function(instance, c, year, month, refYear) 337 { 338 var i, j, arr, 339 opts = instance._o, 340 isMinYear = year === opts.minYear, 341 isMaxYear = year === opts.maxYear, 342 html = '<div class="pika-title">', 343 monthHtml, 344 yearHtml, 345 prev = true, 346 next = true; 347 348 for (arr = [], i = 0; i < 12; i++) { 349 arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' + 350 (i === month ? ' selected': '') + 351 ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled' : '') + '>' + 352 opts.i18n.months[i] + '</option>'); 353 } 354 monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>'; 355 356 if (isArray(opts.yearRange)) { 357 i = opts.yearRange[0]; 358 j = opts.yearRange[1] + 1; 359 } else { 360 i = year - opts.yearRange; 361 j = 1 + year + opts.yearRange; 362 } 363 364 for (arr = []; i < j && i <= opts.maxYear; i++) { 365 if (i >= opts.minYear) { 366 arr.push('<option value="' + i + '"' + (i === year ? ' selected': '') + '>' + (i) + '</option>'); 367 } 368 } 369 yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>'; 370 371 if (opts.showMonthAfterYear) { 372 html += yearHtml + monthHtml; 373 } else { 374 html += monthHtml + yearHtml; 375 } 376 377 if (isMinYear && (month === 0 || opts.minMonth >= month)) { 378 prev = false; 379 } 380 381 if (isMaxYear && (month === 11 || opts.maxMonth <= month)) { 382 next = false; 383 } 384 385 if (c === 0) { 386 html += '<button class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>'; 387 } 388 if (c === (instance._o.numberOfMonths - 1) ) { 389 html += '<button class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>'; 390 } 391 392 return html += '</div>'; 393 }, 394 395 renderTable = function(opts, data) 396 { 397 return '<table cellpadding="0" cellspacing="0" class="pika-table">' + renderHead(opts) + renderBody(data) + '</table>'; 398 }, 399 400 401 /** 402 * Pikaday constructor 403 */ 404 Pikaday = function(options) 405 { 406 var self = this, 407 opts = self.config(options); 408 409 self._onMouseDown = function(e) 410 { 411 if (!self._v) { 412 return; 413 } 414 e = e || window.event; 415 var target = e.target || e.srcElement; 416 if (!target) { 417 return; 418 } 419 420 if (!hasClass(target, 'is-disabled')) { 421 if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) { 422 self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day'))); 423 if (opts.bound) { 424 sto(function() { 425 self.hide(); 426 if (opts.field) { 427 opts.field.blur(); 428 } 429 }, 100); 430 } 431 } 432 else if (hasClass(target, 'pika-prev')) { 433 self.prevMonth(); 434 } 435 else if (hasClass(target, 'pika-next')) { 436 self.nextMonth(); 437 } 438 } 439 if (!hasClass(target, 'pika-select')) { 440 // if this is touch event prevent mouse events emulation 441 if (e.preventDefault) { 442 e.preventDefault(); 443 } else { 444 e.returnValue = false; 445 return false; 446 } 447 } else { 448 self._c = true; 449 } 450 }; 451 452 self._onChange = function(e) 453 { 454 e = e || window.event; 455 var target = e.target || e.srcElement; 456 if (!target) { 457 return; 458 } 459 if (hasClass(target, 'pika-select-month')) { 460 self.gotoMonth(target.value); 461 } 462 else if (hasClass(target, 'pika-select-year')) { 463 self.gotoYear(target.value); 464 } 465 }; 466 467 self._onInputChange = function(e) 468 { 469 var date; 470 471 if (e.firedBy === self) { 472 return; 473 } 474 if (hasMoment) { 475 date = moment(opts.field.value, opts.format); 476 date = (date && date.isValid()) ? date.toDate() : null; 477 } 478 else { 479 date = new Date(Date.parse(opts.field.value)); 480 } 481 if (isDate(date)) { 482 self.setDate(date); 483 } 484 if (!self._v) { 485 self.show(); 486 } 487 }; 488 489 self._onInputFocus = function() 490 { 491 self.show(); 492 }; 493 494 self._onInputClick = function() 495 { 496 self.show(); 497 }; 498 499 self._onInputBlur = function() 500 { 501 // IE allows pika div to gain focus; catch blur the input field 502 var pEl = document.activeElement; 503 do { 504 if (hasClass(pEl, 'pika-single')) { 505 return; 506 } 507 } 508 while ((pEl = pEl.parentNode)); 509 510 if (!self._c) { 511 self._b = sto(function() { 512 self.hide(); 513 }, 50); 514 } 515 self._c = false; 516 }; 517 518 self._onClick = function(e) 519 { 520 e = e || window.event; 521 var target = e.target || e.srcElement, 522 pEl = target; 523 if (!target) { 524 return; 525 } 526 if (!hasEventListeners && hasClass(target, 'pika-select')) { 527 if (!target.onchange) { 528 target.setAttribute('onchange', 'return;'); 529 addEvent(target, 'change', self._onChange); 530 } 531 } 532 do { 533 if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) { 534 return; 535 } 536 } 537 while ((pEl = pEl.parentNode)); 538 if (self._v && target !== opts.trigger && pEl !== opts.trigger) { 539 self.hide(); 540 } 541 }; 542 543 self.el = document.createElement('div'); 544 self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : ''); 545 546 addEvent(self.el, 'mousedown', self._onMouseDown, true); 547 addEvent(self.el, 'touchend', self._onMouseDown, true); 548 addEvent(self.el, 'change', self._onChange); 549 550 if (opts.field) { 551 if (opts.container) { 552 opts.container.appendChild(self.el); 553 } else if (opts.bound) { 554 document.body.appendChild(self.el); 555 } else { 556 opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling); 557 } 558 addEvent(opts.field, 'change', self._onInputChange); 559 560 if (!opts.defaultDate) { 561 if (hasMoment && opts.field.value) { 562 opts.defaultDate = moment(opts.field.value, opts.format).toDate(); 563 } else { 564 opts.defaultDate = new Date(Date.parse(opts.field.value)); 565 } 566 opts.setDefaultDate = true; 567 } 568 } 569 570 var defDate = opts.defaultDate; 571 572 if (isDate(defDate)) { 573 if (opts.setDefaultDate) { 574 self.setDate(defDate, true); 575 } else { 576 self.gotoDate(defDate); 577 } 578 } else { 579 self.gotoDate(new Date()); 580 } 581 582 if (opts.bound) { 583 this.hide(); 584 self.el.className += ' is-bound'; 585 addEvent(opts.trigger, 'click', self._onInputClick); 586 addEvent(opts.trigger, 'focus', self._onInputFocus); 587 addEvent(opts.trigger, 'blur', self._onInputBlur); 588 } else { 589 this.show(); 590 } 591 }; 592 593 594 /** 595 * public Pikaday API 596 */ 597 Pikaday.prototype = { 598 599 600 /** 601 * configure functionality 602 */ 603 config: function(options) 604 { 605 if (!this._o) { 606 this._o = extend({}, defaults, true); 607 } 608 609 var opts = extend(this._o, options, true); 610 611 opts.isRTL = !!opts.isRTL; 612 613 opts.field = (opts.field && opts.field.nodeName) ? opts.field : null; 614 615 opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null; 616 617 opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field); 618 619 opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field; 620 621 opts.disableWeekends = !!opts.disableWeekends; 622 623 opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null; 624 625 var nom = parseInt(opts.numberOfMonths, 10) || 1; 626 opts.numberOfMonths = nom > 4 ? 4 : nom; 627 628 if (!isDate(opts.minDate)) { 629 opts.minDate = false; 630 } 631 if (!isDate(opts.maxDate)) { 632 opts.maxDate = false; 633 } 634 if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) { 635 opts.maxDate = opts.minDate = false; 636 } 637 if (opts.minDate) { 638 this.setMinDate(opts.minDate); 639 } 640 if (opts.maxDate) { 641 this.setMaxDate(opts.maxDate); 642 } 643 644 if (isArray(opts.yearRange)) { 645 var fallback = new Date().getFullYear() - 10; 646 opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback; 647 opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback; 648 } else { 649 opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange; 650 if (opts.yearRange > 100) { 651 opts.yearRange = 100; 652 } 653 } 654 655 return opts; 656 }, 657 658 /** 659 * return a formatted string of the current selection (using Moment.js if available) 660 */ 661 toString: function(format) 662 { 663 return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString(); 664 }, 665 666 /** 667 * return a Moment.js object of the current selection (if available) 668 */ 669 getMoment: function() 670 { 671 return hasMoment ? moment(this._d) : null; 672 }, 673 674 /** 675 * set the current selection from a Moment.js object (if available) 676 */ 677 setMoment: function(date, preventOnSelect) 678 { 679 if (hasMoment && moment.isMoment(date)) { 680 this.setDate(date.toDate(), preventOnSelect); 681 } 682 }, 683 684 /** 685 * return a Date object of the current selection 686 */ 687 getDate: function() 688 { 689 return isDate(this._d) ? new Date(this._d.getTime()) : null; 690 }, 691 692 /** 693 * set the current selection 694 */ 695 setDate: function(date, preventOnSelect) 696 { 697 if (!date) { 698 this._d = null; 699 700 if (this._o.field) { 701 this._o.field.value = ''; 702 fireEvent(this._o.field, 'change', { firedBy: this }); 703 } 704 705 return this.draw(); 706 } 707 if (typeof date === 'string') { 708 date = new Date(Date.parse(date)); 709 } 710 if (!isDate(date)) { 711 return; 712 } 713 714 var min = this._o.minDate, 715 max = this._o.maxDate; 716 717 if (isDate(min) && date < min) { 718 date = min; 719 } else if (isDate(max) && date > max) { 720 date = max; 721 } 722 723 this._d = new Date(date.getTime()); 724 setToStartOfDay(this._d); 725 this.gotoDate(this._d); 726 727 if (this._o.field) { 728 this._o.field.value = this.toString(); 729 fireEvent(this._o.field, 'change', { firedBy: this }); 730 } 731 if (!preventOnSelect && typeof this._o.onSelect === 'function') { 732 this._o.onSelect.call(this, this.getDate()); 733 } 734 }, 735 736 /** 737 * change view to a specific date 738 */ 739 gotoDate: function(date) 740 { 741 var newCalendar = true; 742 743 if (!isDate(date)) { 744 return; 745 } 746 747 if (this.calendars) { 748 var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1), 749 lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1), 750 visibleDate = date.getTime(); 751 // get the end of the month 752 lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1); 753 lastVisibleDate.setDate(lastVisibleDate.getDate()-1); 754 newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate); 755 } 756 757 if (newCalendar) { 758 this.calendars = [{ 759 month: date.getMonth(), 760 year: date.getFullYear() 761 }]; 762 if (this._o.mainCalendar === 'right') { 763 this.calendars[0].month += 1 - this._o.numberOfMonths; 764 } 765 } 766 767 this.adjustCalendars(); 768 }, 769 770 adjustCalendars: function() { 771 this.calendars[0] = adjustCalendar(this.calendars[0]); 772 for (var c = 1; c < this._o.numberOfMonths; c++) { 773 this.calendars[c] = adjustCalendar({ 774 month: this.calendars[0].month + c, 775 year: this.calendars[0].year 776 }); 777 } 778 this.draw(); 779 }, 780 781 gotoToday: function() 782 { 783 this.gotoDate(new Date()); 784 }, 785 786 /** 787 * change view to a specific month (zero-index, e.g. 0: January) 788 */ 789 gotoMonth: function(month) 790 { 791 if (!isNaN(month)) { 792 this.calendars[0].month = parseInt(month, 10); 793 this.adjustCalendars(); 794 } 795 }, 796 797 nextMonth: function() 798 { 799 this.calendars[0].month++; 800 this.adjustCalendars(); 801 }, 802 803 prevMonth: function() 804 { 805 this.calendars[0].month--; 806 this.adjustCalendars(); 807 }, 808 809 /** 810 * change view to a specific full year (e.g. "2012") 811 */ 812 gotoYear: function(year) 813 { 814 if (!isNaN(year)) { 815 this.calendars[0].year = parseInt(year, 10); 816 this.adjustCalendars(); 817 } 818 }, 819 820 /** 821 * change the minDate 822 */ 823 setMinDate: function(value) 824 { 825 setToStartOfDay(value); 826 this._o.minDate = value; 827 this._o.minYear = value.getFullYear(); 828 this._o.minMonth = value.getMonth(); 829 this.draw(); 830 }, 831 832 /** 833 * change the maxDate 834 */ 835 setMaxDate: function(value) 836 { 837 setToStartOfDay(value); 838 this._o.maxDate = value; 839 this._o.maxYear = value.getFullYear(); 840 this._o.maxMonth = value.getMonth(); 841 this.draw(); 842 }, 843 844 setStartRange: function(value) 845 { 846 this._o.startRange = value; 847 }, 848 849 setEndRange: function(value) 850 { 851 this._o.endRange = value; 852 }, 853 854 /** 855 * refresh the HTML 856 */ 857 draw: function(force) 858 { 859 if (!this._v && !force) { 860 return; 861 } 862 var opts = this._o, 863 minYear = opts.minYear, 864 maxYear = opts.maxYear, 865 minMonth = opts.minMonth, 866 maxMonth = opts.maxMonth, 867 html = ''; 868 869 if (this._y <= minYear) { 870 this._y = minYear; 871 if (!isNaN(minMonth) && this._m < minMonth) { 872 this._m = minMonth; 873 } 874 } 875 if (this._y >= maxYear) { 876 this._y = maxYear; 877 if (!isNaN(maxMonth) && this._m > maxMonth) { 878 this._m = maxMonth; 879 } 880 } 881 882 for (var c = 0; c < opts.numberOfMonths; c++) { 883 html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year) + this.render(this.calendars[c].year, this.calendars[c].month) + '</div>'; 884 } 885 886 this.el.innerHTML = html; 887 888 if (opts.bound) { 889 if(opts.field.type !== 'hidden') { 890 sto(function() { 891 opts.trigger.focus(); 892 }, 1); 893 } 894 } 895 896 if (typeof this._o.onDraw === 'function') { 897 var self = this; 898 sto(function() { 899 self._o.onDraw.call(self); 900 }, 0); 901 } 902 }, 903 904 adjustPosition: function() 905 { 906 var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect; 907 908 if (this._o.container) return; 909 910 this.el.style.position = 'absolute'; 911 912 field = this._o.trigger; 913 pEl = field; 914 width = this.el.offsetWidth; 915 height = this.el.offsetHeight; 916 viewportWidth = window.innerWidth || document.documentElement.clientWidth; 917 viewportHeight = window.innerHeight || document.documentElement.clientHeight; 918 scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
vendor: 6,311 bytes, lines 919-1086
919 920 var navHeight = document.getElementById('header').offsetHeight; // added fix 921 922 if (typeof field.getBoundingClientRect === 'function') { 923 clientRect = field.getBoundingClientRect(); 924 left = clientRect.left + window.pageXOffset; 925 top = clientRect.bottom + window.pageYOffset - navHeight; // added fix 926 } else { 927 left = pEl.offsetLeft; 928 top = pEl.offsetTop + pEl.offsetHeight - navHeight; // added fix 929 while((pEl = pEl.offsetParent)) { 930 left += pEl.offsetLeft; 931 top += pEl.offsetTop; 932 } 933 } 934 935 // default position is bottom & left 936 if ((this._o.reposition && left + width > viewportWidth) || 937 ( 938 this._o.position.indexOf('right') > -1 && 939 left - width + field.offsetWidth > 0 940 ) 941 ) { 942 left = left - width + field.offsetWidth; 943 } 944 if ((this._o.reposition && top + height > viewportHeight + scrollTop) || 945 ( 946 this._o.position.indexOf('top') > -1 && 947 top - height - field.offsetHeight > 0 948 ) 949 ) { 950 top = top - height - field.offsetHeight; 951 } 952 953 this.el.style.left = left + 'px'; 954 this.el.style.top = top + 'px'; 955 }, 956 957 /** 958 * render HTML for a particular month 959 */ 960 render: function(year, month) 961 { 962 var opts = this._o, 963 now = new Date(), 964 days = getDaysInMonth(year, month), 965 before = new Date(year, month, 1).getDay(), 966 data = [], 967 row = []; 968 setToStartOfDay(now); 969 if (opts.firstDay > 0) { 970 before -= opts.firstDay; 971 if (before < 0) { 972 before += 7; 973 } 974 } 975 var cells = days + before, 976 after = cells; 977 while(after > 7) { 978 after -= 7; 979 } 980 cells += 7 - after; 981 for (var i = 0, r = 0; i < cells; i++) 982 { 983 var day = new Date(year, month, 1 + (i - before)), 984 isSelected = isDate(this._d) ? compareDates(day, this._d) : false, 985 isToday = compareDates(day, now), 986 isEmpty = i < before || i >= (days + before), 987 isStartRange = opts.startRange && compareDates(opts.startRange, day), 988 isEndRange = opts.endRange && compareDates(opts.endRange, day), 989 isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange, 990 isDisabled = (opts.minDate && day < opts.minDate) || 991 (opts.maxDate && day > opts.maxDate) || 992 (opts.disableWeekends && isWeekend(day)) || 993 (opts.disableDayFn && opts.disableDayFn(day)), 994 dayConfig = { 995 day: 1 + (i - before), 996 month: month, 997 year: year, 998 isSelected: isSelected, 999 isToday: isToday, 1000 isDisabled: isDisabled, 1001 isEmpty: isEmpty, 1002 isStartRange: isStartRange, 1003 isEndRange: isEndRange, 1004 isInRange: isInRange 1005 }; 1006 1007 row.push(renderDay(dayConfig)); 1008 1009 if (++r === 7) { 1010 if (opts.showWeekNumber) { 1011 row.unshift(renderWeek(i - before, month, year)); 1012 } 1013 data.push(renderRow(row, opts.isRTL)); 1014 row = []; 1015 r = 0; 1016 } 1017 } 1018 return renderTable(opts, data); 1019 }, 1020 1021 isVisible: function() 1022 { 1023 return this._v; 1024 }, 1025 1026 show: function() 1027 { 1028 if (!this._v) { 1029 removeClass(this.el, 'is-hidden'); 1030 this._v = true; 1031 this.draw(); 1032 if (this._o.bound) { 1033 addEvent(document, 'click', this._onClick); 1034 this.adjustPosition(); 1035 } 1036 if (typeof this._o.onOpen === 'function') { 1037 this._o.onOpen.call(this); 1038 } 1039 } 1040 }, 1041 1042 hide: function() 1043 { 1044 var v = this._v; 1045 if (v !== false) { 1046 if (this._o.bound) { 1047 removeEvent(document, 'click', this._onClick); 1048 } 1049 this.el.style.position = 'static'; // reset 1050 this.el.style.left = 'auto'; 1051 this.el.style.top = 'auto'; 1052 addClass(this.el, 'is-hidden'); 1053 this._v = false; 1054 if (v !== undefined && typeof this._o.onClose === 'function') { 1055 this._o.onClose.call(this); 1056 } 1057 } 1058 }, 1059 1060 /** 1061 * GAME OVER 1062 */ 1063 destroy: function() 1064 { 1065 this.hide(); 1066 removeEvent(this.el, 'mousedown', this._onMouseDown, true); 1067 removeEvent(this.el, 'touchend', this._onMouseDown, true); 1068 removeEvent(this.el, 'change', this._onChange); 1069 if (this._o.field) { 1070 removeEvent(this._o.field, 'change', this._onInputChange); 1071 if (this._o.bound) { 1072 removeEvent(this._o.trigger, 'click', this._onInputClick); 1073 removeEvent(this._o.trigger, 'focus', this._onInputFocus); 1074 removeEvent(this._o.trigger, 'blur', this._onInputBlur); 1075 } 1076 } 1077 if (this.el.parentNode) { 1078 this.el.parentNode.removeChild(this.el); 1079 } 1080 } 1081 1082 }; 1083 1084 return Pikaday; 1085 1086}));
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.