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