(function ($) { 'use strict'; // ---------- Modal helpers: BS5 (native) or jQuery fallback ---------- function modalGet(id) { var el = document.getElementById(id); if (!el) return null; if (window.bootstrap && bootstrap.Modal) return bootstrap.Modal.getOrCreateInstance(el); if (typeof $(el).modal === 'function') { return { show:()=>$(el).modal('show'), hide:()=>$(el).modal('hide'), toggle:()=>$(el).modal('toggle') }; } return null; } function modalShow(id){ var m=modalGet(id); m&&m.show&&m.show(); } function modalHide(id){ var m=modalGet(id); m&&m.hide&&m.hide(); } function modalToggle(id){ var m=modalGet(id); m&&m.toggle&&m.toggle(); } $(function () { // Footer year (null-safe) var $navLink = $('.mm-navbars-bottom .mm-navbar a'); if ($navLink && $navLink.length) $navLink.text('© ' + new Date().getFullYear() + ' Travel Destinations'); // Favorites count UI helper function updateProfileFavoritesCount(n){ if (n == null) return; var num = Number(n); if (isNaN(num)) return; $('.profile-setting-box .favorites-count').attr('data-count', String(num)).text(num); } // Reviews: expand / read more $(document).on('click', '.review', function (e) { e.preventDefault(); e.stopPropagation(); var $review = $(this), reviewId = $review.data('review-id'); if (reviewId == null) return; $review.find('#review-read-more-link').hide(); $review.find('#review-part2').show(); $('.reviewFeedback[data-review-id="' + reviewId + '"]').show(); }); // Reviews: thumbs up / down (class-based to reduce reflow) $(document).on('click', 'a.addReviewFeedback', function (e) { e.preventDefault(); e.stopPropagation(); var $this = $(this), reviewId = $this.data('review-id'), feedback = String($this.data('feedback')); if (reviewId == null || (feedback !== '1' && feedback !== '0')) return; var yesSel = '.addReviewFeedback[data-review-id="' + reviewId + '"][data-feedback="1"]'; var noSel = '.addReviewFeedback[data-review-id="' + reviewId + '"][data-feedback="0"]'; function setLocalState(val){ $(yesSel + ',' + noSel).removeClass('fb-on fb-off').addClass('fb-off'); if (val === '1') $(yesSel).removeClass('fb-off').addClass('fb-on'); if (val === '0') $(noSel ).removeClass('fb-off').addClass('fb-on'); } setLocalState(feedback); $.ajax({ type: 'GET', url: 'https://cancunmexico.guide/functions.cfc?method=add_review_feedback', data: { review_id: reviewId, feedback: feedback }, success: function (resp) { var data; try { data = (typeof resp === 'object') ? resp : JSON.parse(resp); } catch { return; } if (data.success === 1) setLocalState(String(data.feedback)); else if (data.error === 'login_required') modalToggle('sign-in'); } }); }); // Favorites $(document).on('click', 'a.addToFavorites', function (e) { e.preventDefault(); e.stopPropagation(); var $this = $(this), type = $this.data('type'), id = $this.data('id'); if (!type || id == null) return; $.ajax({ type: 'GET', url: 'https://cancunmexico.guide/functions.cfc?method=add_to_favorites', data: { type: type, id: id }, success: function (resp) { var data; try { data = (typeof resp === 'object') ? resp : JSON.parse(resp); } catch { return; } if (data.success === 1) { $('.inFavorites[data-id="' + id + '"]').show(); $('.addToFavorites[data-id="' + id + '"]').hide().closest('.loc_open').hide(); updateProfileFavoritesCount(data.favorites_count); } else if (data.error === 'not_logged_in') { modalToggle('sign-in'); } } }); }); // Forgot Password (step 1) $(document).on('click', '#submitResetPW', function (e) { e.preventDefault(); var $form = $('#forgotPasswordForm'), formEl = $form[0]; if (!formEl) return; if (!formEl.checkValidity()) { $form.addClass('was-validated'); return; } $.ajax({ type: 'GET', url: 'https://cancunmexico.guide/functions.cfc?method=reset_password1', data: $form.serialize(), success: function (resp) { var data; try { data = (typeof resp === 'object') ? resp : JSON.parse(resp); } catch { return; } if (data.success === 1) { $('#access-code-group,#new-password-group,#new-confirm-password-group').show(); $('#message1').hide(); $('#submitResetPWCode').show(); $('#submitResetPW').hide(); } else if (data.error === 'blank_email') { // basic inline feedback var $g = $form.find('#forgot_email').closest('.form-group'); $g.addClass('has-error').append('
' + (data.message || 'Email required.') + '
'); } } }); $form.addClass('was-validated'); }); // Forgot Password (step 2) $(document).on('click', '#submitResetPWCode', function (e) { e.preventDefault(); var $form = $('#forgotPasswordForm'), formEl = $form[0]; if (!formEl) return; if (!formEl.checkValidity()) { $form.addClass('was-validated'); return; } $.ajax({ type: 'GET', url: 'https://cancunmexico.guide/functions.cfc?method=reset_password2', data: $form.serialize(), success: function (resp) { var data; try { data = (typeof resp === 'object') ? resp : JSON.parse(resp); } catch { return; } $form.find('.form-group').removeClass('has-error'); $form.find('.help-block').remove(); if (data.success === 2) { modalToggle('forgot-password'); modalToggle('sign-in'); } else { if (data.error === 'blank_email') { $('#forgot_email').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } if (data.error === 'invalid_access_code') { $('#access-code-group').addClass('has-error') .append('
' + data.message + '
'); } if (data.error === 'password_length') { $('#new-password-group').addClass('has-error') .append('
' + data.message + '
'); } if (data.error === 'blank_confirmation_password') { $('#new-confirm-password-group').addClass('has-error') .append('
' + data.message + '
'); } if (data.error === 'passwords_no_match') { $('#new-password-group,#new-confirm-password-group').addClass('has-error') .append('
' + data.message + '
'); } } } }); $form.addClass('was-validated'); }); // Login (AJAX) $(document).on('click', '#submitLogin', function (e) { e.preventDefault(); var $form = $('#signinForm'), formEl = $form[0]; if (!formEl) return; if (!formEl.checkValidity()) { $form.addClass('was-validated'); return; } $.ajax({ type: 'POST', url: 'https://cancunmexico.guide/functions.cfc?method=check_login', data: $form.serialize(), success: function (resp) { var data; try { data = (typeof resp === 'object') ? resp : JSON.parse(resp); } catch { return; } if (data.success === 1) { $('#reviewedBy,#submitReviewBtn1').show(); $('#submitReviewBtn2,#menu-sign-in').hide(); $('#userName').val(data.user_first_name + ' ' + data.user_last_name.substring(0, 1) + '.'); modalToggle('sign-in'); $('#menu-profile-setting .name').text(data.user_first_name + ' ' + data.user_last_name); $('#menu-profile-setting .mail').text(data.user_email).show(); $('#menu-profile-setting .visitor').hide(); $('#menu-profile-setting .member').show(); $('#menu-profile-setting').show(); $('#menu-profile-setting .sign-in-section').hide(); $('#menu-profile-setting .sign-out-section').show(); $('#menu-profile-setting .profile-thumb-small img').attr('src', "https://cancunmexico.guide/img/profile_green.jpg"); } else { $form.find('.form-group').removeClass('has-error'); $form.find('.help-block').remove(); if (data.error === 'blank_email') { $('#login_email').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } if (data.error === 'blank_password' || data.error === 'invalid_login') { $('#login_password').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } } } }); $form.addClass('was-validated'); }); // Register (AJAX) $(document).on('click', '#submitRegisterUser', function (e) { e.preventDefault(); var formEl = document.getElementById('signupForm'); if (!formEl) return; if (!formEl.checkValidity()) { $(formEl).addClass('was-validated'); return; } var data = new FormData(formEl); $.ajax({ type: 'POST', url: 'https://cancunmexico.guide/register.cfm', data: data, contentType: false, processData: false, success: function (resp) { var data; try { data = (typeof resp === 'object') ? resp : JSON.parse(resp); } catch { return; } if (data.success === 1) { modalToggle('sign-up'); modalToggle('sign-in'); } else { var $f = $('#signupForm'); $f.find('.form-group').removeClass('has-error'); $f.find('.help-block').remove(); if (data.error === 'blank_first_name') { $('#signup_first_name').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } if (data.error === 'blank_last_name') { $('#signup_last_name').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } if (data.error === 'blank_email' || data.error === 'email_exists') { $('#signup_email').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } if (['password_length', 'invalid_login'].includes(data.error)) { $('#signup_password').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } if (['blank_confirmation_password', 'passwords_no_match'].includes(data.error)) { $('#signup_confirm_password').closest('.form-group').addClass('has-error') .append('
' + data.message + '
'); } } } }); $(formEl).addClass('was-validated'); }); // Rating label $(document).on('click', 'input[type=radio][name=rating]', function () { var labels = { 5:'Excellent', 4:'Good', 3:'Average', 2:'Poor', 1:'Terrible' }; $('#ratingName').html('Overall rating: "' + (labels[this.value] || '') + '"'); }); // Image modal: open + set src $(document).on('click', '.pop', function () { var src = $(this).find('img').attr('popsrc') || ''; $('.imagepreview').attr('src', src); modalShow('imagemodal'); }); // Image modal: focus-safe behavior (fixes aria-hidden warning) (function () { var lastOpener = null; var imgModalEl = document.getElementById('imagemodal'); document.addEventListener('click', function (e) { var pop = e.target.closest && e.target.closest('.pop'); if (!pop) return; lastOpener = pop; setTimeout(function () { var img = document.querySelector('#imagemodal .imagepreview'); if (img) { img.setAttribute('tabindex', '-1'); try { img.blur(); } catch(e){} } }, 0); }, { passive: true }); // clicking the image closes the modal var preview = document.querySelector('#imagemodal .imagepreview'); if (preview) { preview.addEventListener('click', function () { var inst = (window.bootstrap && bootstrap.Modal) ? bootstrap.Modal.getOrCreateInstance(imgModalEl) : null; if (inst && inst.hide) inst.hide(); }, { passive: true }); } imgModalEl?.addEventListener('hide.bs.modal', function () { if (imgModalEl.contains(document.activeElement)) { try { document.activeElement.blur(); } catch(e){} } }, { passive: true }); imgModalEl?.addEventListener('hidden.bs.modal', function () { try { (lastOpener || document.body).focus({ preventScroll:true }); } catch(e){} }, { passive: true }); })(); }); // DOM ready })(jQuery);