1class JCalendar { 2 3 firstDate = null; 4 secondDate = null; 5 6 firstDateF = null; 7 secondDateF = null; 8 9 firstDateId = "firstDateId"; 10 secondDateId = "secondDateId"; 11 dayCellClass = ".calendar-day"; 12 finished = false; 13 debug = true; 14 isCanDraw = true; 15 16 constructor(firstDate = null, secondDate = null, canDraw = true) { 17 this.firstDate = firstDate; 18 this.secondDate = secondDate; 19 this.isCanDraw = canDraw; 20 this.firstDateF = null; 21 this.secondDateF = null; 22 this.firstDateId = "firstDateId"; 23 this.secondDateId = "secondDateId"; 24 this.dayCellClass = ".calendar-day"; 25 this.finished = false; 26 this.debug = true; 27 }; 28 29 resetIfFinished() { 30 return true; 31 } 32 33 reset() { 34 this.firstDate = null; 35 this.secondDate = null; 36 this.finished = false; 37 this.onChangeDate(); 38 } 39 40 swapDates() { 41 let tmp = this.firstDate; 42 let tmpF = this.firstDateF; 43 44 if (this.isSecondDateSetted() && (this.secondDate > this.firstDate)) { 45 return; 46 } 47 48 this.firstDate = this.secondDate; 49 this.firstDateF = this.secondDateF; 50 this.secondDate = tmp; 51 this.secondDateF = tmpF; 52 this.onChangeDate(); 53 } 54 55 setFirstDate(timestamp, formattedDate) { 56 this.firstDate = timestamp; 57 this.firstDateF = formattedDate; 58 this.onChangeDate(formattedDate); 59 } 60 61 setSecondDate(timestamp, formattedDate) { 62 this.secondDate = timestamp; 63 this.secondDateF = formattedDate; 64 this.onChangeDate(formattedDate); 65 } 66 67 showDebug(message) { 68 if (this.debug) { 69 console.log(message); 70 } 71 } 72 73 isFirstDateSetted() { 74 return !(isNaN(this.firstDate) || (this.firstDate == null)); 75 } 76 77 isSecondDateSetted() { 78 return !(isNaN(this.secondDate) || (this.secondDate == null)); 79 } 80 81 isDatesSetted() { 82 return (this.isFirstDateSetted() && this.isSecondDateSetted()); 83 } 84 85 isFinished() { 86 return this.finished; 87 } 88 89 canDraw() { 90 return this.isCanDraw; 91 } 92 93 correctSwapDates() { 94 if (!this.isDatesSetted()) { 95 return; 96 } 97 98 if (this.secondDate < this.firstDate) { 99 let tmp = this.firstDate; 100 this.firstDate = this.secondDate; 101 this.secondDate = tmp; 102 } 103 } 104 105 formatDateWithZeros(timestamp) { 106 107 if(timestamp === null){ 108 return "Â "; 109 } 110 111 const date = new Date(timestamp); 112 if (isNaN(date)) { 113 return "Â "; 114 } 115 const day = ("0" + date.getDate()).slice(-2);
116 const month = ("0" + (date.getMonth() + 1)).slice(-2); 117 const year = date.getFullYear(); 118 return `${day}.${month}.${year}`; 119 } 120 121 onChangeDate() { 122 const $firstInput = $('#' + this.firstDateId); 123 const $secondInput = $('#' + this.secondDateId); 124 125 if ($firstInput.length) { 126 $firstInput.val(this.firstDate); 127 $firstInput.parent('.calendar-fake-input').css('border', ''); 128 } 129 130 if ($secondInput.length) { 131 $secondInput.val(this.secondDate); 132 $secondInput.parent('.calendar-fake-input').css('border', ''); 133 } 134 135 const firstFormatted = this.formatDateWithZeros(this.firstDate); 136 $('#firstDateInputText').html(firstFormatted); 137 if (firstFormatted !== " ") { 138 this.showDebug("Date: " + firstFormatted); 139 } 140 141 const secondFormatted = this.formatDateWithZeros(this.secondDate); 142 $('#secondDateInputText').html(secondFormatted); 143 if (secondFormatted !== " ") { 144 this.showDebug("Date: " + secondFormatted); 145 } 146 147 if (this.canDraw()) this.draw(); 148 } 149 150 isDayBeforeFirst(timestamp) { 151 if (this.firstDate && this.firstDate > timestamp) { 152 return true; 153 } 154 return false; 155 } 156 157 isDayAfterFirst(timestamp) { 158 if (this.isFirstDateSetted() && this.firstDate < timestamp) { 159 return true; 160 } 161 return false; 162 } 163 164 /** 165 * меÑод пÑовеÑÑÐµÑ Ð´Ð°ÑÑ Ð½Ð° забÑлокиÑованнÑе дни, в далÑнейÑем ÑÑда можно допиÑаÑÑ Ð¿Ñавила бÑониÑованиÑ... Ñ Ð¾ÑÑ Ð¸ вÑглÑÐ´Ð¸Ñ ÑложнÑм ÑÐ°ÐºÐ°Ñ Ð´Ð¾ÑабоÑка 166 */ 167 checkDates(){ 168 var params = [this]; 169 $(this.dayCellClass).each(function () { 170 171 let disabled = $(this).hasClass("disabled"); 172 let disabledcheckin = $(this).hasClass("disabled-checkin"); 173 174 var instance = params[0]; 175 let date = $(this).attr("data-date"); 176 let timestamp = Date.parse(date); 177 if (isNaN(timestamp)) { 178 return; 179 } 180 181 if (instance.isSelected(timestamp)) { 182 if (instance.isFirstDay(timestamp)) { 183 if (disabled || disabledcheckin){ 184 instance.reset(); 185 console.log("reset 1"); 186 } 187 } 188 189 if (instance.isLastDay(timestamp)) { 190 if (disabled){ 191 instance.reset(); 192 console.log("reset 2") 193 } 194 } 195 } else if (instance.isDayInRange(timestamp)) { 196 if(disabled || disabledcheckin){ 197 instance.reset(); 198 console.log("reset 3") 199 } 200 } else { 201 202 } 203 }); 204 } 205 206 addDay(timestamp, click = false, formattedDate = "", disabled = false, disabledCheckin = false) { 207 208 if (click) { 209 if (this.isFinished() && this.resetIfFinished()) { 210 this.reset(); 211 } 212 213 if(disabled){ 214 return; 215 } 216 if (this.isFirstDateSetted() && (this.isDayBeforeFirst(timestamp))) { 217 this.setFirstDate(timestamp, formattedDate); 218 } else if (this.isFirstDateSetted() && (this.isDayAfterFirst(timestamp))) { 219 this.setSecondDate(timestamp, formattedDate); 220 } else { 221 this.setFirstDate(timestamp, formattedDate); 222 } 223 224 this.checkDates(); 225 if (this.isDatesSetted()) { 226 this.finished = true; 227 } 228 return; 229 } else { 230 if (this.isFinished()) { 231 return; 232 } 233 234 if(disabled){ 235 return; 236 } 237 238 if ((this.isFirstDateSetted()) && (jCalendar.isDayBeforeFirst(timestamp))) { 239 this.swapDates(); 240 this.setFirstDate(timestamp, formattedDate); 241 } else { 242 if (this.isFirstDateSetted() && (jCalendar.isDayAfterFirst(timestamp))) { 243 this.setSecondDate(timestamp, formattedDate); 244 } 245 } 246 247 this.checkDates(); 248 return; 249 } 250 } 251 252 isDayInRange(timestamp) { 253 if (!this.isDatesSetted()) { 254 return false;
255 } 256 let firstDate = Math.min(this.firstDate, this.secondDate); 257 let secondDate = Math.max(this.firstDate, this.secondDate); 258 259 return (timestamp >= firstDate && timestamp <= secondDate); 260 } 261 262 isSelected(timestamp) { 263 return (timestamp == this.firstDate || timestamp == this.secondDate); 264 } 265 266 isFirstDay(timestamp) { 267 return timestamp == this.firstDate; 268 } 269 270 isLastDay(timestamp) { 271 return timestamp == this.secondDate; 272 } 273 274 draw() { 275 if (this.isFirstDateSetted()) { 276 $('#calendar-bottom-caption-default').hide(); 277 $('#calendar-bottom-caption-first').html(translations.check_in + " " + this.firstDateF); 278 279 if (this.isSecondDateSetted()) { 280 $('#calendar-bottom-caption-second').html("- " + translations.check_out + " " + this.secondDateF); 281 $('#calendar-bottom-caption-night').html(this.getNightsBetweenTimestamps()); 282 } else { 283 $('#calendar-bottom-caption-second').html(""); 284 $('#calendar-bottom-caption-night').html(""); 285 } 286 287 var params = [this]; 288 $(this.dayCellClass).each(function () { 289 var instance = params[0]; 290 let date = $(this).attr("data-date"); 291 let timestamp = Date.parse(date); 292 if (isNaN(timestamp)) { 293 return; 294 } 295 let cssClass = ""; 296 if (instance.isSelected(timestamp)) { 297 cssClass = "selected"; 298 299 if (instance.isFirstDay(timestamp)) { 300 cssClass = "selected first-day"; 301 } 302 303 if (instance.isLastDay(timestamp)) { 304 cssClass = "selected last-day"; 305 } 306 } else if (instance.isDayInRange(timestamp)) { 307 cssClass = "hovered"; 308 } else { 309 cssClass = ""; 310 } 311 312 $(this).removeClass("selected last-day first-day hovered"); 313 314 let tooltip = $(this).children('.tooltip_place'); 315 if (tooltip.length) { 316 $(tooltip).removeClass("tooltip"); 317 $(tooltip).html(""); 318 } 319 320 if (instance.isDayInRange(timestamp) || instance.isSelected(timestamp)) { 321 $(this).addClass(cssClass); 322 } 323 324 if (instance.isDayInRange(timestamp) && instance.isSelected(timestamp)) { 325 if (tooltip.length) { 326 $(tooltip).addClass("tooltip"); 327 let txt = instance.getNightsBetweenTimestamps(); 328 if ($(this).hasClass("disabled-checkin")){ 329 txt += " (" + translations.checkout_only + ")"; 330 } 331 $(tooltip).html(txt.toString()); 332 } 333 }else{ 334 $(tooltip).html(""); 335 $(tooltip).removeClass("tooltip"); 336 } 337 }, params); 338 } else { 339 $('#calendar-bottom-caption-first').html(""); 340 $('#calendar-bottom-caption-second').html(""); 341 $('#calendar-bottom-caption-night').html(""); 342 $('#calendar-bottom-caption-default').show(); 343 $(this.dayCellClass).each(function () { 344 $(this).removeClass("selected hovered"); 345 let tooltip = $(this).children('.tooltip_place'); 346 if (tooltip.length) { 347 $(tooltip).removeClass("tooltip"); 348 $(tooltip).html(""); 349 } 350 }); 351 } 352 } 353 354 getNightsWord(count) { 355 count = Math.abs(Math.floor(count)); 356 const lastDigit = count % 10; 357 const lastTwoDigits = count % 100; 358 359 if (lastTwoDigits >= 11 && lastTwoDigits <= 14) { 360 return `(${count} ${translations.nights_5_plus})`; 361 } 362 363 if (lastDigit === 1) { 364 return `${count} ${translations.night}`; 365 } else if (lastDigit >= 2 && lastDigit <= 4) { 366 return `${count} ${translations.nights_2_4}`; 367 } else { 368 return `${count} ${translations.nights_5_plus}`; 369 } 370 } 371 372 getNightsBetweenTimestamps() { 373 const startDate = new Date(this.firstDate); 374 const endDate = new Date(this.secondDate); 375 if (isNaN(startDate) || isNaN(endDate)) { 376 return ""; 377 } 378 379 const diffMs = endDate - startDate; 380 const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); 381 382 if (diffDays < 0) { 383 return ""; 384 } 385 386 return this.getNightsWord(diffDays); 387 } 388} 389 390function parseDay(day) { 391 let date = $(day).attr('data-date'); 392 let res = Date.parse(date); 393 return res; 394} 395 396function findRoom() { 397 $('#loading-overlay').addClass('active').fadeIn(300); 398 399 let startDate = $('#firstDateId').val(); 400 let lastDate = $('#secondDateId').val(); 401 let selectedRoomTypeId = parseInt($('.room-type-input[name="selectedRoomTypeId"]').val()) || null; 402 let adults = parseInt($('.guests-select_form-input[name="adults"]').val()) || 0;
403 let children = parseInt($('.guests-select_form-input[name="children"]').val()) || 0; 404 let childUnder6 = parseInt($('.guests-select_form-input[name="childUnder6"]').val()) || 0; 405 406 $('#firstDateId').parent('.calendar-fake-input').css('border', ''); 407 $('#secondDateId').parent('.calendar-fake-input').css('border', ''); 408 409 let isValid = true; 410 if (!startDate) { 411 $('#firstDateId').parent('.calendar-fake-input').css('border', '1px solid #dc3545'); 412 isValid = false; 413 } 414 if (!lastDate) { 415 $('#secondDateId').parent('.calendar-fake-input').css('border', '1px solid #dc3545'); 416 isValid = false; 417 } 418 419 if (!isValid) { 420 $('#error-message').text(translations.please_fill_dates).show(); 421 $('#loading-overlay').removeClass('active').fadeOut(300); 422 return; 423 } 424 425 let formData = [ 426 { name: 'startDate', value: startDate }, 427 { name: 'lastDate', value: lastDate }, 428 { name: 'selectedRoomTypeId', value: selectedRoomTypeId }, 429 { name: 'adults', value: adults }, 430 { name: 'children', value: children }, 431 { name: 'childUnder6', value: childUnder6} 432 ]; 433 434 let queryString = $.param(formData); 435 let url_ = '/booking/booking/?' + queryString; 436 437 setTimeout(function() { 438 window.location.href = url_; 439 }, 50); 440} 441 442$(document).ready(function () { 443 const startDate = $('#firstDateId').val(); 444 const lastDate = $('#secondDateId').val(); 445 const adults = $('.guests-select__stepper-input[name="adults"]').val(); 446 const children = $('.guests-select__stepper-input[name="children"]').val(); 447 448 $('#childUnder6-checkbox').on('change', function() { 449 const value = $(this).is(':checked') ? 1 : 0; 450 $('.guests-select_form-input[name="childUnder6"]').val(value); 451 console.log("childUnder6 =" + $('.guests-select_form-input[name="childUnder6"]').val()); 452 }); 453 454 console.log("[JCalendar Init] startDate from input: " + startDate); 455 console.log("[JCalendar Init] lastDate from input: " + lastDate); 456 console.log("[Guests Init] adults from input: " + adults); 457 console.log("[Guests Init] children from input: " + children); 458 459 let i = 0; 460 jCalendar = new JCalendar(); 461 462 if (startDate && !isNaN(startDate) && parseInt(startDate, 10) !== 0) { 463 const timestamp = parseInt(startDate, 10); 464 const formattedDate = jCalendar.formatDateWithZeros(timestamp); 465 if (formattedDate !== " ") { 466 jCalendar.setFirstDate(timestamp, formattedDate); 467 } 468 } 469 470 if (lastDate && !isNaN(lastDate) && parseInt(lastDate, 10) !== 0) { 471 const timestamp = parseInt(lastDate, 10); 472 const formattedDate = jCalendar.formatDateWithZeros(timestamp); 473 if (formattedDate !== " ") { 474 jCalendar.setSecondDate(timestamp, formattedDate); 475 } 476 } 477 478 if (adults && !isNaN(adults)) { 479 $('.guests-select__stepper-input[name="adults"]').val(parseInt(adults, 10)); 480 } 481 if (children && !isNaN(children)) { 482 $('.guests-select__stepper-input[name="children"]').val(parseInt(children, 10)); 483 } 484 updateGuestsString(); 485 486 //клик Ð´Ð»Ñ Ð²ÑбоÑа Ð´Ð½Ñ 487 $('.j-calendar-day').click(function () { 488 timestamp = parseDay($(this)); 489 490 let disabled = $(this).hasClass("disabled"); 491 492 if (isNaN(timestamp)) { 493 return; 494 } 495 let formattedDate = $(this).attr("data-formatted-date"); 496 jCalendar.addDay(timestamp, true, formattedDate, disabled); 497 }); 498 499 //Ñ Ð¾Ð²ÐµÑ Ð´Ð»Ñ Ð²ÑбоÑа Ð´Ð½Ñ 500 $('.j-calendar-day').hover(function () { 501 i++; 502 timestamp = parseDay($(this)); 503 let disabled = $(this).hasClass("disabled"); 504 let disabledCheckin = $(this).hasClass("disabled-checkin"); 505 if (isNaN(timestamp)) { 506 return; 507 } 508 509 let formattedDate = $(this).attr("data-formatted-date"); 510 jCalendar.addDay(timestamp, false, formattedDate, disabled, disabledCheckin); 511 }); 512 513 $('#calendar-widget').modal({ 514 backdrop: false, 515 keyboard: true, 516 show: false 517 }); 518 519 function setGuestWidgetTopLeft() { 520 var windowWidth = $(window).width(); 521 var windowHeight = $(window).height(); 522 var $guestWidget = $('.guests-select-widget-dialog'); 523 524 var referenceTop = $('#guest-input-container').offset().top; 525 var referenceHeight = $('#guest-input-container').outerHeight(); 526 var widgetHeight = $guestWidget.outerHeight(); 527 var newTop = referenceTop + referenceHeight; 528 529 var totalHeight = referenceTop + referenceHeight + widgetHeight; 530 531 console.log("windowHeight = " + windowHeight); 532 console.log("windowWidth = " + windowWidth); 533 console.log("referenceTop = " + referenceTop); 534 console.log("referenceHeight = " + referenceHeight); 535 console.log("widgetHeight = " + widgetHeight); 536 console.log("totalHeight = " + totalHeight); 537 console.log("newTop = " + newTop); 538 539 if (windowWidth < 880) { 540 var styles = { 541 'position': 'fixed', 542 'left': '50%', 543 'transform': 'translateX(-50%)', 544 'margin': '0' 545 }; 546 547 if (windowHeight < totalHeight) { 548 var centeredTop = (windowHeight - widgetHeight) / 2; 549 centeredTop = Math.max(10, centeredTop); 550 console.log("Centering widget (small width), centeredTop = " + centeredTop); 551 styles.top = centeredTop + 'px'; 552 } else { 553 styles.top = newTop + 'px'; 554 } 555 556 $guestWidget.css(styles); 557 } else { 558 var referenceLeft = $('#guest-input-container').parent().offset().left; 559 var dialogWidth = $guestWidget.width(); 560 var newLeft = referenceLeft; 561 562 if ((newLeft + dialogWidth) > windowWidth) { 563 newLeft = windowWidth - dialogWidth; 564 } 565 566 if (windowHeight < totalHeight) { 567 var centeredTop = (windowHeight - widgetHeight) / 2; 568 centeredTop = Math.max(10, centeredTop); 569 console.log("Centering widget (large width), centeredTop = " + centeredTop); 570 $guestWidget.css({ 571 'position': 'fixed', 572 'top': centeredTop + 'px', 573 'left': newLeft + 'px', 574 'margin': '0' 575 }); 576 } else { 577 newTop = referenceTop + referenceHeight - 15; 578 $guestWidget.css({ 579 'position': 'fixed', 580 'top': newTop + 'px', 581 'left': newLeft + 'px', 582 'margin': '0' 583 }); 584 } 585 } 586 } 587 588 function setCalendarWidgetTop() { 589 var windowWidth = $(window).width(); 590 var windowHeight = $(window).height(); 591 var $calendarWidget = $('#calendar-widget'); 592 593 if (windowWidth < 880) { 594 $calendarWidget.css({ 595 'top': '10px', 596 'position': 'fixed', 597 'left': '0', 598 'transform': 'none' 599 }); 600 } else { 601 $calendarWidget.css({ 602 'position': 'fixed', 603 'left': '50%', 604 'transform': 'translate(-50%)' 605 }); 606 607 var referenceTop = $('#calendar-widget-reference-element').offset().top; 608 var referenceHeight = $('#calendar-widget-reference-element').outerHeight(); 609 var widgetHeight = $calendarWidget.outerHeight(); 610 var newTop = referenceTop + referenceHeight + 10; 611 612 var totalHeight = referenceTop + referenceHeight + widgetHeight + 10; 613 614 console.log("windowHeight = " + windowHeight); 615 console.log("referenceTop = " + referenceTop); 616 console.log("referenceHeight = " + referenceHeight); 617 console.log("widgetHeight = " + widgetHeight); 618 console.log("totalHeight = " + totalHeight); 619 console.log("newTop = " + newTop); 620 621 if (windowHeight < totalHeight) { 622 var centeredTop = (windowHeight - widgetHeight) / 2; 623 centeredTop = Math.max(10, centeredTop); 624 console.log("Centering widget, centeredTop = " + centeredTop); 625 $calendarWidget.css('top', centeredTop + 'px'); 626 } else { 627 $calendarWidget.css('top', newTop + 'px'); 628 } 629 } 630 } 631 632 $('#calendar-widget').on('shown.bs.modal', function () { 633 const backdrop = $('<div class="custom-backdrop calendar-widget-backdrop"></div>'); 634 $('body').append(backdrop); 635 backdrop.fadeIn(); 636 setCalendarWidgetTop(); 637 }); 638 639 $('#calendar-widget').on('hidden.bs.modal', function () { 640 $('.calendar-widget-backdrop').fadeOut(300, function () { 641 $(this).remove(); 642 }); 643 }); 644 645 $('#guests-select-widget').on('shown.bs.modal', function () { 646 const backdrop = $('<div class="custom-backdrop guests-select-widget-backdrop"></div>'); 647 $('body').append(backdrop); 648 backdrop.fadeIn(); 649 setGuestWidgetTopLeft(); 650 }); 651 652 $('#guests-select-widget').on('hidden.bs.modal', function () { 653 $('.guests-select-widget-backdrop').fadeOut(300, function () { 654 $(this).remove(); 655 }); 656 }); 657 658 $(window).resize(function() { 659 if ($('#calendar-widget').hasClass('show')) { 660 setCalendarWidgetTop(); 661 } 662 663 if ($('#guests-select-widget').hasClass('show')) { 664 setGuestWidgetTopLeft(); 665 } 666 }); 667 668 $('#guests-select-widget').modal({ 669 backdrop: false, 670 keyboard: true, 671 show: false 672 }); 673 674 $('#find-room').on('click', function() { 675 findRoom(); 676 }); 677 678 $('.show-modal-calendar-btn').on('click', function() { 679 $('#calendar-widget').modal('show'); 680 }); 681 682 $('.show-modal-guest-btn').on('click', function() { 683 $('#guests-select-widget').modal('show'); 684 }); 685 686 $(document).on('click', '.custom-backdrop', function() { 687 $('#calendar-widget').modal('hide'); 688 $('#guests-select-widget').modal('hide'); 689 }); 690 691 const MAX_ADULTS = 2; 692 const MIN_ADULTS = 1; 693 const MAX_TOTAL_GUESTS = 5; 694 695 function getTotalGuests() { 696 const adults = parseInt($('.guests-select__stepper-input[name="adults"]').val()) || 0; 697 const children = parseInt($('.guests-select__stepper-input[name="children"]').val()) || 0; 698 return adults + children; 699 } 700 701 function getGuestsString(adults, children) { 702 const adultWord = (count) => { 703 count = Math.abs(Math.floor(count)); 704 const lastDigit = count % 10; 705 const lastTwoDigits = count % 100; 706 if (lastTwoDigits >= 11 && lastTwoDigits <= 14) return translations.adults_5_plus; 707 if (lastDigit === 1) return translations.adult; 708 if (lastDigit >= 2 && lastDigit <= 4) return translations.adults_2_4; 709 return translations.adults_5_plus; 710 }; 711 712 const childWord = (count) => { 713 count = Math.abs(Math.floor(count)); 714 const lastDigit = count % 10; 715 const lastTwoDigits = count % 100; 716 if (lastTwoDigits >= 11 && lastTwoDigits <= 14) return translations.children_5_plus; 717 if (lastDigit === 1) return translations.child; 718 if (lastDigit >= 2 && lastDigit <= 4) return translations.children_2_4; 719 return translations.children_5_plus; 720 }; 721 722 const adultsStr = `${adults} ${adultWord(adults)}`; 723 const childrenStr = `${children} ${childWord(children)}`; 724 return `${adultsStr}, ${childrenStr}`; 725 } 726 727 function updateGuestsString() { 728 const adults = parseInt($('.guests-select__stepper-input[name="adults"]').val()) || 0; 729 const children = parseInt($('.guests-select__stepper-input[name="children"]').val()) || 0; 730 731 $('.guests-select_form-input[name="adults"]').val(adults); 732 $('.guests-select_form-input[name="children"]').val(children); 733 const guestsString = getGuestsString(adults, children); 734 $('#guests-result').val(guestsString); 735 } 736 737 $('.guests-select__stepper-button.-plus').on('click', function() { 738 const $input = $(this).siblings('.guests-select__stepper-input'); 739 let value = parseInt($input.val()) || 0; 740 const totalGuests = getTotalGuests(); 741 if ($input.attr('name') === 'adults') { 742 if (value < MAX_ADULTS && totalGuests < MAX_TOTAL_GUESTS) { 743 value++; 744 $input.val(value); 745 updateGuestsString(); 746 } 747 } else if ($input.attr('name') === 'children') { 748 if (totalGuests < MAX_TOTAL_GUESTS) { 749 value++; 750 $input.val(value); 751 updateGuestsString(); 752 } 753 } 754 }); 755 756 $('.guests-select__stepper-button.-minus').on('click', function() { 757 const $input = $(this).siblings('.guests-select__stepper-input'); 758 let value = parseInt($input.val()) || 0; 759 760 if ($input.attr('name') === 'adults') { 761 if (value > MIN_ADULTS) { 762 value--; 763 $input.val(value); 764 updateGuestsString(); 765 } 766 767 768 }else if ($input.attr('name') === 'children') { 769 770 if (value > 0) { 771 value--; 772 $input.val(value); 773 updateGuestsString(); 774 } 775 } 776 }); 777 778 $('.j-close-popup-guest .guests-select__button.-apply').on('click', function() { 779 $('#guests-select-widget').modal('hide'); 780 }); 781 782 $('.j-close-popup-calendar .calendar-select__button').on('click', function() { 783 $('#calendar-widget').modal('hide'); 784 }); 785 786 $('.guests-select__close-icon').on('click', function() { 787 $('#guests-select-widget').modal('hide'); 788 }); 789 790 $('.guests-select__stepper-input').on('input', function() { 791 let value = this.value.replace(/[^0-9]/g, ''); 792 if (value === '') value = '0'; 793 value = parseInt(value); 794 if (value > 99) value = 99; 795 if (value < 0) value = 0; 796 $(this).val(value); 797 }); 798 799 updateGuestsString(); 800 801 var $containers = $('.month-container'); 802 var totalContainers = $containers.length; 803 var visibleCount = 2; 804 var firstVisibleIndex = 0; 805 806 var $prevButton = $('.j-month-navigation-prev'); 807 var $nextButton = $('.j-month-navigation-next'); 808 809 function updateDisplay() { 810 if ($containers.length === 0) { 811 return; 812 } 813 814 var $currentVisible = $containers.filter(':visible'); 815 var $newVisible = $containers.slice(firstVisibleIndex, firstVisibleIndex + visibleCount); 816 817 $currentVisible.fadeOut(300, function() { 818 $newVisible.fadeIn(300); 819 var isPrevDisabled = firstVisibleIndex === 0; 820 var isNextDisabled = firstVisibleIndex >= totalContainers - visibleCount; 821 $prevButton.toggleClass('disabled', isPrevDisabled); 822 $nextButton.toggleClass('disabled', isNextDisabled); 823 }); 824 } 825 826 $prevButton.on('click', function() { 827 if (firstVisibleIndex > 0) { 828 firstVisibleIndex--; 829 updateDisplay(); 830 } 831 }); 832 833 $nextButton.on('click', function() { 834 if (firstVisibleIndex < totalContainers - visibleCount) { 835 firstVisibleIndex++; 836 updateDisplay(); 837 } 838 }); 839 840 var intervalId = null; 841 var elapsedSeconds = 0; 842 const UPDATE_SECONDS = 300; 843 const INTERVAL_SECONDS = 5; 844
845 function loadCalendar() { 846 $.ajax({ 847 url: '/booking/booking/load-calendar-data', 848 type: 'POST', 849 data: { 850 _csrf: yii.getCsrfToken() 851 }, 852 dataType: 'json', 853 success: function(response) { 854 if (response.success) { 855 updateCalendarDays(response.days); 856 } else { 857 console.error('Error loading calendar data: ' + response.error); 858 } 859 resetTimer(); 860 }, 861 error: function(xhr, status, error) { 862 console.error('AJAX error: ' + error); 863 resetTimer(); 864 } 865 }); 866 } 867 868 function updateCalendarDays(days) { 869 var $container = $('#calendar'); 870 871 $.each(days, function(index, day) { 872 var $dayBlock = $container.find('.calendar-day[data-date="' + day.date + '"]'); 873 874 if ($dayBlock.length) { 875 $dayBlock.removeClass('before-now enabled disabled disabled-checkin j-calendar-day tooltip-wrapper'); 876 $dayBlock.addClass(day.isBeforeNow ? 'before-now' : (day.isAvailable ? 'enabled j-calendar-day tooltip-wrapper' : (day.checkoutOnly ? 'disabled-checkin j-calendar-day' : 'disabled j-calendar-day'))); 877 878 var $priceSpan = $dayBlock.find('.calendar-day-price span'); 879 if (day.isBeforeNow) { 880 $priceSpan.html('Â '); 881 } else if (day.isAvailable && day.price) { 882 $priceSpan.text(day.price + ' â½'); 883 } else if(day.checkoutOnly){ 884 $priceSpan.text(translations.checkin_not_available); 885 } else { 886 $priceSpan.text(translations.not_available); 887 } 888 889 var $tooltip = $dayBlock.find('.tooltip_place'); 890 if (day.isAvailable && !day.isBeforeNow) { 891 if (!$tooltip.length) { 892 $dayBlock.append($('<span>').addClass('tooltip_place')); 893 } 894 } else if(day.checkoutOnly){ 895 if (!$tooltip.length) { 896 $dayBlock.append($('<span>').addClass('tooltip_place')); 897 } 898 } 899 else { 900 $tooltip.remove(); 901 } 902 903 $dayBlock.attr('data-formatted-date', day.formattedDate); 904 } 905 }); 906 } 907 908 function updateProgressBar() { 909 var $progressBar = $('#progress-bar'); 910 var progressPercent = (elapsedSeconds / UPDATE_SECONDS) * 100; 911 $progressBar.css('width', progressPercent + '%'); 912 } 913 914 function resetTimer() { 915 elapsedSeconds = 0; 916 updateProgressBar(); 917 } 918 919 function startTimer() { 920 if (intervalId === null) { 921 intervalId = setInterval(function() { 922 elapsedSeconds += INTERVAL_SECONDS; 923 updateProgressBar(); 924 if (elapsedSeconds >= UPDATE_SECONDS) { 925 loadCalendar(); 926 } 927 }, INTERVAL_SECONDS * 1000); 928 } 929 } 930 931 function stopTimer() { 932 if (intervalId !== null) { 933 clearInterval(intervalId); 934 intervalId = null; 935 resetTimer(); 936 } 937 } 938 startTimer(); 939 940 console.log('Initializing slider'); 941 $containers.addClass('hidden'); 942 $containers.slice(0, visibleCount).removeClass('hidden'); 943 updateDisplay(); 944 setCalendarWidgetTop(); 945 setGuestWidgetTopLeft(); 946});
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.