1/* global moment */ 2 3var $mixpicker = {}; 4(function ($) { 5 "use strict"; 6 $mixpicker = { 7 //MAP 8 'map': [], 9 'flat_map': [], 10 'status_map': {}, 11 12 // CONFIG 13 'config': { 14 'checkin': null, 15 'checkout': null, 16 'stage': 0, 17 'oldStage': 0, 18 'visible': false, 19 'changed': false, 20 'blocked': false, 21 'hasMonths': false, 22 'monthsRendered': 4, 23 'monthsStart': 4 24 }, 25 26 // OPTIONS 27 'options': { 28 'mode': 'popup', // modal, inline 29 'container': 'body', 30 'firstDay': 0, 31 'start': null, 32 'min': true, 33 'max': false, 34 'disabled': null, 35 'checkin': null, 36 'checkout': null, 37 'select': true, 38 'minNights': null, 39 'numNights': null, 40 'maxNights': null, 41 'trigger': null, 42 'triggerMode': 'click', 43 'mix': false, 44 'hoverMode': null, 45 'forcePosition': false, 46 'forcePositionBox': null, 47 'hoverClass': 'mp-active', 48 'minOverlay': null, 49 'maxOverlay': null, 50 'oneClick': false, 51 'autoScroll': true, 52 'onInit': function (date) { 53 return date; 54 }, 55 'onSetup': function () { 56 return false; 57 }, 58 'onClose': function (date) { 59 return false; 60 }, 61 'onStageChange': function (stage, oldstage) { 62 return false; 63 }, 64 'onSelect': function (date) { 65 return date; 66 }, 67 'onSet': function (date, stage) { 68 return date; 69 }, 70 'beforDayShow': function (day) { 71 return null; 72 }, 73 'beforeSetup': function () { 74 return false; 75 }, 76 'beforeOpen': function () { 77 return this; 78 }, 79 'onBlocked': function () { 80 return false; 81 }, 82 'onTriggerClicked': function () { 83 return false; 84 } 85 }, 86 87 // TEMPLATE 88 'template': '<div class="mixpicker mixpicker__mixbox"><div class="mixpicker__wrapper"><div class="mixpicker__months"> </div><a href="#" class="mixpicker__btn mixpicker__mobile-more" style="display: none">Dalszy termin</a></div><div class="mixpicker__footer"><div class="mixpicker__message"></div><div class="mixpicker__select"><a href="#" class="mixpicker__btn"></a></div></div><a href="#" class="mixpicker__close"></a><div class="mixpicker__nav"><a href="#" class="mixpicker__btn mixpicker__prev" disabled="disabled"></a><a href="#" class="mixpicker__btn mixpicker__next" disabled="disabled"></a></div></div>', 89 90 // BOXES 91 'box': { 92 'container': null, 93 'toggle': null, 94 'wrap': null, 95 'months': null, 96 'nav': { 97 'prev': null, 98 'next': null 99 }, 100 'close': null, 101 'head': null, 102 'footer': null, 103 'select': null, 104 'message': null, 105 'mobile': null 106 }, 107 108 // BIND 109 'bind_toggle': function () { 110 var $self = this; 111 if ($self.options.mode !== 'inline') { 112 if ($self.options.triggerMode === "click") { 113 $self.box.toggle 114 .off() 115 .click(function (e) { 116 $self.options.onTriggerClicked(); 117 e.preventDefault(); 118 e.stopPropagation(); 119 if ($self.config.blocked === false) { 120 $self._setStage(0); 121 122 $self._setPosition(); 123 $self._setToggleData(); 124 $self._visibleToggle(); 125 } else { 126 $self.options.onBlocked(); 127 } 128 }); 129 } 130 if ($self.options.trigger) { 131 if ($self.options.trigger instanceof Array) { 132 133 $.each($self.options.trigger, function (id, trigger) { 134 $(document) 135 .off('click', trigger) 136 .on('click', trigger, function (e) { 137 $self.options.onTriggerClicked(trigger); 138 e.preventDefault(); 139 e.stopPropagation(); 140 if ($self.config.blocked === false) { 141 $self._setPosition(); 142 $self._setToggleData(); 143 $self._visibleToggle(); 144 } else { 145 $self.options.onBlocked(); 146 } 147 }); 148 }); 149 } else if ($self.options.trigger instanceof Object) { 150 151 if ($self.options.trigger.checkin) { 152 $.each($self.options.trigger.checkin, function (id, trigger) { 153 $(trigger, 'body') 154 .off() 155 .click(function (e) { 156 $self.options.onTriggerClicked(trigger); 157 e.preventDefault(); 158 e.stopPropagation(); 159 if ($self.config.blocked === false) { 160 $self._setPosition(); 161 // $self._setToggleData(); 162 $self._visibleToggle(); 163 $self._setStage(0); 164 } else { 165 $self.options.onBlocked(); 166 } 167 }); 168 }); 169 } 170 if ($self.options.trigger.checkout) { 171 $.each($self.options.trigger.checkout, function (id, trigger) { 172 $(trigger) 173 .off() 174 .click(function (e) { 175 $self.options.onTriggerClicked(trigger); 176 e.preventDefault(); 177 e.stopPropagation(); 178 if ($self.config.blocked === false) { 179 $self._setPosition(); 180 // $self._setToggleData(); 181 $self._visibleToggle(); 182 $self._setStage($self.options.numNights ? 0 : 1); 183 if ($self.options.oneClick && $self.config.checkin && !$self.options.numNights) { 184 $self._setStage(1); 185 } else if ($self.options.oneClick && !$self.config.checkin && !$self.options.numNights) { 186 $self._setStage(0); 187 } 188 } else { 189 $self.options.onBlocked(); 190 } 191 }); 192 }); 193 } 194 } 195 } 196 197 var $closeEl = $self.options.mode === 'popup' ? 'body' : '.mixpicker_modal'; 198 $(document) 199 .on('click touchstart', $closeEl, function (e) { 200 var target = $(e.target); 201 if (target.closest('.mixpicker__mixbox').length === 0 && $self.config.visible === true) { 202 if (!($self.options.trigger instanceof Object)) { 203 $self._setCheckin(null); 204 $self._setCheckout(null); 205 $self._setToggleData(); 206 } 207 $self._visibleOff('out-click'); 208 } 209 }); 210 } 211 return $self; 212 }, 213 'makeSelectAction': function () { 214 var $self = this; 215 if ($self.config.checkin && $self.config.checkout) { 216 $self.box.toggle.data({ 217 'checkin': $self.config.checkin.format('YYYY-MM-DD'), 218 'checkout': $self.config.checkout.format('YYYY-MM-DD') 219 }); 220 setTimeout(function () { 221 $self.options.onSelect({ 222 type: 'select', 223 checkin: moment($self.config.checkin), 224 checkout: moment($self.config.checkout) 225 }); 226 }, 0); 227 } 228 $self._visibleOff('select'); 229 return $self; 230 }, 231 'bind_select': function () { 232 var $self = this; 233 if ($self.options.select === false) { 234 return false;
235 } 236 $self.box.select 237 .off() 238 .click(function (e) { 239 e.preventDefault(); 240 e.stopPropagation(); 241 $self.makeSelectAction(); 242 }); 243 return $self; 244 }, 245 'bind_daySelect': function () { 246 var $self = this, 247 $this = null; 248 249 $(document).on('mouseleave', '.mixpicker__table_month', function () { 250 if (!$self.config.checkin || !$self.config.checkout) 251 return; 252 var _inIndex = $self.flat_map.indexOf($self.config.checkin.format('YYYY-MM-DD')), 253 _hIndex = $self.flat_map.indexOf($self.config.checkout.format('YYYY-MM-DD')); 254 if (_inIndex < _hIndex) { 255 $self.box.wrap 256 .find('div.mixpicker__day') 257 .eq(_hIndex) 258 .addClass('mixpicker__checkout'); 259 } 260 }); 261 var dragging = false; 262 263 //only on mobile 264 $(document).on('click', '.mixpicker__mobile-more', function (e) { 265 e.preventDefault(); 266 e.stopPropagation(); 267 if (!$self.detectMobile()) return; 268 269 $self._mapAppendNew(); 270 $self._mapAppendNew(); 271 272 $self._updateMoreButton(); 273 274 $self._mobileScrollToMore(); 275 }); 276 277 $(document) 278 .on("touchmove", function () { 279 dragging = true; 280 }) 281 .on("touchstart", function () { 282 dragging = false; 283 }) 284 .on('touchend click', 'td.mixpicker__day', function (e) { 285 e.stopPropagation(); 286 e.preventDefault(); 287 var $thisd = this; 288 $(this).blur(); 289 if (dragging) 290 return; 291 if (e.handled !== true) { 292 $self._selectDay($thisd); 293 e.handled = true; 294 295 } else { 296 return false; 297 } 298 }); 299 300 $(document).on('mouseover', '.mixpicker__day', function () { 301 var $this = $('div', this); 302 var _inIndex, _hIndex, _d, _mIndex, _hIndexNum, dayBox; 303 304 if ($self.config.stage === 1) { 305 _d = moment($this.data('date')); 306 _inIndex = $self.flat_map.indexOf($self.config.checkin.format('YYYY-MM-DD')); 307 _hIndex = $self.flat_map.indexOf($this.data('date')); 308 309 310 if ((!$self.options.numNights) && _hIndex < _inIndex) { 311 if ($self.box.wrap 312 .find('div.mixpicker__day') 313 .eq(_inIndex + ($self.options.minNights ? $self.options.minNights : 1)) 314 .hasClass('mixpicker__checkoutRemoved')) { 315 $self.box.wrap 316 .find('div.mixpicker__day') 317 .eq(_inIndex + ($self.options.minNights ? $self.options.minNights : 1)) 318 .addClass('mixpicker__checkout') 319 .removeClass('mixpicker__checkoutRemoved'); 320 } 321 } else if ((!$self.options.numNights) && _inIndex === _hIndex) { 322 $self.box.wrap 323 .find('div.mixpicker__day') 324 .eq(_hIndex + ($self.options.minNights ? $self.options.minNights : 1)) 325 .removeClass('mixpicker__checkout') 326 .addClass('mixpicker__checkoutRemoved'); 327 return; 328 } 329 330 if (_hIndex > _inIndex) { 331 if ($self.box.wrap.find('.mixpicker__checkout')) { 332 $self.box.wrap 333 .find('.mixpicker__checkout') 334 .removeClass('mixpicker__checkout') 335 .removeClass('mixpicker__checkoutRemoved'); 336 } 337 } 338 339 if (_d.isAfter($self.config.checkin)) { 340 341 if ($self.options.maxNights && (_hIndex - _inIndex) > $self.options.maxNights) { 342 _hIndex = _inIndex + $self.options.maxNights; 343 } 344 345 if (_hIndex > -1) { 346 $self.box.wrap 347 .find('div.mixpicker__day') 348 .removeClass('mixpicker__checkio') 349 .slice(_inIndex, _hIndex) 350 .addClass('mixpicker__checkio'); 351 $self.box.wrap 352 .find('div.mixpicker__day') 353 .removeClass('mixpicker__hover') 354 .slice(_inIndex + 1, _hIndex - 1) 355 .addClass('mixpicker__hover'); 356 357 } 358 359 // if($self.options.maxNights) { 360 // $self.box.wrap.find('div.mixpicker__day').slice(_hIndex, _hIndex + 5).addClass('mixpicker__error'); 361 // } 362 } else if ($self.config.checkin && _d.isBefore($self.config.checkin)) { 363 $self.box.wrap.find('div.mixpicker__day').removeClass('mixpicker__checkio'); 364 } 365 } else if ($self.config.stage === 0 && ($self.options.minNights || $self.options.numNights)) { 366 367 if ($self.config.checkin && $self.config.checkout) { 368 _inIndex = $self.flat_map.indexOf($self.config.checkin.format('YYYY-MM-DD')); 369 _hIndex = $self.flat_map.indexOf($self.config.checkout.format('YYYY-MM-DD')); 370 $self.box.wrap 371 .find('div.mixpicker__day') 372 .eq(_hIndex) 373 .addClass('mixpicker__checkout'); 374 $self.box.wrap 375 .find('div.mixpicker__day') 376 .eq(_inIndex) 377 .addClass('mixpicker__checkin'); 378 } 379 380 381 _hIndexNum = $self.box.wrap.find('div.mixpicker__day').index($this); 382 _mIndex = 0; 383 if ($self.options.numNights || $self.options.minNights) { 384 _mIndex = _hIndexNum + parseInt(($self.options.numNights ? $self.options.numNights + 1 : null) || ($self.options.minNights ? $self.options.minNights + 1 : null)); 385 } 386 387 dayBox = $self.box.wrap.find('div.mixpicker__day'); 388 389 $self.box.wrap.find('.mixpicker__checkin_tmp').removeClass('mixpicker__checkin_tmp'); 390 $self.box.wrap.find('.mixpicker__checkout_tmp').removeClass('mixpicker__checkout_tmp'); 391 392 dayBox.eq(_hIndexNum).removeClass('mixpicker__checkout'); 393 if (!dayBox.eq(_hIndexNum).hasClass('mixpicker__disabled')) { 394 dayBox.eq(_hIndexNum).addClass('mixpicker__checkin_tmp'); 395 } 396 397 //$self.box.wrap.find('div.mixpicker__day').eq(_hIndexNum).removeClass('mixpicker__checkout').addClass('mixpicker__checkin_tmp'); 398 $self.box.wrap.find('div.mixpicker__day').removeClass('mixpicker__checkio').slice(_hIndexNum, _mIndex).addClass('mixpicker__checkio'); 399 $self.box.wrap.find('div.mixpicker__day').removeClass('mixpicker__hover').slice(_hIndexNum + 1, _mIndex - 1).addClass('mixpicker__hover'); 400 401 402 dayBox.eq(_mIndex - 1).removeClass('mixpicker__checkin'); 403 if (!dayBox.eq(_mIndex - 2).hasClass('mixpicker__disabled')) { 404 dayBox.eq(_mIndex - 1).addClass('mixpicker__checkout_tmp'); 405 } 406 407 //$self.box.wrap.find('div.mixpicker__day').eq(_mIndex - 1).removeClass('mixpicker__checkin').addClass('mixpicker__checkout_tmp'); 408 } 409 }); 410 $self.box.wrap.mouseleave(function () { 411 $self.box.wrap.find('div.mixpicker__day').removeClass('mixpicker__checkio mixpicker__checkin_tmp mixpicker__checkout_tmp mixpicker__hover'); 412 }); 413 414 //exp 415 $self.box.wrap.find('.mixpicker__month').mouseleave(function () { 416 $self.box.wrap.find('div.mixpicker__day').removeClass('mixpicker__checkio mixpicker__checkin_tmp mixpicker__checkout_tmp mixpicker__hover'); 417 }); 418 return $self; 419 }, 420 'bind_nav': function () { 421 var $self = this; 422 $self.box.nav.next 423 .off() 424 .click(function (e) { 425 e.preventDefault(); 426 e.stopPropagation(); 427 if ($self.box.nav.next.attr('disabled') !== 'disabled') { 428 $self._moveNav(1); 429 } 430 $self._updateNav(); 431 }); 432 $self.box.nav.prev 433 .off() 434 .click(function (e) { 435 e.preventDefault(); 436 e.stopPropagation(); 437 if ($self.box.nav.prev.attr('disabled') !== 'disabled') { 438 $self._moveNav(-1); 439 } 440 $self._updateNav(); 441 }); 442 return $self; 443 }, 444 'bind_close': function () { 445 var $self = this; 446 $self.box.close 447 .click(function (e) { 448 e.preventDefault(); 449 e.stopPropagation(); 450 $self._visibleOff('close-button'); 451 }); 452 return $self; 453 }, 454 'bind_resize': function () { 455 var $self = this; 456 $(window) 457 .on('resize', function () { 458 if ($self.config.visible === true) { 459 $self._setPosition(); 460 $self._updateNav();
461 $self.update(); 462 463 if ($self.detectMobile() === true) { 464 $self.box.container.addClass('mixpicker__mobile'); 465 if ($self.box.mobile) { 466 $self.box.mobile.addClass('mixpicker__mobile-hld'); 467 } 468 } else { 469 $self.box.container.removeClass('mixpicker__mobile'); 470 if ($self.box.mobile) { 471 $self.box.mobile.removeClass('mixpicker__mobile-hld'); 472 } 473 } 474 } 475 }); 476 $(window) 477 .on('scroll', function () { 478 if ($self.config.visible === true) { 479 $self._setPosition(); 480 $self._updateNav(); 481 } 482 }); 483 484 return $self; 485 }, 486 487 // RENDERS 488 'render_container': function () { 489 var $self = this; 490 var _template = $('<div/>', { 491 'class': 'mixpicker__template' 492 }).html($self.template).find('.mixpicker__mixbox'); 493 _template.attr('id', 'mb-' + ($self.id ? $self.id : 'mixpickerbox')); 494 if ($self.options.mode === 'inline') { 495 $($self.options.container).after(_template); 496 } else { 497 $($self.options.container).append(_template); 498 } 499 500 $self.box.container = _template; 501 if ($self.options.mode !== 'inline') { 502 $self.box.container.hide(); 503 } else { 504 $self.box.toggle.hide(); 505 } 506 $self.box.select = $self.box.container.find('.mixpicker__select > a'); 507 508 $self.box.select.html(_l('select')); 509 510 $self.box.months = $self.box.container.find('.mixpicker__months'); 511 $self.box.wrap = $self.box.container.find('.mixpicker__wrapper'); 512 513 $self.box.head = $self.box.container.find('.mixpicker__header'); 514 515 $self.box.nav.prev = $self.box.container.find('.mixpicker__prev'); 516 $self.box.nav.next = $self.box.container.find('.mixpicker__next'); 517 $self.box.close = $self.box.container.find('.mixpicker__close'); 518 $self.box.message = $self.box.container.find('.mixpicker__message'); 519 520 if ($self.options.select === false) { 521 $self.box.select.remove(); 522 } 523 524 $self.box.container.addClass('mixpicker__' + $self.options.mode); 525 526 if ($self.detectMobile() === true && $self.options.mode !== 'inline' || $self.detectMobile() === false && $self.options.mode == 'modal') { 527 $self.box.container.addClass('mixpicker__mobile'); 528 $self.box.mobile = $('<div/>', { 529 'class': 'mixpicker_modal' 530 }); 531 $self.box.mobile.addClass('mixpicker__mobile-hld'); 532 // $self.options.mode = 'mobile'; 533 $self.box.container = $self.box.container.detach(); 534 $self.box.container.removeClass('mixpicker__popup'); 535 // $self.box.container.addClass('mixpicker__mobile'); 536 $self.box.mobile.append($self.box.container); 537 $($self.options.container).append($self.box.mobile); 538 } 539 540 return $self; 541 }, 542 'render_monthTemplate': function () { 543 544 var $html = $('<div/>', { 545 'class': 'mixpicker__month' 546 }), 547 $table = $('<table/>', { 548 'class': 'mixpicker__table_month' 549 }), 550 $month_name = $('<div/>', { 551 'class': 'mixpicker__month_name' 552 }), 553 $thead = $('<thead/>'), 554 $tbody = $('<tbody/>'); 555 556 for (var w = 0; w < 7; w++) { 557 if (typeof(w) === 'number') { 558 $thead.append('<th>' + moment().isoWeekday(w + 1).format('ddd') + '</th>'); 559 } 560 } 561 562 $html.append($month_name); 563 $table.append($thead); 564 $table.append($tbody); 565 $html.append($table); 566 return $html; 567 }, 568 'render_months': function () { 569 var $self = this; 570 $self.box.months.empty(); 571 var monthTemplate = $self.render_monthTemplate(); 572 573 var _stat, month, days, d, _date, $t, tr; 574 for (month in $self.map) { 575 if ($self.map.hasOwnProperty(month)) { 576 days = $self.map[month]; 577 _date = moment(days.code + '-01'); 578 $t = monthTemplate.clone(); 579 tr = '<tr>'; 580 581 days = days.days; 582 for (d in days) { 583 if (days.hasOwnProperty(d)) { 584 if (d > 0 && d % 7 === 0) { 585 tr += '</tr><tr>'; 586 } 587 if (days[d]) { 588 var statusFunction = $self.options.beforDayShow(days[d].date); 589 _stat = $self.status_map[days[d].date] ? $self.status_map[days[d].date].join(' ') : ''; 590 if (statusFunction) { 591 var _tstatus = statusFunction.join(' '); 592 _stat = _stat + ' ' + _tstatus; 593 } 594 tr += '<td class="mixpicker__day"><div data-date="' + days[d].date + '" class="mixpicker__day ' + _stat + '"><a href="#">
594' + days[d].day + '</a></div></td>'; 595 } else { 596 tr += '<td></td>'; 597 } 598 } 599 } 600 tr += '</tr>'; 601 $('.mixpicker__month_name', $t).html(_date.format('MMMM YYYY')); 602 $('.mixpicker__table_month', $t).append(tr); 603 $self.box.months.append($t); 604 } 605 } 606 return $self; 607 }, 608 'update_months': function () { 609 var $self = this; 610 var date; 611 $('.mixpicker__day', $self.box.months).attr('class', 'mixpicker__day'); 612 for (date in $self.status_map) { 613 if ($self.status_map[date].length) { 614 $('.mixpicker__day[data-date="' + date + '"]', $self.box.months) 615 .addClass($self.status_map[date].join(' ')); 616 } 617 } 618 return $self; 619 }, 620 621 622 // FUNCTIONS 623 '_setOptions': function (options) { 624 var $self = this; 625 $self.options = $.extend({}, $self.options, options); 626 627 if ($self.options.numNights) { 628 $self.options.numNights = parseInt($self.options.numNights); 629 } 630 if ($self.options.minNights) { 631 $self.options.minNights = parseInt($self.options.minNights); 632 } 633 if ($self.options.maxNights) { 634 $self.options.maxNights = parseInt($self.options.maxNights); 635 } 636 637 if ($self.options.oneClick) { 638 //$self.options.select = false; 639 } 640 641 $self._setToggleData(); 642 return true; 643 }, 644 645 '_setToggleData': function () { 646 var $self = this; 647 if ($self.box.toggle.data('checkin')) { 648 $self._setCheckin($self.box.toggle.data('checkin')); 649 } 650 if ($self.box.toggle.data('checkout')) { 651 $self._setCheckout($self.box.toggle.data('checkout')); 652 } 653 return $self; 654 }, 655 '_prepareConfig': function () { 656 var $self = this; 657 if ($self.options.checkin) { 658 $self._setCheckin($self.options.checkin); 659 } 660 if ($self.options.checkout) { 661 $self._setCheckout($self.options.checkout); 662 } 663 if ($self.options.mode === 'inline') { 664 $self.options.container = $self.box.toggle; 665 } 666 return true; 667 }, 668 '_setCheckin': function (date) { 669 var $self = this; 670 date = moment(date); 671 if ($self.box.wrap) { 672 $self.box.wrap.find('div.mixpicker__day').removeClass('mixpicker__selected'); 673 } 674 $self.config.checkin = date; 675 $self._updateMap(date, 'mixpicker__checkin'); 676 setTimeout(function () { 677 $self.options.onSet($self.config.checkin, 0, $self.config.visible); 678 }, 0); 679 return true; 680 }, 681 '_setCheckout': function (date) { 682 var $self = this; 683 if (date) { 684 date = moment(date); 685 if (date.isAfter($self.config.checkin)) { 686 $self.config.checkout = date; 687 } else { 688 $self.config.checkout = moment($self.config.checkin).add(1, 'd'); 689 } 690 $self._updateMap(date, 'mixpicker__checkout'); 691 } else { 692 $self.config.checkout = null; 693 } 694 setTimeout(function () { 695 $self.options.onSet($self.config.checkout, 1, $self.config.visible); 696 }, 0); 697 return true; 698 }, 699 '_mobileScrollToMore': function () { 700 if (!this.detectMobile()) return; 701 var $self = this; 702 703 var monthToScroll = this.config.monthsRendered - 2; 704 var lastMonth = this.map[monthToScroll]; 705 var halfScroll = false; 706 707 if (this.config.stage === 1) { 708 var checkinCode = this.config.checkin.format('YYYY-MM'); 709 if (checkinCode == lastMonth.code) halfScroll = true; 710 } 711 var element = $('.mixpicker__month').eq(halfScroll ? monthToScroll : monthToScroll + 1); 712 if (element) 713 setTimeout(function () { 714 $self.box.mobile.animate({ 715 scrollTop: element.position().top 716 }, 500); 717 }, 250); 718 719 }, 720 '_updateMap': function (date, type) { 721 var $self = this; 722 var checkin = null, 723 checkout = null; 724 if (typeof(date) === 'object' && date.isValid() === true) { 725 var arrayIndex; 726 var checkinIndex, checkoutIndex; 727 var items; 728 729 var _iDate; 730 for (_iDate in $self.status_map) { 731 if (type === 'mixpicker__checkin') { 732 arrayIndex = $self.status_map[_iDate].indexOf('mixpicker__checkin'); 733 if (arrayIndex > -1) { 734 $self.status_map[_iDate].splice(arrayIndex, 1); 735 } 736 arrayIndex = $self.status_map[_iDate].indexOf('mixpicker__checkout'); 737 if (arrayIndex > -1) { 738 $self.status_map[_iDate].splice(arrayIndex, 1); 739 } 740 arrayIndex = $self.status_map[_iDate].indexOf('mixpicker__selected'); 741 if (arrayIndex > -1) { 742 $self.status_map[_iDate].splice(arrayIndex, 1); 743 } 744 } else if (type === 'mixpicker__checkout') { 745 arrayIndex = $self.status_map[_iDate].indexOf('mixpicker__checkout'); 746 if (arrayIndex > -1) { 747 $self.status_map[_iDate].splice(arrayIndex, 1); 748 } 749 arrayIndex = $self.status_map[_iDate].indexOf('mixpicker__selected'); 750 if (arrayIndex > -1) { 751 $self.status_map[_iDate].splice(arrayIndex, 1); 752 } 753 } else { 754 arrayIndex = $self.status_map[_iDate].indexOf(type); 755 if (arrayIndex > -1) { 756 $self.status_map[_iDate].splice(arrayIndex, 1); 757 } 758 } 759 760 //for2 761 if (_iDate === date.format('YYYY-MM-DD')) { 762 $self.status_map[_iDate].push(type); 763 } 764 765 } 766 767 checkin = $.map($self.status_map, function (e, id) { 768 if (e.indexOf('mixpicker__checkin') > -1) return id; 769 })[0]; 770 checkout = $.map($self.status_map, function (e, id) { 771 if (e.indexOf('mixpicker__checkout') > -1) return id; 772 })[0]; 773 774 if (checkin && checkout) { 775 checkinIndex = $self.flat_map.indexOf(checkin); 776 checkoutIndex = $self.flat_map.indexOf(checkout); 777 items = $self.flat_map.slice(checkinIndex, checkoutIndex); 778 for (var item in items) { 779 if ($self.status_map.hasOwnProperty(items[item]) && $self.status_map[items[item]].indexOf('mixpicker__selected') < 0) { 780 $self.status_map[items[item]].push('mixpicker__selected'); 781 } 782 } 783 } 784 } 785 786 return $self; 787 }, 788 '_moveNav': function (mode, pixels) { 789 var $self = this;
790 var _wrapperWidth = $self.box.wrap.outerWidth(true), 791 _segmentWidth = $self.box.months.find('.mixpicker__month').first().outerWidth(true), 792 _monthsLeft = parseInt($self.box.months.attr('data-offset')), 793 _maxWidth = (function () { 794 var max = 0; 795 $self.box.months.find('.mixpicker__month').each(function (id, el) { 796 max -= parseInt($(el).outerWidth(true)); 797 }); 798 return max; 799 }()) + _wrapperWidth; 800 801 if (pixels) { 802 if (mode < _maxWidth) { 803 mode = _maxWidth; 804 } 805 if (mode <= (_maxWidth + _segmentWidth)) { 806 $self._mapAppendNew(); 807 } 808 $self.box.months.attr('data-offset', mode); 809 810 //14.09 - remove animate, use css 811 $self.box.months.stop(true, true).css({ 812 marginLeft: mode + 'px' 813 }).attr('data-offset', mode); 814 815 $self._updateNav(); 816 return $self; 817 } 818 819 var dest = 0; 820 if (mode > 0) { 821 dest = _monthsLeft - _segmentWidth; 822 if (dest < _maxWidth) { 823 dest = _maxWidth; 824 } 825 mode -= 1; 826 827 if (dest <= (_maxWidth + _segmentWidth)) { 828 $self._mapAppendNew(); 829 } 830 } else if (mode < 0) { 831 dest = _monthsLeft + _segmentWidth; 832 if (dest > 0) { 833 dest = 0; 834 } 835 mode += 1; 836 } 837 838 $self.box.months.attr('data-offset', dest); 839 if (mode === 0) { 840 $self.box.months.stop(true, true).animate({ 841 marginLeft: dest + 'px' 842 }, 500).attr('data-offset', dest); 843 } else { 844 this._moveNav(mode); 845 } 846 847 return $self; 848 }, 849 '_clickMove': function (element) { 850 var wrapWidth = this.box.wrap.width(), 851 mWidth = this.box.months.find('.mixpicker__month').first().outerWidth(true) * 2; 852 853 if (element && $(element).position() && wrapWidth + 10 >= mWidth && $(element).position().left > wrapWidth / 2) { 854 this._moveNav(1); 855 } 856 else if (this.box.container.hasClass('mixpicker__fullsize')) { 857 //move when last date in tablet mode 858 this._moveNav(1); 859 } 860 return this; 861 }, 862 '_updateNav': function () { 863 var $self = this; 864 var _prev = $self.box.nav.prev, 865 _next = $self.box.nav.next, 866 _wrapperWidth = $self.box.wrap.outerWidth(true), 867 _maxWidth = (function () { 868 var max = 0; 869 $('.mixpicker__table_month', $self.box.months).each(function (id, el) { 870 max -= parseInt($(el).width()); 871 }); 872 return max; 873 }()) + _wrapperWidth, 874 _monthsLeft = parseInt($self.box.months.attr('data-offset')); 875 if (!_monthsLeft) { 876 _monthsLeft = 0; 877 $self.box.months.attr('data-offset', 0); 878 } 879 880 if (_monthsLeft < 0) { 881 _prev.attr('disabled', null); 882 } else if (_monthsLeft >= 0) { 883 _prev.attr('disabled', 'disabled'); 884 } 885 886 var limit = null; 887 888 if ($self.config.maxMonth) { 889 limit = ( ($('.mixpicker__table_month', $self.box.months).eq(0).width() * -1) * $self.config.maxMonth) + _wrapperWidth; 890 } 891 892 if (( limit && _monthsLeft <= limit) || ($self.config.monthsRendered > 48 && _monthsLeft <= _maxWidth)) { 893 _next.attr('disabled', 'disabled'); 894 } else if (_monthsLeft <= 0) { 895 _next.attr('disabled', null); 896 } 897 898 return $self; 899 }, 900 '_visibleToggle': function () { 901 var $self = this; 902 if ($self.options.mode === 'inline' || $self.config.visible === true) { 903 $self._visibleOff(); 904 } else if ($self.config.visible === false) { 905 $self._visibleOn(); 906 } 907 908 return $self; 909 }, 910 '_visibleOff': function (mode) { 911 var $self = this; 912 if ($self.options.mode === 'inline' || $self.config.visible === false) { 913 return; 914 } 915 916 917 if ($self.box.mobile) { 918 $self.box.mobile.removeClass('active'); 919 } 920 921 $self.box.container.removeClass('active'); 922 923 setTimeout(function () { 924 if ($self.options.mode === 'popup') { 925 $("body").css("overflow", "auto"); 926 } 927 $('html').removeClass('disable-scroll'); 928 if ($self.box.mobile) $self.box.mobile.hide(0); 929 $self.box.container.hide(0); 930 }, 200); 931 932 $self.config.visible = false;
933 $self.config.hasMonths = false; 934 935 $self.update(); 936 937 var closeParams = {}; 938 if ($self.config.checkin && $self.config.checkout) { 939 closeParams.checkin = moment($self.config.checkin); 940 closeParams.checkout = moment($self.config.checkout); 941 } 942 setTimeout(function () { 943 $self.options.onClose(closeParams, $self.config.change, mode || 'select'); 944 }, 0); 945 $self.config.change = false; 946 947 return $self; 948 }, 949 '_visibleOn': function () { 950 var $self = this; 951 $self.options.beforeOpen(); 952 953 if ($self.config.monthsRendered > $self.config.monthsStart) { 954 //$self.map; 955 $self._mapReset(); 956 } 957 958 if ($self.options.select) { 959 $self.box.select.html(_l('select')); 960 } 961 962 if ($self.options.mode === 'inline' || $self.config.visible === true) { 963 return; 964 } 965 $('body').trigger('click'); 966 if ($self.options.mode === "modal") { 967 $self.box.container.css('top', (window.innerHeight - 454) / 2); 968 } 969 970 if ($self.box.mobile) { 971 $self.box.mobile.show(0).addClass('active'); 972 } 973 $self.box.container.show(0).addClass('active'); 974 975 976 $self.config.visible = true; 977 $self.update(); 978 979 if ($self.config.checkin) { 980 setTimeout(function () { 981 var _monthsLeft = parseInt($self.box.months.attr('data-offset')), 982 position = 0, 983 positionMobile = 0, 984 _ewi = $self.box.months.find('.mixpicker__month').first().outerWidth(true); 985 986 $self.box.months.find('.mixpicker__month').each(function (seq, element) { 987 if ($(element).find('.mixpicker__checkin').length > 0) { 988 position = seq; 989 positionMobile = $(element).offset().top - 10; 990 } 991 }); 992 993 if ($self.detectMobile() && $self.box.mobile) { 994 $self.box.mobile.animate({ 995 scrollTop: positionMobile 996 }, 200); 997 } else { 998 if (($self.options.autoScroll === true || !$self.initiallyScrolled) && _monthsLeft < position * _ewi) { 999 $self._moveNav(-position * _ewi, true); 1000 } 1001 $self.initiallyScrolled = true; 1002 } 1003 }, 150); 1004 } 1005 1006 if ($self.detectMobile() === true) { 1007 $('html').addClass('disable-scroll'); 1008 $self.box.container.addClass('mixpicker__mobile'); 1009 if ($self.box.mobile) { 1010 $self.box.mobile.addClass('mixpicker__mobile-hld'); 1011 } 1012 } else { 1013 $self.box.container.removeClass('mixpicker__mobile'); 1014 if ($self.box.mobile) { 1015 $self.box.mobile.removeClass('mixpicker__mobile-hld'); 1016 } 1017 } 1018 1019 $self.config.maxMonth = $self.options.max ? moment($self.options.max).endOf('month').diff(moment(), 'month') + 1 : null; 1020 1021 $self._updateNav(); 1022 return $self; 1023 }, 1024 '_updateStageHover': function (remove) { 1025 var $self = this; 1026 if ($self.config.visible === false || remove) { 1027 $('.' + $self.options.hoverClass).removeClass($self.options.hoverClass); 1028 return; 1029 } else if ($self.config.visible && $self.options.hoverMode) { 1030 $($self.options.hoverMode.checkout.join(', ')).removeClass($self.options.hoverClass); 1031 $($self.options.hoverMode.checkin.join(', ')).removeClass($self.options.hoverClass); 1032 if ($self.config.stage === 0) { 1033 $($self.options.hoverMode.checkin.join(', ')).addClass($self.options.hoverClass); 1034 } else if ($self.config.stage === 1) { 1035 $($self.options.hoverMode.checkout.join(', ')).addClass($self.options.hoverClass); 1036 } 1037 } 1038 }, 1039 '_setStage': function (stage) { 1040 var $self = this; 1041 1042 $self.config.oldStage = $self.config.stage; 1043 $self.config.stage = stage; 1044 1045 $self.updateMessage(); 1046 1047 setTimeout(function () { 1048 $self._updateStageHover(); 1049 $self.options.onStageChange(stage, $self.config.oldStage); 1050 }, 0); 1051 }, 1052 '_setPosition': function () { 1053 var $self = this; 1054 if ($self.box.mobile !== null) { 1055 return false;
1056 } 1057 if ($self.options.mode === 'popup') { 1058 // var _mixWidth = parseInt($self.box.container.css('width')), 1059 var _mixWidth = $self.box.container.outerWidth(), 1060 _mixHeight = $self.box.container.outerHeight(true), 1061 1062 _toggleWidth = $self.box.toggle.outerWidth(true), 1063 _toggleHeight = $self.box.toggle.outerHeight(true), 1064 _toggleOffset = $self.box.toggle.offset(), 1065 1066 _windowHeight = window.innerHeight, 1067 _windowWidth = window.innerWidth, 1068 1069 _documentTop = $(document).scrollTop(); 1070 1071 var horizontal; 1072 if ($self.options.forcePosition === false) { 1073 var vertical = 1074 _toggleOffset.top + _mixHeight < _documentTop + _windowHeight ? 'bottom' : 1075 _toggleOffset.top - _mixHeight > _documentTop ? 'top' : 1076 'center'; //pion 1077 horizontal = _toggleOffset.left + _mixWidth < _windowWidth ? 'right' : 1078 _toggleOffset.left - _mixWidth > 0 ? 'left' : 1079 'center'; //poziom 1080 1081 $self.box.container.css({ 1082 left: horizontal === 'right' ? _toggleOffset.left : horizontal === 'left' ? _toggleOffset.left - _mixWidth + _toggleWidth : 0, 1083 top: vertical === 'top' ? _toggleOffset.top - _documentTop - _mixHeight + _toggleHeight : vertical === 'bottom' ? _toggleOffset.top - _documentTop : 0 1084 }); 1085 } else { 1086 if ($self.options.forcePositionBox) { 1087 var $toggle = $($self.options.forcePositionBox); 1088 if ($toggle.length) { 1089 _toggleWidth = $toggle.outerWidth(true); 1090 _toggleHeight = $toggle.outerHeight(true); 1091 _toggleOffset = $toggle.offset(); 1092 } 1093 } 1094 1095 horizontal = _toggleOffset.left + _mixWidth > _windowWidth ? 'right' : 1096 _toggleOffset.left - _mixWidth < 0 ? 'left' : 1097 'left'; //poziom 1098 1099 if (horizontal === "left") { 1100 $self.box.container.css({ 1101 left: _toggleOffset.left, 1102 top: _toggleOffset.top - _documentTop 1103 }); 1104 } else if (horizontal === "right") { 1105 $self.box.container.css({ 1106 left: (_toggleOffset.left + _toggleWidth) - _mixWidth, 1107 top: _toggleOffset.top - _documentTop 1108 }); 1109 } 1110 } 1111 } else if ($self.options.mode === 'inline') { 1112 1113 } 1114 1115 return $self; 1116 }, 1117 '_dateIsDisabled': function (date) { 1118 var $self = this; 1119 if (typeof($self.options.min) === 'string' && date.isBefore(moment($self.options.min))) { 1120 return true; 1121 } 1122 if (typeof($self.options.max) === 'string' && date.isAfter(moment($self.options.max))) { 1123 return true; 1124 } 1125 if ($self.options.disabled && $self.options.disabled.length > 0) { 1126 return $self.options.disabled.indexOf(date.format('YYYY-MM-DD')) > -1; 1127 } 1128 return false; 1129 }, 1130 '_getDayStatus': function (_date) { 1131 var $self = this; 1132 var today = moment(); 1133 var $s = []; 1134 if ((_date.isBefore(today) && ($self.options.min === true && _date.format('YYYY-MM-DD') !== today.format('YYYY-MM-DD'))) || $self._dateIsDisabled(_date)) { 1135 $s.push('mixpicker__disabled'); 1136 } else if (today.format('YYYY-MM-DD') === _date.format('YYYY-MM-DD')) { 1137 $s.push('mixpicker__current'); 1138 } 1139 1140 if ($self.options.minOverlay && $self.options.maxOverlay && $s.indexOf('mixpicker__disabled') < 0) {
1141 var mMin = moment($self.options.minOverlay), 1142 mMax = moment($self.options.maxOverlay); 1143 if ((_date.isSame(mMin) || _date.isAfter(mMin)) && (_date.isBefore(mMax) || _date.isSame(mMax))) { 1144 $s.push('mixpicker__checkoverlay'); 1145 } 1146 } 1147 1148 if ($self.config.checkin && _date.isSame($self.config.checkin)) { 1149 $s.push('mixpicker__checkin'); 1150 $s.push('mixpicker__selected'); 1151 } else if ($self.config.checkout && _date.isSame($self.config.checkout)) { 1152 $s.push('mixpicker__checkout'); 1153 $s.push('mixpicker__selected'); 1154 } else if ($self.config.checkin && $self.config.checkout && _date.isAfter($self.config.checkin) && _date.isBefore($self.config.checkout)) { 1155 $s.push('mixpicker__selected'); 1156 } 1157 return $s; 1158 }, 1159 1160 '_getMounthsWeek': function (date, position) { 1161 var start = moment(date), 1162 end = moment(start).endOf('month'), 1163 isEnd = false, 1164 dayIndex = position, 1165 weeks = 1, 1166 _date = null, 1167 inc = 0; 1168 while (isEnd !== true) { 1169 if (dayIndex > 6) { 1170 dayIndex = 1; 1171 weeks++; 1172 } else { 1173 dayIndex++; 1174 } 1175 _date = moment(start).add(inc++, 'd'); 1176 1177 if (weeks > 7 || (_date.isSame(end) || _date.isAfter(end))) { 1178 isEnd = true; 1179 } 1180 } 1181 return weeks; 1182 }, 1183 1184 '_mapReset': function () { 1185 var $self = this; 1186 1187 var startMonth, startYear, end, days, month; 1188 1189 if (typeof($self.options.min) === 'string') { 1190 var _tempDate = moment($self.options.min); 1191 startMonth = _tempDate.format('MM'); 1192 startYear = _tempDate.format('YYYY'); 1193 } else { 1194 startMonth = moment().format('MM'); 1195 startYear = moment().format('YYYY'); 1196 } 1197 1198 var lastDay = $self.config.checkout || $self.config.checkin || null; 1199 var start = moment(startYear + '-' + startMonth + '-01'); 1200 1201 var end = lastDay ? moment(lastDay).add(2, 'month').endOf('month') : moment(start).add($self.config.monthsStart, 'month').endOf('month') 1202 , days = end.diff(start, 'd') 1203 , month = end.diff(start, 'month'); 1204 1205 for (var i in $self.map) { 1206 if (i > month) { 1207 delete $self.map[i]; 1208 } 1209 } 1210 1211 var indexC = 0; 1212 for (var c in $self.status_map) { 1213 if (++indexC > (days + 1)) { 1214 delete $self.status_map[c]; 1215 } 1216 } 1217 1218 $self.flat_map = $self.flat_map.slice(0, days + 1); 1219 this.config.monthsRendered = Object.keys(this.map).length - 1;//this.config.monthsStart; 1220 this._updateNav(); 1221 1222 }, 1223 '_mapAppendNew': function () { 1224 var $self = this, 1225 startMonth, startYear; 1226 1227 var _sM = ++this.config.monthsRendered; 1228 1229 if (typeof($self.options.min) === 'string') { 1230 var _tempDate = moment($self.options.min); 1231 startMonth = _tempDate.format('MM'); 1232 startYear = _tempDate.format('YYYY'); 1233 } else { 1234 startMonth = moment().format('MM'); 1235 startYear = moment().format('YYYY'); 1236 } 1237 1238 var startDate = moment(startYear + '-' + startMonth + '-01'); 1239 1240 //dodanie jednego miesiąca do puli - 1 jest w buforze 1241 var lastMonth = moment(startDate).add($self.config.monthsRendered - 1, 'month').endOf('month'); 1242 var newMonth = moment(lastMonth).add(1, 'day'); 1243 1244 var _date = newMonth, 1245 firstDaty = parseInt(_date.format('d')) - 1, 1246 _index = (_date.format('YYYY-MM')), 1247 _cM = _date.format('M'), 1248 _tempDayLast = moment(_date).endOf('month'); 1249 $self.map[_sM] = { 1250 code: _index, 1251 days: [], 1252 order: _sM 1253 }; 1254 if (firstDaty < 0) { 1255 firstDaty = 7 + firstDaty; 1256 } 1257 var limit = $self._getMounthsWeek(_index + '-01', firstDaty); 1258 if (limit > 5) { 1259 $self.box.wrap.addClass('mixpicker__addedWeek'); 1260 } 1261 for (var i = 0; i < (limit * 7); i++) { 1262 if (i < firstDaty || _date.format('M') !== _cM) { 1263 $self.map[_sM].days[i] = null; 1264 } else { 1265 var _obj = { 1266 year: parseInt(_date.format('YYYY')), 1267 month: parseInt(_date.format('M')), 1268 day: parseInt(_date.format('D')), 1269 date: _date.format('YYYY-MM-DD') 1270 }; 1271 $self.map[_sM].days[i] = _obj; 1272 $self.status_map[_date.format('YYYY-MM-DD')] = $self._getDayStatus(_date); 1273 1274 $self.flat_map.push(_date.format('YYYY-MM-DD')); 1275 _date.add(1, 'd'); 1276 } 1277 } 1278 1279 $self.config.hasMonths = false;
1280 $self.update(); 1281 $self._updateNav(); 1282 }, 1283 '_createMap': function () { 1284 var $self = this, 1285 startMonth, startYear; 1286 if (typeof($self.options.min) === 'string') { 1287 var _tempDate = moment($self.options.min); 1288 startMonth = _tempDate.format('MM'); 1289 startYear = _tempDate.format('YYYY'); 1290 } else { 1291 startMonth = moment().format('MM'); 1292 startYear = moment().format('YYYY'); 1293 } 1294 1295 var startDate = moment(startYear + '-' + startMonth + '-01'); 1296 var lastMaxDate; 1297 if (typeof($self.options.max) === 'string') { 1298 lastMaxDate = moment($self.options.max).endOf('month'); 1299 } else { 1300 var last = $self.config.checkout || $self.config.checkin || null; 1301 last = moment(last).add(1, 'month').endOf('month'); 1302 lastMaxDate = moment(startDate).add($self.config.monthsRendered, 'month').endOf('month'); 1303 1304 if (lastMaxDate.diff(last, 'month') < 2) { 1305 lastMaxDate = moment(last).endOf('month'); 1306 } 1307 } 1308 1309 // var monthsCount = lastMaxDate.diff(startDate, 'months'); 1310 1311 var monthsCount = 0, 1312 stop = false, 1313 _d = moment(startDate); 1314 while (stop !== true) { 1315 monthsCount++; 1316 _d.add(1, 'month'); 1317 if (_d.isAfter(lastMaxDate) || monthsCount > 1000) { 1318 stop = true; 1319 } 1320 } 1321 1322 if (monthsCount <= 1) { 1323 monthsCount += 1; 1324 } 1325 1326 this.config.monthsRendered = monthsCount - 1; 1327 1328 for (var m = 0; m < monthsCount; m++) { 1329 var _date = startDate, 1330 firstDaty = parseInt(_date.format('d')) - 1, 1331 _index = (_date.format('YYYY-MM')), 1332 _cM = _date.format('M'), 1333 _tempDayLast = moment(_date).endOf('month'); 1334 $self.map[m] = { 1335 code: _index, 1336 days: [], 1337 order: m 1338 }; 1339 if (firstDaty < 0) { 1340 firstDaty = 7 + firstDaty; 1341 } 1342 var limit = $self._getMounthsWeek(_index + '-01', firstDaty); 1343 if (limit > 5) { 1344 $self.box.wrap.addClass('mixpicker__addedWeek'); 1345 } 1346 for (var i = 0; i < (limit * 7); i++) { 1347 if (i < firstDaty || _date.format('M') !== _cM) { 1348 $self.map[m].days[i] = null; 1349 } else { 1350 var _obj = { 1351 year: parseInt(_date.format('YYYY')), 1352 month: parseInt(_date.format('M')), 1353 day: parseInt(_date.format('D')), 1354 date: _date.format('YYYY-MM-DD') 1355 }; 1356 $self.map[m].days[i] = _obj; 1357 $self.status_map[_date.format('YYYY-MM-DD')] = $self._getDayStatus(_date); 1358 1359 $self.flat_map.push(_date.format('YYYY-MM-DD')); 1360 _date.add(1, 'd'); 1361 } 1362 } 1363 } 1364 1365 if (this.detectMobile()) this._updateMoreButton(); 1366 return $self; 1367 }, 1368 1369 '_updateMoreButton': function () { 1370 var lastMonth = this.map[this.config.monthsRendered]; 1371 var lastDate = moment(lastMonth.code + '-01').add(1, 'month'); 1372 $('.mixpicker__mobile-more').text(lastDate.format('MMMM YYYY')); 1373 1374 }, 1375 1376 'updateMessage': function () { 1377 if (this.config.stage === 0) { 1378 this.status('info', _l('select_checkin')); 1379 } else if (this.config.stage === 1) { 1380 this.status('info', _l('select_checkout')); 1381 } 1382 }, 1383 1384 'update': function (selectable, element) { 1385 var $self = this; 1386 if ($self.config.hasMonths) { 1387 $self.update_months(); 1388 } else { 1389 $self.render_months(); 1390 $self.config.hasMonths = true; 1391 } 1392 $self._updateNav(); 1393 1394 if (typeof(selectable) === 'undefined' || selectable === true) { 1395 $self.updateMessage(); 1396 } 1397 $self._updateStageHover(); 1398 $self.fixHover(element); 1399 setTimeout(function () { 1400 $self.backError(); 1401 }, 1000); 1402 1403
1404 var mWidths = (function () { 1405 var w = 0; 1406 $self.box.months.find('.mixpicker__month').each(function (id, element) { 1407 w += $(element).outerWidth(true); 1408 }); 1409 return w + 50; 1410 }); 1411 $self.box.months.css('width', mWidths); 1412 1413 if ($(document).width() < 800) { 1414 $self.box.container.removeClass('mixpicker__fullsize').addClass('mixpicker__fullsize'); 1415 var sum = 0; 1416 $self.box.months.find('.mixpicker__month').each(function (id, el) { 1417 $(el).width($self.box.wrap.outerWidth() - 20); 1418 sum += $self.box.wrap.outerWidth(); 1419 }); 1420 $self.box.months.width(sum); 1421 // $self.update(); 1422 } else if ($(document).width() > 800 && $self.box.container.hasClass('mixpicker__fullsize')) { 1423 $self.box.container.removeClass('mixpicker__fullsize'); 1424 } 1425 1426 return $self; 1427 }, 1428 1429 'fixHover': function (date) { 1430 var $self = this; 1431 if (date) { 1432 $self.box.container.find('div[data-date="' + date + '"]').trigger('mouseover'); 1433 } 1434 }, 1435 'backError': function () { 1436 var $self = this; 1437 for (var b in $self.map) { 1438 if ($self.map.hasOwnProperty(b)) { 1439 var days = $self.map[b].days; 1440 for (var date in days) { 1441 if (days.hasOwnProperty(date)) { 1442 var _d = days[date]; 1443 if (_d) { 1444 if ($self.status_map[_d.date].indexOf('mixpicker__error') > -1) { 1445 $self.status_map[_d.date].splice($self.status_map[_d.date].indexOf('mixpicker__error'), 1); 1446 } 1447 } 1448 } 1449 } 1450 } 1451 } 1452 $self.box.wrap.find('div.day.mixpicker__error').removeClass('mixpicker__error'); 1453 return $self; 1454 }, 1455 '_hasDisabled': function (inIndex, outIndex) { 1456 var $self = this, 1457 dIndex = -1; 1458 1459 $.each($self.box.wrap.find('div.mixpicker__day').slice(inIndex, outIndex), function (id, element) { 1460 if ($(element).hasClass('mixpicker__disabled')) { 1461 dIndex = id; 1462 return false; 1463 } 1464 }); 1465 return dIndex; 1466 }, 1467 '_selectDay': function (element) { 1468 var $self = this, 1469 $element = $('div', element), 1470 date = moment($element.data('date')), 1471 update = true, 1472 lock = true; 1473 1474 if ($self.config.stage === 0 && $element.hasClass('mixpicker__disabled') || ($self.config.stage === 1 && date.isBefore($self.config.checkin) && $element.hasClass('mixpicker__disabled'))) { 1475 $self.update(); 1476 $self.status('error', _l('day_disabled')); 1477 return; 1478 } 1479 if ($self.config.stage === 0 && $element.hasClass('mixpicker__nocheckin')) { 1480 $self.update(); 1481 $self.status('error', _l('day_only_checkin')); 1482 return; 1483 } 1484 if ($self.config.stage === 1 && $element.hasClass('mixpicker__nocheckout')) { 1485 $self.update(); 1486 $self.status('error', _l('day_only_checkout')); 1487 return; 1488 } 1489 if (!$element.hasClass('mixpicker__day') || ($self.config.stage === 1 && date.isSame($self.config.checkin))) { 1490 $self.update(); 1491 return; 1492 } 1493 var _tCheckout, _inIndex, _outIndex, disabled; 1494 var endOfM = moment(date).endOf('month'); 1495 $self.config.change = true; 1496 if ($self.config.stage === 0) { 1497 1498 if (moment(date).isSame(moment(endOfM), 'day')) { 1499 $self._clickMove(element); 1500 } 1501 $self._setCheckin(date); 1502 $self._setCheckout(moment(date).add(1, 'd'), false); 1503 $self._setStage(1); 1504 if (!$self.options.numNights) { 1505 if ($self.options.minNights) { 1506 _tCheckout = moment(date).add($self.options.minNights, 'd'); 1507 _inIndex = $self.flat_map.indexOf(date.format('YYYY-MM-DD')); 1508 _outIndex = $self.flat_map.indexOf(_tCheckout.format('YYYY-MM-DD')); 1509 1510 disabled = $self._hasDisabled(_inIndex, _outIndex); 1511 1512 if (disabled === -1) { 1513 $self._setCheckout(_tCheckout); 1514 $self._setStage(1); 1515 if (moment(_tCheckout).isAfter(moment(endOfM), 'month')) { 1516 $self._clickMove(element); 1517 } 1518 } else { 1519 $self._setCheckin(null); 1520 $self._setCheckout(null); 1521 $self._setStage(0); 1522 $self.bounce(date.format('YYYY-MM-DD'), _tCheckout.format('YYYY-MM-DD')); 1523 $self.status('error', _l('no_avail_day')); 1524 update = false;
1525 } 1526 } 1527 } else { 1528 _tCheckout = moment(date).add($self.options.numNights, 'd'); 1529 _inIndex = $self.flat_map.indexOf(date.format('YYYY-MM-DD')); 1530 _outIndex = $self.flat_map.indexOf(_tCheckout.format('YYYY-MM-DD')); 1531 1532 disabled = $self._hasDisabled(_inIndex, _outIndex); 1533 1534 if (disabled === -1 && _outIndex > -1) { 1535 $self._setCheckout(_tCheckout); 1536 if (moment(_tCheckout).isAfter(moment(endOfM), 'month')) { 1537 $self._clickMove(element); 1538 } 1539 1540 lock = false; 1541 } else { 1542 $self._setCheckin(null); 1543 $self._setCheckout(null); 1544 $self.bounce(date.format('YYYY-MM-DD'), _tCheckout.format('YYYY-MM-DD')); 1545 $self.status('error', _l('no_avail_day')); 1546 update = false; 1547 } 1548 $self._setStage(0); 1549 } 1550 } else if ($self.config.stage === 1) { 1551 $self._setStage(0); 1552 _inIndex = $self.flat_map.indexOf($self.config.checkin.format('YYYY-MM-DD')); 1553 _outIndex = $self.flat_map.indexOf(date.format('YYYY-MM-DD')); 1554 disabled = $self._hasDisabled(_inIndex, _outIndex); 1555 if (disabled > -1) { 1556 $self._setStage(1); 1557 $self.bounce($self.config.checkin.format('YYYY-MM-DD'), date.format('YYYY-MM-DD')); 1558 $self.status('error', _l('no_avail_day')); 1559 update = false; 1560 } else if ($self.config.stage === 0) { 1561 if ($self.options.minNights) { 1562 if (date.diff($self.config.checkout, 'days') < 0) { 1563 $self._setStage(0); 1564 $self._selectDay(element); 1565 } else { 1566 $self._setCheckout(date); 1567 lock = false; 1568 } 1569 } else if ($self.options.maxNights) { 1570 if (date.diff($self.config.checkin, 'days') < 0) { 1571 $self._setStage(0); 1572 $self._selectDay(element); 1573 } else { 1574 if (_inIndex + $self.options.maxNights < _outIndex) { 1575 $self.bounce(moment($self.config.checkin).add($self.options.maxNights, 'd').format('YYYY-MM-DD'), date.format('YYYY-MM-DD')); 1576 $self.status('error', _l('max_nights').replace(':nights', $self.options.maxNights)); 1577 update = false; 1578 $self._setStage(1); 1579 } else { 1580 $self._setCheckout(date); 1581 lock = false; 1582 } 1583 } 1584 } else { 1585 if (date.diff($self.config.checkin, 'days') < 0) { 1586 $self._setStage(0); 1587 $self._selectDay(element); 1588 } else { 1589 $self._setCheckout(date); 1590 lock = false; 1591 } 1592 } 1593 } 1594 } 1595 $self.update(update, date.format('YYYY-MM-DD')); 1596 1597 if ($self.options.oneClick || ($self.options.select === false && $self.config.checkin && $self.config.checkout && lock === false)) { 1598 $self.makeSelectAction(); 1599 } 1600 1601 return $self; 1602 }, 1603 1604 'status': function (type, msg) { 1605 var $self = this; 1606 $self.box.message.empty().removeClass('mixpicker__message--error mixpicker__message--info'); 1607 if (type === 'error') { 1608 $self.box.message.addClass('mixpicker__message--error'); 1609 } else { 1610 $self.box.message.addClass('mixpicker__message--info'); 1611 } 1612 $self.box.message.html('<span>' + msg + '</span>'); 1613 1614 return $self; 1615 }, 1616 'bounce': function (start, stop, block) { 1617 var $self = this, 1618 _start = moment(start), 1619 _stop = moment(stop), 1620 dates = $self.map[_start.format('YYYY-MM')]; 1621 for (var d in dates) { 1622 if (dates.hasOwnProperty(d)) { 1623 if (dates[d] && moment(dates[d].date).isAfter(_start) && moment(dates[d].date).isBefore(_stop) && $self.status_map[dates[d].date].indexOf('mixpicker__disabled') > -1) { 1624 $self.status_map[dates[d].date].push('mixpicker__error'); 1625 } 1626 } 1627 } 1628 if (!block && _start.format('YYYY-MM') !== _stop.format('YYYY-MM')) { 1629 $self.bounce(moment(_start.add(1, 'M').format('YYYY-MM') + '-01').format('YYYY-MM-DD'), _stop.format('YYYY-MM-DD'), true); 1630 } 1631 1632 return $self; 1633 }, 1634 1635 'detectMobile': function () {
1636 if (this.options.mode !== 'inline' && (window.innerWidth <= 480 || window.innerHeight <= 430)) { 1637 return true; 1638 } 1639 return false; 1640 }, 1641 1642 1643 // INIT 1644 'init': function (options) { 1645 var $self = this; 1646 if (this.length > 0) { 1647 this.data('mixpicker', jQuery.extend(true, {}, $mixpicker)); 1648 $self.data('mixpicker').id = $self.attr('id'); 1649 $self.data('mixpicker').box.toggle = $self; 1650 $self.data('mixpicker')._setOptions(options); 1651 $self.data('mixpicker')._prepareConfig($self); 1652 $self.data('mixpicker').options.beforeSetup(); 1653 1654 1655 $self.data('mixpicker').render_container($self); 1656 1657 $self.data('mixpicker').bind_toggle($self); 1658 $self.data('mixpicker').bind_select($self); 1659 $self.data('mixpicker').bind_nav($self); 1660 $self.data('mixpicker').bind_close($self); 1661 $self.data('mixpicker').bind_resize($self); 1662 $self.data('mixpicker').bind_daySelect($self); 1663 1664 $self.data('mixpicker')._createMap($self); 1665 1666 1667 if ($self.data('mixpicker').options.mode === 'inline') { 1668 $self.data('mixpicker').update(); 1669 $self.data('mixpicker').config.stage = 0; 1670 $self.data('mixpicker').config.visible = true; 1671 } 1672 1673 if ($self.data('mixpicker').config.checkin && $self.data('mixpicker').config.checkout) { 1674 setTimeout(function () { 1675 $self.data('mixpicker').options.onInit({ 1676 type: 'init', 1677 checkin: moment($self.data('mixpicker').config.checkin), 1678 checkout: moment($self.data('mixpicker').config.checkout) 1679 }); 1680 }, 0); 1681 } 1682 1683 setTimeout(function () { 1684 $self.data('mixpicker').options.onSetup(); 1685 }, 0); 1686 1687 return $self; 1688 } 1689 }, 1690 1691 'defineLocale': function (locale, translations) { 1692 this.lang = translations; 1693 return this; 1694 }, 1695 1696 'defaultLang': { 1697 format: 'YYYY-MM-DD', 1698 dayName: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], 1699 select: 'Select', 1700 select_checkin: 'Select check-in date.', 1701 select_checkout: 'Select check-out date.', 1702 no_avail_day: 'In selected date range this day is not available!', 1703 max_nights: 'You can not select more than :nights nights!', 1704 day_disabled: 'This day is not available to select.', 1705 day_only_checkin: 'This day is available only to check-in.', 1706 day_only_checkout: 'This day is available only to check-out.' 1707 } 1708 }; 1709 1710 // HELPERS 1711 function _l(key) { 1712 if (!$mixpicker.lang || typeof($mixpicker.lang[key]) === 'undefined') { 1713 if (!$mixpicker.defaultLang || typeof($mixpicker.defaultLang[key]) === 'undefined') { 1714 $.error('[MixPicker] Missing translations file !!!!'); 1715 return false; 1716 } else { 1717 return $mixpicker.defaultLang[key]; 1718 } 1719 return false; 1720 } 1721 return $mixpicker.lang[key]; 1722 } 1723 1724 $.fn.mixpicker = function (methodOrOptions) { 1725 if ($mixpicker[methodOrOptions]) { 1726 return $mixpicker[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1)); 1727 } else if (typeof methodOrOptions === 'object' || !methodOrOptions) { 1728 return $mixpicker.init.apply(this, arguments); 1729 } else { 1730 $.error('Method ' + methodOrOptions + ' does not exist on jQuery.tooltip'); 1731 } 1732 }; 1733}(jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.