1window.addEventListener("scroll", function (e) { 2 var t = this.scrollY; 3 document.getElementById("scrollToTop").style.display = t >= 100 ? "block" : "none" 4}), 5 6 window.onscroll = function () { 7 let nav = document.getElementById('navbar'); 8 let sub = document.getElementById('subNavbar'); 9 let options = document.getElementById('destination-options'); 10 let logo = document.getElementById('navbar-image'); 11 let dropDownItem = document.getElementById('dropdown'); 12 let tourDropDown = document.getElementById('tourdropdown'); 13 let navBar = document.getElementById('navbarCollapse'); 14 15 if (window.scrollY > 100) { 16 nav.classList.add("fixed"); 17 if (logo) { 18 logo.src = "/images/logo_menu.png"; 19 } 20 21 if (sub) { 22 sub.classList.add("fixed-sub"); 23 dropDownItem.addEventListener('mouseenter', function () { 24 sub.classList.remove("fixed-sub"); 25 }); 26 sub.classList.add("fixed-sub"); 27 tourDropDown.addEventListener('mouseenter', function () { 28 sub.classList.remove("fixed-sub"); 29 }); 30 } 31 } else { 32 nav.classList.remove("fixed"); 33 if (logo) { 34 logo.src = "/images/logo.png"; 35 } 36 37 if (sub) { 38 sub.classList.remove("fixed-sub"); 39 } 40 } 41 } 42 43 44let myCarousel = document.querySelectorAll('#featureContainer .carousel .carousel-item'); 45myCarousel.forEach((el) => { 46 const minPerSlide = 3 47 let next = el.nextElementSibling 48 for (var i = 1; i < minPerSlide; i++) { 49 if (!next) { 50 next = myCarousel[0] 51 } 52 let cloneChild = next.cloneNode(true) 53 el.appendChild(cloneChild.children[0]) 54 next = next.nextElementSibling 55 } 56}) 57 58// blog carousel 59let blogCarousel = document.querySelectorAll('#blogContainer .carousel .carousel-item'); 60blogCarousel.forEach((el) => { 61 const minPerSlide = 2 62 let next = el.nextElementSibling 63 for (var i = 1; i < minPerSlide; i++) { 64 if (!next) { 65 next = blogCarousel[0] 66 } 67 let cloneChild = next.cloneNode(true) 68 el.appendChild(cloneChild.children[0]) 69 next = next.nextElementSibling 70 } 71}) 72 73let tourViews = document.querySelectorAll('#tourContainer .carousel .carousel-item'); 74tourViews.forEach((el) => { 75 const minPerSlide = 3 76 let next = el.nextElementSibling 77 for (var i = 1; i < minPerSlide; i++) { 78 if (!next) { 79 next = tourViews[0] 80 } 81 let cloneChild = next.cloneNode(true) 82 el.appendChild(cloneChild.children[0]) 83 next = next.nextElementSibling 84 } 85}) 86 87 88function changeIcon(anchor, showLogin = false) { 89 var icon = document.getElementById('faPlus'); 90 let login = document.getElementById('show-login'); 91 92 if (showLogin) { 93 icon.classList.remove('fa-plus'); 94 icon.classList.add('fa-minus'); 95 login.classList.remove('visually-hidden'); 96 } else { 97 icon.classList.toggle('fa-plus'); 98 icon.classList.toggle('fa-minus'); 99 100 login.classList.toggle('visually-hidden', icon.classList.contains('fa-plus')); 101 } 102} 103 104 105 106function checkAll(e) { 107 var checkboxes = document.querySelectorAll('.destinationCheck'); 108 if (e.checked) { 109 for (var i = 0; i < checkboxes.length; i++) { 110 if (checkboxes[i].type == 'checkbox') { 111 checkboxes[i].checked = true; 112 } 113 } 114 } else { 115 for (var i = 0; i < checkboxes.length; i++) { 116 if (checkboxes[i].type == 'checkbox') { 117 checkboxes[i].checked = false; 118 } 119 } 120 } 121} 122 123const currentUrl = window.location.href; 124const newUrl = new URL(currentUrl); 125const pathname = newUrl.pathname; 126const segments = pathname.split('/'); 127const segment = segments[1]; 128 129$(function () { 130 const $searchInput = $('#search-input') 131 const $navSearch = $('.nav-search') 132 const $hitsContainer = $('#hits-container') 133 const $searchResults = $('.search-results') 134 135 $searchInput.on('focus', () => { 136 if ($searchInput.val() !== '') { 137 $navSearch.addClass('active') 138 } 139 }) 140 141 $searchInput.on('keyup', () => { 142 $hitsContainer.scrollTop(0) 143 }) 144 145 $('.close-search').on('click', evt => { 146 evt.preventDefault() 147 $searchInput.val('') 148 $navSearch.removeClass('active') 149 $searchResults.hide() // Hide search results when input is cleared 150 }) 151 152 $searchInput.on('blur', evt => { 153 if (!evt.isDefaultPrevented) { 154 $navSearch.removeClass('active') 155 } 156 }) 157 158 const performSearch = async (query) => { 159 if (query === '') { 160 $searchResults.hide() 161 return 162 } 163 164 try { 165 const response = await fetch(`/api/blog-search/${query}`) 166 const results = await response.json() 167 168 if (results.length > 0) { 169 renderHits(results) 170 $searchResults.show() 171 } else { 172 renderNoResultsMessage(query) 173 $searchResults.show() 174 } 175 } catch (error) { 176 console.error('Error fetching search results:', error) 177 $searchResults.hide() 178 } 179 } 180 181 const renderHits = (hits) => { 182 const newBlogPosts = `<div class="p-0 m-0 search-results-heading"><i class="text-primary-100 p-1 fa-regular fa-newspaper" size="xl"></i>Blog Posts</div>` 183 const hitsHtml = hits.map(blog => ` 184 <a href="${microsite === 'us' ? `/blog/${blog.slug}` : `/${microsite}/blog/${blog.slug}`}"> 185 <div class="hit"> 186 <div class="hit-content d-flex flex-column"> 187 <small class="fw-semibold">${blog.name.toUpperCase()}</small> 188 <small> 189 Author: ${blog.author} 190 </small> 191 </div> 192 </div> 193 </a> 194 `).join('') 195 196 $hitsContainer.html(newBlogPosts + hitsHtml) 197 } 198 199 const renderNoResultsMessage = (query) => { 200 $hitsContainer.html(` 201 <div id="no-results-message"> 202 <a href="/searchalltours">We didn't find any results for the search <em>"${query}"</em>.</a> 203 </div> 204 `) 205 } 206 207 $searchInput.on('input', () => { 208 const query = $searchInput.val() 209 if (query !== '') { 210 $navSearch.addClass('active') 211 } else { 212 $navSearch.removeClass('active') 213 } 214 performSearch(query) 215 }) 216}) 217 218const toTitleCase = str => str.replace(/(?:^|\s)\w/g, match => match.toUpperCase()) 219 220$(function () { 221 const $searchInput = $('#search-input0') 222 const $navSearch = $('.blog-search') 223 const $hitsContainer = $('#hits-container0') 224 const $searchResults = $('.search-results') 225 226 $searchInput.on('focus', () => { 227 if ($searchInput.val() !== '') { 228 $navSearch.addClass('active') 229 } 230 }) 231 232 $searchInput.on('keyup', () => { 233 $hitsContainer.scrollTop(0) 234 }) 235 236 $('.close-search').on('click', evt => { 237 evt.preventDefault() 238 $searchInput.val('') 239 $navSearch.removeClass('active') 240 $searchResults.hide() // Hide search results when input is cleared 241 }) 242 243 $searchInput.on('blur', evt => { 244 if (!evt.isDefaultPrevented) { 245 $navSearch.removeClass('active') 246 } 247 }) 248 249 const performSearch = async (query) => { 250 if (query === '') { 251 $searchResults.hide() 252 return 253 } 254 255 try { 256 const response = await fetch(`/api/blog-search/${query}`) 257 const results = await response.json() 258 259 if (results.length > 0) { 260 renderHits(results) 261 $searchResults.show() 262 } else { 263 renderNoResultsMessage(query) 264 $searchResults.show() 265 } 266 } catch (error) { 267 console.error('Error fetching search results:', error) 268 $searchResults.hide() 269 } 270 } 271 272 const renderHits = (hits) => { 273 const newBlogPosts = `<div class="p-0 m-0 search-results-heading"><i class="text-primary-100 p-1 fa-regular fa-newspaper" size="xl"></i>Blog Posts</div>` 274 const hitsHtml = hits.map(blog => ` 275 <a href="${microsite === 'us' ? `/blog/${blog.slug}` : `/${microsite}/blog/${blog.slug}`}"> 276 <div class="hit"> 277 <div class="hit-content d-flex flex-column"> 278 <small class="fw-semibold">${blog.name.toUpperCase()}</small> 279 <small> 280 Author: ${blog.author} 281 </small> 282 </div> 283 </div> 284 </a> 285 `).join('') 286 287 $hitsContainer.html(newBlogPosts + hitsHtml) 288 } 289 290 const renderNoResultsMessage = (query) => { 291 $hitsContainer.html(` 292 <div id="no-results-message"> 293 <a href="/searchalltours">We didn't find any results for the search <em>"${query}"</em>.</a> 294 </div> 295 `) 296 } 297 298 $searchInput.on('input', () => { 299 const query = $searchInput.val() 300 if (query !== '') { 301 $navSearch.addClass('active') 302 } else { 303 $navSearch.removeClass('active') 304 } 305 performSearch(query) 306 }) 307}) 308 309const toTitleCase3 = str => str.replace(/(?:^|\s)\w/g, match => match.toUpperCase()) 310 311$(function () { 312 const $searchInput = $('#search-input1') 313 const $navSearch = $('.nav-search') 314 const $hitsContainer = $('#hits-container1') 315 const $searchResults = $('.search-results') 316 317 $searchInput.on('focus', () => { 318 if ($searchInput.val() !== '') { 319 $navSearch.addClass('active') 320 } 321 }) 322 323 $searchInput.on('keyup', () => { 324 $hitsContainer.scrollTop(0) 325 }) 326 327 $('.close-search').on('click', evt => { 328 evt.preventDefault() 329 $searchInput.val('') 330 $navSearch.removeClass('active') 331 $searchResults.hide() // Hide search results when input is cleared 332 }) 333 334 $searchInput.on('blur', evt => { 335 if (!evt.isDefaultPrevented) { 336 $navSearch.removeClass('active') 337 } 338 }) 339 340 const performSearch = async (query) => { 341 if (query === '') { 342 $searchResults.hide() 343 return 344 } 345 346 try { 347 const response = await fetch(`/api/blog-search/${query}`) 348 const results = await response.json() 349 350 if (results.length > 0) { 351 renderHits(results) 352 $searchResults.show() 353 } else { 354 renderNoResultsMessage(query) 355 $searchResults.show() 356 } 357 } catch (error) { 358 console.error('Error fetching search results:', error) 359 $searchResults.hide() 360 } 361 } 362 363 const renderHits = (hits) => { 364 const newBlogPosts = `<div class="p-0 m-0 search-results-heading"><i class="text-primary-100 p-1 fa-regular fa-newspaper" size="xl"></i>Blog Posts</div>` 365 const hitsHtml = hits.map(blog => ` 366 <a href="${microsite === 'us' ? `/blog/${blog.slug}` : `/${microsite}/blog/${blog.slug}`}"> 367 <div class="hit"> 368 <div class="hit-content d-flex flex-column"> 369 <small class="fw-semibold">${blog.name.toUpperCase()}</small> 370 <small> 371 Author: ${blog.author} 372 </small> 373 </div> 374 </div> 375 </a> 376 `).join('') 377 378 $hitsContainer.html(newBlogPosts + hitsHtml) 379 } 380 381 const renderNoResultsMessage = (query) => { 382 $hitsContainer.html(` 383 <div id="no-results-message"> 384 <a href="/searchalltours">We didn't find any results for the search <em>"${query}"</em>.</a> 385 </div> 386 `) 387 } 388 389 $searchInput.on('input', () => { 390 const query = $searchInput.val() 391 if (query !== '') { 392 $navSearch.addClass('active') 393 } else { 394 $navSearch.removeClass('active') 395 } 396 performSearch(query) 397 }) 398}) 399 400const toTitleCase1 = str => str.replace(/(?:^|\s)\w/g, match => match.toUpperCase()) 401 402$(function () { 403 const $searchInput = $('#search-input2') 404 const $navSearch = $('.nav-search') 405 const $hitsContainer = $('#hits-container2') 406 const $searchResults = $('.search-results') 407 408 $searchInput.on('focus', () => { 409 if ($searchInput.val() !== '') { 410 $navSearch.addClass('active') 411 } 412 }) 413 414 $searchInput.on('keyup', () => { 415 $hitsContainer.scrollTop(0) 416 }) 417 418 $('.close-search').on('click', evt => { 419 evt.preventDefault() 420 $searchInput.val('') 421 $navSearch.removeClass('active') 422 $searchResults.hide() // Hide search results when input is cleared 423 }) 424 425 $searchInput.on('blur', evt => { 426 if (!evt.isDefaultPrevented) { 427 $navSearch.removeClass('active') 428 } 429 }) 430 431 const performSearch = async (query) => { 432 if (query === '') { 433 $searchResults.hide() 434 return 435 } 436 437 try { 438 const response = await fetch(`/api/blog-search/${query}`) 439 const results = await response.json() 440 441 if (results.length > 0) { 442 renderHits(results) 443 $searchResults.show() 444 } else { 445 renderNoResultsMessage(query) 446 $searchResults.show() 447 } 448 } catch (error) { 449 console.error('Error fetching search results:', error) 450 $searchResults.hide() 451 } 452 } 453 454 const renderHits = (hits) => { 455 const newBlogPosts = `<div class="p-0 m-0 search-results-heading"><i class="text-primary-100 p-1 fa-regular fa-newspaper" size="xl"></i>Blog Posts</div>` 456 const hitsHtml = hits.map(blog => ` 457 <a href="${microsite === 'us' ? `/blog/${blog.slug}` : `/${microsite}/blog/${blog.slug}`}"> 458 <div class="hit"> 459 <div class="hit-content d-flex flex-column"> 460 <small class="fw-semibold">${blog.name.toUpperCase()}</small> 461 <small> 462 Author: ${blog.author} 463 </small> 464 </div> 465 </div> 466 </a> 467 `).join('') 468 469 $hitsContainer.html(newBlogPosts + hitsHtml) 470 } 471 472 const renderNoResultsMessage = (query) => { 473 $hitsContainer.html(` 474 <div id="no-results-message"> 475 <a href="/searchalltours">We didn't find any results for the search <em>"${query}"</em>.</a> 476 </div> 477 `) 478 } 479 480 $searchInput.on('input', () => { 481 const query = $searchInput.val() 482 if (query !== '') { 483 $navSearch.addClass('active') 484 } else { 485 $navSearch.removeClass('active') 486 } 487 performSearch(query) 488 }) 489}) 490 491const toTitleCase2 = str => str.replace(/(?:^|\s)\w/g, match => match.toUpperCase()) 492 493 494// navbar global search 495$(function () { 496 const $globalSearchInput = $('#navbar-search-input') 497 const $globalNavSearch = $('.navbar-search') 498 const $globalContainer = $('#navbar-container') 499 const $globalSearch = $('.navbar-search-results') 500 501 $globalSearchInput.on('focus', () => { 502 if ($globalSearchInput.val() !== '') { 503 $globalNavSearch.addClass('active') 504 } 505 }) 506 507 $globalSearchInput.on('keyup', () => { 508 $globalContainer.scrollTop(0) 509 }) 510 511 $('.close-search').on('click', evt => { 512 evt.preventDefault() 513 $globalSearchInput.val('') 514 $globalNavSearch.removeClass('active') 515 $globalSearch.hide() // Hide search results when input is cleared 516 }) 517 518 $globalSearchInput.on('blur', evt => { 519 if (!evt.isDefaultPrevented) { 520 $globalNavSearch.removeClass('active') 521 } 522 }) 523 524 const performSearch = async (query) => { 525 if (query === '') { 526 $globalSearch.hide() 527 return 528 } 529 530 try { 531 const response = await fetch(`/api/${microsite ? microsite + '/' : ''}global-filter/${query}`) 532 const results = await response.json() 533 534 if (results.tours.length > 0 || results.blogPosts.length > 0 || results.destinations.length > 0) { 535 renderHits(results) 536 $globalSearch.show() 537 } else { 538 renderNoResultsMessage(query) 539 $globalSearch.show() 540 } 541 } catch (error) { 542 console.error('Error fetching search results:', error) 543 $globalSearch.hide() 544 } 545 } 546 547 const renderHits = (hits) => { 548 const availableTours = `<div class="p-0 m-0 search-results-heading"><i class="text-primary-100 p-1 fa-solid fa-location-dot" size="xl"></i>Available Tours</div>` 549 const countriesHtml = `<div class="p-0 m-0 search-results-heading"><i class="text-primary-100 p-1 fa-solid fa-globe" size="xl"></i>Countries</div>` 550 const blogPosts = `<div class="p-0 m-0 search-results-heading"><i class="text-primary-100 p-1 fa-regular fa-newspaper" size="xl"></i>Blog Posts</div>` 551 const toursHtml = hits.tours.map(tour => ` 552 <a href="${microsite === 'us' ? `/tour/${tour.slug}` : `/${microsite}/tour/${tour.slug}`}"> 553 <div class="hit"> 554 <div class="hit-content d-flex flex-column"> 555 <small class="fw-semibold">${tour.name.toUpperCase()}:</small> 556 <small> 557 ${tour.days} Days From: ${tour.price} 558 </small> 559 </div> 560 </div> 561 </a> 562 `).join('') 563 const destinationsHtml = hits.destinations.map(destination => ` 564 <a href="${microsite === 'us' ? `/destination/${destination.name.toLowerCase()}` : `/${microsite}/destination/${destination.name.toLowerCase()}`}> 565 <div class="hit"> 566 <div class="hit-content d-flex flex-column"> 567 <small class="fw-semibold">${destination.name.toUpperCase()}:</small> 568 <small> 569 ${destination.tours_count === 0 ? 'No tours available' : `${destination.tours_count} Tours Starting F
569rom: ${destination.lowest_tour_price === null ? 'On Request' : `${destination.microsite_currency}${destination.lowest_tour_price}`}`} 570 </small> 571 </div> 572 </div> 573 </a> 574 `).join('') 575 const blogPostsHtml = hits.blogPosts.map(blogPost => ` 576 <a href="${microsite === 'us' ? `/blog/${blogPost.slug}` : `/${microsite}/blog/${blogPost.slug}`}> 577 <div class="hit"> 578 <div class="hit-content d-flex flex-column"> 579 <small class="fw-semibold">${blogPost.name.toUpperCase()}</small> 580 <small> 581 Author: ${blogPost.author} 582 </small> 583 </div> 584 </div> 585 </a> 586 `).join('') 587 588 $globalContainer.html(countriesHtml + destinationsHtml + availableTours + toursHtml + blogPosts + blogPostsHtml) 589 } 590 591 592 const renderNoResultsMessage = (query) => { 593 $globalContainer.html(` 594 <div id="no-results-message"> 595 <a href="/searchalltours">We didn't find any results for the search <em>"${query}"</em>.</a> 596 </div> 597 `) 598 } 599 600 $globalSearchInput.on('input', () => { 601 const query = $globalSearchInput.val() 602 if (query !== '') { 603 $globalNavSearch.addClass('active') 604 } else { 605 $globalNavSearch.removeClass('active') 606 } 607 performSearch(query) 608 }) 609}) 610 611const navbarGlobalInput = str => str.replace(/(?:^|\s)\w/g, match => match.toUpperCase()) 612 613 614JsLoadingOverlay.setOptions({ 615 overlayBackgroundColor: "#FFFFFF", 616 overlayOpacity: 0.6, 617 spinnerIcon: "ball-spin-clockwise-fade", 618 spinnerColor: "#8e5104", 619 spinnerSize: "2x", 620 overlayIDName: "overlay", 621 spinnerIDName: "spinner", 622 offsetX: 0, 623 offsetY: 0, 624 containerID: null, 625 lockScroll: true, 626 overlayZIndex: 9998, 627 spinnerZIndex: 9999, 628}); 629 630var tourCards; 631var lastPage; 632function scrollToID() { 633 var scrollToHere = document.getElementById("emptycontainer"); 634 var scrollToY = 635 scrollToHere.getBoundingClientRect().top + window.pageYOffset; 636 window.scrollTo({ 637 top: scrollToY - 150, 638 behavior: "smooth", 639 }); 640} 641 642var originalTourImages = []; 643let currentMicrosite = microsite === "us" ? "" : microsite; 644function toggle(index, newImageUrl) { 645 // Select all span elements 646 var spans = document.getElementsByClassName("tourElement"); 647 var images = document.querySelectorAll("#tourImage img"); 648 649 if (index >= 0 && index < images.length) { 650 // Toggle between original and new source 651 if (!originalTourImages[index]) { 652 originalTourImages[index] = images[index].src; 653 images[index].src = newImageUrl; 654 } else { 655 // Revert to original source 656 images[index].src = originalTourImages[index]; 657 originalTourImages[index] = null; // Reset original source for future toggles 658 } 659 } 660 661 // Check if index is valid 662 if (index >= 0 && index < spans.length) { 663 // Store original text if not already stored 664 if (!spans[index].originalText) { 665 spans[index].originalText = spans[index].innerHTML; 666 } 667 668 // Toggle between original and new text 669 if (spans[index].innerHTML === spans[index].originalText) { 670 spans[index].innerHTML = "Images"; 671 } else { 672 spans[index].innerHTML = spans[index].originalText; 673 } 674 } 675} 676 677var originalImageSources = []; 678 679function toggleTextAtIndex(index, newImageUrl) { 680 // Select all span elements 681 var spans = document.getElementsByClassName("myElement"); 682 var images = document.querySelectorAll("#imageContainer img"); 683 684 if (index >= 0 && index < images.length) { 685 // Toggle between original and new source 686 if (!originalImageSources[index]) { 687 originalImageSources[index] = images[index].src; 688 images[index].src = newImageUrl; 689 } else { 690 // Revert to original source 691 images[index].src = originalImageSources[index]; 692 originalImageSources[index] = null; // Reset original source for future toggles 693 } 694 } 695 696 // Check if index is valid 697 if (index >= 0 && index < spans.length) { 698 // Store original text if not already stored 699 if (!spans[index].originalText) { 700 spans[index].originalText = spans[index].innerHTML; 701 } 702 703 // Toggle between original and new text 704 if (spans[index].innerHTML === spans[index].originalText) { 705 spans[index].innerHTML = "Image"; 706 } else { 707 spans[index].innerHTML = spans[index].originalText; 708 } 709 } 710} 711 712let sliderData = { 713 priceRange: { from: 0, to: 100 }, 714 durationMonth: { from: 3, to: 30 }, 715 monthYearRange: { from: null, to: null } 716}; 717 718let mobileSliderData = { 719 priceRange: { from: 0, to: 100 }, 720 durationMonth: { from: 3, to: 30 }, 721 monthYearRange: { from: null, to: null } 722}; 723 724const getTours = ( 725 microsite, 726 destination, 727 tourTypes, 728 on_sale = Boolean, 729 sort, 730 min_duration, 731 max_duration, 732 start_date, 733 end_date, 734 min_price, 735 max_price, 736 per_page, 737 page 738) => { 739 JsLoadingOverlay.show(); 740 axios 741 .get( 742 `/api/${microsite ? microsite + '/' : ''}tour-filter`, { 743 params: { 744 destination: destination, 745 tourTypes: tourTypes, 746 per_page: per_page, 747 sort: sort, 748 min_duration: min_duration, 749 max_duration: max_duration, 750 start_date: start_date, 751 end_date: end_date, 752 on_sale: on_sale, 753 min_price: min_price, 754 max_price: max_price, 755 page: page, 756 domain_id: 2, 757 } 758 }, 759 ) 760 .then((response) => { 761 document.getElementById("tours-cards").innerHTML = ""; 762 this.tourCards = response.data.data; 763 764 document.getElementById("tour-number").innerHTML = 765 response.data.total; 766 767 document.getElementById("mobile-tour-number").innerHTML = 768 response.data.total; 769 document.getElementById("mobile-tour-number1").innerHTML = 770 response.data.total; 771 document.getElementById("mobile-tour-number2").innerHTML = 772 response.data.total; 773 this.lastPage = response.data.last_page; 774 775 function stripHtml(html) { 776 const temp = document.createElement('div'); 777 temp.innerHTML = html; 778 return temp.textContent || temp.innerText || ''; 779 } 780 781 const currencySymbol = response.data.microsite.currency_symbol 782 783 function buildTourSchema(responseData) { 784 const tours = responseData.data; 785 const baseSchema = window.schemaDataFromServer || {}; 786 const touristTrips = tours.map((tour, index) => ({ 787 "@type": "TouristTrip", 788 "@id": `#trip${index + 1}`, 789 "name": `${tour.name}`, 790 "description": stripHtml(tour.highlights), 791 "touristType": tour.tour_type, 792 "url": `${window.location.origin}/tour/${tour.slug}`, 793 "provider": { "@id": "#agency" }, 794 "offers": { 795 "@type": "Offer", 796 "price": tour.price_details?.offer_price || tour.price_details?.price || '0', 797 "priceCurrency": baseSchema?.destinationCurrency || 'USD', 798 "availability": "https://schema.org/InStock" 799 } 800 })); 801 802 const itemList = { 803 "@type": "ItemList", 804 "itemListOrder": "ItemListOrderAscending", 805 "numberOfItems": tours.length, 806 // "itemListElement": tours.map((tour, index) => ({ 807 // "@type": "ListItem", 808 // "position": index + 1, 809 // "item": { "@id": `#trip${index + 1}` } 810 // })) 811 }; 812 const schema = { 813 "@context": "https://schema.org", 814 "@graph": [ 815 { 816 "@type": "TouristDestination", 817 "@id": "#destination", 818 "name": baseSchema?.destinationName, 819 "description": (baseSchema?.destinationDescription || '').replace(/<[^>]*>/g, '').trim(), 820 // "description": "Discover the wonders of ancient Egypt – from the pyramids of Giza to the temples of Luxor, plus curated itineraries, FAQs, and highlights.", 821 "image": baseSchema?.destinationImage || `${window.location.origin}/images/egypt-main.jpg`, 822 "url": `${window.location.origin}/destinations` 823 }, 824 { 825 "@type": "TravelAgency", 826 "@id": "#agency", 827 "name": responseData.microsite?.name, 828 "url": window.location.origin, 829 "image": `${window.location.origin}/images/logo.png`, 830 "telephone": baseSchema?.destinationPhone || "+20 2 12345678", 831 "priceRange": `${currencySymbol}${response.data.lowest_price} - ${currencySymbol}${response.data.highest_price}`, 832 "address": { 833 "@type": "PostalAddress", 834 "streetAddress": "123 Travel Street", 835 "addressLocality": "Cairo", 836 "addressRegion": "Cairo Governorate", 837 "postalCode": "11511", 838 "addressCountry": "EG" 839 }, 840 "sameAs": [ 841 "https://www.facebook.com/egyptuncovered", 842 "https://twitter.com/egyptuncovered", 843 "https://www.instagram.com/egyptuncovered" 844 ], 845 "aggregateRating": { 846 "@type": "AggregateRating", 847 "ratingValue": "4.3", 848 "reviewCount": "145" 849 } 850 }, 851 itemList, 852 ...touristTrips 853 ] 854 }; 855 856 const existingSchema = document.querySelector('script[type="application/ld+json"]'); 857 if (existingSchema) { 858 existingSchema.remove(); 859 } 860 861 const script = document.createElement('script'); 862 script.type = 'application/ld+json'; 863 script.text = JSON.stringify(schema, null, 2); 864 document.head.appendChild(script); 865 } 866
867 const normalizePath = (path) => { 868 return path.replace(/^\/+/, '').toLowerCase(); 869 }; 870 871 const pathname = window.location.pathname; 872 873 const isDestinationPath = (pathname, microsite) => { 874 const normalizedPathname = normalizePath(pathname); 875 const normalizedMicrosite = normalizePath(microsite); 876 877 const micrositePath = normalizedMicrosite ? `${normalizedMicrosite}/destination/` : 'destination/'; 878 return normalizedPathname.startsWith(micrositePath); 879 }; 880 881 882 if (isDestinationPath(pathname, microsite) || window.location.pathname.startsWith('/destination/') ) { 883 buildTourSchema(response.data); 884 } 885 886 //tourtype schema 887 function stripHtml(html) { 888 const temp = document.createElement('div'); 889 temp.innerHTML = html; 890 return temp.textContent || temp.innerText || ''; 891 } 892 893 function buildTourTypeSchema(responseData) { 894 const tours = responseData.data; 895 const baseSchema = window.schemaDataFromServer || {}; 896 const travelAgencyId = `${window.location.origin}#travelagency`; 897 const currencySymbol = response.data.microsite.currency_symbol 898 899 const schema = { 900 "@context": "https://schema.org", 901 "@graph": [ 902 // Single TravelAgency entry 903 { 904 "@type": "TravelAgency", 905 "@id": travelAgencyId, 906 "name": responseData.microsite?.name, 907 "image": `${window.location.origin}/images/logo.png`, 908 "aggregateRating": { 909 "@type": "AggregateRating", 910 "ratingValue": "4.8", 911 "reviewCount": "1689" 912 }, 913 "telephone": baseSchema?.tourTypePhone || "+20 2 12345678", 914 "url": window.location.origin, 915 "priceRange": `${currencySymbol}${responseData.lowest_price} - ${currencySymbol}${responseData.highest_price}`, 916 "address": { 917 "@type": "PostalAddress", 918 "streetAddress": "123 Travel Street", 919 "addressLocality": "Cairo", 920 "addressRegion": "Cairo Governorate", 921 "postalCode": "11511", 922 "addressCountry": "EG" 923 } 924 }, 925 // TouristTrip entries 926 ...tours.map(tour => ({ 927 "@type": "TouristTrip", 928 "name": tour.name, 929 "description": stripHtml(tour.highlights), 930 "image": tour.images?.map(img => img.url) || [ 931 `${window.location.origin}/images/default-tour.jpg` 932 ], 933 "provider": { "@id": travelAgencyId }, 934 "touristType": Array.isArray(tour.tour_type) ? tour.tour_type : [tour.tour_type], 935 "itinerary": { 936 "@type": "ItemList", 937 "itemListOrder": "Sequential" 938 939 }, 940 "offers": { 941 "@type": "Offer", 942 "url": `${window.location.origin}/tour/${tour.slug}`, 943 "price": tour.price_details?.offer_price || tour.price_details?.price || '0', 944 "priceCurrency": baseSchema?.tourTypeCurrency || 'USD', 945 "priceSpecification": { 946 "@type": "PriceSpecification", 947 "price": tour.price_details?.price || '0', 948 "priceCurrency": baseSchema?.tourTypeCurrency || 'USD', 949 "eligibleQuantity": { 950 "@type": "QuantitativeValue", 951 "minValue": 1 952 } 953 }, 954 "availability": "https://schema.org/InStock" 955 }, 956 "location": Array.isArray(tour.locations) 957 ? tour.locations.map(loc => ({ 958 "@type": "Place", 959 "name": loc.name, 960 "address": { 961 "@type": "PostalAddress", 962 "addressCountry": "EG" 963 } 964 })) 965 : [] 966 })) 967 ] 968 }; 969 970 // Remove existing schema 971 const existingSchema = document.querySelector('script[type="application/ld+json"]'); 972 if (existingSchema) { 973 existingSchema.remove(); 974 } 975 976 // Append new schema 977 const script = document.createElement('script'); 978 script.type = 'application/ld+json'; 979 script.text = JSON.stringify(schema, null, 2); 980 document.head.appendChild(script); 981 } 982 983 984 const isTourtypePath = (pathname, microsite) => {
985 const normalizedPathname = normalizePath(pathname); 986 const normalizedMicrosite = normalizePath(microsite); 987 988 const micrositePath = normalizedMicrosite ? `${normalizedMicrosite}/tourtype/` : 'tourtype/'; 989 return normalizedPathname.startsWith(micrositePath); 990 }; 991 992 993 if (isTourtypePath(pathname, microsite) || window.location.pathname.startsWith('/tourtype/') ) { 994 buildTourTypeSchema(response.data); 995 } 996 997 const updatePath = (path) => { 998 return path.replace(/^\/+/, '').toLowerCase(); 999 }; 1000 1001 const specialofferPath = (pathname, microsite) => { 1002 const normalizedPathname = updatePath(pathname); 1003 const normalizedMicrosite = updatePath(microsite); 1004 1005 const micrositePath = normalizedMicrosite ? `${normalizedMicrosite}/specialoffers` : 'specialoffers'; 1006 return normalizedPathname.startsWith(micrositePath); 1007 }; 1008 1009 1010 1011 if (specialofferPath(pathname, microsite) || window.location.pathname.startsWith('/specialoffers')) { 1012 buildTourTypeSchema(response.data); 1013 } 1014 1015 1016 function createPagination(totalPages, currentPage) { 1017 const container = document.getElementById( 1018 "pagination-container" 1019 ); 1020 container.innerHTML = ""; 1021 1022 if (totalPages <= 1) { 1023 return; 1024 } 1025 1026 const maxVisiblePages = response.data.per_page; 1027 const halfMaxVisiblePages = Math.floor(maxVisiblePages / 2); 1028 let startPage = Math.max(1, currentPage - halfMaxVisiblePages); 1029 const endPage = Math.min( 1030 totalPages, 1031 startPage + maxVisiblePages - 1 1032 ); 1033 1034 // Adjust startPage to keep currentPage in the center if possible 1035 if (endPage - startPage + 1 < maxVisiblePages) { 1036 startPage = Math.max(1, endPage - maxVisiblePages + 1); 1037 } 1038 1039 const paginationList = document.createElement("ul"); 1040 paginationList.classList.add("pagination"); 1041 1042 // Add Previous Button 1043 const previousButton = createPaginationItem( 1044 currentPage - 1, 1045 "<", 1046 currentPage === 1 1047 ); 1048 paginationList.appendChild(previousButton); 1049 1050 // Add First Page 1051 if (startPage > 1) { 1052 const firstPage = createPaginationItem(1, "1", false); 1053 paginationList.appendChild(firstPage); 1054 if (startPage > 2) { 1055 paginationList.appendChild(createTripDot()); 1056 } 1057 } 1058 1059 // Add Pages 1060 for (let i = startPage; i <= endPage; i++) { 1061 const pageItem = createPaginationItem( 1062 i, 1063 i.toString(), 1064 i === currentPage 1065 ); 1066 paginationList.appendChild(pageItem); 1067 } 1068 1069 // Add Last Page 1070 if (endPage < totalPages) { 1071 if (endPage < totalPages - 1) { 1072 paginationList.appendChild(createTripDot()); 1073 } 1074 const lastPage = createPaginationItem( 1075 totalPages, 1076 totalPages.toString(), 1077 false 1078 ); 1079 paginationList.appendChild(lastPage); 1080 } 1081 1082 // Add Next Button 1083 const nextButton = createPaginationItem( 1084 currentPage + 1, 1085 ">", 1086 currentPage === totalPages 1087 ); 1088 paginationList.appendChild(nextButton); 1089 1090 container.appendChild(paginationList); 1091 } 1092 1093 function createPaginationItem(pageNumber, text, disabled) { 1094 const listItem = document.createElement("li"); 1095 listItem.classList.add("page-item"); 1096 if (disabled) { 1097 listItem.classList.add("disabled"); 1098 } 1099 1100 const link = document.createElement("a"); 1101 link.classList.add("page-link"); 1102 link.href = "#"; 1103 link.textContent = text; 1104 1105 if (!disabled && pageNumber !== 0) { 1106 link.addEventListener("click", (event) => { 1107 event.preventDefault(); 1108 getTours( 1109 microsite, 1110 destination, 1111 tourTypes, 1112 on_sale = on_sale, 1113 sort = "price_asc", 1114 sliderData.durationMonth.from, 1115 sliderData.durationMonth.to, 1116 sliderData.monthYearRange.from, 1117 sliderData.monthYearRange.to, 1118 sliderData.priceRange.from, 1119 sliderData.priceRange.to, 1120 per_page, 1121 pageNumber 1122 ); 1123 // getTours(microsite, destinations) 1124 }); 1125 } 1126 1127 listItem.appendChild(link); 1128 return listItem; 1129 } 1130 1131 function createTripDot() { 1132 const listItem = document.createElement("li"); 1133 listItem.classList.add("page-item"); 1134 listItem.classList.add("disabled"); 1135 listItem.innerHTML = '<span class="page-link">…</span>'; 1136 return listItem; 1137 } 1138 1139 1140 1141 createPagination( 1142 response.data.last_page, 1143 response.data.current_page 1144 ); 1145 1146 document.getElementById("tour-min-price").innerHTML = 1147 response.data.lowest_price ? `${response.data.microsite.currency_symbol} ${response.data.lowest_price}` : 'On Request'; 1148 1149 document.getElementById("mobile-min-price").innerHTML = 1150 response.data.lowest_price ? `${response.data.microsite.currency_symbol} ${response.data.lowest_price}` : 'On Request'; 1151 1152 document.getElementById("mobile-min-price1").innerHTML = 1153 response.data.lowest_price ? `${response.data.microsite.currency_symbol} ${response.data.lowest_price}` : 'On Request'; 1154 1155 document.getElementById("mobile-min-price2").innerHTML = 1156 response.data.lowest_price ? `${response.data.microsite.currency_symbol} ${response.data.lowest_price}` : 'On Request'; 1157 1158 1159 const minPrice = response.data.lowest_price; 1160 const maxPrice = response.data.highest_price; 1161 1162 document.getElementById("price_range").setAttribute('data-max', response.data.highest_price); 1163 document.getElementById("price_range").setAttribute('data-min', response.data.lowest_price); 1164 1165 // document.getElementById("mobile_price_range").setAttribute('data-max', response.data.highest_price); 1166 // document.getElementById("mobile_price_range").setAttribute('data-min', response.data.lowest_price); 1167 function getFirstNumber(inputString) { 1168 var regex = /\d+/; 1169 var match = inputString.match(regex); 1170 return match ? parseInt(match[0], 10) : ""; 1171 } 1172 1173 function getUniqueCountriesFromObject(inputObject) {
1174 const countries = Object.values(inputObject) 1175 .flat() 1176 .map(country => country.trim().toLowerCase()); 1177 1178 const uniqueCountries = [...new Set(countries)]; 1179 1180 return uniqueCountries.map(country => { 1181 const countrySlug = country.replace(/\s+/g, '-'); 1182 const capitalizedCountry = country.charAt(0).toUpperCase() + country.slice(1); 1183 return `<a class="link-orange" href="${microsite === 'us' ? '' : `/${microsite}`}/destination/${countrySlug}">${capitalizedCountry}</a>`; 1184 }).join(', '); 1185 } 1186 1187 function getUniqueTourType(inputTourType) { 1188 const countries = Object.values(inputTourType) 1189 .flat() 1190 .map(country => country.trim().toLowerCase()); 1191 1192 const uniqueCountries = [...new Set(countries)]; 1193 1194 return uniqueCountries.map(country => { 1195 const countrySlug = country.replace(/\s+/g, '-'); 1196 const capitalizedCountry = country.charAt(0).toUpperCase() + country.slice(1); 1197 return `<a class="link-orange" href="${microsite === 'us' ? '' : `/${microsite}`}/tourtype/${countrySlug}">${capitalizedCountry}</a>`; 1198 }).join(', '); 1199 } 1200 1201 if (response.data.data.length === 0) { 1202 console.log("No tours found"); 1203 let tourCard = ` 1204 <div class="d-flex justify-content-center mt-5"> 1205 <p class="text-center lead-big noresults"> 1206 <strong>Sorry, we couldn't find any tours matching your requirements. <br> Please <span>reset</span> your search results and <span class="text-primary-100">try again</span>.</strong> 1207 </p> 1208 </div> 1209 `; 1210 document.getElementById("tours-cards").innerHTML = tourCard; 1211 JsLoadingOverlay.hide(); 1212 } else { 1213 tourCards.forEach((tour, index) => { 1214 let tourCard = ` 1215 <div class="col-xl-4 col-lg-6 col-md-6 col-xs-6 col-12 bg-white tour-search-info mx-auto p-md-1 pb-2 mb-3"> 1216 <div class="m-0 p-0 tour-box box-shadow-dark d-flex flex-column justify-content-between" style="min-height: 100%;"> 1217 <div> 1218 <div class="tour-box-title p-2 text-uppercase"><a class="link-orange" 1219 href="${microsite === 'us' ? `/tour/${tour.slug}` : `/${microsite}/tour/${tour.slug}`}">${tour.name 1220 }</a></div> 1221 <div class="tour-search-thumb-container" id="imageContainer"> 1222 ${tour.price_details.saving != 0 && tour.price_details.saving != null ? `<div class="corner" id="corner"><span>-${tour.price_details.saving}%</span> </div>` : ""} 1223 1224 1225 <a class="link-orange togglemapimage px-2 myElement" style="cursor: pointer;" onclick="toggleTextAtIndex(${index}, '${tour.map_image 1226 }')">Map</a> 1227 <a href="${microsite === 'us' ? `/tour/${tour.slug}` : `/${microsite}/tour/${tour.slug}`}"> 1228 <img src="${tour.coupon_image 1229 }" width="96%" height="220px" 1230 alt="Map" class="tour-search-thumb show myImage"> 1231 </a> 1232 </div> 1233 <div class="tour-box-destination px-1 m-1"> 1234 </div> 1235 <div class="col-md-12 p-2 toursummary"> 1236 <div class="row"> 1237 <p class="leadsmallheading col-4 col-lg-5 p-0 m-0"> Duration: </p> 1238 <p class="leadsmall col-8 col-lg-7 p-0 m-0 fw-bold">${tour.days 1239 } Days</p> 1240 <p class="leadsmallheading col-4 col-lg-5 p-0 m-0"> Country(ies): </p> 1241 <p class="leadsmall col-8 col-lg-7 p-0 m-0 fw-bold"> 1242 <a class="link-orange" href="/${microsite == 'us' ? '' : microsite}/destination/egypt" > 1243 ${getUniqueCountriesFromObject(tour.countries)} 1244 </a> 1245 <p class="leadsmallheading col-4 col-lg-5 p-0 m-0"> Tour Type: </p> 1246 <p class="leadsmall col-8 col-lg-7 p-0 m-0 fw-bold"> 1247 <a class="link-orange" href="${microsite === 'us' ? '' : `/${microsite}`}/tourtype/${tour.tour_type.replace(/\s+/g, '-').toLowerCase()}"> 1248 ${tour.tour_type} 1249 </a> 1250 </p> 1251 <p class="leadsmallheading col-4 col-lg-5 p-0 m-0"> Group size:</p> 1252 <p class="leadsmall col-8 col-lg-7 p-0 m-0 fw-bold">Min: ${tour.group_min_size 1253 } | Max: ${tour.group_max_size}</p> 1254 <p class="leadsmallheading col-4 col-lg-5 p-0 m-0"> Meals:</p> 1255 <p class="leadsmall col-8 col-lg-7 p-0 m-0 fw-bold"> 1256 B - ${tour.meals.breakfast || 0}, 1257 L - ${tour.meals.lunch || 0}, 1258 D - ${tour.meals.dinner || 0} 1259 </p> 1260 <p class="leadsmallheading col-4 col-lg-5 p-0 m-0"> Highlights: </p> 1261 <p class="leadsmall col-8 col-lg-7 p-0 m-0 fw-bold">${tour.highlights 1262 }</p> 1263 </div> 1264 </div> 1265 </div> 1266 <div class="row p-2" style="background:#d7d7d7;"> 1267 <div class="col-1 p-0 m-0 d-flex justify-content-center align-items-center"> 1268 <p class="vertical-text px-1 m-0"> 1269 From 1270 </p> 1271 </div> 1272 <div class="col-5 p-0 m-0 mt-2" style="height:50px;"> 1273 <p class="text-left m-0 p-0 mt-2 tour-box-bold"> 1274 ${tour.price_details.offer_price !== null 1275 ? `<span class="text-black" style="font-size: 1.2rem;">${response.data.microsite.currency_symbol}${tour.price_details.offer_price}</span>
1276 <span class="tour-box-bold-f">(p/p)</span>` 1277 : '<p class="text-left m-0 p-0 tour-box-request text-black">On Request</p>'} 1278 </p> 1279 ${tour.price_details.saving > 0 ? `<del class="text-danger"><small>${response.data.microsite.currency_symbol} ${tour.price_details.price}</small></del>` : ""} 1280 </div> 1281 <div class="col-6 align-self-center text-right d-flex justify-content-end"> 1282 <a href="${microsite === 'us' ? `/tour/${tour.slug}` : `/${microsite}/tour/${tour.slug}`}" class="btn btn-orange booknow-btn" 1283 title="Book Now">View Tour</a> 1284 </div> 1285 </div> 1286 </div> 1287 </div> 1288 `; 1289 document.getElementById("tours-cards").innerHTML += 1290 tourCard; 1291 JsLoadingOverlay.hide(); 1292 scrollToID(); 1293 }); 1294 1295 var selectedValueDisplay = document.getElementById( 1296 "selectedValueDisplay" 1297 ); 1298 1299 1300 // Initialize priceRange slider 1301 var priceRange = $("#price_range") 1302 .ionRangeSlider({ 1303 grid: true, 1304 min: 0, 1305 max: 100, 1306 from: 50, 1307 step: 5, 1308 prefix: response.data.microsite.currency_symbol, 1309 onFinish: function (data) { 1310 sliderData.priceRange = { from: data.from, to: data.to }; 1311 1312 const durationData = sliderData.durationMonth; 1313 1314 getTours( 1315 microsite, 1316 [...new Set(newCheckedValues)].join(','), 1317 [...new Set(newSelectedValues)].join(','), 1318 onSale.checked ? true : false, 1319 regionSort.value + sortSelecet.value, 1320 durationData.from, 1321 durationData.to, 1322 start_date, 1323 end_date, 1324 data.from, 1325 data.to, 1326 selectElement.value, 1327 page 1328 ); 1329 }, 1330 }) 1331 .data("priceRange"); 1332 1333 1334 var priceRange = $("#mobile_price_range") 1335 .ionRangeSlider({ 1336 grid: true, 1337 min: 0, 1338 max: 100, 1339 from: 50, 1340 step: 5, 1341 prefix: response.data.microsite.currency_symbol, 1342 onFinish: function (data) { 1343 mobileSliderData.priceRange = { from: data.from, to: data.to }; 1344 1345 const durationData = mobileSliderData.durationMonth; 1346 getTours( 1347 microsite, 1348 [...new Set(newCheckedValues)].join(','), 1349 [...new Set(newSelectedValues)].join(','), 1350 onSale.checked ? true : false, 1351 regionSort.value + sortSelecet.value, 1352 durationData.from, 1353 durationData.to, 1354 start_date, 1355 end_date, 1356 data.from, 1357 data.to, 1358 selectElement.value, 1359 page 1360 ); 1361 }, 1362 }) 1363 .data("mobilePriceRange"); 1364 1365 // Initialize durationMonth slider 1366 var durationMonth = $("#duration") 1367 .ionRangeSlider({ 1368 type: "double", 1369 grid: true, 1370 min: 1, 1371 max: 30, 1372 from: 1, 1373 step: 1, 1374 postfix: " days", 1375 onFinish: function (data) { 1376 // Store durationMonth data in the shared object 1377 sliderData.durationMonth = { from: data.from, to: data.to }; 1378 1379 // Retrieve data from priceRange if needed 1380 const priceData = sliderData.priceRange; 1381 1382 // Use the data to call getTours 1383 getTours( 1384 microsite, 1385 [...new Set(newCheckedValues)].join(','), 1386 [...new Set(newSelectedValues)].join(','), 1387 onSale.checked ? true : false, 1388 regionSort.value + sortSelecet.value, 1389 data.from, 1390 data.to, 1391 start_date, 1392 end_date, 1393 priceData.from, 1394 priceData.to, 1395 selectElement.value, 1396 page 1397 ); 1398 }, 1399 }) 1400 .data("durationMonth"); 1401 1402 var durationMonth = $("#mobile_duration") 1403 .ionRangeSlider({ 1404 type: "double", 1405 grid: true, 1406 min: 1, 1407 max: 30, 1408 from: 1, 1409 step: 1, 1410 postfix: " days", 1411 onFinish: function (data) { 1412 mobileSliderData.durationMonth = { from: data.from, to: data.to }; 1413 1414 const priceData = mobileSliderData.priceRange; 1415 getTours( 1416 microsite, 1417 [...new Set(newCheckedValues)].join(','), 1418 [...new Set(newSelectedValues)].join(','), 1419 onSale.checked ? true : false, 1420 regionSort.value + sortSelecet.value, 1421 data.from, 1422 data.to, 1423 start_date, 1424 end_date, 1425 priceData.from, 1426 priceData.to, 1427 selectElement.value, 1428 page 1429 ); 1430 }, 1431 }) 1432 .data("mobileDurationMonth"); 1433 1434 1435 $(document).ready(function () { 1436 var today = new Date(); 1437 var minYear = today.getFullYear(); 1438 var minMonth = today.getMonth(); 1439 var maxYear = minYear + 2; 1440 var maxMonth = minMonth; 1441 1442 var minDate = new Date(minYear, minMonth, 1).getTime(); 1443 var maxDate = new Date(maxYear, maxMonth, 1).getTime(); 1444 1445 $("#month-year-range-slider").ionRangeSlider({ 1446 type: "double", 1447 min: minDate, 1448 max: maxDate, 1449 from: minDate, 1450 to: maxDate, 1451 prettify: function (num) { 1452 var date = new Date(num);
1453 var month = date.toLocaleString("default", { month: "short" }); 1454 var year = date.getFullYear(); 1455 return month + " " + year; 1456 }, 1457 onFinish: function (data) { 1458 var fromDate = new Date(data.from); 1459 var toDate = new Date(data.to); 1460 1461 var fromMonth = ("0" + (fromDate.getMonth() + 1)).slice(-2); 1462 var fromYear = fromDate.getFullYear(); 1463 var toMonth = ("0" + (toDate.getMonth() + 1)).slice(-2); 1464 var toYear = toDate.getFullYear(); 1465 1466 sliderData.monthYearRange = { 1467 from: `${fromYear}-${fromMonth}`, 1468 to: `${toYear}-${toMonth}` 1469 }; 1470 1471 const priceData = sliderData.priceRange; 1472 const durationData = sliderData.durationMonth; 1473 1474 getTours( 1475 microsite, 1476 [...new Set(newCheckedValues)].join(','), 1477 [...new Set(newSelectedValues)].join(','), 1478 onSale.checked ? true : false, 1479 regionSort.value + sortSelecet.value, 1480 durationData.from, 1481 durationData.to, 1482 sliderData.monthYearRange.from, 1483 sliderData.monthYearRange.to, 1484 priceData.from, 1485 priceData.to, 1486 selectElement.value, 1487 page 1488 ); 1489 }, 1490 }); 1491 }); 1492 1493 1494 function hasNumber(inputString) { 1495 var regex = /\d/; 1496 return regex.test(inputString); 1497 } 1498 } 1499 1500 1501 $(document).ready(function () { 1502 var today = new Date(); 1503 var minYear = today.getFullYear(); 1504 var minMonth = today.getMonth(); 1505 var maxYear = minYear + 2; 1506 var maxMonth = minMonth; 1507 1508 var minDate = new Date(minYear, minMonth, 1).getTime(); 1509 var maxDate = new Date(maxYear, maxMonth, 1).getTime(); 1510 1511 $("#mobile-month-year-range-slider").ionRangeSlider({ 1512 type: "double", 1513 min: minDate, 1514 max: maxDate, 1515 from: minDate, 1516 to: maxDate, 1517 prettify: function (num) { 1518 var date = new Date(num); 1519 var month = date.toLocaleString("default", { month: "short" }); 1520 var year = date.getFullYear(); 1521 return month + " " + year; 1522 }, 1523 onFinish: function (data) { 1524 var fromDate = new Date(data.from); 1525 var toDate = new Date(data.to); 1526 1527 var fromMonth = ("0" + (fromDate.getMonth() + 1)).slice(-2); 1528 var fromYear = fromDate.getFullYear(); 1529 var toMonth = ("0" + (toDate.getMonth() + 1)).slice(-2); 1530 var toYear = toDate.getFullYear(); 1531 1532 mobileSliderData.monthYearRange = { 1533 from: `${fromYear}-${fromMonth}`, 1534 to: `${toYear}-${toMonth}` 1535 }; 1536 1537 const priceData = mobileSliderData.priceRange; 1538 const durationData = mobileSliderData.durationMonth; 1539 1540 getTours( 1541 microsite, 1542 [...new Set(newCheckedValues)].join(','), 1543 [...new Set(newSelectedValues)].join(','), 1544 onSale.checked ? true : false, 1545 regionSort.value + sortSelecet.value, 1546 durationData.from, 1547 durationData.to, 1548 sliderData.monthYearRange.from, 1549 sliderData.monthYearRange.to, 1550 priceData.from, 1551 priceData.to, 1552 selectElement.value, 1553 page 1554 ); 1555 }, 1556 }); 1557 }); 1558 }) 1559 .catch((error) => { 1560 console.log(error); 1561 }); 1562}; 1563 1564document.addEventListener("DOMContentLoaded", function () { 1565 const items = document.querySelectorAll('.date-price-item'); 1566 const showDateAndPrices = document.getElementById('showDateAndPrices'); 1567 const showAllDateAndPrices = document.getElementById('showAllDateAndPrices'); 1568 let numItemsToShow = 5; 1569 1570 function displayItems() { 1571 items.forEach((item, index) => { 1572 item.style.display = index < numItemsToShow ? "block" : "none"; 1573 }); 1574 if (items.length <= numItemsToShow) { 1575 showDateAndPrices.style.display = "none"; 1576 showAllDateAndPrices.style.display = "none"; 1577 } else { 1578 showDateAndPrices.style.display = numItemsToShow < items.length ? "inline-block" : "none"; 1579 showAllDateAndPrices.style.display = numItemsToShow < items.length ? "inline-block" : "none"; 1580 } 1581 } 1582 function showMoreItems() { 1583 numItemsToShow += 5; 1584 displayItems(); 1585 } 1586 function showAllItems() { 1587 numItemsToShow = items.length; 1588 displayItems(); 1589 } 1590 1591 showDateAndPrices.addEventListener("click", showMoreItems); 1592 showAllDateAndPrices.addEventListener("click", showAllItems); 1593 1594 displayItems(); 1595}); 1596 1597 1598var perPage = document.getElementById('perpage') 1599var sortSelect = document.getElementById('sortorder') 1600var regionSelect = document.getElementById('regionsort') 1601var onSale = document.getElementById('on_sale') 1602var hidePrice = document.getElementById('hide_price') 1603// const onSale = document.getElementById('on_sale'); 1604 1605var selectElement = document.getElementById('perpage') 1606var sortSelecet = document.getElementById('sortorder') 1607var regionSort = document.getElementById('regionsort') 1608 1609var mobileSelectElement = document.getElementById('mobileperpage') 1610var mobileSortSelecet = document.getElementById('mobilesortorder') 1611var mobileRegionSort = document.getElementById('mobileregion') 1612var mobileonSale = document.getElementById('mobile_on_sale') 1613 1614var newCheckedDestination = [] 1615var newCheckedTourTypes = [] 1616let checkedDestinations = "" 1617let checkedTourTypes = "" 1618var newSelectedValues = [] 1619var newCheckedValues = [] 1620var toggleSelectAllData = [] 1621 1622let sort = "price_asc" 1623let min_duration = 1 1624let max_duration = 30 1625let start_date = "" 1626let end_date = "" 1627let min_price; 1628let max_price; 1629let per_page = 9 1630let page = 1 1631 1632function toggleSelectAll(inputName, value = null) { 1633 var checkboxes = document.querySelectorAll('input[name="' + inputName + '"]'); 1634 var areAllChecked = true; 1635 var checkedValues = []; 1636
1637 checkboxes.forEach(function (checkbox) { 1638 if (value && checkbox.value.toLowerCase() === value.toLowerCase()) { 1639 // If this checkbox's value matches the one provided, handle it separately 1640 if (checkbox.checked) { 1641 checkedValues = checkedValues.filter(function (val) { 1642 return val !== checkbox.value.replace(/\s+/g, '-').toLowerCase(); 1643 }); 1644 } 1645 } else { 1646 // Toggle the checkbox and update the checkedValues array 1647 if (checkbox.checked) { 1648 // If already checked, keep it in the checkedValues 1649 checkedValues.push(checkbox.value.replace(/\s+/g, '-').toLowerCase()); 1650 } else { 1651 // If not checked, mark as checked 1652 checkbox.checked = true; 1653 checkedValues.push(checkbox.value.replace(/\s+/g, '-').toLowerCase()); 1654 areAllChecked = false; 1655 } 1656 } 1657 }); 1658 1659 // Uncheck all checkboxes if not all are checked 1660 if (areAllChecked) { 1661 checkboxes.forEach(function (checkbox) { 1662 checkbox.checked = false; 1663 }); 1664 checkedValues = []; // Clear array if all are unchecked 1665 } 1666 1667 newCheckedValues = checkedValues 1668 1669 getTours(microsite, [...new Set(newCheckedValues)].join(','), [...new Set(newSelectedValues)].join(','), onSale.checked ? true : false, regionSort.value + sortSelecet.value, 1670 sliderData.durationMonth.from, 1671 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 1672 sliderData.priceRange.from, sliderData.priceRange.to, selectElement.value, page) 1673 1674 return { 1675 areAllChecked: areAllChecked, 1676 checkedValues: checkedValues 1677 }; 1678} 1679 1680var url = window.location.pathname; 1681 1682// Split the URL by '/' and filter out empty strings 1683var parts = url.split('/').filter(function (part) { 1684 return part.trim() !== ''; 1685}); 1686 1687// Get the last parameter 1688var lastParam = parts[parts.length - 1]; 1689 1690var newSelectedValues = false 1691 1692function getCheckedValues(inputName, value = null) { 1693 var checkboxes = document.querySelectorAll('input[name="' + inputName + '"]'); 1694 var selectedCheckboxes = document.querySelectorAll('input[name="tourChecked"]'); 1695 1696 // Helper function to normalize values 1697 function normalizeValue(value) { 1698 return value.replace(/\s+/g, '-').toLowerCase(); 1699 } 1700 1701 // Process tourChecked checkboxes 1702 var selectedValues = [] 1703 var checkedValues = [] 1704 selectedCheckboxes.forEach(function (checkbox) { 1705 if (checkbox.checked) { 1706 selectedValues.push(normalizeValue(checkbox.value)); 1707 } 1708 return checkedValues 1709 }); 1710 1711 // Process inputName checkboxes 1712 1713 checkboxes.forEach(function (checkbox) { 1714 if (checkbox.checked) { 1715 checkedValues.push(normalizeValue(checkbox.value)); 1716 } 1717 return selectedValues 1718 }); 1719 1720 // If there is a special case for specific values 1721 var selectedCheck = false; 1722 var selectedChecked = false; 1723 var normalizedValue = normalizeValue(lastParam); 1724 1725 // Process the checkboxes based on the value 1726 if (value === 2 || value === 3) { 1727 var targetCheckboxes = (value === 2) ? selectedCheckboxes : checkboxes; 1728 var targetValues = (value === 2) ? selectedValues : checkedValues; 1729 var isSelectedCheck = (value === 2) ? selectedCheck : selectedChecked; 1730 1731 targetCheckboxes.forEach(function (checkbox) { 1732 if (checkbox.value.replace(/\s+/g, '-').toLowerCase() === lastParam.toLowerCase()) { 1733 // If the checkbox is not already checked, update the checkbox and add value 1734 if (!isSelectedCheck) { 1735 checkbox.checked = true; 1736 isSelectedCheck = true; // Ensure the condition is met only once 1737 targetValues.push(normalizedValue); // Add the normalized value to the array 1738 } 1739 } 1740 }); 1741 } 1742 1743 1744 // Update the tour options 1745 let destinations = [...new Set(checkedValues)].join(","); 1746 let tourTypes = [...new Set(selectedValues)].join(","); 1747 1748 checkedDestinations = destinations; 1749 checkedTourTypes = tourTypes; 1750 1751 newCheckedDestination = destinations; 1752 newCheckedTourTypes = tourTypes; 1753 1754 newCheckedValues = checkedValues 1755 newSelectedValues = selectedValues 1756 1757 1758 getTours(microsite, [...new Set(newCheckedValues)].join(','), [...new Set(newSelectedValues)].join(','), onSale.checked ? true : false, regionSort.value + sortSelecet.value, sliderData.durationMonth.from, 1759 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 1760 sliderData.priceRange.from, sliderData.priceRange.to, per_page, page) 1761 1762 if (checkedTourTypes.length > 0) { 1763 getTours(microsite, [...new Set(newCheckedValues)].join(','), [...new Set(newSelectedValues)].join(','), onSale.checked ? true : false, regionSort.value + sortSelecet.value, sliderData.durationMonth.from, 1764 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 1765 sliderData.priceRange.from, sliderData.priceRange.to, per_page, page) 1766 } 1767} 1768 1769 1770if (['united-arab-emirates', 'egypt', 'jordan', 'israel', 'lebanon', 'sudan'].includes(lastParam)) { 1771 getCheckedValues('egyptCheck', 3) 1772} 1773 1774 1775if (['india', 'nepal', 'maldives', 'pakistan'].includes(lastParam)) { 1776 getCheckedValues('subcontinentCheck', 3) 1777} 1778 1779if (['bhutan', 'tibet', 'china', 'uzbekistan', 'kazakhstan', 'kyrgyzstan', 'tajikistan'].includes(lastParam)) { 1780 getCheckedValues('asiaCheck', 3) 1781} 1782 1783if (['thailand', 'vietnam', 'laos', 'cambodia', 'south-korea'].includes(lastParam)) { 1784 getCheckedValues('southeastAsia', 3) 1785}
1785 1786 1787if (['peru', 'bolivia', 'Argentina', 'argentina'].includes(lastParam)) { 1788 getCheckedValues('southAmerica', 3) 1789} 1790 1791if (['turkey', 'greece'].includes(lastParam)) { 1792 getCheckedValues('europeCheck', 3) 1793} 1794 1795if (['tonga'].includes(lastParam)) { 1796 getCheckedValues('oceaniaCheck', 3) 1797} 1798 1799if (['antarctic', 'arctic'].includes(lastParam)) { 1800 getCheckedValues('polarRegions', 3) 1801} 1802 1803if (['small-group', 'shoestring', 'city-break', 'private', 'family', 'special-interest', 'cruise'].includes(lastParam)) { 1804 getCheckedValues('', 2) 1805} 1806 1807 1808 1809document.addEventListener('DOMContentLoaded', (event) => { 1810 let destinationsArray = checkedDestinations.split(','); 1811 let uniqueDestinations = [...new Set(destinationsArray)]; 1812 const onSaleCheckbox = document.getElementById('on_sale'); 1813 if (window.location.pathname === `/${microsite}/specialoffers` || window.location.pathname === 1814 `/specialoffers`) { 1815 getTours(microsite, checkedDestinations, checkedTourTypes, onSale.checked = true, regionSort.value + sortSelecet.value, 1816 sliderData.durationMonth.from, 1817 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 1818 sliderData.priceRange.from, sliderData.priceRange.to, selectElement.value, page) 1819 1820 } 1821}); 1822 1823 1824document.addEventListener('DOMContentLoaded', (event) => { 1825 if (window.location.pathname === `/${microsite}/safer-encounters` || window.location.pathname === 1826 `/safer-encounters` || window.location.pathname === `/p/safer-encounters`) { 1827 // checkedDestinations = checkedDestinations ? `${checkedDestinations},laos` : 'laos'; 1828 getTours(microsite, checkedDestinations, checkedTourTypes, onSale.checked, regionSort.value + sortSelecet.value, 1829 sliderData.durationMonth.from, 1830 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 1831 sliderData.priceRange.from, sliderData.priceRange.to, selectElement.value, page) 1832 } 1833}); 1834 1835document.addEventListener('DOMContentLoaded', function () { 1836 const currentUrl = new URL(window.location.href); 1837 const pathParts = currentUrl.pathname.split('/').filter(Boolean); 1838 1839 // If the path is "/p/safer-encounters", redirect to "/safer-encounters" 1840 if (pathParts.length === 2 && pathParts[0] === 'p' && pathParts[1] === 'safer-encounters') { 1841 const newPath = '/' + pathParts[1]; 1842 window.history.replaceState(null, '', newPath); 1843 } 1844}); 1845 1846document.addEventListener('DOMContentLoaded', (event) => { 1847 let destinationsArray = checkedDestinations.split(','); 1848 let uniqueDestinations = [...new Set(destinationsArray)]; 1849 const onSaleCheckbox = document.getElementById('on_sale'); 1850 if (window.location.pathname === `/${microsite}/destinations` || window.location.pathname === 1851 `/destinations`) { 1852 getTours(microsite, checkedDestinations, checkedTourTypes, onSale.checked ? true : false, regionSort.value + sortSelecet.value, 1853 sliderData.durationMonth.from, 1854 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 1855 sliderData.priceRange.from, sliderData.priceRange.to, selectElement.value, page) 1856 1857 } 1858}); 1859 1860 1861function getSale() { 1862 // Remove duplicates 1863 let destinationsArray = checkedDestinations.split(','); 1864 let uniqueDestinations = [...new Set(destinationsArray)]; 1865 1866 // Ensure newCheckedValues and newSelectedValues are defined 1867 let newCheckedValues = []; // Define this as needed 1868 let newSelectedValues = []; // Define this as needed 1869 1870 // Call getTours with properly formatted parameters 1871 getTours( 1872 microsite, 1873 [...new Set(newCheckedValues)].join(','), // Convert to string 1874 [...new Set(newSelectedValues)].join(','), // Convert to string 1875 onSale.checked, // This can directly be used as it's a boolean 1876 regionSort.value + sortSelect.value, // Ensure these are strings 1877 sliderData.durationMonth.from, 1878 sliderData.durationMonth.to, 1879 sliderData.monthYearRange.from, 1880 sliderData.monthYearRange.to, 1881 sliderData.priceRange.from, 1882 sliderData.priceRange.to, 1883 selectElement.value, 1884 page 1885 ); 1886} 1887 1888document.addEventListener('DOMContentLoaded', (event) => { 1889 let destinationsArray = checkedDestinations.split(','); 1890 let uniqueDestinations = [...new Set(destinationsArray)]; 1891 1892 if (window.location.pathname === `/${microsite}/searchalltours` || window.location.pathname === `/searchalltours`) { 1893 // Get URL parameters
1894 const urlParams = new URLSearchParams(window.location.search); 1895 const countryParam = urlParams.get('countries'); 1896 1897 // Initialize checkedDestinations as a string 1898 checkedDestinations = ''; 1899 1900 // Define Egypt & Middle East countries with proper capitalization 1901 const egyptMiddleEastCountries = { 1902 'egypt': 'Egypt', 1903 'jordan': 'Jordan', 1904 'israel': 'Israel', 1905 'lebanon': 'Lebanon', 1906 'sudan': 'Sudan' 1907 }; 1908 1909 // If countries parameter exists 1910 if (countryParam) { 1911 checkedDestinations = countryParam; 1912 const countryLower = countryParam.toLowerCase(); 1913 1914 // Check if it's an Egypt & Middle East country 1915 if (Object.keys(egyptMiddleEastCountries).includes(countryLower)) { 1916 // Check the Egypt & Middle East main checkbox 1917 const egyptCheckbox = document.querySelector('#egyptCheck'); 1918 if (egyptCheckbox) { 1919 egyptCheckbox.checked = true; 1920 } 1921 1922 // Find and check the specific country checkbox using proper capitalization 1923 const properCountryName = egyptMiddleEastCountries[countryLower]; 1924 const countryCheckbox = document.querySelector(`input[value="${properCountryName}"][name="egyptCheck"]`); 1925 if (countryCheckbox) { 1926 countryCheckbox.checked = true; 1927 } 1928 1929 // Call getCheckedValues after checking boxes 1930 getCheckedValues('egyptCheck', 3); 1931 } 1932 } 1933 1934 // Continue with existing getTours call 1935 getTours( 1936 microsite, 1937 checkedDestinations, 1938 checkedTourTypes, 1939 onSale.checked ? true : false, 1940 regionSort.value + sortSelecet.value, 1941 min_duration, 1942 max_duration, 1943 start_date, 1944 end_date, 1945 min_price, 1946 max_price, 1947 selectElement.value, 1948 page 1949 ); 1950 } 1951 1952 if (window.location.pathname === `/${microsite}/tourtypes` || window.location.pathname === `/tourtypes`) { 1953 getTours( 1954 microsite, 1955 checkedDestinations, 1956 checkedTourTypes, 1957 onSale.checked ? true : false, 1958 regionSort.value + sortSelecet.value, 1959 min_duration, 1960 max_duration, 1961 start_date, 1962 end_date, 1963 min_price, 1964 max_price, 1965 selectElement.value, 1966 page 1967 ); 1968 } 1969}); 1970 1971 1972function mobileGetSale() { 1973 // remove duplicate 1974 let destinationsArray = checkedDestinations.split(','); 1975 let uniqueDestinations = [...new Set(destinationsArray)]; 1976 1977 1978 getTours(microsite, [...new Set(newCheckedValues)].join(','), [...new Set(newSelectedValues)].join(','), mobileonSale.checked ? true : false, regionSort.value + sortSelecet.value, 1979 mobileSliderData.durationMonth.from, 1980 mobileSliderData.durationMonth.to, 1981 mobileSliderData.monthYearRange.from, 1982 mobileSliderData.monthYearRange.to, 1983 mobileSliderData.priceRange.from, 1984 mobileSliderData.priceRange.to, 1985 selectElement.value, 1986 selectElement.value, 1987 page 1988 ) 1989} 1990function getAllTours() { 1991 // remove duplicate 1992 let destinationsArray = checkedDestinations.split(','); 1993 let uniqueDestinations = [...new Set(destinationsArray)]; 1994 getTours(microsite, [...new Set(newCheckedValues)].join(','), [...new Set(newSelectedValues)].join(','), onSale.checked ? true : false, regionSort.value + sortSelecet.value, 1995 min_duration, max_duration, start_date, end_date, min_price, max_price, selectElement.value, page) 1996} 1997 1998function mobileAllTours() { 1999 // remove duplicate 2000 let destinationsArray = checkedDestinations.split(','); 2001 let uniqueDestinations = [...new Set(destinationsArray)]; 2002 getTours(microsite, [...new Set(newCheckedValues)].join(','), [...new Set(newSelectedValues)].join(','), mobileonSale.checked ? true : false, regionSort.value + sortSelecet.value, 2003 mobileSliderData.durationMonth.from, 2004 mobileSliderData.durationMonth.to, 2005 mobileSliderData.monthYearRange.from, 2006 mobileSliderData.monthYearRange.to, 2007 mobileSliderData.priceRange.from, 2008 mobileSliderData.priceRange.to, 2009 selectElement.value, 2010 selectElement.value, page) 2011} 2012 2013 2014function getSelectedOption() { 2015 let destinations = ''; 2016 let tourTypes = ''; 2017 // let onSale = true 2018 let min_duration = 1 2019 let max_duration = 30 2020 let start_date = "" 2021 let end_date = "" 2022 let min_price; 2023 let max_price; 2024 let page = 1 2025 // remove duplicate 2026 let destinationsArray = checkedDestinations.split(','); 2027 let uniqueDestinations = [...new Set(destinationsArray)]; 2028 const checkedValues = newCheckedValues.length > 0 2029 ? [...new Set(newCheckedValues)].join(',') 2030 : '' 2031 2032 const selectedValues = newSelectedValues.length > 0 2033 ? [...new Set(newSelectedValues)].join(',') 2034 : '' 2035 2036 getTours(microsite, checkedValues, selectedValues, onSale.checked ? true : false, regionSort.value + sortSelecet.value, sliderData.durationMonth.from, 2037 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 2038 sliderData.priceRange.from, sliderData.priceRange.to, selectElement.value, page) 2039 2040} 2041 2042function mobileSelecectedOption() { 2043 let destinations = ''; 2044 let tourTypes = ''; 2045 // let onSale = true 2046 let min_duration = 1 2047 let max_duration = 30 2048 let start_date = "" 2049 let end_date = "" 2050 let min_price; 2051 let max_price; 2052 let page = 1 2053 // remove duplicate 2054 let destinationsArray = checkedDestinations.split(','); 2055 let uniqueDestinations = [...new Set(destinationsArray)]; 2056 const checkedValues = newCheckedValues.length > 0 2057 ? [...new Set(newCheckedValues)].join(',') 2058 : '' 2059 2060 const selectedValues = newSelectedValues.length > 0 2061 ? [...new Set(newSelectedValues)].join(',') 2062 : '' 2063 getTours(microsite, checkedValues, selectedValues, onSale.checked ? true : false, mobileRegionSort.value + mobileSortSelecet.value, 2064 mobileSliderData.durationMonth.from, 2065 mobileSliderData.durationMonth.to, 2066 mobileSliderData.monthYearRange.from, 2067 mobileSliderData.monthYearRange.to, 2068 mobileSliderData.priceRange.from, 2069 mobileSliderData.priceRange.to, 2070 selectElement.value, 2071 mobileSelectElement.value, page) 2072 2073} 2074 2075function getSortSelected() { 2076 let destinations = ''; 2077 let tourTypes = ''; 2078 // let onSale = true 2079 let min_duration = 1 2080 let max_duration = 30 2081 let start_date = "" 2082 let end_date = "" 2083 let min_price; 2084 let max_price; 2085 let per_page = 9 2086 let page = 1 2087 // remove duplicate 2088 let destinationsArray = checkedDestinations.split(','); 2089 let uniqueDestinations = [...new Set(destinationsArray)]; 2090 const checkedValues = newCheckedValues.length > 0 2091 ? [...new Set(newCheckedValues)].join(',') 2092 : '' 2093 2094 const selectedValues = newSelectedValues.length > 0 2095 ? [...new Set(newSelectedValues)].join(',') 2096 : '' 2097 getTours(microsite, checkedValues, selectedValues, onSale.checked ? true : false, regionSort.value + sortSelecet.value, sliderData.durationMonth.from, 2098 sliderData.durationMonth.to, sliderData.monthYearRange.from, sliderData.monthYearRange.to, 2099 sliderData.priceRange.from, sliderData.priceRange.to, selectElement.value, page) 2100 2101} 2102 2103function mobileSortSelected() { 2104 let destinations = ''; 2105 let tourTypes = ''; 2106 // let onSale = true 2107 let min_duration = 1 2108 let max_duration = 30 2109 let start_date = "" 2110 let end_date = "" 2111 let min_price; 2112 let max_price; 2113 let per_page = 9 2114 let page = 1 2115 // remove duplicate 2116 let destinationsArray = checkedDestinations.split(','); 2117 let uniqueDestinations = [...new Set(destinationsArray)]; 2118 const checkedValues = newCheckedValues.length > 0 2119 ? [...new Set(newCheckedValues)].join(',') 2120 : '' 2121 2122 const selectedValues = newSelectedValues.length > 0 2123 ? [...new Set(newSelectedValues)].join(',') 2124 : '' 2125 getTours(microsite, checkedValues, selectedValues, onSale.checked ? true : false, mobileRegionSort.value + mobileSortSelecet.value, 2126 mobileSliderData.durationMonth.from, 2127 mobileSliderData.durationMonth.to, 2128 mobileSliderData.monthYearRange.from, 2129 mobileSliderData.monthYearRange.to, 2130 mobileSliderData.priceRange.from, 2131 mobileSliderData.priceRange.to, 2132 selectElement.value, 2133 mobileSelectElement.value, page) 2134 2135} 2136 2137 2138function getSortedRegion() { 2139 let destinations = ''; 2140 let tourTypes = ''; 2141 // let onSale = true 2142 let min_duration = 1 2143 let max_duration = 30 2144 let start_date = "" 2145 let end_date = "" 2146 let min_price; 2147 let max_price; 2148 let per_page = 9 2149 let page = 1 2150 // remove duplicate 2151 let destinationsArray = checkedDestinations.split(','); 2152 let uniqueDestinations = [...new Set(destinationsArray)]; 2153 const checkedValues = newCheckedValues.length > 0 2154 ? [...new Set(newCheckedValues)].join(',') 2155 : '' 2156 2157 const selectedValues = newSelectedValues.length > 0 2158 ? [...new Set(newSelectedValues)].join(',') 2159 : '' 2160 getTours( 2161 microsite, 2162 checkedValues, 2163 selectedValues, 2164 onSale.checked, 2165 regionSort.value + sortSelect.value, 2166 sliderData.durationMonth.from, 2167 sliderData.durationMonth.to, 2168 sliderData.monthYearRange.from, 2169 sliderData.monthYearRange.to, 2170 sliderData.priceRange.from, 2171 sliderData.priceRange.to, 2172 selectElement.value, 2173 page 2174 ) 2175} 2176 2177function mobileGetSorted() { 2178 let destinations = ''; 2179 let tourTypes = ''; 2180 // let onSale = true 2181 let min_duration = 1 2182 let max_duration = 30 2183 let start_date = "" 2184 let end_date = "" 2185 let min_price; 2186 let max_price; 2187 let per_page = 9 2188 let page = 1 2189 // remove duplicate 2190 let destinationsArray = checkedDestinations.split(','); 2191 let uniqueDestinations = [...new Set(destinationsArray)]; 2192 const checkedValues = newCheckedValues.length > 0 2193 ? [...new Set(newCheckedValues)].join(',') 2194 : '' 2195 2196 const selectedValues = newSelectedValues.length > 0 2197 ? [...new Set(newSelectedValues)].join(',') 2198 : '' 2199 getTours(microsite, checkedValues, selectedValues, onSale.checked ? true : false, mobileRegionSort.value + mobileSortSelecet.value, 2200 mobileSliderData.durationMonth.from, 2201 mobileSliderData.durationMonth.to, 2202 mobileSliderData.monthYearRange.from, 2203 mobileSliderData.monthYearRange.to, 2204 mobileSliderData.priceRange.from, 2205 mobileSliderData.priceRange.to, 2206 selectElement.value, 2207 mobileSelectElement.value, page) 2208 2209} 2210document.addEventListener('DOMContentLoaded', () => { 2211 // Select the div elements and buttons 2212 const div1 = document.getElementById('div1'); 2213 const div2 = document.getElementById('div2'); 2214 const div3 = document.getElementById('div3'); 2215 const div4 = document.getElementById('div4'); 2216 const toDiv2Button = document.getElementById('toDiv2'); 2217 const toDiv1Button = document.getElementById('toDiv1'); 2218 const toDiv3Button = document.getElementById('toDiv3'); 2219 const toDiv4Button = document.getElementById('toDiv4'); 2220 const goBackButton = document.getElementById('goBack'); 2221 const goBack1Button = document.getElementById('goback1'); 2222 const backtoDestination = document.getElementById('backDestination'); 2223 2224 // Function to show a specific div 2225 const showDiv = (divToShow, divToHide) => { 2226 divToShow.classList.remove('d-none'); 2227 divToHide.classList.add('d-none'); 2228 }; 2229 2230 // Event listeners for the buttons 2231 toDiv2Button.addEventListener('click', () => showDiv(div2, div1)) 2232 toDiv1Button.addEventListener('click', () => showDiv(div1, div2)) 2233 goBackButton.addEventListener('click', () => showDiv(div1, div2)) 2234 goBack1Button.addEventListener('click', () => showDiv(div1, div3)) 2235 backtoDestination.addEventListener('click', () => showDiv(div3, div4)) 2236 toDiv3Button.addEventListener('click', () => showDiv(div3, div1)) 2237 toDiv4Button.addEventListener('click', () => showDiv(div4, div3)) 2238}); 2239 2240document.addEventListener("DOMContentLoaded", function () { 2241 const items = document.querySelectorAll('.date-price-item'); 2242 const showDateAndPrices = document.getElementById('showDateAndPrices'); 2243 const showAllDateAndPrices = document.getElementById('showAllDateAndPrices'); 2244 let numItemsToShow = 5; 2245 2246 const allBtn = document.querySelector('[data-filter="all"]'); 2247 const buttons = document.querySelectorAll("[data-filter]"); 2248 2249 function setAllActive() { 2250 buttons.forEach(b => { 2251 b.classList.remove("btn-orange", "active"); 2252 b.classList.add("bg-gray-100", "text-white"); 2253 }); 2254 if (allBtn) { 2255 allBtn.classList.remove("bg-gray-100", "text-white"); 2256 allBtn.classList.add("btn-orange", "active"); 2257 } 2258 } 2259 2260 function displayItems() { 2261 if (items.length === 0) { 2262 if (showDateAndPrices) showDateAndPrices.style.display = "none"; 2263 if (showAllDateAndPrices) showAllDateAndPrices.style.display = "none"; 2264 return; 2265 } 2266
2267 items.forEach((item, index) => { 2268 item.style.display = index < numItemsToShow ? "block" : "none"; 2269 }); 2270 2271 if (items.length <= numItemsToShow) { 2272 showDateAndPrices.style.display = "none"; 2273 showAllDateAndPrices.style.display = "none"; 2274 } else { 2275 showDateAndPrices.style.display = "inline-block"; 2276 showAllDateAndPrices.style.display = "inline-block"; 2277 } 2278 } 2279 2280 function showMoreItems() { 2281 numItemsToShow += 5; 2282 displayItems(); 2283 setAllActive(); 2284 } 2285 2286 function showAllItems() { 2287 numItemsToShow = items.length; 2288 displayItems(); 2289 setAllActive(); 2290 } 2291 2292 if (showDateAndPrices) showDateAndPrices.addEventListener("click", showMoreItems); 2293 if (showAllDateAndPrices) showAllDateAndPrices.addEventListener("click", showAllItems); 2294 2295 displayItems(); 2296 if (items.length > 0) { 2297 setAllActive(); 2298 } 2299}); 2300 2301document.addEventListener("DOMContentLoaded", function() { 2302 const datePriceContainers = document.querySelectorAll('.list-group-flush.bg-white'); 2303 const showMoreBtn = document.getElementById('showMoreDates'); 2304 const showAllBtn = document.getElementById('showAllDates'); 2305 let visibleItems = 5; 2306 2307 // Initialize display 2308 function updateDisplay() { 2309 datePriceContainers.forEach((container, index) => { 2310 container.style.display = index < visibleItems ? 'block' : 'none'; 2311 }); 2312 2313 // Show/hide buttons based on remaining items 2314 if (datePriceContainers.length <= visibleItems) { 2315 showMoreBtn.style.display = 'none'; 2316 showAllBtn.style.display = 'none'; 2317 } else { 2318 showMoreBtn.style.display = 'inline-block'; 2319 showAllBtn.style.display = 'inline-block'; 2320 } 2321 2322 // Disable "Show More" if we're showing all or nearly all 2323 if (visibleItems >= datePriceContainers.length) { 2324 showMoreBtn.disabled = true; 2325 showAllBtn.disabled = true; 2326 } 2327 } 2328 2329 // Event listeners 2330 showMoreBtn?.addEventListener('click', function() { 2331 visibleItems = Math.min(visibleItems + 3, datePriceContainers.length); 2332 updateDisplay(); 2333 }); 2334 2335 showAllBtn?.addEventListener('click', function() { 2336 visibleItems = datePriceContainers.length; 2337 updateDisplay(); 2338 }); 2339 2340 // Initial display 2341 updateDisplay(); 2342}); 2343 2344 // show all the tour notes 2345 document.addEventListener("DOMContentLoaded", function () { 2346 const showMoreBtn = document.getElementById("showDateAndPrices"); 2347 const showAllBtn = document.getElementById("showAllDateAndPrices"); 2348 2349 const allBtn = document.querySelector('[data-filter="all"]'); 2350 const buttons = document.querySelectorAll("[data-filter]"); 2351 2352 let numItemsToShow = 5; 2353 let currentFilter = "all"; 2354 2355 function getVisibleItems() { 2356 if (window.innerWidth >= 576) { 2357 return document.querySelectorAll(".desktop-item"); 2358 } else { 2359 return document.querySelectorAll(".mobile-item"); 2360 } 2361 } 2362 2363 function updateDisplay() { 2364 const items = getVisibleItems(); 2365 let visibleCount = 0; 2366 const isAll = currentFilter === "all"; 2367 2368 items.forEach(item => { 2369 const rawCategory = item.getAttribute("data-category") || "all"; 2370 const category = rawCategory.trim().toLowerCase(); 2371 const match = isAll || category === currentFilter.toLowerCase(); 2372 2373 if (match) { 2374 if (isAll && visibleCount >= numItemsToShow) { 2375 item.style.display = "none"; 2376 } else { 2377 item.style.display = "block"; 2378 visibleCount++; 2379 } 2380 } else { 2381 item.style.display = "none"; 2382 } 2383 }); 2384 2385 if (isAll) { 2386 if (items.length <= numItemsToShow) { 2387 showMoreBtn?.style && (showMoreBtn.style.display = "none"); 2388 showAllBtn?.style && (showAllBtn.style.display = "none"); 2389 } else { 2390 showMoreBtn?.style && (showMoreBtn.style.display = "inline-block"); 2391 showAllBtn?.style && (showAllBtn.style.display = "inline-block"); 2392 } 2393 } else { 2394 showMoreBtn?.style && (showMoreBtn.style.display = "none"); 2395 showAllBtn?.style && (showAllBtn.style.display = "none"); 2396 } 2397 } 2398 2399 function setActiveButton(btn) { 2400 buttons.forEach(b => { 2401 b.classList.remove("btn-orange", "active"); 2402 b.classList.add("bg-gray-100", "text-white"); 2403 }); 2404 btn.classList.remove("bg-gray-100", "text-white"); 2405 btn.classList.add("btn-orange", "active"); 2406 } 2407 2408 if (allBtn) { 2409 setActiveButton(allBtn); 2410 updateDisplay(); 2411 } 2412 2413 buttons.forEach(btn => { 2414 btn.addEventListener("click", function () { 2415 currentFilter = this.getAttribute("data-filter"); 2416 2417 if (currentFilter === "all") { 2418 numItemsToShow = 5; 2419 } else { 2420 numItemsToShow = getVisibleItems().length; 2421 } 2422
2423 setActiveButton(this); 2424 updateDisplay(); 2425 }); 2426 }); 2427 2428 showMoreBtn?.addEventListener("click", function () { 2429 numItemsToShow += 5; 2430 updateDisplay(); 2431 }); 2432 2433 showAllBtn?.addEventListener("click", function () { 2434 numItemsToShow = getVisibleItems().length; 2435 updateDisplay(); 2436 }); 2437 2438 window.addEventListener("resize", function () { 2439 updateDisplay(); 2440 }); 2441}); 2442 2443document.addEventListener("DOMContentLoaded", function () { 2444 const accordionButtons = document.querySelectorAll('.accordion-button-dates'); 2445 2446 accordionButtons.forEach(button => { 2447 const bookNowButton = document.createElement('button'); 2448 bookNowButton.classList.add('btn-orange', 'btn', 'text-white', 'text-uppercase', 'p-2', 'rounded', 'badge-date', 'cursor-click', 'border-0', 'booknow-btn', 'fs-7'); 2449 bookNowButton.textContent = 'book now'; 2450 2451 // Create the icon element 2452 const icon = document.createElement('i'); 2453 icon.classList.add('fa-solid', 'fa-square-minus', 'cursor-click', 'fs-5', 'text-black'); 2454 2455 button.appendChild(bookNowButton); 2456 2457 button.addEventListener('click', function () { 2458 if (button.classList.contains('collapsed')) { 2459 if (!button.contains(bookNowButton)) { 2460 button.appendChild(bookNowButton); 2461 } 2462 if (button.contains(icon)) { 2463 button.removeChild(icon); 2464 } 2465 } else { 2466 if (button.contains(bookNowButton)) { 2467 button.removeChild(bookNowButton); 2468 } 2469 if (!button.contains(icon)) { 2470 button.appendChild(icon); 2471 } 2472 } 2473 }); 2474 }); 2475})
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.