1/** 2 * Main JS 3 * @version 2021 4 * @author vioma GmbH - www.vioma.de 5 * @license this code is distributed under the terms of the WTFPL 6 */ 7var nst2021_wrapper = function ( $ ) { 8 "use strict"; 9 10 // globally accessible for external template calls 11 var me = window.nst2021 = {}; 12 13 me.opt = { 14 variants: { 15 template: '', 16 header: '', 17 navigation: '' 18 }, 19 window: $( window ), 20 body_scroll: $( 'html,body' ), 21 html: $( 'html' ), 22 site: $( '#site' ), 23 head: $( 'head' ), 24 header: $( '#header' ).add( '#header_c' ), 25 hash: '', 26 main: $( '#main' ), 27 scroll: 0, 28 scroll_breakpoint: function(){ 29 return (me.opt.scroll >= me.opt.main_top * 0.5); 30 }, 31 already_scrolled: false, 32 noscript_afterload: $('noscript.styleafterscroll'), 33 std_domain: '', 34 mq: { 35 obj: $( '#layout' ), 36 width: 0, 37 portrait: false 38 }, 39 gals: [], 40 gal_std_ratio: 16 / 9, 41 gal_parallax: [], 42 gal_parallax_listening: false, 43 nstVideos: document.querySelectorAll('video.nst21-video'), 44 urlSearchParameters: window.location.search ? new URLSearchParams(window.location.search) : null, 45 userPrefers: { 46 colorScheme: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : false, 47 contrast: window.matchMedia('(prefers-contrast: more)').matches ? 'more' : window.matchMedia('(prefers-contrast: less)').matches ? 'less' : false, 48 reducedData: window.matchMedia('(prefers-reduced-data: reduce)').matches, 49 reducedMotion: window.matchMedia('(prefers-reduced-motion: reduce)').matches, 50 reducedTransparency: window.matchMedia('(prefers-reduced-transparency: reduce)').matches 51 } 52 }; 53 54 me.setup = function () { 55 if ( window.Modernizr === undefined ) { 56 window.Modernizr = { touchevents: false }; 57 } 58 if ( window.devicePixelRatio === undefined ) { 59 window.devicePixelRatio = 1; 60 61 } 62 me.opt.touch = window.Modernizr.touchevents; 63 me.opt.intersectionobserver = window.Modernizr.intersectionobserver; 64 me.opt.lang = me.opt.html.attr( 'lang' ); 65 me.opt.dev = me.opt.html.data('dev') === 'yes'; 66 me.opt.std_domain = me.opt.html.data('dev-domain') || ''; 67 me.opt.variants.header = me.opt.header.data( 'variant' ); 68 me.opt.banner = me.opt.header.find( '.banner' ); 69 me.opt.smoothscroll = ( me.opt.site.data( 'smoothscroll' ) !== 'no' ); 70 me.opt.main_top = me.opt.main.length ? me.opt.main.offset().top : 0; 71 me.opt.scroll = me.opt.window.scrollTop(); 72 me.opt.mq.width = me.opt.mq.obj.width(); 73 me.opt.bandwidth = ((!!navigator.connection) && (navigator.connection.downlink > 0)) ? navigator.connection.downlink : 0; 74 if ( me.opt.dev ) { 75 window.me = me; 76 } 77 78 try { 79 window.addEventListener("load", function() { 80 81 if (!window['scrolledBannerHeight']) { 82 window['scrolledBannerHeight'] = 0; 83 } 84 if (me.opt.banner.css("position") == "fixed" && window['scrolledBannerHeight'] == 0) { 85 window['scrolledBannerHeight'] = parseFloat(me.opt.banner.css("height")); 86 } 87 if (typeof window['scrolledBannerHeight'] == "number" && window['scrolledBannerHeight'] > 0) { 88 document.documentElement.style.setProperty("--scroll-margin-block", window['scrolledBannerHeight'] + "px"); 89 } 90 }, {passive: true}); 91 } catch(e) {}; 92 93 me.loadingClasses(); 94 me.nst_accessibility(); 95 me.nst_website_help(); 96 }; 97 98 me.init = function() { 99 me.content_place(); 100 me.listeners(); 101 me.custom_events(); 102 }; 103 104 me.content_place = function () { 105 me.scroll_event(); 106 107 if ( document.location.hash && !document.location.hash.match(/^#\//) ){ 108 me.opt.hash = document.location.hash; 109 } 110 }; 111 112 me.listeners = function () { 113 if ( me.opt.variants.header == 'C' ) { 114 me.opt.headc_chk = $('#header_c_nav_chk'); 115 $('.main-menu-toggle').on( 'change', function(){ 116 var handle = $(this); 117 var item = handle.closest('.main-menu-item'); 118 119 if(me.opt.mq.width <= 768) { 120 item.toggleClass('open-mobile'); 121 } 122 }); 123 124 if (!me.opt.headc_no_accessibility && me.opt.headc_chk.length) { 125 me.opt.headc_chk.checked = false; // If user presses back button 126 let $nav = $('#nav_menu'); 127 if (!$nav.length) return; 128 129 $nav.attr('inert', ''); 130 me.opt.headc_chk.attr('aria-controls', 'nav_menu').attr('aria-expanded', 'false').attr('aria-label', me.opt.headc_chk.data('label') || 'Toggle navigation menu'); 131 132 me.opt.headc_chk.on('change', function() { 133 if (this.checked) { 134 $nav.removeAttr('inert'); 135 $nav.find('.main-menu a').first().focus(); 136 me.opt.headc_chk.attr('aria-expanded', 'true'); 137 me.opt.headc_chk._escKeyPressed = false;
138 } 139 else { 140 $nav.attr('inert', ''); 141 me.opt.headc_chk.focus(); 142 me.opt.headc_chk.attr('aria-expanded', 'false'); 143 me.opt.headc_chk._escKeyPressed = true; 144 } 145 }); 146 147 $(document).on('keydown', function(e) { 148 if (!me.opt.headc_chk._escKeyPressed && e.key === 'Escape') { 149 me.opt.headc_chk.prop('checked', false).trigger('change'); 150 me.opt.headc_chk._escKeyPressed = false; 151 } 152 }); 153 } 154 155 $( 'a' ).on( 'click', me.smooth_scroll ); 156 } 157 else if (me.opt.variants.header == 'A') { 158 $( '.main-menu a', me.opt.header ).on( 'click', me.smooth_scroll ); 159 me.opt.heada_chk = $('input.main-menu-toggle', me.opt.header); 160 } 161 me.opt.header.find( '.widget-handle' ).click( function ( ev ) { 162 $( ev.target ).closest( '.nst21-widget' ).toggleClass( 'open' ); 163 } ); 164 165 me.opt.window.on( 'resize orientationchange', function () { 166 me.opt.main_top = me.opt.main.length ? me.opt.main.offset().top : 0; 167 me.opt.mq.width = me.opt.mq.obj.width(); 168 } ); 169 170 me.opt.scroll_handler = function ( ev ) { 171 me.opt.scroll = me.opt.window.scrollTop(); 172 me.scroll_event( ev ); 173 }; 174 175 try { 176 window.addEventListener( 'scroll', me.opt.scroll_handler, { passive: true } ); 177 window.addEventListener( 'touchmove', me.opt.scroll_handler, { passive: true } ); 178 } 179 catch(e) { 180 me.opt.window.on( 'scroll touchmove', me.opt.scroll_handler ); 181 } 182 183 $( '#site_anchor' ).click( function () { 184 var scrollspeed = me.opt.smoothscroll ? 400 : 1; 185 me.opt.body_scroll.animate( { scrollTop: 0 }, scrollspeed ); 186 } ); 187 188 if ( me.opt.hash !== '' ) { 189 me.opt.window.on( 'load', function () { 190 setTimeout( function () { 191 me.smooth_scroll( { 192 'hash': me.opt.hash.replace(/^#+/,''), 193 'banner_height': window['scrolledBannerHeight'] || false 194 } ); 195 }, 300 ); 196 } ); 197 } 198 else if( me.opt.site.data('autoscroll') ){ 199 var scrollto = $( me.opt.site.data('autoscroll') ); 200 if( scrollto.length && me.opt.scroll == 0 ) { 201 me.opt.window.on( 'load', function () { 202 setTimeout( function () { 203 me.smooth_scroll( { 204 'scrollto': scrollto.eq( 0 ), 205 'banner_height': window['scrolledBannerHeight'] || false 206 } ); 207 }, 300 ); 208 } ); 209 } 210 } 211 212 function nst21_video_handler(video, autoplay) { 213 if (!autoplay && !video.dataset.poster) return; 214 215 const observer = new IntersectionObserver(callback); 216 observer.observe(video); 217 function callback(entries, observer) { 218 entries.forEach(function(entry) { 219 const target = entry.target; 220 if (autoplay) { 221 entry.isIntersecting ? target.play() : target.pause(); 222 target.onended = function() { 223 observer.unobserve(target); 224 }; 225 } 226 else if (target.dataset.poster) { 227 if (entry.isIntersecting) { 228 target.poster = target.dataset.poster; 229 target.removeAttribute('data-poster'); 230 observer.unobserve(target); 231 } 232 } 233 }); 234 } 235 } 236 237 me.opt.nstVideos.forEach(function(video) { 238 if (me.opt.userPrefers.reducedMotion || me.opt.userPrefers.reducedData) { 239 video.removeAttribute('autoplay'); 240 video.setAttribute('controls', ''); 241 return; 242 } 243 var allowAutoplay = video.classList.contains('nst21-video-autoplay') && 244 me.opt.intersectionobserver && 245 ((me.opt.bandwidth > 2) || (me.opt.bandwidth == 0)); 246 nst21_video_handler(video, allowAutoplay); 247 }); 248 }; 249 250 me.custom_events = $.noop; 251 252 me.smooth_scroll = function ( ev ) { 253 var scrollspeed = me.opt.smoothscroll ? ( parseInt( ev.speed, 10 ) || 400 ) : 1, 254 boundingrect, 255 link, 256 link_href, 257 target, 258 match, 259 offset_px, 260 banner_height = parseInt( ev['banner_height'], 10 ) || window['scrolledBannerHeight'] || me.opt.banner.outerHeight() || 0; 261 262 /* if the click event is fired by javascript on an anchor in the page */ 263 if ( ev.hash ) { 264 target = $( '#' + ev.hash ); 265 if ( target.length === 0 ) { 266 if( ev.hash.indexOf('cid-') == 0 ){ 267 target = $('[data-cid="' + ev.hash.substr(4) + '"]') 268 } 269 else { 270 target = $('[id="' + ev.hash + '"],[name="' + ev.hash + '"]') 271 } 272 } 273 if ( target && target.filter(':visible').length > 0 ) { 274 /* removing the hash from the url to prevent the browser from jumping on its own after the animation */ 275 document.location.hash = ''; 276 offset_px = Math.round( target.offset().top - banner_height ); 277 me.opt.body_scroll.animate( { scrollTop: offset_px }, scrollspeed ); 278 } 279 return; 280 } 281 if( ev.scrollto && ev.scrollto.length > 0 ){ 282 offset_px = Math.round( ev.scrollto.eq(0).offset().top - banner_height ); 283 me.opt.body_scroll.animate( { scrollTop: offset_px }, scrollspeed ); 284 return; 285 } 286 link = ev.target ? $( ev.target ) : $( this ); 287 288 if ( !link.is( 'a' ) ) { 289 link = link.closest( 'a' ); 290 } 291 /* if the click event is fired on a link */ 292 if ( link.length === 1 ) { 293 link_href = link.attr( 'href' ); 294 /* links with an attached event or which open in a new window are not treated */ 295 if ( !link_href || link.attr( 'target' ) || link.attr( 'onclick' ) || link.attr( 'data-fancybox' ) ) { 296 return; 297 } 298 299 match = link_href.match( /^([^#]*)#+(.+)$/ ); 300 /* if the link has a page#anchor, comparing the current page with the requested page and try to
300softscroll if it's the same */ 301 if ( match && ( !match[1] || match[1] === document.location.pathname || ( document.location.pathname === '/' && match[1] === '/' + me.opt.lang + '/' ) ) ) { 302 target = $( '#' + match[2] ); 303 if ( target.length === 0 ) { 304 target = $('[id="' + match[2] + '"],[name="' + match[2] + '"]') 305 } 306 if ( target && target.filter(':visible').length > 0 ) { 307 ev.preventDefault(); 308 me.smooth_scroll_callback(ev,target); 309 offset_px = Math.round( target.eq( 0 ).offset().top - banner_height ); 310 if ( me.opt.banner.css('position')=='fixed' ){ 311 boundingrect = me.opt.banner.get( 0 ).getBoundingClientRect(); 312 if ( boundingrect && boundingrect.top ) { 313 offset_px -= boundingrect.top; 314 } 315 } 316 me.opt.body_scroll.animate( { scrollTop: offset_px }, scrollspeed ); 317 document.activeElement.blur(); 318 } 319 } 320 } 321 }; 322 323 me.smooth_scroll_callback = function(){ 324 if ( me.opt.headc_chk && me.opt.headc_chk.is(':checked') ) { 325 me.opt.headc_chk.prop('checked', false); 326 } 327 else if (me.opt.heada_chk) { 328 me.opt.heada_chk.each(function() { 329 $(this).prop('checked', false); 330 }) 331 } 332 }; 333 334 me.scroll_event = function () { 335 me.opt.site.toggleClass( 'scrolled', me.opt.scroll_breakpoint() ); 336 if ((me.opt.already_scrolled == false) && (me.opt.scroll_breakpoint() == true)) { 337 me.opt.noscript_afterload.each(function() { 338 var i = $(this) 339 me.opt.head.append(i.text()); 340 i.remove(); 341 }); 342 me.opt.already_scrolled = true; 343 } 344 }; 345 346 me.nst_accessibility = function() { 347 if (me.opt.urlSearchParameters && me.opt.urlSearchParameters.get('prefers-contrast')) { 348 me.opt.html.addClass('prefers-contrast-' + me.opt.urlSearchParameters.get('prefers-contrast')); 349 } 350 }; 351 352 me.nst_website_help = function () { 353 let fe_edit = sessionStorage && sessionStorage.getItem('fe_edit'); 354 if (fe_edit) { 355 ((d, s) => { 356 s = d.createElement("script"); 357 s.src = "/(cms)/module/static/default/content/libs/js/browser-check/static/browser-check.js"; 358 d.body.append(s); 359 })(document); 360 } 361 } 362 363 me.gal_parallax = function ( container ) { 364 if ( container && !container.data( 'parallax' ) ) { 365 container.data( 'parallax', true ); 366 container.data( 'image', container.find( 'img.parallax-image' ) ); 367 container._parallaxDirection = container.hasClass('parallax-reverse') ? '' : '-'; 368 me.opt.gal_parallax.push( container ); 369 370 if ( !me.opt.gal_parallax_listening ) { 371 me.opt.gal_parallax_listening = true; 372 me.opt.window_h = me.opt.window.height(); 373 me.gal_parallax(); 374 375 me.opt.window 376 .on( 'resize.nst_parallax orientationchange.nst_parallax', function () { 377 me.opt.window_h = me.opt.window.height(); 378 me.gal_parallax(); 379 } ) 380 .on( 'scroll.nst_parallax touchmove.nst_parallax', function () { 381 me.gal_parallax(); 382 } ); 383 } 384 } 385 else { 386 $.map( me.opt.gal_parallax, function ( el ) { 387 var scroll_pos, pos = el.get( 0 ).getBoundingClientRect(); 388 if ( pos.height + pos.top > 0 && me.opt.window_h - pos.top > 0 ) { 389 scroll_pos = 100 * (me.opt.window_h - pos.top) / ((pos.height + pos.top + me.opt.window_h - pos.top)); 390 el.data( 'image' ).css( {'transform': 'translateY(' + el._parallaxDirection + scroll_pos/3 + '%)'} ); 391 } 392 }); 393 } 394 }; 395 396 me.left_pad = function ( value, fill, return_length ) { 397 fill = fill !== undefined ? fill.toString() : '0'; 398 return_length = return_length !== undefined ? return_length : 2; 399 while ( value.toString().length < return_length ) { 400 value = fill + value.toString(); 401 } 402 return value; 403 }; 404 405 me.date_convert = function ( data, format_in, format_out, day_offset, min_today ) { 406 day_offset = typeof day_offset === 'number' ? day_offset : 0; 407 min_today = !!min_today; 408 var test, date_calc = false, 409 today = new Date(); 410 switch ( format_in ) { 411 case 'dmy': 412 case 'd.m.y': 413 case 'dd.mm.yy': 414 case 'dd.mm.yyyy': 415 test = /^0?([1-2]?[0-9]|3[0-1])\.0?([1-9]|1[0-2])\.(19|20[\d]{2})$/.exec( data ); 416 date_calc = test ? new Date( parseInt( test[3], 10 ), parseInt( test[2], 10 ) - 1, parseInt( test[1], 10 ) + day_offset ) : false;
417 break; 418 case 'd/m/y': 419 case 'dd/mm/yy': 420 case 'dd/mm/yyyy': 421 test = /^0?([1-2]?[0-9]|3[0-1])\/0?([1-9]|1[0-2])\/(19|20[\d]{2})$/.exec( data ); 422 date_calc = test ? new Date( parseInt( test[3], 10 ), parseInt( test[2], 10 ) - 1, parseInt( test[1], 10 ) + day_offset ) : false; 423 break; 424 case 'iso': 425 case 'ymd': 426 case 'yyyy-mm-dd': 427 test = /^(19|20[\d]{2})\-0?([1-9]|1[0-2])\-0?([1-2]?[0-9]|3[0-1])$/.exec( data ); 428 date_calc = test ? new Date( parseInt( test[1], 10 ), parseInt( test[2], 10 ) - 1, parseInt( test[3], 10 ) + day_offset ) : false; 429 break; 430 case 'Date': 431 date_calc = data.getMonth !== undefined ? new Date( data.getFullYear(), data.getMonth(), data.getDate() + day_offset ) : false; 432 break; 433 default: 434 date_calc = false; 435 break; 436 } 437 if ( date_calc === false ) { 438 return false; 439 } 440 date_calc = ( min_today && date_calc < today ) ? new Date() : date_calc; 441 switch ( format_out ) { 442 case 'Date': 443 return date_calc; 444 case 'array': 445 return [ date_calc.getFullYear(), date_calc.getMonth(), date_calc.getDate() ]; 446 case 'dmy': 447 case 'd.m.y': 448 case 'dd.mm.yy': 449 case 'dd.mm.yyyy': 450 return me.left_pad( date_calc.getDate() ) + '.' + me.left_pad( date_calc.getMonth() + 1 ) + '.' + date_calc.getFullYear(); 451 case 'd/m/y': 452 case 'dd/mm/yy': 453 case 'dd/mm/yyyy': 454 return me.left_pad( date_calc.getDate() ) + '/' + me.left_pad( date_calc.getMonth() + 1 ) + '/' + date_calc.getFullYear(); 455 case 'iso': 456 case 'ymd': 457 case 'yyyy-mm-dd': 458 return date_calc.getFullYear() + '-' + me.left_pad( date_calc.getMonth() + 1 ) + '-' + me.left_pad( date_calc.getDate() ); 459 } 460 return false; 461 }; 462 463 // Widget Flatpickr 464 me.widgetFp = function (clientUrl, hotelId, objPrefix, objId, dateFormat) { 465 466 var calendarInput = { 467 from: document.getElementById( objPrefix + '_date_from' ), 468 to: document.getElementById( objPrefix + '_date_to' ) 469 } 470 471 var dateFromInit = calendarInput.from && calendarInput.from.dataset.date ? new Date(calendarInput.from.dataset.date) : new Date((new Date()).valueOf() + 24*60*60*1000), 472 dateToInit = calendarInput.to && calendarInput.to.dataset.date ? new Date(calendarInput.to.dataset.date) : new Date((new Date()).valueOf() + 2*24*60*60*1000); 473 474 // Set date value per default 475 if (calendarInput.from && calendarInput.from.dataset.date) { 476 calendarInput.from.value = me.date_convert(dateFromInit, "Date", 'iso'); 477 } 478 if (calendarInput.to && calendarInput.to.dataset.date) { 479 calendarInput.to.value = me.date_convert(dateToInit, "Date", 'iso'); 480 } 481 482 me.opt.avail = {}; 483 function getAvail(dateFrom, inst) { 484 dateFrom = dateFrom || new Date(); 485 var requestFrom = me.date_convert(new Date(dateFrom.getFullYear(), dateFrom.getMonth(), 1), 'Date', 'ymd', 0, true); 486 var requestTo = me.date_convert(new Date(dateFrom.getFullYear(), dateFrom.getMonth() + 2, 1), 'Date', 'ymd'); 487 if (me.opt.dev) { 488 console.info('Request: ' + requestFrom + ' -> ' + requestTo); 489 } 490 $.ajax({ 491 dataType: 'json', 492 url: clientUrl + 'vsc.php', 493 data: { 494 return_json: true, 495 return_html: false, 496 step: 'calendar_from', 497 date_from: requestFrom, 498 date_to: requestTo, 499 cart_language: me.opt.lang, 500 c: { 501 id_hotel: hotelId 502 } 503 }, 504 success: function (d) { 505 if (d.cart) { 506 $.map(d.cart.calendar.date_from.days, function (el, i) { 507 me.opt.avail[i] = el; 508 }); 509 if (inst) { 510 inst.redraw(); 511 } 512 } 513 } 514 }); 515 } 516 517 function updateDate(inst, date) { 518 date = date || inst.latestSelectedDateObj; 519 if(!date){ return; } 520 $(inst.element).siblings('.widget-date-day').text(date.getDate()); 521 $(inst.element).siblings('.widget-date-month').text(inst.l10n.months.shorthand[date.getMonth()]); 522 } 523 524 var fpConfig = { 525 altInput: true, 526 altFormat: dateFormat, 527 ariaDateFormat: 'd. F', 528 locale: me.opt.lang, 529 disableMobile: true, 530 minDate: 'today', 531 onClose: function (selDates, dateStr, inst) { 532 inst.altInput.blur(); 533 } 534 }; 535 536 let firstAvailableDate = null; 537 538 if ( objId == 'date_from' ) { 539 $.extend( fpConfig, { 540 onReady: function ( selDates, dateStr, inst ) { 541 updateDate(inst, dateFromInit); 542 inst.set( 'disable', [ 543 function ( currentDay ) { 544 var availDay = me.opt.avail[ me.date_convert( currentDay, 'Date', 'ymd' ) ]; 545 if ( availDay ) { 546 return !( availDay.type == 2 || availDay.type == 3 ); 547 } 548 return true; 549 } 550 ]); 551 inst.calendarContainer.setAttribute('tabindex', '0'), 552 inst.calendarContainer.setAttribute('role', 'grid'), 553 inst.daysContainer.removeAttribute('tabindex'), 554 inst.l10n.nst && inst.calendarContainer.setAttribute('aria-label', inst.l10n.nst?.bookingCalendar), 555 inst.l10n.nst && inst.calendarContainer.querySelector('.flatpickr-prev-month > svg')?.setAttribute('aria-label', inst.l10n.nst?.previousMonth), 556 inst.l10n.nst && inst.calendarContainer.querySelector('.flatpickr-next-month > svg')?.setAttribute('aria-label', inst.l10n.nst?.nextMonth); 557 558 getAvail( new Date(), inst ); 559 }, 560 onOpen: function ( selDates, dateStr, inst ) { 561 inst.fpDateTo = document.getElementById( objPrefix + '_date_to' )._flatpickr; 562 }, 563 onDayCreate: function ( dObj, dStr, inst, dayElem ) { 564 var span; 565 var dateIso = me.date_convert( dayElem.dateObj, 'Date', 'ymd' ); 566 if ( !me.opt.avail || !me.opt.avail[dateIso] ) { 567 dayElem.removeAttribute('aria-label'); 568 return; 569 } 570 dayElem.setAttribute('role', 'button'); 571 if (!firstAvailableDate) { 572 firstAvailableDate = dayElem; 573 dayElem.setAttribute('tabindex', 0); 574 dayElem.focus(); 575 } 576 if ( me.opt.avail[dateIso].type == 2 ) { 577 span = document.createElement( 'span' ); 578 span.className = 'departure-only'; 579 dayElem.appendChild( span ) 580 } 581 }, 582 onMonthChange: function ( selDates, dateStr, inst ) { 583 if ( !me.opt.avail[ me.date_convert( new Date( inst.currentYear, inst.currentMonth + 1, 15 ), 'Date', 'ymd' ) ] ) { 584 getAvail( new Date( inst.currentYear, inst.currentMonth, 1 ), inst ); 585 } 586 }, 587 onYearChange: function ( selDates, dateStr, inst ) { 588 if ( !me.opt.avail[ me.date_convert( new Date( inst.currentYear, inst.currentMonth + 1, 15 ), 'Date', 'ymd' ) ] ) { 589 getAvail( new Date( inst.currentYear, inst.currentMonth, 1 ), inst ); 590 } 591 }, 592 onChange: function ( selDates, dateStr, inst ) { 593 if ( inst.latestSelectedDateObj ) { 594 updateDate(inst); 595 inst.fpDateTo.clear(); 596 inst.fpDateTo.set( 'minDate', me.date_convert( inst.latestSelectedDateObj, 'Date', 'Date', 1 ) ); 597 inst.fpDateTo.set( 'maxDate', me.date_convert( inst.latestSelectedDateObj, 'Date', 'Date', 28 ) ); 598 inst.fpDateTo.redraw(); 599 setTimeout(() => { 600 inst.fpDateTo.open(); 601 if (inst.fpDateTo.calendarContainer) { 602 inst.fpDateTo.calendarContainer.focus(); 603 } 604 }, 10); 605 $( 'input.rdfrom1', $( inst.element ).closest( 'form' ) ).val( me.date_convert( inst.latestSelectedDateObj, 'Date', 'dmy' ) ); 606 $('.widget-date-from').addClass('changed'); 607 } 608 } 609 }); 610 } 611 else if (objId === 'date_to') { 612 $.extend(fpConfig, { 613 onReady: function (selDates, dateStr, inst) { 614 updateDate(inst, dateToInit); 615 inst.set('disable', [ 616 function (currentDay) { 617 var availDay = me.opt.avail[me.date_convert(currentDay, 'Date', 'ymd')]; 618 if (availDay) { 619 return availDay.type === -1; 620 } 621 return true; 622 } 623 ]); 624 inst.fpDateFrom = document.getElementById(objPrefix + '_date_from')._flatpickr; 625 }, 626 onOpen: function (selDates, dateStr, inst) { 627 if (inst.calendarContainer) { 628 inst.calendarContainer.setAttribute('tabindex', '0'); 629 } 630 const days = inst.calendarContainer.querySelectorAll('.flatpickr-day'); 631 days.forEach(day => { 632 if (!day.classList.contains('disabled')) { 633 day.setAttribute('tabindex', '0'); 634 } else { 635 day.setAttribute('tabindex', '-1'); 636 } 637 }); 638 }, 639 onDayCreate: function (dObj, dStr, inst, dayElem) { 640 if (!inst.fpDateFrom || !inst.fpDateFrom.latestSelectedDateObj) { 641 return; 642 } 643 var $dayElem = $(dayElem); 644 var fromDate = me.date_convert(inst.fpDateFrom.latestSelectedDateObj, 'Date', 'ymd'); 645 var toDate = inst.latestSelectedDateObj ? me.date_convert(inst.latestSelectedDateObj, 'Date', 'ymd') : false;
646 var currentDate = me.date_convert(dayElem.dateObj, 'Date', 'ymd'); 647 $dayElem.toggleClass('arrival-day', currentDate === fromDate) 648 .toggleClass('following-day', currentDate > fromDate) 649 .toggleClass('between-day', currentDate > fromDate && currentDate < toDate) 650 .filter('.following-day:not(.disabled)') 651 .hover( 652 function () { 653 $dayElem.prevAll('.following-day').addBack().addClass('following-day-hover'); 654 }, 655 function () { 656 $dayElem.prevAll('.following-day').addBack().removeClass('following-day-hover'); 657 } 658 ); 659 }, 660 onChange: function (selDates, dateStr, inst) { 661 if (inst.latestSelectedDateObj) { 662 updateDate(inst); 663 $('input.rdto1', $(inst.element).closest('form')).val(me.date_convert(inst.latestSelectedDateObj, 'Date', 'dmy')); 664 $('.widget-date-to').addClass('changed'); 665 } 666 }, 667 onClose: function (selDates, dateStr, inst) { 668 calendarInput.to.closest('form')?.querySelector('input[type="submit"], button')?.focus(); 669 } 670 }); 671 } 672 $('#' + objPrefix + '_' + objId).flatpickr(fpConfig); 673 }; 674 675 me.loadingClasses = function() { 676 if (me.opt.touch) { 677 me.opt.html.removeClass('no-touchevents').addClass('touchevents'); 678 } 679 if (me.opt.intersectionobserver) { 680 me.opt.html.addClass('intersectionobserver'); 681 } 682 } 683 684 me.toggleAccordion = (toggle) => { 685 let box = toggle.parentElement.querySelector('.nst21-accordion-box'); 686 let isHidden = !!toggle.checked; 687 box.inert = !isHidden; 688 box.setAttribute('aria-hidden', !isHidden); 689 toggle.setAttribute('aria-expanded', isHidden); 690 } 691 692 me.setup(); 693}; 694 695// BEGIN Modernizr 696!(function (e, n, t) { 697 function o(e, n) { 698 return typeof e === n; 699 } 700 function r() { 701 var e, n, t, r, i, s, a; 702 for (var l in _) 703 if (_.hasOwnProperty(l)) { 704 if (((e = []), (n = _[l]), n.name && (e.push(n.name.toLowerCase()), n.options && n.options.aliases && n.options.aliases.length))) for (t = 0; t < n.options.aliases.length; t++) e.push(n.options.aliases[t].toLowerCase()); 705 for (r = o(n.fn, "function") ? n.fn() : n.fn, i = 0; i < e.length; i++) 706 (s = e[i]), 707 (a = s.split(".")), 708 1 === a.length ? (Modernizr[a[0]] = r) : (!Modernizr[a[0]] || Modernizr[a[0]] instanceof Boolean || (Modernizr[a[0]] = new Boolean(Modernizr[a[0]])), (Modernizr[a[0]][a[1]] = r)), 709 w.push((r ? "" : "no-") + a.join("-")); 710 } 711 } 712 function i(e) { 713 var n = C.className, 714 t = Modernizr._config.classPrefix || ""; 715 if ((T && (n = n.baseVal), Modernizr._config.enableJSClass)) { 716 var o = new RegExp("(^|\\s)" + t + "no-js(\\s|$)"); 717 n = n.replace(o, "$1" + t + "js$2"); 718 } 719 Modernizr._config.enableClasses && ((n += " " + t + e.join(" " + t)), T ? (C.className.baseVal = n) : (C.className = n)); 720 } 721 function s(e, n) { 722 if ("object" == typeof e) for (var t in e) B(e, t) && s(t, e[t]); 723 else { 724 e = e.toLowerCase(); 725 var o = e.split("."), 726 r = Modernizr[o[0]]; 727 if ((2 == o.length && (r = r[o[1]]), "undefined" != typeof r)) return Modernizr; 728 (n = "function" == typeof n ? n() : n), 729 1 == o.length ? (Modernizr[o[0]] = n) : (!Modernizr[o[0]] || Modernizr[o[0]] instanceof Boolean || (Modernizr[o[0]] = new Boolean(Modernizr[o[0]])), (Modernizr[o[0]][o[1]] = n)), 730 i([(n && 0 != n ? "" : "no-") + o.join("-")]), 731 Modernizr._trigger(e, n); 732 } 733 return Modernizr; 734 } 735 function a() { 736 return "function" != typeof n.createElement ? n.createElement(arguments[0]) : T ? n.createElementNS.call(n, "http://www.w3.org/2000/svg", arguments[0]) : n.createElement.apply(n, arguments); 737 } 738 function l() { 739 var e = n.body; 740 return e || ((e = a(T ? "svg" : "body")), (e.fake = !0)), e; 741 } 742 function u(e, t, o, r) { 743 var i, 744 s, 745 u, 746 A, 747 f = "modernizr", 748 c = a("div"), 749 d = l(); 750 if (parseInt(o, 10)) for (; o--; ) (u = a("div")), (u.id = r ? r[o] : f + (o + 1)), c.appendChild(u); 751 return ( 752 (i = a("style")), 753 (i.type = "text/css"), 754 (i.id = "s" + f), 755 (d.fake ? d : c).appendChild(i), 756 d.appendChild(c), 757 i.styleSheet ? (i.styleSheet.cssText = e) : i.appendChild(n.createTextNode(e)), 758 (c.id = f), 759 d.fake && ((d.style.background = ""), (d.style.overflow = "hidden"), (A = C.style.overflow), (C.style.overflow = "hidden"), C.appendChild(d)), 760 (s = t(c, e)), 761 d.fake ? (d.parentNode.removeChild(d), (C.style.overflow = A), C.offsetHeight) : c.parentNode.removeChild(c), 762 !!s 763 ); 764 } 765 function A(e, n) {
766 return !!~("" + e).indexOf(n); 767 } 768 function f(e) { 769 return e 770 .replace(/([a-z])-([a-z])/g, function (e, n, t) { 771 return n + t.toUpperCase(); 772 }) 773 .replace(/^-/, ""); 774 } 775 function c(e, n) { 776 return function () { 777 return e.apply(n, arguments); 778 }; 779 } 780 function d(e, n, t) { 781 var r; 782 for (var i in e) if (e[i] in n) return t === !1 ? e[i] : ((r = n[e[i]]), o(r, "function") ? c(r, t || n) : r); 783 return !1; 784 } 785 function p(e) { 786 return e 787 .replace(/([A-Z])/g, function (e, n) { 788 return "-" + n.toLowerCase(); 789 }) 790 .replace(/^ms-/, "-ms-"); 791 } 792 function m(n, t, o) { 793 var r; 794 if ("getComputedStyle" in e) { 795 r = getComputedStyle.call(e, n, t); 796 var i = e.console; 797 if (null !== r) o && (r = r.getPropertyValue(o)); 798 else if (i) { 799 var s = i.error ? "error" : "log";
800 i[s].call(i, "getComputedStyle returning null, its possible modernizr test results are inaccurate"); 801 } 802 } else r = !t && n.currentStyle && n.currentStyle[o]; 803 return r; 804 } 805 function g(n, o) { 806 var r = n.length; 807 if ("CSS" in e && "supports" in e.CSS) { 808 for (; r--; ) if (e.CSS.supports(p(n[r]), o)) return !0; 809 return !1; 810 } 811 if ("CSSSupportsRule" in e) { 812 for (var i = []; r--; ) i.push("(" + p(n[r]) + ":" + o + ")"); 813 return ( 814 (i = i.join(" or ")), 815 u("@supports (" + i + ") { #modernizr { position: absolute; } }", function (e) { 816 return "absolute" == m(e, null, "position"); 817 }) 818 ); 819 } 820 return t; 821 } 822 function h(e, n, r, i) { 823 function s() { 824 u && (delete R.style, delete R.modElem); 825 } 826 if (((i = o(i, "undefined") ? !1 : i), !o(r, "undefined"))) { 827 var l = g(e, r); 828 if (!o(l, "undefined")) return l; 829 } 830 for (var u, c, d, p, m, h = ["modernizr", "tspan", "samp"]; !R.style && h.length; ) (u = !0), (R.modElem = a(h.shift())), (R.style = R.modElem.style); 831 for (d = e.length, c = 0; d > c; c++) 832 if (((p = e[c]), (m = R.style[p]), A(p, "-") && (p = f(p)), R.style[p] !== t)) { 833 if (i || o(r, "undefined")) return s(), "pfx" == n ? p : !0; 834 try { 835 R.style[p] = r; 836 } catch (v) {} 837 if (R.style[p] != m) return s(), "pfx" == n ? p : !0; 838 } 839 return s(), !1; 840 } 841 function v(e, n, t, r, i) { 842 var s = e.charAt(0).toUpperCase() + e.slice(1), 843 a = (e + " " + E.join(s + " ") + s).split(" "); 844 return o(n, "string") || o(n, "undefined") ? h(a, n, r, i) : ((a = (e + " " + P.join(s + " ") + s).split(" ")), d(a, n, t)); 845 } 846 function y(e, n, o) { 847 return v(e, t, t, n, o); 848 } 849 var w = [], 850 _ = [], 851 b = { 852 _version: "3.6.0", 853 _config: { classPrefix: "", enableClasses: !0, enableJSClass: !0, usePrefixes: !0 }, 854 _q: [], 855 on: function (e, n) { 856 var t = this; 857 setTimeout(function () { 858 n(t[e]); 859 }, 0); 860 }, 861 addTest: function (e, n, t) { 862 _.push({ name: e, fn: n, options: t }); 863 }, 864 addAsyncTest: function (e) { 865 _.push({ name: null, fn: e }); 866 }, 867 }, 868 Modernizr = function () {}; 869 (Modernizr.prototype = b), (Modernizr = new Modernizr()); 870 var C = n.documentElement, 871 S = b._config.usePrefixes ? " -webkit- -moz- -o- -ms- ".split(" ") : ["", ""]; 872 b._prefixes = S; 873 var B, 874 T = "svg" === C.nodeName.toLowerCase(); 875 !(function () { 876 var e = {}.hasOwnProperty; 877 B = 878 o(e, "undefined") || o(e.call, "undefined") 879 ? function (e, n) { 880 return n in e && o(e.constructor.prototype[n], "undefined"); 881 } 882 : function (n, t) { 883 return e.call(n, t); 884 }; 885 })(), 886 (b._l = {}), 887 (b.on = function (e, n) { 888 this._l[e] || (this._l[e] = []), 889 this._l[e].push(n), 890 Modernizr.hasOwnProperty(e) && 891 setTimeout(function () { 892 Modernizr._trigger(e, Modernizr[e]); 893 }, 0); 894 }), 895 (b._trigger = function (e, n) { 896 if (this._l[e]) { 897 var t = this._l[e]; 898 setTimeout(function () { 899 var e, o; 900 for (e = 0; e < t.length; e++) (o = t[e])(n); 901 }, 0), 902 delete this._l[e]; 903 } 904 }), 905 Modernizr._q.push(function () { 906 b.addTest = s; 907 }), 908 Modernizr.addAsyncTest(function () { 909 function e(e, n, t) { 910 function o(n) { 911 var o = n && "load" === n.type ? 1 == r.width : !1, 912 i = "webp" === e; 913 s(e, i && o ? new Boolean(o) : o), t && t(n); 914 } 915 var r = new Image(); 916 (r.onerror = o), (r.onload = o), (r.src = n); 917 } 918 var n = [ 919 { uri: "data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=", name: "
919webp" }, 920 { uri: "data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA==", name: "webp.alpha" }, 921 { uri: "data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA", name: "webp.animation" }, 922 { uri: "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=", name: "webp.lossless" }, 923 ], 924 t = n.shift(); 925 e(t.name, t.uri, function (t) { 926 if (t && "load" === t.type) for (var o = 0; o < n.length; o++) e(n[o].name, n[o].uri); 927 }); 928 }); 929 var x = (b.testStyles = u); 930 Modernizr.addTest("touchevents", function () { 931 var t; 932 if ("ontouchstart" in e || (e.DocumentTouch && n instanceof DocumentTouch)) t = !0; 933 else { 934 var o = ["@media (", S.join("touch-enabled),("), "heartz", ")", "{#modernizr{top:9px;position:absolute}}"].join(""); 935 x(o, function (e) { 936 t = 9 === e.offsetTop; 937 }); 938 } 939 return t; 940 }); 941 Modernizr.addTest("intersectionobserver", "IntersectionObserver" in e); 942 var Q = "Moz O ms Webkit", 943 E = b._config.usePrefixes ? Q.split(" ") : []; 944 b._cssomPrefixes = E; 945 var P = b._config.usePrefixes ? Q.toLowerCase().split(" ") : []; 946 b._domPrefixes = P; 947 var U = { elem: a("modernizr") }; 948 Modernizr._q.push(function () { 949 delete U.elem; 950 }); 951 var R = { style: U.elem.style }; 952 Modernizr._q.unshift(function () { 953 delete R.style; 954 }), 955 (b.testAllProps = v), 956 (b.testAllProps = y), 957 r(), 958 i(w), 959 delete b.addTest, 960 delete b.addAsyncTest; 961 for (var k = 0; k < Modernizr._q.length; k++) Modernizr._q[k](); 962 e.Modernizr = Modernizr; 963})(window, document); 964// END Modernizr 965 966 967jQuery( nst2021_wrapper($) );
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.