(function () { /** * Sole hamburger binder. Sets V10 flag immediately so the mu-plugin footer * (which used to boot twice and stack document listeners) exits early. */ window.__jnpHamburgerFixV10 = true; if ( window.__jnpHamburgerFixV11 ) { return; } window.__jnpHamburgerFixV11 = true; var bound = false; function boot() { if ( bound ) { return; } var header = document.getElementById( 'jnp-header' ); var ham = document.querySelector( '.jnp-hamburger' ); var menu = document.getElementById( 'jnp-mobile-menu' ); if ( header ) { var toggleScrolled = function () { if ( window.scrollY > 10 ) { header.classList.add( 'is-scrolled' ); } else { header.classList.remove( 'is-scrolled' ); } }; toggleScrolled(); window.addEventListener( 'scroll', toggleScrolled, { passive: true } ); } if ( ! ham || ! menu || ! ham.parentNode ) { return; } bound = true; var fresh = ham.cloneNode( true ); ham.parentNode.replaceChild( fresh, ham ); ham = fresh; if ( menu.parentElement !== document.body ) { document.body.appendChild( menu ); } ham.setAttribute( 'type', 'button' ); if ( ! ham.getAttribute( 'aria-expanded' ) ) { ham.setAttribute( 'aria-expanded', 'false' ); } menu.setAttribute( 'aria-hidden', menu.classList.contains( 'is-open' ) ? 'false' : 'true' ); var ignoreUntil = 0; var lockY = 0; function setOpen( open ) { ham.setAttribute( 'aria-expanded', open ? 'true' : 'false' ); ham.setAttribute( 'aria-label', open ? 'Close menu' : 'Open menu' ); menu.classList.toggle( 'is-open', open ); menu.setAttribute( 'aria-hidden', open ? 'false' : 'true' ); document.body.classList.toggle( 'jnp-menu-open', open ); if ( open ) { lockY = window.scrollY || 0; document.body.style.position = 'fixed'; document.body.style.top = '-' + lockY + 'px'; document.body.style.left = '0'; document.body.style.right = '0'; document.body.style.width = '100%'; document.body.style.overflow = 'hidden'; } else { document.body.style.position = ''; document.body.style.top = ''; document.body.style.left = ''; document.body.style.right = ''; document.body.style.width = ''; document.body.style.overflow = ''; window.scrollTo( 0, lockY ); } } ham.addEventListener( 'click', function ( e ) { e.preventDefault(); e.stopPropagation(); if ( e.stopImmediatePropagation ) { e.stopImmediatePropagation(); } var open = ham.getAttribute( 'aria-expanded' ) === 'true'; setOpen( ! open ); if ( ! open ) { ignoreUntil = Date.now() + 500; } }, true ); document.addEventListener( 'click', function ( e ) { if ( Date.now() < ignoreUntil ) { return; } if ( ! menu.classList.contains( 'is-open' ) ) { return; } var t = e.target; if ( t && ( menu.contains( t ) || ham.contains( t ) ) ) { return; } setOpen( false ); }, true ); document.addEventListener( 'keydown', function ( e ) { if ( e.key === 'Escape' && menu.classList.contains( 'is-open' ) ) { setOpen( false ); ham.focus(); } } ); window.addEventListener( 'resize', function () { if ( window.innerWidth > 1024 && menu.classList.contains( 'is-open' ) ) { setOpen( false ); } }, { passive: true } ); } if ( document.readyState === 'loading' ) { document.addEventListener( 'DOMContentLoaded', boot ); } else { boot(); } })(); (function () { var WA_HREF = 'https://wa.me/6287740098436?text=' + encodeURIComponent( 'Hi J&P Bali! I would like to ask about custom trip apparel.' ); var PAYMENT_LINE = 'Payment: PayPal, Credit Card, or Bank Transfer (IDR/AUD)'; function rewriteWhatsApp() { document.querySelectorAll( 'a[href*="wa.me"], a[href*="api.whatsapp.com"], a[href*="whatsapp.com"], a.jnp-wa' ).forEach( function ( a ) { var href = a.getAttribute( 'href' ) || ''; if ( href.indexOf( '6287740098436' ) !== -1 ) { return; } var textMatch = href.match( /[?&]text=([^&]*)/ ); a.setAttribute( 'href', textMatch ? ( 'https://wa.me/6287740098436?text=' + textMatch[ 1 ] ) : WA_HREF ); } ); document.querySelectorAll( 'a[href^="tel:"]' ).forEach( function ( a ) { var href = ( a.getAttribute( 'href' ) || '' ).replace( /\s/g, '' ); if ( /6281234567890|1234567890/.test( href ) ) { a.setAttribute( 'href', 'tel:+6287740098436' ); } } ); } function rewritePaymentLine() { document.querySelectorAll( '.elementor-icon-list-text, .jnp-payment-note' ).forEach( function ( el ) { var t = ( el.textContent || '' ).replace( /\s+/g, ' ' ).trim(); if ( /^Payment:/i.test( t ) && t !== PAYMENT_LINE ) { el.textContent = PAYMENT_LINE; } } ); } function blockSyntheticGalleryClicks() { document.addEventListener( 'click', function ( e ) { var raw = e.target; var el = raw && raw.nodeType === 1 ? raw : ( raw && raw.parentElement ); var modal = el && el.closest && el.closest( '.js-product-modal, .woocommerce-product-gallery__image a' ); if ( ! modal ) { return; } if ( e.isTrusted ) { return; } e.preventDefault(); e.stopImmediatePropagation(); }, true ); } function improveCartLinks() { document.querySelectorAll( 'a[href*="/cart"]' ).forEach( function ( link ) { var text = ( link.textContent || '' ).replace( /\s+/g, ' ' ).trim(); var countMatch = text.match( /^(\d+)$/ ); if ( ! countMatch ) { return; } var count = countMatch[ 1 ]; var label = count === '1' ? 'Cart, 1 item' : 'Cart, ' + count + ' items'; link.setAttribute( 'aria-label', label ); } ); var floatBtn = document.querySelector( '.jnp-float-cart__btn' ); if ( floatBtn ) { var countEl = floatBtn.querySelector( '.jnp-float-cart__count' ); var n = countEl ? parseInt( countEl.getAttribute( 'data-count' ) || countEl.textContent || '0', 10 ) : 0; if ( n > 0 ) { floatBtn.setAttribute( 'aria-label', n === 1 ? 'Open shopping cart, 1 item' : 'Open shopping cart, ' + n + ' items' ); } } } function goToColorSlide( slug ) { var gal = document.querySelector( '.woocommerce-product-gallery' ); if ( ! gal || ! slug ) { return; } var imgs = gal.querySelectorAll( '.woocommerce-product-gallery__image' ); var i; for ( i = 0; i < imgs.length; i++ ) { var im = imgs[ i ].querySelector( 'img' ); var src = im ? ( im.getAttribute( 'src' ) || '' ) : ''; var hay = src.toLowerCase(); if ( hay.indexOf( '-' + slug + '.' ) > -1 || hay.indexOf( '-' + slug + '-' ) > -1 ) { var dots = document.querySelectorAll( '.c-product__slider [aria-label^="Slide"], .js-single-product-carousel .dot' ); if ( dots[ i ] ) { dots[ i ].click(); } break; } } } function bindColorSwatches() { var wrap = document.querySelector( '[data-jnp-color-swatch]' ); if ( ! wrap ) { return; } wrap.querySelectorAll( '.jnp-color-swatch__dot' ).forEach( function ( dot, index ) { dot.setAttribute( 'role', 'button' ); dot.setAttribute( 'tabindex', '0' ); if ( ! dot.getAttribute( 'aria-label' ) ) { var slug = dot.getAttribute( 'data-color-slug' ) || ( 'Color ' + ( index + 1 ) ); dot.setAttribute( 'aria-label', 'Show ' + slug.replace( /-/g, ' ' ) + ' product image' ); } function activateSwatch() { wrap.querySelectorAll( '.jnp-color-swatch__dot' ).forEach( function ( other ) { other.classList.remove( 'is-selected' ); other.setAttribute( 'aria-pressed', 'false' ); } ); dot.classList.add( 'is-selected' ); dot.setAttribute( 'aria-pressed', 'true' ); goToColorSlide( dot.getAttribute( 'data-color-slug' ) ); } dot.addEventListener( 'click', activateSwatch ); dot.addEventListener( 'keydown', function ( e ) { if ( e.key === 'Enter' || e.key === ' ' ) { e.preventDefault(); activateSwatch(); } } ); } ); } function syncHotelFields() { var search = document.getElementById( 'jnp_hotel_search' ); var name = document.getElementById( 'jnp_hotel_name' ); var form = document.querySelector( 'form.checkout' ); if ( ! search || ! name ) { return; } function copy() { if ( search.value && ! name.value ) { name.value = search.value; } } search.addEventListener( 'change', copy ); search.addEventListener( 'blur', copy ); if ( form ) { form.addEventListener( 'submit', copy ); } } function closeCartOnCheckout() { if ( ! document.body.classList.contains( 'woocommerce-checkout' ) ) { return; } var root = document.getElementById( 'jnp-float-cart' ); if ( ! root ) { return; } root.classList.remove( 'is-open' ); var panel = root.querySelector( '.jnp-float-cart__panel' ); var btn = root.querySelector( '.jnp-float-cart__btn' ); if ( panel ) { panel.setAttribute( 'hidden', 'hidden' ); } if ( btn ) { btn.setAttribute( 'aria-expanded', 'false' ); } } function hideHotelDupes() { if ( ! document.body.classList.contains( 'woocommerce-checkout' ) ) { return; } var nameField = document.getElementById( 'jnp_hotel_name_field' ); if ( nameField ) { nameField.style.display = 'none'; } Array.prototype.forEach.call( document.querySelectorAll( '.form-row, p.form-row' ), function ( row ) { var lab = row.querySelector( 'label' ); if ( ! lab ) { return; } var t = ( lab.textContent || '' ).replace( /\s+/g, ' ' ).trim(); if ( ! /Hotel\s*\/\s*Villa/i.test( t ) ) { return; } if ( row.querySelector( '#jnp_hotel_search' ) ) { return; } row.style.display = 'none'; } ); } function hideMugDesignStyle() { if ( ! /mug/i.test( location.pathname + ' ' + document.body.className ) ) { return; } var sel = document.querySelector( '[name="attribute_design-style"], [name="attribute_pa_design-style"]' ); if ( ! sel ) { return; } if ( sel.tagName === 'SELECT' && ! sel.value ) { var i; for ( i = 0; i < sel.options.length; i++ ) { if ( sel.options[ i ].value ) { sel.value = sel.options[ i ].value; sel.dispatchEvent( new Event( 'change', { bubbles: true } ) ); break; } } } var row = sel.closest( 'tr' ); if ( row ) { row.style.display = 'none'; } } function relocateExpressCheckout() { var payment = document.getElementById( 'payment' ); if ( ! payment ) { return; } var anchor = payment.querySelector( '.jnp-checkout-step-badge--pay' ) || payment.firstChild; var selectors = [ '.wc-stripe-express-checkout', '#wc-stripe-express-checkout-element', '.wc-stripe-express-checkout-button-separator', ]; selectors.forEach( function ( sel ) { document.querySelectorAll( sel ).forEach( function ( el ) { var mount = el.closest( '.wc-stripe-express-checkout' ) || el; if ( mount && ! payment.contains( mount ) ) { payment.insertBefore( mount, anchor ); } } ); } ); } function relocateCheckoutChrome() { if ( ! document.body.classList.contains( 'woocommerce-checkout' ) ) { return; } var col1 = document.querySelector( '.c-cart__col-1--checkout' ) || document.querySelector( '.c-cart__col-1' ); var colTarget = col1 && ( col1.querySelector( '.js-sticky-sidebar-nearby' ) || col1 ); var progress = document.querySelector( '.jnp-checkout-progress' ); if ( progress && colTarget && ! colTarget.contains( progress ) ) { colTarget.insertBefore( progress, colTarget.firstChild ); } var payNote = document.querySelector( '.jnp-checkout-payment-note' ); var payment = document.getElementById( 'payment' ); if ( payNote && payment && ! payment.contains( payNote ) ) { payment.insertBefore( payNote, payment.firstChild ); } relocateExpressCheckout(); var fieldWrapper = document.querySelector( '.woocommerce-billing-fields__field-wrapper' ); var step2Badge = document.querySelector( '.jnp-checkout-step-badge[data-jnp-step="2"]' ); if ( fieldWrapper && step2Badge && ! fieldWrapper.contains( step2Badge ) ) { fieldWrapper.insertBefore( step2Badge, fieldWrapper.firstChild ); } } function getCheckoutStep() { var step = parseInt( document.body.getAttribute( 'data-jnp-checkout-step' ), 10 ); return step >= 1 && step <= 3 ? step : 1; } function setSectionHidden( el, hidden ) { if ( ! el ) { return; } if ( hidden ) { el.setAttribute( 'hidden', 'hidden' ); el.setAttribute( 'aria-hidden', 'true' ); el.classList.add( 'jnp-step-hidden' ); el.style.setProperty( 'display', 'none', 'important' ); } else { el.removeAttribute( 'hidden' ); el.setAttribute( 'aria-hidden', 'false' ); el.classList.remove( 'jnp-step-hidden' ); el.style.removeProperty( 'display' ); } } function applyCheckoutStepVisibility( step ) { var billing = document.querySelector( '.woocommerce-billing-fields' ); var chWrap = document.querySelector( '.jnp-ch-wrap' ); var fieldWrapper = billing && billing.querySelector( '.woocommerce-billing-fields__field-wrapper' ); var additional = document.querySelector( '.woocommerce-additional-fields' ); var payment = document.getElementById( 'payment' ); var col2 = document.querySelector( '.c-cart__col-1 .col-2' ); var billingTitle = billing && billing.querySelector( 'h3' ); setSectionHidden( chWrap, step !== 1 ); setSectionHidden( fieldWrapper, step !== 2 ); if ( billing ) { Array.prototype.forEach.call( billing.children, function ( child ) { if ( child.classList.contains( 'jnp-ch-wrap' ) || child.classList.contains( 'woocommerce-billing-fields__field-wrapper' ) || child.classList.contains( 'jnp-checkout-anchor' ) ) { return; } if ( child.classList.contains( 'jnp-checkout-nav' ) ) { var navStep = parseInt( child.getAttribute( 'data-jnp-step' ), 10 ); setSectionHidden( child, navStep !== step ); return; } if ( child.classList.contains( 'jnp-checkout-step-badge' ) ) { var badgeStep = parseInt( child.getAttribute( 'data-jnp-step' ), 10 ); setSectionHidden( badge, badgeStep !== step ); return; } setSectionHidden( child, step !== 2 ); } ); } document.querySelectorAll( '.jnp-checkout-nav[data-jnp-step]' ).forEach( function ( nav ) { var navStep = parseInt( nav.getAttribute( 'data-jnp-step' ), 10 ); setSectionHidden( nav, navStep !== step ); } ); setSectionHidden( additional, step !== 2 ); setSectionHidden( col2, step !== 2 ); setSectionHidden( payment, step !== 3 ); document.querySelectorAll( '.jnp-checkout-step-badge--pay' ).forEach( function ( badge ) { setSectionHidden( badge, step !== 3 ); } ); document.querySelectorAll( '.jnp-checkout-nav--step1, .jnp-checkout-nav--step2' ).forEach( function ( nav ) { setSectionHidden( nav, true ); } ); document.querySelectorAll( '.jnp-checkout-nav a[href^="#jnp-step"]' ).forEach( function ( link ) { link.style.display = 'none'; } ); if ( billingTitle ) { billingTitle.textContent = 'How can we reach you?'; setSectionHidden( billingTitle, step !== 2 ); } if ( step !== 3 ) { document.querySelectorAll( '.wc-stripe-express-checkout, #wc-stripe-express-checkout-element, .wc-stripe-express-checkout-button-separator, .ppc-button-wrapper, .c-cart__col-2 .separator, .c-cart__sidebar .separator, .woocommerce-checkout-payment .separator' ).forEach( function ( el ) { setSectionHidden( el, true ); } ); } else { document.querySelectorAll( '.wc-stripe-express-checkout, #wc-stripe-express-checkout-element, .wc-stripe-express-checkout-button-separator' ).forEach( function ( el ) { setSectionHidden( el, false ); } ); relocateExpressCheckout(); } } function setCheckoutStep( step ) { document.body.setAttribute( 'data-jnp-checkout-step', String( step ) ); var progressItems = document.querySelectorAll( '.jnp-checkout-progress__item' ); Array.prototype.forEach.call( progressItems, function ( item, index ) { var num = index + 1; item.classList.toggle( 'is-current', num === step ); item.classList.toggle( 'is-done', num < step ); } ); applyCheckoutStepVisibility( step ); } function clearCheckoutNavError( nav ) { if ( ! nav ) { return; } var err = nav.querySelector( '.jnp-checkout-nav__error' ); if ( err ) { err.remove(); } } function showCheckoutNavError( nav, message ) { clearCheckoutNavError( nav ); if ( ! nav || ! message ) { return; } var err = document.createElement( 'p' ); err.className = 'jnp-checkout-nav__error'; err.setAttribute( 'role', 'alert' ); err.textContent = message; nav.insertBefore( err, nav.firstChild ); } function validateVisibleFields( container ) { if ( ! container ) { return true; } var fields = container.querySelectorAll( 'input, select, textarea' ); for ( var i = 0; i < fields.length; i++ ) { var field = fields[ i ]; if ( field.type === 'hidden' || field.disabled ) { continue; } if ( field.offsetParent === null && field.type !== 'radio' && field.type !== 'checkbox' ) { continue; } if ( typeof field.checkValidity === 'function' && ! field.checkValidity() ) { field.reportValidity(); field.focus(); return false; } } return true; } function ensureCheckoutNav( container, step ) { if ( ! container ) { return null; } var existing = container.querySelector( ':scope > .jnp-checkout-nav[data-jnp-step="' + step + '"]' ); if ( existing ) { return existing; } var nav = document.createElement( 'div' ); nav.className = 'jnp-checkout-nav'; nav.setAttribute( 'data-jnp-step', String( step ) ); if ( step > 1 ) { var back = document.createElement( 'button' ); back.type = 'button'; back.className = 'jnp-checkout-nav__btn jnp-checkout-nav__btn--back jnp-checkout-nav--back'; back.textContent = step === 2 ? 'Back to hotel' : 'Back to contact'; back.addEventListener( 'click', function () { clearCheckoutNavError( nav ); setCheckoutStep( step - 1 ); window.scrollTo( { top: 0, behavior: 'smooth' } ); } ); nav.appendChild( back ); } if ( step < 3 ) { var next = document.createElement( 'button' ); next.type = 'button'; next.className = 'jnp-checkout-nav__btn jnp-checkout-nav--continue'; next.textContent = step === 1 ? 'Continue to contact' : 'Continue to payment'; next.addEventListener( 'click', function () { clearCheckoutNavError( nav ); var valid = step === 1 ? validateVisibleFields( document.querySelector( '.jnp-ch-wrap' ) ) : validateVisibleFields( document.querySelector( '.woocommerce-billing-fields' ) ); if ( ! valid ) { return; } setCheckoutStep( step + 1 ); window.scrollTo( { top: 0, behavior: 'smooth' } ); } ); nav.appendChild( next ); } container.appendChild( nav ); return nav; } function initCheckoutWizard() { if ( ! document.body.classList.contains( 'woocommerce-checkout' ) ) { return; } if ( document.body.classList.contains( 'woocommerce-order-received' ) ) { return; } var firstRun = document.body.dataset.jnpCheckoutWizard !== '1'; if ( firstRun ) { document.body.classList.add( 'jnp-checkout-wizard' ); document.body.dataset.jnpCheckoutWizard = '1'; relocateCheckoutChrome(); ensureCheckoutNav( document.querySelector( '.jnp-ch-wrap' ), 1 ); ensureCheckoutNav( document.querySelector( '.woocommerce-billing-fields' ), 2 ); } setCheckoutStep( getCheckoutStep() || 1 ); } function initTouristCheckout() { if ( ! document.body.classList.contains( 'woocommerce-checkout' ) ) { return; } if ( document.body.classList.contains( 'woocommerce-order-received' ) ) { return; } initCheckoutWizard(); var wrap = document.querySelector( '.jnp-ch-wrap' ); if ( wrap && ! wrap.querySelector( '.jnp-checkout-step-badge[data-jnp-step="1"]' ) ) { var stepBadge = document.createElement( 'p' ); stepBadge.className = 'jnp-checkout-step-badge'; stepBadge.setAttribute( 'data-jnp-step', '1' ); stepBadge.textContent = 'Step 1 of 3'; var title = wrap.querySelector( '.jnp-ch-title' ); if ( title && title.parentNode ) { title.parentNode.insertBefore( stepBadge, title ); } else { wrap.insertBefore( stepBadge, wrap.firstChild ); } } var search = document.getElementById( 'jnp_hotel_search' ); var list = document.querySelector( '.jnp-ch-list' ); if ( search ) { if ( list && ! list.id ) { list.id = 'jnp_hotel_autocomplete'; } search.setAttribute( 'role', 'combobox' ); search.setAttribute( 'aria-autocomplete', 'list' ); search.setAttribute( 'aria-haspopup', 'listbox' ); if ( list ) { search.setAttribute( 'aria-controls', list.id ); list.setAttribute( 'role', 'listbox' ); } function syncExpanded() { var open = list && list.classList.contains( 'is-open' ); search.setAttribute( 'aria-expanded', open ? 'true' : 'false' ); } search.addEventListener( 'input', syncExpanded ); search.addEventListener( 'focus', syncExpanded ); search.addEventListener( 'blur', function () { window.setTimeout( syncExpanded, 200 ); } ); if ( window.MutationObserver && list ) { new MutationObserver( syncExpanded ).observe( list, { attributes: true, attributeFilter: [ 'class' ], } ); } syncExpanded(); } var progressItems = document.querySelectorAll( '.jnp-checkout-progress__item' ); if ( progressItems.length ) { Array.prototype.forEach.call( progressItems, function ( item, index ) { item.style.cursor = 'pointer'; item.addEventListener( 'click', function () { var targetStep = index + 1; var current = getCheckoutStep(); if ( targetStep < current ) { setCheckoutStep( targetStep ); window.scrollTo( { top: 0, behavior: 'smooth' } ); } } ); } ); } } rewriteWhatsApp(); rewritePaymentLine(); blockSyntheticGalleryClicks(); bindColorSwatches(); syncHotelFields(); closeCartOnCheckout(); hideHotelDupes(); hideMugDesignStyle(); initTouristCheckout(); improveCartLinks(); if ( document.readyState === 'loading' ) { document.addEventListener( 'DOMContentLoaded', function () { rewriteWhatsApp(); rewritePaymentLine(); bindColorSwatches(); syncHotelFields(); closeCartOnCheckout(); hideHotelDupes(); hideMugDesignStyle(); initTouristCheckout(); improveCartLinks(); } ); } window.setTimeout( function () { rewriteWhatsApp(); rewritePaymentLine(); relocateCheckoutChrome(); initTouristCheckout(); }, 800 ); if ( window.MutationObserver ) { var waTimer = null; new MutationObserver( function () { window.clearTimeout( waTimer ); waTimer = window.setTimeout( rewriteWhatsApp, 200 ); } ).observe( document.documentElement, { childList: true, subtree: true } ); } })();