vendor: 14,982 bytes, lines 1-374
1/** 2* @version: 3.0.1 3* @author: Dan Grossman http://www.dangrossman.info/ 4* @copyright: Copyright (c) 2012-2018 Dan Grossman. All rights reserved. 5* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php 6* @website: http://www.daterangepicker.com/ 7*/ 8// Following the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js 9(function (root, factory) { 10 if (typeof define === 'function' && define.amd) { 11 // AMD. Make globaly available as well 12 define(['moment', 'jquery'], function (moment, jquery) { 13 if (!jquery.fn) jquery.fn = {}; // webpack server rendering 14 return factory(moment, jquery); 15 }); 16 } else if (typeof module === 'object' && module.exports) { 17 // Node / Browserify 18 //isomorphic issue 19 var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined; 20 if (!jQuery) { 21 jQuery = require('jquery'); 22 if (!jQuery.fn) jQuery.fn = {}; 23 } 24 var moment = (typeof window != 'undefined' && typeof window.moment != 'undefined') ? window.moment : require('moment'); 25 module.exports = factory(moment, jQuery); 26 } else { 27 // Browser globals 28 root.daterangepicker = factory(root.moment, root.jQuery); 29 } 30}(this, function(moment, $) { 31 var DateRangePicker = function(element, options, cb) { 32 33 //default settings for options 34 this.parentEl = 'body'; 35 this.element = $(element); 36 this.startDate = moment().startOf('day'); 37 this.endDate = moment().endOf('day'); 38 this.minDate = false; 39 this.maxDate = false; 40 this.maxSpan = false; 41 this.autoApply = false; 42 this.singleDatePicker = false; 43 this.showDropdowns = false; 44 this.minYear = moment().subtract(100, 'year').format('YYYY'); 45 this.maxYear = moment().add(100, 'year').format('YYYY'); 46 this.showWeekNumbers = false; 47 this.showISOWeekNumbers = false; 48 this.showCustomRangeLabel = true; 49 this.timePicker = false; 50 this.timePicker24Hour = false; 51 this.timePickerIncrement = 1; 52 this.timePickerSeconds = false; 53 this.linkedCalendars = true; 54 this.autoUpdateInput = true; 55 this.alwaysShowCalendars = false; 56 this.ranges = {}; 57 58 this.opens = 'right'; 59 if (this.element.hasClass('pull-right')) 60 this.opens = 'left'; 61 62 this.drops = 'down'; 63 if (this.element.hasClass('dropup')) 64 this.drops = 'up'; 65 66 this.buttonClasses = 'btn btn-sm'; 67 this.applyButtonClasses = 'btn-primary'; 68 this.cancelButtonClasses = 'btn-default'; 69 70 this.locale = { 71 direction: 'ltr', 72 format: moment.localeData().longDateFormat('L'), 73 separator: ' - ', 74 applyLabel: 'Apply', 75 cancelLabel: 'Cancel', 76 weekLabel: 'W', 77 customRangeLabel: 'Custom Range', 78 daysOfWeek: moment.weekdaysMin(), 79 monthNames: moment.monthsShort(), 80 firstDay: moment.localeData().firstDayOfWeek() 81 }; 82 83 this.callback = function() { }; 84 85 //some state information 86 this.isShowing = false; 87 this.leftCalendar = {}; 88 this.rightCalendar = {}; 89 90 //custom options from user 91 if (typeof options !== 'object' || options === null) 92 options = {}; 93 94 //allow setting options with data attributes 95 //data-api options will be overwritten with custom javascript options 96 options = $.extend(this.element.data(), options); 97 98 //html template for the picker UI 99 if (typeof options.template !== 'string' && !(options.template instanceof $)) 100 options.template = 101 '<div class="daterangepicker">' + 102 '<div class="ranges"></div>' + 103 '<div class="calendar left">' + 104 '<div class="calendar-table"></div>' + 105 '<div class="calendar-time"></div>' + 106 '</div>' + 107 '<div class="calendar right">' + 108 '<div class="calendar-table"></div>' + 109 '<div class="calendar-time"></div>' + 110 '</div>' + 111 '<div class="drp-buttons">' + 112 '<span class="drp-selected"></span>' + 113 '<button class="cancelBtn" type="button"></button>' + 114 '<button class="applyBtn" disabled="disabled" type="button"></button> ' + 115 '</div>' + 116 '</div>'; 117 118 this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl); 119 this.container = $(options.template).appendTo(this.parentEl); 120 121 // 122 // handle all the possible options overriding defaults 123 // 124 125 if (typeof options.locale === 'object') { 126 127 if (typeof options.locale.direction === 'string') 128 this.locale.direction = options.locale.direction; 129 130 if (typeof options.locale.format === 'string') 131 this.locale.format = options.locale.format; 132 133 if (typeof options.locale.separator === 'string') 134 this.locale.separator = options.locale.separator; 135 136 if (typeof options.locale.daysOfWeek === 'object') 137 this.locale.daysOfWeek = options.locale.daysOfWeek.slice(); 138 139 if (typeof options.locale.monthNames === 'object') 140 this.locale.monthNames = options.locale.monthNames.slice(); 141 142 if (typeof options.locale.firstDay === 'number') 143 this.locale.firstDay = options.locale.firstDay; 144 145 if (typeof options.locale.applyLabel === 'string') 146 this.locale.applyLabel = options.locale.applyLabel; 147 148 if (typeof options.locale.cancelLabel === 'string') 149 this.locale.cancelLabel = options.locale.cancelLabel; 150 151 if (typeof options.locale.weekLabel === 'string') 152 this.locale.weekLabel = options.locale.weekLabel; 153 154 if (typeof options.locale.customRangeLabel === 'string'){ 155 //Support unicode chars in the custom range name. 156 var elem = document.createElement('textarea'); 157 elem.innerHTML = options.locale.customRangeLabel; 158 var rangeHtml = elem.value; 159 this.locale.customRangeLabel = rangeHtml; 160 } 161 } 162 this.container.addClass(this.locale.direction); 163 164 if (typeof options.startDate === 'string') 165 this.startDate = moment(options.startDate, this.locale.format); 166 167 if (typeof options.endDate === 'string') 168 this.endDate = moment(options.endDate, this.locale.format); 169 170 if (typeof options.minDate === 'string') 171 this.minDate = moment(options.minDate, this.locale.format); 172 173 if (typeof options.maxDate === 'string') 174 this.maxDate = moment(options.maxDate, this.locale.format); 175 176 if (typeof options.startDate === 'object') 177 this.startDate = moment(options.startDate); 178 179 if (typeof options.endDate === 'object') 180 this.endDate = moment(options.endDate); 181 182 if (typeof options.minDate === 'object') 183 this.minDate = moment(options.minDate); 184 185 if (typeof options.maxDate === 'object') 186 this.maxDate = moment(options.maxDate); 187 188 // sanity check for bad options 189 if (this.minDate && this.startDate.isBefore(this.minDate)) 190 this.startDate = this.minDate.clone(); 191 192 // sanity check for bad options 193 if (this.maxDate && this.endDate.isAfter(this.maxDate)) 194 this.endDate = this.maxDate.clone(); 195 196 if (typeof options.applyButtonClasses === 'string') 197 this.applyButtonClasses = options.applyButtonClasses; 198 199 if (typeof options.applyClass === 'string') //backwards compat 200 this.applyButtonClasses = options.applyClass; 201 202 if (typeof options.cancelButtonClasses === 'string') 203 this.cancelButtonClasses = options.cancelButtonClasses; 204 205 if (typeof options.cancelClass === 'string') //backwards compat 206 this.cancelButtonClasses = options.cancelClass; 207 208 if (typeof options.maxSpan === 'object') 209 this.maxSpan = options.maxSpan; 210 211 if (typeof options.dateLimit === 'object') //backwards compat 212 this.maxSpan = options.dateLimit; 213 214 if (typeof options.opens === 'string') 215 this.opens = options.opens; 216 217 if (typeof options.drops === 'string') 218 this.drops = options.drops; 219 220 if (typeof options.showWeekNumbers === 'boolean') 221 this.showWeekNumbers = options.showWeekNumbers; 222 223 if (typeof options.showISOWeekNumbers === 'boolean') 224 this.showISOWeekNumbers = options.showISOWeekNumbers; 225 226 if (typeof options.buttonClasses === 'string') 227 this.buttonClasses = options.buttonClasses; 228 229 if (typeof options.buttonClasses === 'object') 230 this.buttonClasses = options.buttonClasses.join(' '); 231 232 if (typeof options.showDropdowns === 'boolean') 233 this.showDropdowns = options.showDropdowns; 234 235 if (typeof options.minYear === 'number') 236 this.minYear = options.minYear; 237 238 if (typeof options.maxYear === 'number') 239 this.maxYear = options.maxYear; 240 241 if (typeof options.showCustomRangeLabel === 'boolean') 242 this.showCustomRangeLabel = options.showCustomRangeLabel; 243 244 if (typeof options.singleDatePicker === 'boolean') { 245 this.singleDatePicker = options.singleDatePicker; 246 if (this.singleDatePicker) 247 this.endDate = this.startDate.clone(); 248 } 249 250 if (typeof options.timePicker === 'boolean') 251 this.timePicker = options.timePicker; 252 253 if (typeof options.timePickerSeconds === 'boolean') 254 this.timePickerSeconds = options.timePickerSeconds; 255 256 if (typeof options.timePickerIncrement === 'number') 257 this.timePickerIncrement = options.timePickerIncrement; 258 259 if (typeof options.timePicker24Hour === 'boolean') 260 this.timePicker24Hour = options.timePicker24Hour; 261 262 if (typeof options.autoApply === 'boolean') 263 this.autoApply = options.autoApply; 264 265 if (typeof options.autoUpdateInput === 'boolean') 266 this.autoUpdateInput = options.autoUpdateInput; 267 268 if (typeof options.linkedCalendars === 'boolean') 269 this.linkedCalendars = options.linkedCalendars; 270 271 if (typeof options.isInvalidDate === 'function') 272 this.isInvalidDate = options.isInvalidDate; 273 274 if (typeof options.isCustomDate === 'function') 275 this.isCustomDate = options.isCustomDate; 276 277 if (typeof options.alwaysShowCalendars === 'boolean') 278 this.alwaysShowCalendars = options.alwaysShowCalendars; 279 280 // update day names order to firstDay 281 if (this.locale.firstDay != 0) { 282 var iterator = this.locale.firstDay; 283 while (iterator > 0) { 284 this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift()); 285 iterator--; 286 } 287 } 288 289 var start, end, range; 290 291 //if no start/end dates set, check if an input element contains initial values 292 if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') { 293 if ($(this.element).is('input[type=text]')) { 294 var val = $(this.element).val(), 295 split = val.split(this.locale.separator); 296 297 start = end = null; 298 299 if (split.length == 2) { 300 start = moment(split[0], this.locale.format); 301 end = moment(split[1], this.locale.format); 302 } else if (this.singleDatePicker && val !== "") { 303 start = moment(val, this.locale.format); 304 end = moment(val, this.locale.format); 305 } 306 if (start !== null && end !== null) { 307 this.setStartDate(start); 308 this.setEndDate(end); 309 } 310 } 311 } 312 313 if (typeof options.ranges === 'object') { 314 for (range in options.ranges) { 315 316 if (typeof options.ranges[range][0] === 'string') 317 start = moment(options.ranges[range][0], this.locale.format); 318 else 319 start = moment(options.ranges[range][0]); 320 321 if (typeof options.ranges[range][1] === 'string') 322 end = moment(options.ranges[range][1], this.locale.format); 323 else 324 end = moment(options.ranges[range][1]); 325 326 // If the start or end date exceed those allowed by the minDate or maxSpan 327 // options, shorten the range to the allowable period. 328 if (this.minDate && start.isBefore(this.minDate)) 329 start = this.minDate.clone(); 330 331 var maxDate = this.maxDate; 332 if (this.maxSpan && maxDate && start.clone().add(this.maxSpan).isAfter(maxDate)) 333 maxDate = start.clone().add(this.maxSpan); 334 if (maxDate && end.isAfter(maxDate)) 335 end = maxDate.clone(); 336 337 // If the end of the range is before the minimum or the start of the range is 338 // after the maximum, don't display this range option at all. 339 if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day')) 340 || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day'))) 341 continue; 342 343 //Support unicode chars in the range names. 344 var elem = document.createElement('textarea'); 345 elem.innerHTML = range; 346 var rangeHtml = elem.value; 347 348 this.ranges[rangeHtml] = [start, end]; 349 } 350 351 var list = '<ul>'; 352 for (range in this.ranges) { 353 list += '<li data-range-key="' + range + '">' + range + '</li>'; 354 } 355 if (this.showCustomRangeLabel) { 356 list += '<li data-range-key="' + this.locale.customRangeLabel + '">' + this.locale.customRangeLabel + '</li>'; 357 } 358 list += '</ul>'; 359 this.container.find('.ranges').prepend(list); 360 } 361 362 if (typeof cb === 'function') { 363 this.callback = cb; 364 } 365 366 if (!this.timePicker) { 367 this.startDate = this.startDate.startOf('day'); 368 this.endDate = this.endDate.endOf('day'); 369 this.container.find('.calendar-time').hide(); 370 } 371 372 //can't be used together for now 373 if (this.timePicker && this.autoApply) 374 this.autoApply = false;
375 376 if (this.autoApply) { 377 this.container.addClass('auto-apply'); 378 } 379 380 if (typeof options.ranges === 'object') 381 this.container.addClass('show-ranges'); 382 383 if (this.singleDatePicker) { 384 this.container.addClass('single'); 385 this.container.find('.calendar.left').addClass('single'); 386 this.container.find('.calendar.left').show(); 387 this.container.find('.calendar.right').hide(); 388 if (!this.timePicker) { 389 this.container.addClass('auto-apply'); 390 } 391 } 392 393 if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) { 394 this.container.addClass('show-calendar'); 395 } 396 397 this.container.addClass('opens' + this.opens); 398 399 //apply CSS classes and labels to buttons 400 this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses); 401 if (this.applyButtonClasses.length) 402 this.container.find('.applyBtn').addClass(this.applyButtonClasses); 403 if (this.cancelButtonClasses.length) 404 this.container.find('.cancelBtn').addClass(this.cancelButtonClasses); 405 this.container.find('.applyBtn').html(this.locale.applyLabel); 406 this.container.find('.cancelBtn').html(this.locale.cancelLabel); 407 408 // 409 // event listeners 410 // 411 412 this.container.find('.calendar') 413 .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this)) 414 .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this)) 415 .on('mousedown.daterangepicker', 'td.available', $.proxy(this.clickDate, this)) 416 .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this)) 417 .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this)) 418 .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this)) 419 420 this.container.find('.ranges') 421 .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this)) 422 423 this.container.find('.drp-buttons') 424 .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this)) 425 .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this)) 426 427 if (this.element.is('input') || this.element.is('button')) { 428 this.element.on({ 429 'click.daterangepicker': $.proxy(this.show, this), 430 'focus.daterangepicker': $.proxy(this.show, this), 431 'keyup.daterangepicker': $.proxy(this.elementChanged, this), 432 'keydown.daterangepicker': $.proxy(this.keydown, this) //IE 11 compatibility 433 }); 434 } else { 435 this.element.on('click.daterangepicker', $.proxy(this.toggle, this)); 436 this.element.on('keydown.daterangepicker', $.proxy(this.toggle, this)); 437 } 438 439 // 440 // if attached to a text input, set the initial value 441 // 442 443 if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) { 444 this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); 445 this.element.trigger('change'); 446 } else if (this.element.is('input') && this.autoUpdateInput) { 447 this.element.val(this.startDate.format(this.locale.format)); 448 this.element.trigger('change'); 449 } 450 451 }; 452 453 DateRangePicker.prototype = { 454 455 constructor: DateRangePicker, 456 457 setStartDate: function(startDate) { 458 if (typeof startDate === 'string') 459 this.startDate = moment(startDate, this.locale.format); 460 461 if (typeof startDate === 'object') 462 this.startDate = moment(startDate); 463 464 if (!this.timePicker) 465 this.startDate = this.startDate.startOf('day'); 466 467 if (this.timePicker && this.timePickerIncrement) 468 this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 469 470 if (this.minDate && this.startDate.isBefore(this.minDate)) { 471 this.startDate = this.minDate.clone(); 472 if (this.timePicker && this.timePickerIncrement) 473 this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 474 } 475 476 if (this.maxDate && this.startDate.isAfter(this.maxDate)) { 477 this.startDate = this.maxDate.clone(); 478 if (this.timePicker && this.timePickerIncrement) 479 this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 480 } 481 482 if (!this.isShowing) 483 this.updateElement(); 484 485 this.updateMonthsInView(); 486 }, 487
vendor: 19,931 bytes, lines 488-937
488 setEndDate: function(endDate) { 489 if (typeof endDate === 'string') 490 this.endDate = moment(endDate, this.locale.format); 491 492 if (typeof endDate === 'object') 493 this.endDate = moment(endDate); 494 495 if (!this.timePicker) 496 this.endDate = this.endDate.add(1,'d').startOf('day').subtract(1,'second'); 497 498 if (this.timePicker && this.timePickerIncrement) 499 this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 500 501 if (this.endDate.isBefore(this.startDate)) 502 this.endDate = this.startDate.clone(); 503 504 if (this.maxDate && this.endDate.isAfter(this.maxDate)) 505 this.endDate = this.maxDate.clone(); 506 507 if (this.maxSpan && this.startDate.clone().add(this.maxSpan).isBefore(this.endDate)) 508 this.endDate = this.startDate.clone().add(this.maxSpan); 509 510 this.previousRightTime = this.endDate.clone(); 511 512 this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); 513 514 if (!this.isShowing) 515 this.updateElement(); 516 517 this.updateMonthsInView(); 518 }, 519 520 isInvalidDate: function() { 521 return false; 522 }, 523 524 isCustomDate: function() { 525 return false; 526 }, 527 528 updateView: function() { 529 if (this.timePicker) { 530 this.renderTimePicker('left'); 531 this.renderTimePicker('right'); 532 if (!this.endDate) { 533 this.container.find('.right .calendar-time select').attr('disabled', 'disabled').addClass('disabled'); 534 } else { 535 this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled'); 536 } 537 } 538 if (this.endDate) 539 this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); 540 this.updateMonthsInView(); 541 this.updateCalendars(); 542 this.updateFormInputs(); 543 }, 544 545 updateMonthsInView: function() { 546 if (this.endDate) { 547 548 //if both dates are visible already, do nothing 549 if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month && 550 (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) 551 && 552 (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) 553 ) { 554 return; 555 } 556 557 this.leftCalendar.month = this.startDate.clone().date(2); 558 if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) { 559 this.rightCalendar.month = this.endDate.clone().date(2); 560 } else { 561 this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month'); 562 } 563 564 } else { 565 if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) { 566 this.leftCalendar.month = this.startDate.clone().date(2); 567 this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month'); 568 } 569 } 570 if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) { 571 this.rightCalendar.month = this.maxDate.clone().date(2); 572 this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month'); 573 } 574 }, 575 576 updateCalendars: function() { 577 578 if (this.timePicker) { 579 var hour, minute, second; 580 if (this.endDate) { 581 hour = parseInt(this.container.find('.left .hourselect').val(), 10); 582 minute = parseInt(this.container.find('.left .minuteselect').val(), 10); 583 second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0; 584 if (!this.timePicker24Hour) { 585 var ampm = this.container.find('.left .ampmselect').val(); 586 if (ampm === 'PM' && hour < 12) 587 hour += 12; 588 if (ampm === 'AM' && hour === 12) 589 hour = 0; 590 } 591 } else { 592 hour = parseInt(this.container.find('.right .hourselect').val(), 10); 593 minute = parseInt(this.container.find('.right .minuteselect').val(), 10); 594 second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0; 595 if (!this.timePicker24Hour) { 596 var ampm = this.container.find('.right .ampmselect').val(); 597 if (ampm === 'PM' && hour < 12) 598 hour += 12; 599 if (ampm === 'AM' && hour === 12) 600 hour = 0; 601 } 602 } 603 this.leftCalendar.month.hour(hour).minute(minute).second(second); 604 this.rightCalendar.month.hour(hour).minute(minute).second(second); 605 } 606 607 this.renderCalendar('left'); 608 this.renderCalendar('right'); 609 610 //highlight any predefined range matching the current start and end dates 611 this.container.find('.ranges li').removeClass('active'); 612 if (this.endDate == null) return; 613 614 this.calculateChosenLabel(); 615 }, 616 617 renderCalendar: function(side) { 618 619 // 620 // Build the matrix of dates that will populate the calendar 621 // 622 623 var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar; 624 var month = calendar.month.month(); 625 var year = calendar.month.year(); 626 var hour = calendar.month.hour(); 627 var minute = calendar.month.minute(); 628 var second = calendar.month.second(); 629 var daysInMonth = moment([year, month]).daysInMonth(); 630 var firstDay = moment([year, month, 1]); 631 var lastDay = moment([year, month, daysInMonth]); 632 var lastMonth = moment(firstDay).subtract(1, 'month').month(); 633 var lastYear = moment(firstDay).subtract(1, 'month').year(); 634 var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth(); 635 var dayOfWeek = firstDay.day(); 636 637 //initialize a 6 rows x 7 columns array for the calendar 638 var calendar = []; 639 calendar.firstDay = firstDay; 640 calendar.lastDay = lastDay; 641 642 for (var i = 0; i < 6; i++) { 643 calendar[i] = []; 644 } 645 646 //populate the calendar with date objects 647 var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1; 648 if (startDay > daysInLastMonth) 649 startDay -= 7; 650 651 if (dayOfWeek == this.locale.firstDay) 652 startDay = daysInLastMonth - 6; 653 654 var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]); 655 656 var col, row; 657 for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) { 658 if (i > 0 && col % 7 === 0) { 659 col = 0; 660 row++; 661 } 662 calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second); 663 curDate.hour(12); 664 665 if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') { 666 calendar[row][col] = this.minDate.clone(); 667 } 668 669 if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') { 670 calendar[row][col] = this.maxDate.clone(); 671 } 672 673 } 674 675 //make the calendar object available to hoverDate/clickDate 676 if (side == 'left') { 677 this.leftCalendar.calendar = calendar; 678 } else { 679 this.rightCalendar.calendar = calendar; 680 } 681 682 // 683 // Display the calendar 684 // 685 686 var minDate = side == 'left' ? this.minDate : this.startDate; 687 var maxDate = this.maxDate; 688 var selected = side == 'left' ? this.startDate : this.endDate; 689 var arrow = this.locale.direction == 'ltr' ? {left: 'chevron-left', right: 'chevron-right'} : {left: 'chevron-right', right: 'chevron-left'}; 690 691 var html = '<table class="table-condensed">'; 692 html += '<thead>'; 693 html += '<tr>'; 694 695 // add empty cell for week number 696 if (this.showWeekNumbers || this.showISOWeekNumbers) 697 html += '<th></th>'; 698 699 if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) { 700 html += '<th class="prev available"><span></span></th>'; 701 } else { 702 html += '<th></th>'; 703 } 704 705 var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY"); 706 707 if (this.showDropdowns) { 708 var currentMonth = calendar[1][1].month(); 709 var currentYear = calendar[1][1].year(); 710 var maxYear = (maxDate && maxDate.year()) || (this.maxYear); 711 var minYear = (minDate && minDate.year()) || (this.minYear); 712 var inMinYear = currentYear == minYear; 713 var inMaxYear = currentYear == maxYear; 714 715 var monthHtml = '<select class="monthselect">'; 716 for (var m = 0; m < 12; m++) { 717 if ((!inMinYear || m >= minDate.month()) && (!inMaxYear || m <= maxDate.month())) { 718 monthHtml += "<option value='" + m + "'" + 719 (m === currentMonth ? " selected='selected'" : "") + 720 ">" + this.locale.monthNames[m] + "</option>"; 721 } else { 722 monthHtml += "<option value='" + m + "'" + 723 (m === currentMonth ? " selected='selected'" : "") + 724 " disabled='disabled'>" + this.locale.monthNames[m] + "</option>"; 725 } 726 } 727 monthHtml += "</select>"; 728 729 var yearHtml = '<select class="yearselect">'; 730 for (var y = minYear; y <= maxYear; y++) { 731 yearHtml += '<option value="' + y + '"' + 732 (y === currentYear ? ' selected="selected"' : '') + 733 '>' + y + '</option>'; 734 } 735 yearHtml += '</select>'; 736 737 dateHtml = monthHtml + yearHtml; 738 } 739 740 html += '<th colspan="5" class="month">' + dateHtml + '</th>'; 741 if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) { 742 html += '<th class="next available"><span></span></th>'; 743 } else { 744 html += '<th></th>'; 745 } 746 747 html += '</tr>'; 748 html += '<tr>'; 749 750 // add week number label 751 if (this.showWeekNumbers || this.showISOWeekNumbers) 752 html += '<th class="week">' + this.locale.weekLabel + '</th>'; 753 754 $.each(this.locale.daysOfWeek, function(index, dayOfWeek) { 755 html += '<th>' + dayOfWeek + '</th>'; 756 }); 757 758 html += '</tr>'; 759 html += '</thead>'; 760 html += '<tbody>'; 761 762 //adjust maxDate to reflect the maxSpan setting in order to 763 //grey out end dates beyond the maxSpan 764 if (this.endDate == null && this.maxSpan) { 765 var maxLimit = this.startDate.clone().add(this.maxSpan).endOf('day'); 766 if (!maxDate || maxLimit.isBefore(maxDate)) { 767 maxDate = maxLimit; 768 } 769 } 770 771 for (var row = 0; row < 6; row++) { 772 html += '<tr>'; 773 774 // add week number 775 if (this.showWeekNumbers) 776 html += '<td class="week">' + calendar[row][0].week() + '</td>'; 777 else if (this.showISOWeekNumbers) 778 html += '<td class="week">' + calendar[row][0].isoWeek() + '</td>'; 779 780 for (var col = 0; col < 7; col++) { 781 782 var classes = []; 783 784 //highlight today's date 785 if (calendar[row][col].isSame(new Date(), "day")) 786 classes.push('today'); 787 788 //highlight weekends 789 if (calendar[row][col].isoWeekday() > 5) 790 classes.push('weekend'); 791 792 //grey out the dates in other months displayed at beginning and end of this calendar 793 if (calendar[row][col].month() != calendar[1][1].month()) 794 classes.push('off'); 795 796 //don't allow selection of dates before the minimum date 797 if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day')) 798 classes.push('off', 'disabled'); 799 800 //don't allow selection of dates after the maximum date 801 if (maxDate && calendar[row][col].isAfter(maxDate, 'day')) 802 classes.push('off', 'disabled'); 803 804 //don't allow selection of date if a custom function decides it's invalid 805 if (this.isInvalidDate(calendar[row][col])) 806 classes.push('off', 'disabled'); 807 808 //highlight the currently selected start date 809 if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) 810 classes.push('active', 'start-date'); 811 812 //highlight the currently selected end date 813 if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) 814 classes.push('active', 'end-date'); 815 816 //highlight dates in-between the selected dates 817 if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate) 818 classes.push('in-range'); 819 820 //apply custom classes for this date 821 var isCustom = this.isCustomDate(calendar[row][col]); 822 if (isCustom !== false) { 823 if (typeof isCustom === 'string') 824 classes.push(isCustom); 825 else 826 Array.prototype.push.apply(classes, isCustom); 827 } 828 829 var cname = '', disabled = false; 830 for (var i = 0; i < classes.length; i++) { 831 cname += classes[i] + ' '; 832 if (classes[i] == 'disabled') 833 disabled = true; 834 } 835 if (!disabled) 836 cname += 'available'; 837 838 html += '<td class="' + cname.replace(/^\s+|\s+$/g, '') + '" data-title="' + 'r' + row + 'c' + col + '">' + calendar[row][col].date() + '</td>'; 839 840 } 841 html += '</tr>'; 842 } 843 844 html += '</tbody>'; 845 html += '</table>'; 846 847 this.container.find('.calendar.' + side + ' .calendar-table').html(html); 848 849 }, 850 851 renderTimePicker: function(side) { 852 853 // Don't bother updating the time picker if it's currently disabled 854 // because an end date hasn't been clicked yet 855 if (side == 'right' && !this.endDate) return; 856 857 var html, selected, minDate, maxDate = this.maxDate; 858 859 if (this.maxSpan && (!this.maxDate || this.startDate.clone().add(this.maxSpan).isAfter(this.maxDate))) 860 maxDate = this.startDate.clone().add(this.maxSpan); 861 862 if (side == 'left') { 863 selected = this.startDate.clone(); 864 minDate = this.minDate; 865 } else if (side == 'right') { 866 selected = this.endDate.clone(); 867 minDate = this.startDate; 868 869 //Preserve the time already selected 870 var timeSelector = this.container.find('.calendar.right .calendar-time'); 871 if (timeSelector.html() != '') { 872 873 selected.hour(selected.hour() || timeSelector.find('.hourselect option:selected').val()); 874 selected.minute(selected.minute() || timeSelector.find('.minuteselect option:selected').val()); 875 selected.second(selected.second() || timeSelector.find('.secondselect option:selected').val()); 876 877 if (!this.timePicker24Hour) { 878 var ampm = timeSelector.find('.ampmselect option:selected').val(); 879 if (ampm === 'PM' && selected.hour() < 12) 880 selected.hour(selected.hour() + 12); 881 if (ampm === 'AM' && selected.hour() === 12) 882 selected.hour(0); 883 } 884 885 } 886 887 if (selected.isBefore(this.startDate)) 888 selected = this.startDate.clone(); 889 890 if (maxDate && selected.isAfter(maxDate)) 891 selected = maxDate.clone(); 892 893 } 894 895 // 896 // hours 897 // 898 899 html = '<select class="hourselect">'; 900 901 var start = this.timePicker24Hour ? 0 : 1; 902 var end = this.timePicker24Hour ? 23 : 12; 903 904 for (var i = start; i <= end; i++) { 905 var i_in_24 = i; 906 if (!this.timePicker24Hour) 907 i_in_24 = selected.hour() >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i); 908 909 var time = selected.clone().hour(i_in_24); 910 var disabled = false; 911 if (minDate && time.minute(59).isBefore(minDate)) 912 disabled = true; 913 if (maxDate && time.minute(0).isAfter(maxDate)) 914 disabled = true; 915 916 if (i_in_24 == selected.hour() && !disabled) { 917 html += '<option value="' + i + '" selected="selected">' + i + '</option>'; 918 } else if (disabled) { 919 html += '<option value="' + i + '" disabled="disabled" class="disabled">' + i + '</option>'; 920 } else { 921 html += '<option value="' + i + '">' + i + '</option>'; 922 } 923 } 924 925 html += '</select> '; 926 927 // 928 // minutes 929 // 930 931 html += ': <select class="minuteselect">'; 932 933 for (var i = 0; i < 60; i += this.timePickerIncrement) { 934 var padded = i < 10 ? '0' + i : i; 935 var time = selected.clone().minute(i); 936 937 var disabled = false;
938 if (minDate && time.second(59).isBefore(minDate)) 939 disabled = true; 940 if (maxDate && time.second(0).isAfter(maxDate)) 941 disabled = true; 942 943 if (selected.minute() == i && !disabled) { 944 html += '<option value="' + i + '" selected="selected">' + padded + '</option>'; 945 } else if (disabled) { 946 html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>'; 947 } else { 948 html += '<option value="' + i + '">' + padded + '</option>'; 949 } 950 } 951 952 html += '</select> '; 953 954 // 955 // seconds 956 // 957 958 if (this.timePickerSeconds) { 959 html += ': <select class="secondselect">'; 960 961 for (var i = 0; i < 60; i++) { 962 var padded = i < 10 ? '0' + i : i; 963 var time = selected.clone().second(i); 964 965 var disabled = false; 966 if (minDate && time.isBefore(minDate)) 967 disabled = true; 968 if (maxDate && time.isAfter(maxDate)) 969 disabled = true; 970 971 if (selected.second() == i && !disabled) { 972 html += '<option value="' + i + '" selected="selected">' + padded + '</option>'; 973 } else if (disabled) { 974 html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>'; 975 } else { 976 html += '<option value="' + i + '">' + padded + '</option>'; 977 } 978 } 979 980 html += '</select> '; 981 } 982 983 // 984 // AM/PM 985 // 986 987 if (!this.timePicker24Hour) { 988 html += '<select class="ampmselect">'; 989 990 var am_html = ''; 991 var pm_html = ''; 992 993 if (minDate && selected.clone().hour(12).minute(0).second(0).isBefore(minDate)) 994 am_html = ' disabled="disabled" class="disabled"'; 995 996 if (maxDate && selected.clone().hour(0).minute(0).second(0).isAfter(maxDate)) 997 pm_html = ' disabled="disabled" class="disabled"'; 998 999 if (selected.hour() >= 12) { 1000 html += '<option value="AM"' + am_html + '>AM</option><option value="PM" selected="selected"' + pm_html + '>PM</option>'; 1001 } else { 1002 html += '<option value="AM" selected="selected"' + am_html + '>AM</option><option value="PM"' + pm_html + '>PM</option>'; 1003 } 1004 1005 html += '</select>'; 1006 } 1007 1008 this.container.find('.calendar.' + side + ' .calendar-time').html(html); 1009 1010 }, 1011 1012 updateFormInputs: function() { 1013 1014 if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) { 1015 this.container.find('button.applyBtn').removeAttr('disabled'); 1016 } else { 1017 this.container.find('button.applyBtn').attr('disabled', 'disabled'); 1018 } 1019 1020 }, 1021 1022 move: function() { 1023 var parentOffset = { top: 0, left: 0 }, 1024 containerTop; 1025 var parentRightEdge = $(window).width(); 1026 if (!this.parentEl.is('body')) { 1027 parentOffset = { 1028 top: this.parentEl.offset().top - this.parentEl.scrollTop(), 1029 left: this.parentEl.offset().left - this.parentEl.scrollLeft() 1030 }; 1031 parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left; 1032 } 1033 1034 if (this.drops == 'up') 1035 containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top; 1036 else 1037 containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top; 1038 this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('drop-up'); 1039 1040 if (this.opens == 'left') { 1041 this.container.css({ 1042 top: containerTop, 1043 right: parentRightEdge - this.element.offset().left - this.element.outerWidth(), 1044 left: 'auto' 1045 }); 1046 if (this.container.offset().left < 0) { 1047 this.container.css({ 1048 right: 'auto', 1049 left: 9 1050 }); 1051 } 1052 } else if (this.opens == 'center') { 1053 this.container.css({ 1054 top: containerTop, 1055 left: this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2 1056 - this.container.outerWidth() / 2, 1057 right: 'auto' 1058 }); 1059 if (this.container.offset().left < 0) { 1060 this.container.css({ 1061 right: 'auto', 1062 left: 9 1063 }); 1064 } 1065 } else { 1066 this.container.css({ 1067 top: containerTop, 1068 left: this.element.offset().left - parentOffset.left, 1069 right: 'auto' 1070 }); 1071 if (this.container.offset().left + this.container.outerWidth() > $(window).width()) { 1072 this.container.css({ 1073 left: 'auto', 1074 right: 0 1075 }); 1076 } 1077 } 1078 }, 1079 1080 show: function(e) { 1081 if (this.isShowing) return; 1082 1083 // Create a click proxy that is private to this instance of datepicker, for unbinding 1084 this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this); 1085 1086 // Bind global datepicker mousedown for hiding and 1087 $(document) 1088 .on('mousedown.daterangepicker', this._outsideClickProxy) 1089 // also support mobile devices 1090 .on('touchend.daterangepicker', this._outsideClickProxy) 1091 // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them 1092 .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy)
vendor: 18,146 bytes, lines 1093-1533
1093 // and also close when focus changes to outside the picker (eg. tabbing between controls) 1094 .on('focusin.daterangepicker', this._outsideClickProxy); 1095 1096 // Reposition the picker if the window is resized while it's open 1097 $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this)); 1098 1099 this.oldStartDate = this.startDate.clone(); 1100 this.oldEndDate = this.endDate.clone(); 1101 this.previousRightTime = this.endDate.clone(); 1102 1103 this.updateView(); 1104 this.container.show(); 1105 this.move(); 1106 this.element.trigger('show.daterangepicker', this); 1107 this.isShowing = true; 1108 }, 1109 1110 hide: function(e) { 1111 if (!this.isShowing) return; 1112 1113 //incomplete date selection, revert to last values 1114 if (!this.endDate) { 1115 this.startDate = this.oldStartDate.clone(); 1116 this.endDate = this.oldEndDate.clone(); 1117 } 1118 1119 //if a new date range was selected, invoke the user callback function 1120 if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) 1121 this.callback(this.startDate.clone(), this.endDate.clone(), this.chosenLabel); 1122 1123 //if picker is attached to a text input, update it 1124 this.updateElement(); 1125 1126 $(document).off('.daterangepicker'); 1127 $(window).off('.daterangepicker'); 1128 this.container.hide(); 1129 this.element.trigger('hide.daterangepicker', this); 1130 this.isShowing = false; 1131 }, 1132 1133 toggle: function(e) { 1134 if (this.isShowing) { 1135 this.hide(); 1136 } else { 1137 this.show(); 1138 } 1139 }, 1140 1141 outsideClick: function(e) { 1142 var target = $(e.target); 1143 // if the page is clicked anywhere except within the daterangerpicker/button 1144 // itself then call this.hide() 1145 if ( 1146 // ie modal dialog fix 1147 e.type == "focusin" || 1148 target.closest(this.element).length || 1149 target.closest(this.container).length || 1150 target.closest('.calendar-table').length 1151 ) return; 1152 this.hide(); 1153 this.element.trigger('outsideClick.daterangepicker', this); 1154 }, 1155 1156 showCalendars: function() { 1157 this.container.addClass('show-calendar'); 1158 this.move(); 1159 this.element.trigger('showCalendar.daterangepicker', this); 1160 }, 1161 1162 hideCalendars: function() { 1163 this.container.removeClass('show-calendar'); 1164 this.element.trigger('hideCalendar.daterangepicker', this); 1165 }, 1166 1167 clickRange: function(e) { 1168 var label = e.target.getAttribute('data-range-key'); 1169 this.chosenLabel = label; 1170 if (label == this.locale.customRangeLabel) { 1171 this.showCalendars(); 1172 } else { 1173 var dates = this.ranges[label]; 1174 this.startDate = dates[0]; 1175 this.endDate = dates[1]; 1176 1177 if (!this.timePicker) { 1178 this.startDate.startOf('day'); 1179 this.endDate.endOf('day'); 1180 } 1181 1182 if (!this.alwaysShowCalendars) 1183 this.hideCalendars(); 1184 this.clickApply(); 1185 } 1186 }, 1187 1188 clickPrev: function(e) { 1189 var cal = $(e.target).parents('.calendar'); 1190 if (cal.hasClass('left')) { 1191 this.leftCalendar.month.subtract(1, 'month'); 1192 if (this.linkedCalendars) 1193 this.rightCalendar.month.subtract(1, 'month'); 1194 } else { 1195 this.rightCalendar.month.subtract(1, 'month'); 1196 } 1197 this.updateCalendars(); 1198 }, 1199 1200 clickNext: function(e) { 1201 var cal = $(e.target).parents('.calendar'); 1202 if (cal.hasClass('left')) { 1203 this.leftCalendar.month.add(1, 'month'); 1204 } else { 1205 this.rightCalendar.month.add(1, 'month'); 1206 if (this.linkedCalendars) 1207 this.leftCalendar.month.add(1, 'month'); 1208 } 1209 this.updateCalendars(); 1210 }, 1211 1212 hoverDate: function(e) { 1213 1214 //ignore mouse movements while an above-calendar text input has focus 1215 //if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus")) 1216 // return; 1217 1218 //ignore dates that can't be selected 1219 if (!$(e.target).hasClass('available')) return; 1220 1221 //have the text inputs above calendars reflect the date being hovered over 1222 var title = $(e.target).attr('data-title'); 1223 var row = title.substr(1, 1); 1224 var col = title.substr(3, 1); 1225 var cal = $(e.target).parents('.calendar'); 1226 var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col]; 1227 1228 //highlight the dates between the start date and the date being hovered as a potential end date 1229 var leftCalendar = this.leftCalendar; 1230 var rightCalendar = this.rightCalendar; 1231 var startDate = this.startDate; 1232 if (!this.endDate) { 1233 this.container.find('.calendar tbody td').each(function(index, el) { 1234 1235 //skip week numbers, only look at dates 1236 if ($(el).hasClass('week')) return; 1237 1238 var title = $(el).attr('data-title'); 1239 var row = title.substr(1, 1); 1240 var col = title.substr(3, 1); 1241 var cal = $(el).parents('.calendar'); 1242 var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col]; 1243 1244 if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) { 1245 $(el).addClass('in-range'); 1246 } else { 1247 $(el).removeClass('in-range'); 1248 } 1249 1250 }); 1251 } 1252 1253 }, 1254 1255 clickDate: function(e) { 1256 1257 if (!$(e.target).hasClass('available')) return; 1258 1259 var title = $(e.target).attr('data-title'); 1260 var row = title.substr(1, 1); 1261 var col = title.substr(3, 1); 1262 var cal = $(e.target).parents('.calendar'); 1263 var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col]; 1264 1265 // 1266 // this function needs to do a few things: 1267 // * alternate between selecting a start and end date for the range, 1268 // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date 1269 // * if autoapply is enabled, and an end date was chosen, apply the selection 1270 // * if single date picker mode, and time picker isn't enabled, apply the selection immediately 1271 // * if one of the inputs above the calendars was focused, cancel that manual input 1272 // 1273 1274 if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start 1275 if (this.timePicker) { 1276 var hour = parseInt(this.container.find('.left .hourselect').val(), 10); 1277 if (!this.timePicker24Hour) { 1278 var ampm = this.container.find('.left .ampmselect').val(); 1279 if (ampm === 'PM' && hour < 12) 1280 hour += 12; 1281 if (ampm === 'AM' && hour === 12) 1282 hour = 0; 1283 } 1284 var minute = parseInt(this.container.find('.left .minuteselect').val(), 10); 1285 var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0; 1286 date = date.clone().hour(hour).minute(minute).second(second); 1287 } 1288 this.endDate = null; 1289 this.setStartDate(date.clone()); 1290 } else if (!this.endDate && date.isBefore(this.startDate)) { 1291 //special case: clicking the same date for start/end, 1292 //but the time of the end date is before the start date 1293 this.setEndDate(this.startDate.clone()); 1294 } else { // picking end 1295 if (this.timePicker) { 1296 var hour = parseInt(this.container.find('.right .hourselect').val(), 10); 1297 if (!this.timePicker24Hour) { 1298 var ampm = this.container.find('.right .ampmselect').val(); 1299 if (ampm === 'PM' && hour < 12) 1300 hour += 12; 1301 if (ampm === 'AM' && hour === 12) 1302 hour = 0; 1303 } 1304 var minute = parseInt(this.container.find('.right .minuteselect').val(), 10); 1305 var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0; 1306 date = date.clone().hour(hour).minute(minute).second(second); 1307 } 1308 this.setEndDate(date.clone()); 1309 if (this.autoApply) { 1310 this.calculateChosenLabel(); 1311 this.clickApply(); 1312 } 1313 } 1314 1315 if (this.singleDatePicker) { 1316 this.setEndDate(this.startDate); 1317 if (!this.timePicker) 1318 this.clickApply(); 1319 } 1320 1321 this.updateView(); 1322 1323 //This is to cancel the blur event handler if the mouse was in one of the inputs 1324 e.stopPropagation(); 1325 1326 }, 1327 1328 calculateChosenLabel: function () { 1329 var customRange = true; 1330 var i = 0; 1331 for (var range in this.ranges) { 1332 if (this.timePicker) { 1333 var format = this.timePickerSeconds ? "YYYY-MM-DD hh:mm:ss" : "YYYY-MM-DD hh:mm"; 1334 //ignore times when comparing dates if time picker seconds is not enabled 1335 if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) { 1336 customRange = false; 1337 this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key'); 1338 break; 1339 } 1340 } else { 1341 //ignore times when comparing dates if time picker is not enabled 1342 if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) { 1343 customRange = false; 1344 this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key'); 1345 break; 1346 } 1347 } 1348 i++; 1349 } 1350 if (customRange) { 1351 if (this.showCustomRangeLabel) { 1352 this.chosenLabel = this.container.find('.ranges li:last').addClass('active').attr('data-range-key'); 1353 } else { 1354 this.chosenLabel = null; 1355 } 1356 this.showCalendars(); 1357 } 1358 }, 1359 1360 clickApply: function(e) { 1361 this.hide(); 1362 this.element.trigger('apply.daterangepicker', this); 1363 }, 1364 1365 clickCancel: function(e) { 1366 this.startDate = this.oldStartDate; 1367 this.endDate = this.oldEndDate; 1368 this.hide(); 1369 this.element.trigger('cancel.daterangepicker', this); 1370 }, 1371 1372 monthOrYearChanged: function(e) { 1373 var isLeft = $(e.target).closest('.calendar').hasClass('left'), 1374 leftOrRight = isLeft ? 'left' : 'right', 1375 cal = this.container.find('.calendar.'+leftOrRight); 1376 1377 // Month must be Number for new moment versions 1378 var month = parseInt(cal.find('.monthselect').val(), 10); 1379 var year = cal.find('.yearselect').val(); 1380 1381 if (!isLeft) { 1382 if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) { 1383 month = this.startDate.month(); 1384 year = this.startDate.year(); 1385 } 1386 } 1387 1388 if (this.minDate) { 1389 if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) { 1390 month = this.minDate.month(); 1391 year = this.minDate.year(); 1392 } 1393 } 1394 1395 if (this.maxDate) { 1396 if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) { 1397 month = this.maxDate.month(); 1398 year = this.maxDate.year(); 1399 } 1400 } 1401 1402 if (isLeft) { 1403 this.leftCalendar.month.month(month).year(year); 1404 if (this.linkedCalendars) 1405 this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month'); 1406 } else { 1407 this.rightCalendar.month.month(month).year(year); 1408 if (this.linkedCalendars) 1409 this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month'); 1410 } 1411 this.updateCalendars(); 1412 }, 1413 1414 timeChanged: function(e) { 1415 1416 var cal = $(e.target).closest('.calendar'), 1417 isLeft = cal.hasClass('left'); 1418 1419 var hour = parseInt(cal.find('.hourselect').val(), 10); 1420 var minute = parseInt(cal.find('.minuteselect').val(), 10); 1421 var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0; 1422 1423 if (!this.timePicker24Hour) { 1424 var ampm = cal.find('.ampmselect').val(); 1425 if (ampm === 'PM' && hour < 12) 1426 hour += 12; 1427 if (ampm === 'AM' && hour === 12) 1428 hour = 0; 1429 } 1430 1431 if (isLeft) { 1432 var start = this.startDate.clone(); 1433 start.hour(hour); 1434 start.minute(minute); 1435 start.second(second); 1436 this.setStartDate(start); 1437 if (this.singleDatePicker) { 1438 this.endDate = this.startDate.clone(); 1439 } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) { 1440 this.setEndDate(start.clone()); 1441 } 1442 } else if (this.endDate) { 1443 var end = this.endDate.clone(); 1444 end.hour(hour); 1445 end.minute(minute); 1446 end.second(second); 1447 this.setEndDate(end); 1448 } 1449 1450 //update the calendars so all clickable dates reflect the new time component 1451 this.updateCalendars(); 1452 1453 //update the form inputs above the calendars with the new time 1454 this.updateFormInputs(); 1455 1456 //re-render the time pickers because changing one selection can affect what's enabled in another 1457 this.renderTimePicker('left'); 1458 this.renderTimePicker('right'); 1459 1460 }, 1461 1462 elementChanged: function() { 1463 if (!this.element.is('input')) return; 1464 if (!this.element.val().length) return; 1465 1466 var dateString = this.element.val().split(this.locale.separator), 1467 start = null, 1468 end = null; 1469 1470 if (dateString.length === 2) { 1471 start = moment(dateString[0], this.locale.format); 1472 end = moment(dateString[1], this.locale.format); 1473 } 1474 1475 if (this.singleDatePicker || start === null || end === null) { 1476 start = moment(this.element.val(), this.locale.format); 1477 end = start; 1478 } 1479 1480 if (!start.isValid() || !end.isValid()) return; 1481 1482 this.setStartDate(start); 1483 this.setEndDate(end); 1484 this.updateView(); 1485 }, 1486 1487 keydown: function(e) { 1488 //hide on tab or enter 1489 if ((e.keyCode === 9) || (e.keyCode === 13)) { 1490 this.hide(); 1491 } 1492 1493 //hide on esc and prevent propagation 1494 if (e.keyCode === 27) { 1495 e.preventDefault(); 1496 e.stopPropagation(); 1497 1498 this.hide(); 1499 } 1500 }, 1501 1502 updateElement: function() { 1503 if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) { 1504 this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); 1505 this.element.trigger('change'); 1506 } else if (this.element.is('input') && this.autoUpdateInput) { 1507 this.element.val(this.startDate.format(this.locale.format)); 1508 this.element.trigger('change'); 1509 } 1510 }, 1511 1512 remove: function() { 1513 this.container.remove(); 1514 this.element.off('.daterangepicker'); 1515 this.element.removeData(); 1516 } 1517 1518 }; 1519 1520 $.fn.daterangepicker = function(options, callback) { 1521 var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options); 1522 this.each(function() { 1523 var el = $(this); 1524 if (el.data('daterangepicker')) 1525 el.data('daterangepicker').remove(); 1526 el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback)); 1527 }); 1528 return this; 1529 }; 1530 1531 return DateRangePicker; 1532 1533}));
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.