vendor: 6,663 bytes, lines 1-236
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 default flag for moment's strict date parsing 206 formatStrict: false, 207 208 // the minimum/earliest date that can be selected 209 minDate: null, 210 // the maximum/latest date that can be selected 211 maxDate: null, 212 213 // number of years either side, or array of upper/lower range 214 yearRange: 10, 215 216 // show week numbers at head of row 217 showWeekNumber: false, 218 219 // used internally (don't config outside) 220 minYear: 0, 221 maxYear: 9999, 222 minMonth: undefined, 223 maxMonth: undefined, 224 225 startRange: null, 226 endRange: null, 227 228 isRTL: false, 229 230 // Additional text to append to the year in the calendar title 231 yearSuffix: '', 232 233 // Render the month after year in the calendar title 234 showMonthAfterYear: false, 235 236 // Render days of the calendar grid that fall in the next or previous month
vendor: 10,580 bytes, lines 237-556
237 showDaysInNextAndPreviousMonths: false, 238 239 // how many months are visible 240 numberOfMonths: 1, 241 242 // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`) 243 // only used for the first display or when a selected date is not visible 244 mainCalendar: 'left', 245 246 // Specify a DOM element to render the calendar in 247 container: undefined, 248 249 // internationalization 250 i18n: { 251 previousMonth : 'Previous Month', 252 nextMonth : 'Next Month', 253 months : ['January','February','March','April','May','June','July','August','September','October','November','December'], 254 weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], 255 weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'] 256 }, 257 258 // Theme Classname 259 theme: null, 260 261 // callback function 262 onSelect: null, 263 onOpen: null, 264 onClose: null, 265 onDraw: null 266 }, 267 268 269 /** 270 * templating functions to abstract HTML rendering 271 */ 272 renderDayName = function(opts, day, abbr) 273 { 274 day += opts.firstDay; 275 while (day >= 7) { 276 day -= 7; 277 } 278 return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day]; 279 }, 280 281 renderDay = function(opts) 282 { 283 var arr = []; 284 var ariaSelected = 'false'; 285 if (opts.isEmpty) { 286 if (opts.showDaysInNextAndPreviousMonths) { 287 arr.push('is-outside-current-month'); 288 } else { 289 return '<td class="is-empty"></td>'; 290 } 291 } 292 if (opts.isDisabled) { 293 arr.push('is-disabled'); 294 } 295 if (opts.isToday) { 296 arr.push('is-today'); 297 } 298 if (opts.isSelected) { 299 arr.push('is-selected'); 300 ariaSelected = 'true'; 301 } 302 if (opts.isInRange) { 303 arr.push('is-inrange'); 304 } 305 if (opts.isStartRange) { 306 arr.push('is-startrange'); 307 } 308 if (opts.isEndRange) { 309 arr.push('is-endrange'); 310 } 311 return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '" aria-selected="' + ariaSelected + '">' + 312 '<button class="pika-button pika-day" type="button" ' + 313 'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' + 314 opts.day + 315 '</button>' + 316 '</td>'; 317 }, 318 319 renderWeek = function (d, m, y) { 320 // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified. 321 var onejan = new Date(y, 0, 1), 322 weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7); 323 return '<td class="pika-week">' + weekNum + '</td>'; 324 }, 325 326 renderRow = function(days, isRTL) 327 { 328 return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>'; 329 }, 330 331 renderBody = function(rows) 332 { 333 return '<tbody>' + rows.join('') + '</tbody>'; 334 }, 335 336 renderHead = function(opts) 337 { 338 var i, arr = []; 339 if (opts.showWeekNumber) { 340 arr.push('<th></th>'); 341 } 342 for (i = 0; i < 7; i++) { 343 arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>'); 344 } 345 return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>'; 346 }, 347 348 renderTitle = function(instance, c, year, month, refYear, randId) 349 { 350 var i, j, arr, 351 opts = instance._o, 352 isMinYear = year === opts.minYear, 353 isMaxYear = year === opts.maxYear, 354 html = '<div id="' + randId + '" class="pika-title" role="heading" aria-live="assertive">', 355 monthHtml, 356 yearHtml, 357 prev = true, 358 next = true; 359 360 for (arr = [], i = 0; i < 12; i++) { 361 arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' + 362 (i === month ? ' selected="selected"': '') + 363 ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled="disabled"' : '') + '>' + 364 opts.i18n.months[i] + '</option>'); 365 } 366 367 monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>'; 368 369 if (isArray(opts.yearRange)) { 370 i = opts.yearRange[0]; 371 j = opts.yearRange[1] + 1; 372 } else { 373 i = year - opts.yearRange; 374 j = 1 + year + opts.yearRange; 375 } 376 377 for (arr = []; i < j && i <= opts.maxYear; i++) { 378 if (i >= opts.minYear) { 379 arr.push('<option value="' + i + '"' + (i === year ? ' selected="selected"': '') + '>' + (i) + '</option>'); 380 } 381 } 382 yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>'; 383 384 if (opts.showMonthAfterYear) { 385 html += yearHtml + monthHtml; 386 } else { 387 html += monthHtml + yearHtml; 388 } 389 390 if (isMinYear && (month === 0 || opts.minMonth >= month)) { 391 prev = false; 392 } 393 394 if (isMaxYear && (month === 11 || opts.maxMonth <= month)) { 395 next = false; 396 } 397 398 if (c === 0) { 399 html += '<button class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>'; 400 } 401 if (c === (instance._o.numberOfMonths - 1) ) { 402 html += '<button class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>'; 403 } 404 405 return html += '</div>'; 406 }, 407 408 renderTable = function(opts, data, randId) 409 { 410 return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + '</table>'; 411 }, 412 413 414 /** 415 * Pikaday constructor 416 */ 417 Pikaday = function(options) 418 { 419 var self = this, 420 opts = self.config(options); 421 422 self._onMouseDown = function(e) 423 { 424 if (!self._v) { 425 return; 426 } 427 e = e || window.event; 428 var target = e.target || e.srcElement; 429 if (!target) { 430 return; 431 } 432 433 if (!hasClass(target, 'is-disabled')) { 434 if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty') && !hasClass(target.parentNode, 'is-disabled')) { 435 self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day'))); 436 if (opts.bound) { 437 sto(function() { 438 self.hide(); 439 if (opts.field) { 440 opts.field.blur(); 441 } 442 }, 100); 443 } 444 } 445 else if (hasClass(target, 'pika-prev')) { 446 self.prevMonth(); 447 } 448 else if (hasClass(target, 'pika-next')) { 449 self.nextMonth(); 450 } 451 } 452 if (!hasClass(target, 'pika-select')) { 453 // if this is touch event prevent mouse events emulation 454 if (e.preventDefault) { 455 e.preventDefault(); 456 } else { 457 e.returnValue = false; 458 return false; 459 } 460 } else { 461 self._c = true; 462 } 463 }; 464 465 self._onChange = function(e) 466 { 467 e = e || window.event; 468 var target = e.target || e.srcElement; 469 if (!target) { 470 return; 471 } 472 if (hasClass(target, 'pika-select-month')) { 473 self.gotoMonth(target.value); 474 } 475 else if (hasClass(target, 'pika-select-year')) { 476 self.gotoYear(target.value); 477 } 478 }; 479 480 self._onKeyChange = function(e) 481 { 482 e = e || window.event; 483 484 if (self.isVisible()) { 485 486 switch(e.keyCode){ 487 case 13: 488 case 27: 489 opts.field.blur(); 490 break; 491 case 37: 492 e.preventDefault(); 493 self.adjustDate('subtract', 1); 494 break; 495 case 38: 496 self.adjustDate('subtract', 7); 497 break; 498 case 39: 499 self.adjustDate('add', 1); 500 break; 501 case 40: 502 self.adjustDate('add', 7); 503 break; 504 } 505 } 506 }; 507 508 self._onInputChange = function(e) 509 { 510 var date; 511 512 if (e.firedBy === self) { 513 return; 514 } 515 if (hasMoment) { 516 date = moment(opts.field.value, opts.format, opts.formatStrict); 517 date = (date && date.isValid()) ? date.toDate() : null; 518 } 519 else { 520 date = new Date(Date.parse(opts.field.value)); 521 } 522 if (isDate(date)) { 523 self.setDate(date); 524 } 525 if (!self._v) { 526 self.show(); 527 } 528 }; 529 530 self._onInputFocus = function() 531 { 532 self.show(); 533 }; 534 535 self._onInputClick = function() 536 { 537 self.show(); 538 }; 539 540 self._onInputBlur = function() 541 { 542 // IE allows pika div to gain focus; catch blur the input field 543 var pEl = document.activeElement; 544 do { 545 if (hasClass(pEl, 'pika-single')) { 546 return; 547 } 548 } 549 while ((pEl = pEl.parentNode)); 550 551 if (!self._c) { 552 self._b = sto(function() { 553 self.hide(); 554 }, 50); 555 } 556 self._c = false;
vendor: 7,093 bytes, lines 557-778
557 }; 558 559 self._onClick = function(e) 560 { 561 e = e || window.event; 562 var target = e.target || e.srcElement, 563 pEl = target; 564 if (!target) { 565 return; 566 } 567 if (!hasEventListeners && hasClass(target, 'pika-select')) { 568 if (!target.onchange) { 569 target.setAttribute('onchange', 'return;'); 570 addEvent(target, 'change', self._onChange); 571 } 572 } 573 do { 574 if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) { 575 return; 576 } 577 } 578 while ((pEl = pEl.parentNode)); 579 if (self._v && target !== opts.trigger && pEl !== opts.trigger) { 580 self.hide(); 581 } 582 }; 583 584 self.el = document.createElement('div'); 585 self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : ''); 586 587 addEvent(self.el, 'mousedown', self._onMouseDown, true); 588 addEvent(self.el, 'touchend', self._onMouseDown, true); 589 addEvent(self.el, 'change', self._onChange); 590 addEvent(document, 'keydown', self._onKeyChange); 591 592 if (opts.field) { 593 if (opts.container) { 594 opts.container.appendChild(self.el); 595 } else if (opts.bound) { 596 document.body.appendChild(self.el); 597 } else { 598 opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling); 599 } 600 addEvent(opts.field, 'change', self._onInputChange); 601 602 if (!opts.defaultDate) { 603 if (hasMoment && opts.field.value) { 604 opts.defaultDate = moment(opts.field.value, opts.format).toDate(); 605 } else { 606 opts.defaultDate = new Date(Date.parse(opts.field.value)); 607 } 608 opts.setDefaultDate = true; 609 } 610 } 611 612 var defDate = opts.defaultDate; 613 614 if (isDate(defDate)) { 615 if (opts.setDefaultDate) { 616 self.setDate(defDate, true); 617 } else { 618 self.gotoDate(defDate); 619 } 620 } else { 621 self.gotoDate(new Date()); 622 } 623 624 if (opts.bound) { 625 this.hide(); 626 self.el.className += ' is-bound'; 627 addEvent(opts.trigger, 'click', self._onInputClick); 628 addEvent(opts.trigger, 'focus', self._onInputFocus); 629 addEvent(opts.trigger, 'blur', self._onInputBlur); 630 } else { 631 this.show(); 632 } 633 }; 634 635 636 /** 637 * public Pikaday API 638 */ 639 Pikaday.prototype = { 640 641 642 /** 643 * configure functionality 644 */ 645 config: function(options) 646 { 647 if (!this._o) { 648 this._o = extend({}, defaults, true); 649 } 650 651 var opts = extend(this._o, options, true); 652 653 opts.isRTL = !!opts.isRTL; 654 655 opts.field = (opts.field && opts.field.nodeName) ? opts.field : null; 656 657 opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null; 658 659 opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field); 660 661 opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field; 662 663 opts.disableWeekends = !!opts.disableWeekends; 664 665 opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null; 666 667 var nom = parseInt(opts.numberOfMonths, 10) || 1; 668 opts.numberOfMonths = nom > 4 ? 4 : nom; 669 670 if (!isDate(opts.minDate)) { 671 opts.minDate = false; 672 } 673 if (!isDate(opts.maxDate)) { 674 opts.maxDate = false; 675 } 676 if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) { 677 opts.maxDate = opts.minDate = false; 678 } 679 if (opts.minDate) { 680 this.setMinDate(opts.minDate); 681 } 682 if (opts.maxDate) { 683 this.setMaxDate(opts.maxDate); 684 } 685 686 if (isArray(opts.yearRange)) { 687 var fallback = new Date().getFullYear() - 10; 688 opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback; 689 opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback; 690 } else { 691 opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange; 692 if (opts.yearRange > 100) { 693 opts.yearRange = 100; 694 } 695 } 696 697 return opts; 698 }, 699 700 /** 701 * return a formatted string of the current selection (using Moment.js if available) 702 */ 703 toString: function(format) 704 { 705 return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString(); 706 }, 707 708 /** 709 * return a Moment.js object of the current selection (if available) 710 */ 711 getMoment: function() 712 { 713 return hasMoment ? moment(this._d) : null; 714 }, 715 716 /** 717 * set the current selection from a Moment.js object (if available) 718 */ 719 setMoment: function(date, preventOnSelect) 720 { 721 if (hasMoment && moment.isMoment(date)) { 722 this.setDate(date.toDate(), preventOnSelect); 723 } 724 }, 725 726 /** 727 * return a Date object of the current selection with fallback for the current date 728 */ 729 getDate: function() 730 { 731 return isDate(this._d) ? new Date(this._d.getTime()) : new Date(); 732 }, 733 734 /** 735 * set the current selection 736 */ 737 setDate: function(date, preventOnSelect) 738 { 739 if (!date) { 740 this._d = null; 741 742 if (this._o.field) { 743 this._o.field.value = ''; 744 fireEvent(this._o.field, 'change', { firedBy: this }); 745 } 746 747 return this.draw(); 748 } 749 if (typeof date === 'string') { 750 date = new Date(Date.parse(date)); 751 } 752 if (!isDate(date)) { 753 return; 754 } 755 756 var min = this._o.minDate, 757 max = this._o.maxDate; 758 759 if (isDate(min) && date < min) { 760 date = min; 761 } else if (isDate(max) && date > max) { 762 date = max; 763 } 764 765 this._d = new Date(date.getTime()); 766 setToStartOfDay(this._d); 767 this.gotoDate(this._d); 768 769 if (this._o.field) { 770 this._o.field.value = this.toString(); 771 fireEvent(this._o.field, 'change', { firedBy: this }); 772 } 773 if (!preventOnSelect && typeof this._o.onSelect === 'function') { 774 this._o.onSelect.call(this, this.getDate()); 775 } 776 }, 777 778 /**
vendor: 11,415 bytes, lines 779-1102
779 * change view to a specific date 780 */ 781 gotoDate: function(date) 782 { 783 var newCalendar = true; 784 785 if (!isDate(date)) { 786 return; 787 } 788 789 if (this.calendars) { 790 var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1), 791 lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1), 792 visibleDate = date.getTime(); 793 // get the end of the month 794 lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1); 795 lastVisibleDate.setDate(lastVisibleDate.getDate()-1); 796 newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate); 797 } 798 799 if (newCalendar) { 800 this.calendars = [{ 801 month: date.getMonth(), 802 year: date.getFullYear() 803 }]; 804 if (this._o.mainCalendar === 'right') { 805 this.calendars[0].month += 1 - this._o.numberOfMonths; 806 } 807 } 808 809 this.adjustCalendars(); 810 }, 811 812 adjustDate: function(sign, days) { 813 814 var day = this.getDate(); 815 var difference = parseInt(days)*24*60*60*1000; 816 817 var newDay; 818 819 if (sign === 'add') { 820 newDay = new Date(day.valueOf() + difference); 821 } else if (sign === 'subtract') { 822 newDay = new Date(day.valueOf() - difference); 823 } 824 825 if (hasMoment) { 826 if (sign === 'add') { 827 newDay = moment(day).add(days, "days").toDate(); 828 } else if (sign === 'subtract') { 829 newDay = moment(day).subtract(days, "days").toDate(); 830 } 831 } 832 833 this.setDate(newDay); 834 }, 835 836 adjustCalendars: function() { 837 this.calendars[0] = adjustCalendar(this.calendars[0]); 838 for (var c = 1; c < this._o.numberOfMonths; c++) { 839 this.calendars[c] = adjustCalendar({ 840 month: this.calendars[0].month + c, 841 year: this.calendars[0].year 842 }); 843 } 844 this.draw(); 845 }, 846 847 gotoToday: function() 848 { 849 this.gotoDate(new Date()); 850 }, 851 852 /** 853 * change view to a specific month (zero-index, e.g. 0: January) 854 */ 855 gotoMonth: function(month) 856 { 857 if (!isNaN(month)) { 858 this.calendars[0].month = parseInt(month, 10); 859 this.adjustCalendars(); 860 } 861 }, 862 863 nextMonth: function() 864 { 865 this.calendars[0].month++; 866 this.adjustCalendars(); 867 }, 868 869 prevMonth: function() 870 { 871 this.calendars[0].month--; 872 this.adjustCalendars(); 873 }, 874 875 /** 876 * change view to a specific full year (e.g. "2012") 877 */ 878 gotoYear: function(year) 879 { 880 if (!isNaN(year)) { 881 this.calendars[0].year = parseInt(year, 10); 882 this.adjustCalendars(); 883 } 884 }, 885 886 /** 887 * change the minDate 888 */ 889 setMinDate: function(value) 890 { 891 if(value instanceof Date) { 892 setToStartOfDay(value); 893 this._o.minDate = value; 894 this._o.minYear = value.getFullYear(); 895 this._o.minMonth = value.getMonth(); 896 } else { 897 this._o.minDate = defaults.minDate; 898 this._o.minYear = defaults.minYear; 899 this._o.minMonth = defaults.minMonth; 900 this._o.startRange = defaults.startRange; 901 } 902 903 this.draw(); 904 }, 905 906 /** 907 * change the maxDate 908 */ 909 setMaxDate: function(value) 910 { 911 if(value instanceof Date) { 912 setToStartOfDay(value); 913 this._o.maxDate = value; 914 this._o.maxYear = value.getFullYear(); 915 this._o.maxMonth = value.getMonth(); 916 } else { 917 this._o.maxDate = defaults.maxDate; 918 this._o.maxYear = defaults.maxYear; 919 this._o.maxMonth = defaults.maxMonth; 920 this._o.endRange = defaults.endRange; 921 } 922 923 this.draw(); 924 }, 925 926 setStartRange: function(value) 927 { 928 this._o.startRange = value; 929 }, 930 931 setEndRange: function(value) 932 { 933 this._o.endRange = value; 934 }, 935 936 /** 937 * refresh the HTML 938 */ 939 draw: function(force) 940 { 941 if (!this._v && !force) { 942 return; 943 } 944 var opts = this._o, 945 minYear = opts.minYear, 946 maxYear = opts.maxYear, 947 minMonth = opts.minMonth, 948 maxMonth = opts.maxMonth, 949 html = '', 950 randId; 951 952 if (this._y <= minYear) { 953 this._y = minYear; 954 if (!isNaN(minMonth) && this._m < minMonth) { 955 this._m = minMonth; 956 } 957 } 958 if (this._y >= maxYear) { 959 this._y = maxYear; 960 if (!isNaN(maxMonth) && this._m > maxMonth) { 961 this._m = maxMonth; 962 } 963 } 964 965 randId = 'pika-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2); 966 967 for (var c = 0; c < opts.numberOfMonths; c++) { 968 html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId) + '</div>'; 969 } 970 971 this.el.innerHTML = html; 972 973 if (opts.bound) { 974 if(opts.field.type !== 'hidden') { 975 sto(function() { 976 opts.trigger.focus(); 977 }, 1); 978 } 979 } 980 981 if (typeof this._o.onDraw === 'function') { 982 this._o.onDraw(this); 983 } 984 // let the screen reader user know to use arrow keys 985 this._o.field.setAttribute('aria-label', 'Use the arrow keys to pick a date'); 986 }, 987 988 adjustPosition: function() 989 { 990 var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect; 991 992 if (this._o.container) return; 993 994 this.el.style.position = 'absolute'; 995 996 field = this._o.trigger; 997 pEl = field; 998 width = this.el.offsetWidth; 999 height = this.el.offsetHeight; 1000 viewportWidth = window.innerWidth || document.documentElement.clientWidth; 1001 viewportHeight = window.innerHeight || document.documentElement.clientHeight; 1002 scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop; 1003 1004 if (typeof field.getBoundingClientRect === 'function') { 1005 clientRect = field.getBoundingClientRect(); 1006 left = clientRect.left + window.pageXOffset; 1007 top = clientRect.bottom + window.pageYOffset; 1008 } else { 1009 left = pEl.offsetLeft; 1010 top = pEl.offsetTop + pEl.offsetHeight; 1011 while((pEl = pEl.offsetParent)) { 1012 left += pEl.offsetLeft; 1013 top += pEl.offsetTop; 1014 } 1015 } 1016 1017 // default position is bottom & left 1018 if ((this._o.reposition && left + width > viewportWidth) || 1019 ( 1020 this._o.position.indexOf('right') > -1 && 1021 left - width + field.offsetWidth > 0 1022 ) 1023 ) { 1024 left = left - width + field.offsetWidth; 1025 } 1026 if ((this._o.reposition && top + height > viewportHeight + scrollTop) || 1027 ( 1028 this._o.position.indexOf('top') > -1 && 1029 top - height - field.offsetHeight > 0 1030 ) 1031 ) { 1032 top = top - height - field.offsetHeight; 1033 } 1034 1035 this.el.style.left = left + 'px'; 1036 this.el.style.top = top + 'px'; 1037 }, 1038 1039 /** 1040 * render HTML for a particular month 1041 */ 1042 render: function(year, month, randId) 1043 { 1044 var opts = this._o, 1045 now = new Date(), 1046 days = getDaysInMonth(year, month), 1047 before = new Date(year, month, 1).getDay(), 1048 data = [], 1049 row = []; 1050 setToStartOfDay(now); 1051 if (opts.firstDay > 0) { 1052 before -= opts.firstDay; 1053 if (before < 0) { 1054 before += 7; 1055 } 1056 } 1057 var previousMonth = month === 0 ? 11 : month - 1, 1058 nextMonth = month === 11 ? 0 : month + 1, 1059 yearOfPreviousMonth = month === 0 ? year - 1 : year, 1060 yearOfNextMonth = month === 11 ? year + 1 : year, 1061 daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth); 1062 var cells = days + before, 1063 after = cells; 1064 while(after > 7) { 1065 after -= 7; 1066 } 1067 cells += 7 - after; 1068 for (var i = 0, r = 0; i < cells; i++) 1069 { 1070 var day = new Date(year, month, 1 + (i - before)), 1071 isSelected = isDate(this._d) ? compareDates(day, this._d) : false, 1072 isToday = compareDates(day, now), 1073 isEmpty = i < before || i >= (days + before), 1074 dayNumber = 1 + (i - before), 1075 monthNumber = month, 1076 yearNumber = year, 1077 isStartRange = opts.startRange && compareDates(opts.startRange, day), 1078 isEndRange = opts.endRange && compareDates(opts.endRange, day), 1079 isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange, 1080 isDisabled = (opts.minDate && day < opts.minDate) || 1081 (opts.maxDate && day > opts.maxDate) || 1082 (opts.disableWeekends && isWeekend(day)) || 1083 (opts.disableDayFn && opts.disableDayFn(day)); 1084 1085 if (isEmpty) { 1086 if (i < before) { 1087 dayNumber = daysInPreviousMonth + dayNumber; 1088 monthNumber = previousMonth; 1089 yearNumber = yearOfPreviousMonth; 1090 } else { 1091 dayNumber = dayNumber - days; 1092 monthNumber = nextMonth; 1093 yearNumber = yearOfNextMonth; 1094 } 1095 } 1096 1097 var dayConfig = { 1098 day: dayNumber, 1099 month: monthNumber, 1100 year: yearNumber, 1101 isSelected: isSelected, 1102 isToday: isToday,
vendor: 2,863 bytes, lines 1103-1190
1103 isDisabled: isDisabled, 1104 isEmpty: isEmpty, 1105 isStartRange: isStartRange, 1106 isEndRange: isEndRange, 1107 isInRange: isInRange, 1108 showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths 1109 }; 1110 1111 row.push(renderDay(dayConfig)); 1112 1113 if (++r === 7) { 1114 if (opts.showWeekNumber) { 1115 row.unshift(renderWeek(i - before, month, year)); 1116 } 1117 data.push(renderRow(row, opts.isRTL)); 1118 row = []; 1119 r = 0; 1120 } 1121 } 1122 return renderTable(opts, data, randId); 1123 }, 1124 1125 isVisible: function() 1126 { 1127 return this._v; 1128 }, 1129 1130 show: function() 1131 { 1132 if (!this.isVisible()) { 1133 removeClass(this.el, 'is-hidden'); 1134 this._v = true; 1135 this.draw(); 1136 if (this._o.bound) { 1137 addEvent(document, 'click', this._onClick); 1138 this.adjustPosition(); 1139 } 1140 if (typeof this._o.onOpen === 'function') { 1141 this._o.onOpen.call(this); 1142 } 1143 } 1144 }, 1145 1146 hide: function() 1147 { 1148 var v = this._v; 1149 if (v !== false) { 1150 if (this._o.bound) { 1151 removeEvent(document, 'click', this._onClick); 1152 } 1153 this.el.style.position = 'static'; // reset 1154 this.el.style.left = 'auto'; 1155 this.el.style.top = 'auto'; 1156 addClass(this.el, 'is-hidden'); 1157 this._v = false; 1158 if (v !== undefined && typeof this._o.onClose === 'function') { 1159 this._o.onClose.call(this); 1160 } 1161 } 1162 }, 1163 1164 /** 1165 * GAME OVER 1166 */ 1167 destroy: function() 1168 { 1169 this.hide(); 1170 removeEvent(this.el, 'mousedown', this._onMouseDown, true); 1171 removeEvent(this.el, 'touchend', this._onMouseDown, true); 1172 removeEvent(this.el, 'change', this._onChange); 1173 if (this._o.field) { 1174 removeEvent(this._o.field, 'change', this._onInputChange); 1175 if (this._o.bound) { 1176 removeEvent(this._o.trigger, 'click', this._onInputClick); 1177 removeEvent(this._o.trigger, 'focus', this._onInputFocus); 1178 removeEvent(this._o.trigger, 'blur', this._onInputBlur); 1179 } 1180 } 1181 if (this.el.parentNode) { 1182 this.el.parentNode.removeChild(this.el); 1183 } 1184 } 1185 1186 }; 1187 1188 return Pikaday; 1189 1190}));
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.