HEX
Server: Microsoft-IIS/10.0
System: Windows NT ITPWINWEBSVR22 10.0 build 20348 (Windows Server 2022) AMD64
User: www.conferencesearch.co.uk (0)
PHP: 8.3.30
Disabled: NONE
Upload Files
File: D:/web/hyperflight/2026-07-30/new/inc-template-currency.asp
<%
' (SS,26/7/26) Combined delivery country and currency selector.
' The compact header control is rendered with the page. The larger country
' and currency panel is loaded from ajax.asp only when the Bootstrap modal
' is opened for the first time.
' (SS,26/7/26) Created using ChatGPT
' (SS,30/7/26) modified to ensure the wavy flag sprite image is only loaded when this selector is rendered
' to reduce the download bandwidth because the country-flags-24@2x-wavy-q75.webp file is 170K
Sub ShowCountryCurrencySelector
  Dim LDeliveryCountry, LCountryCodeA2, LCurrencyCode

  GetCountryCurrencyHeaderDetails LDeliveryCountry, LCountryCodeA2, LCurrencyCode
  
  LDeliveryCountry = Server.HTMLEncode(LDeliveryCountry)
  LCountryCodeA2 = Server.HTMLEncode(LCountryCodeA2)
  LCurrencyCode = Server.HTMLEncode(LCurrencyCode)
%>
<input type="hidden" id="CurrencyCode" value="<%=LCurrencyCode%>">

<div id="countryCurrencySelector"
     class="country-currency-selector"
     data-country="<%=LDeliveryCountry%>"
     data-country-code="<%=LCountryCodeA2%>"
     data-currency="<%=LCurrencyCode%>">
  <button type="button"
          id="countryCurrencyButton"
          class="country-currency-button"
          data-bs-toggle="modal"
          data-bs-target="#countryCurrencyModal"
          aria-haspopup="dialog"
          aria-controls="countryCurrencyModal"
          aria-label="Country <%=LDeliveryCountry%>, currency <%=LCurrencyCode%>">
      
    <img class="country-currency-header-flag"
         src="/common/flags/country/wavy-64/<%=LCountryCodeA2%>.png"
         width="64"
         height="48"
         alt=""
         aria-hidden="true">
      
    <span class="country-currency-code"><%=LCurrencyCode%></span>
    <i class="fa-solid fa-caret-down country-currency-caret" aria-hidden="true"></i>
  </button>
</div>

<div class="modal fade"
     id="countryCurrencyModal"
     tabindex="-1"
     aria-labelledby="countryCurrencyModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered country-currency-modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h2 class="modal-title fs-5" id="countryCurrencyModalLabel">Country and currency</h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body" id="countryCurrencyModalContent">
        <div class="country-currency-loading text-center py-4" role="status">
          <span class="spinner-border spinner-border-sm me-2" aria-hidden="true"></span>
          Loading settings...
        </div>
      </div>
    </div>
  </div>
</div>
<%

  AddScript "ScriptCountryCurrencySelector"
End Sub

ShowCountryCurrencySelector

Sub ScriptCountryCurrencySelector
%>
<script>
document.addEventListener("DOMContentLoaded", function () {
  const selector = document.getElementById("countryCurrencySelector");
  const openButton = document.getElementById("countryCurrencyButton");
  const modalElement = document.getElementById("countryCurrencyModal");
  const contentElement = document.getElementById("countryCurrencyModalContent");
  if (!selector || !openButton || !modalElement || !contentElement) return;

  let panelLoaded = false;
  let panelLoading = false;

  function showLoadError() {
    contentElement.innerHTML =
      '<div class="alert alert-danger mb-3" role="alert">' +
        'The country and currency settings could not be loaded.' +
      '</div>' +
      '<button type="button" class="btn btn-outline-primary" id="countryCurrencyRetry">Try again</button>';
  }

  function loadPanel(forceReload) {
    if (panelLoading) return;
    if (panelLoaded && !forceReload) return;

    panelLoading = true;
    panelLoaded = false;

    contentElement.innerHTML =
      '<div class="country-currency-loading text-center py-4" role="status">' +
        '<span class="spinner-border spinner-border-sm me-2" aria-hidden="true"></span>' +
        'Loading settings...' +
      '</div>';

    $.ajax({
      url: "/ajax.asp",
      method: "GET",
      cache: false,
      data: {
        cmd: "country_currency_panel"
      }
    })
    .done(function (html) {
      contentElement.innerHTML = html;
      panelLoaded = true;
      initialisePanel();
    })
    .fail(function () {
      showLoadError();
    })
    .always(function () {
      panelLoading = false;
    });
  }

  function reloadCurrentPageWithGet() {
    const url = new URL(window.location.href);

    // Do not allow a currency selection left in the query string by the old
    // frmSearch route to overwrite the country/currency just saved by AJAX.
    url.searchParams.delete("xcmd");
    url.searchParams.delete("xcode");

    window.location.replace(
      url.pathname + url.search + url.hash
    );
  }

  function initialisePanel() {
    const panel = contentElement.querySelector(".country-currency-panel");
    if (!panel) return;

    const countryToggle = panel.querySelector("#countryCurrencyCountryButton");
    const countryMenu = panel.querySelector("#countryCurrencyCountryMenu");
    const countrySearch = panel.querySelector("#countryCurrencyCountrySearch");
    const noCountries = panel.querySelector("#countryCurrencyNoCountries");
    const countryInput = panel.querySelector("#countryCurrencyCountry");
    const countryText = panel.querySelector(".country-picker-selected-name");
    const countryFlag = panel.querySelector(".country-picker-selected-flag");
    const vatMessage = panel.querySelector("#countryCurrencyVatMessage");
    const currencySelect = panel.querySelector("#countryCurrencyCurrency");
    const saveButton = panel.querySelector("#countryCurrencySave");
    const errorElement = panel.querySelector("#countryCurrencyError");
    const defaultCurrency = panel.dataset.defaultCurrency || "GBP";

    if (!countryToggle || !countryMenu || !countryInput || !countryText ||
        !countryFlag || !currencySelect || !saveButton || !errorElement) return;

    function setCountryMenuOpen(isOpen) {
      countryMenu.classList.toggle("d-none", !isOpen);
      countryToggle.setAttribute("aria-expanded", isOpen ? "true" : "false");

      if (isOpen && countrySearch) {
        window.setTimeout(function () {
          countrySearch.focus();
        }, 0);
      }
    }

    function clearCountrySearch() {
      if (!countrySearch) return;

      countrySearch.value = "";
      panel.querySelectorAll(".country-picker-option").forEach(function (option) {
        option.classList.remove("d-none");
      });

      panel.querySelectorAll(".country-picker-section").forEach(function (section) {
        section.classList.remove("d-none");
      });

      if (noCountries) noCountries.classList.add("d-none");
    }

    countryToggle.addEventListener("click", function () {
      setCountryMenuOpen(countryMenu.classList.contains("d-none"));
    });
    
    function updateVatMessage(country) {
      if (!vatMessage) {
        return;
      }

      const isUnitedKingdom =
        country.trim().toLowerCase() === "united kingdom";

      vatMessage.textContent = isUnitedKingdom
        ? "Prices will include VAT."
        : "Prices will exclude VAT.";
    }    

    updateVatMessage(countryInput.value);

    panel.querySelectorAll(".country-picker-option").forEach(function (option) {
      option.addEventListener("click", function () {
        const country = option.dataset.country;
        const countryCode = option.dataset.countryCode;
        const recommendedCurrency = option.dataset.currency || defaultCurrency;

        countryInput.value = country;
        countryText.textContent = country;
        countryFlag.className =
          "country-picker-selected-flag country-flag country-flag-" + countryCode;

        updateVatMessage(country);

        if (currencySelect.querySelector('option[value="' + recommendedCurrency + '"]')) {
          currencySelect.value = recommendedCurrency;
        }
        else {
          currencySelect.value = defaultCurrency;
        }

        panel.querySelectorAll(".country-picker-option").forEach(function (item) {
          const isSelected = item.dataset.country === country;
          item.classList.toggle("selected", isSelected);
          item.setAttribute("aria-selected", isSelected ? "true" : "false");
        });

        clearCountrySearch();
        setCountryMenuOpen(false);
        countryToggle.focus();
      });
    });

    if (countrySearch) {
      countrySearch.addEventListener("input", function () {
        const query = countrySearch.value.trim().toLowerCase();
        let visibleCount = 0;

        panel.querySelectorAll(".country-picker-option").forEach(function (option) {
          const matches = !query || option.dataset.search.indexOf(query) !== -1;
          option.classList.toggle("d-none", !matches);
          if (matches) visibleCount += 1;
        });

        panel.querySelectorAll(".country-picker-section").forEach(function (section) {
          const hasVisibleOption = section.querySelector(".country-picker-option:not(.d-none)");
          section.classList.toggle("d-none", !hasVisibleOption);
        });

        if (noCountries) noCountries.classList.toggle("d-none", visibleCount !== 0);
      });
    }

    panel.addEventListener("click", function (event) {
      if (!countryMenu.classList.contains("d-none") &&
          !countryMenu.contains(event.target) &&
          !countryToggle.contains(event.target)) {
        setCountryMenuOpen(false);
      }
    });

    panel.addEventListener("keydown", function (event) {
      if (event.key === "Escape" && !countryMenu.classList.contains("d-none")) {
        event.preventDefault();
        event.stopPropagation();
        setCountryMenuOpen(false);
        countryToggle.focus();
      }
    });

    saveButton.addEventListener("click", function () {
      const selectedCountry = countryInput.value;
      const selectedCurrency = currencySelect.value || defaultCurrency;
      const originalCountry = panel.dataset.originalCountry;
      const originalCurrency = panel.dataset.originalCurrency;

      errorElement.classList.add("d-none");
      errorElement.textContent = "";

      if (selectedCountry === originalCountry && selectedCurrency === originalCurrency) {
        const modal = bootstrap.Modal.getInstance(modalElement);
        if (modal) modal.hide();
        return;
      }

      saveButton.disabled = true;
      saveButton.innerHTML =
        '<span class="spinner-border spinner-border-sm me-2" aria-hidden="true"></span>' +
        'Applying...';

      $.ajax({
        url: "/ajax.asp",
        method: "POST",
        dataType: "json",
        data: {
          cmd: "country_currency_save",
          deliverycountry: selectedCountry,
          currency: selectedCurrency
        }
      })
      .done(function (result) {
        if (!result || result.success !== true) {
          errorElement.textContent =
            result && result.message ? result.message : "The settings could not be saved.";
          errorElement.classList.remove("d-none");
          saveButton.disabled = false;
          saveButton.textContent = "Save";
          return;
        }

        // Both values have already been stored by apputils.asp. Perform a
        // normal GET so Classic ASP re-renders all prices, VAT, delivery and
        // header information from the new session/cookie state.
        reloadCurrentPageWithGet();
      })
      .fail(function () {
        errorElement.textContent = "The settings could not be saved. Please try again.";
        errorElement.classList.remove("d-none");
        saveButton.disabled = false;
        saveButton.textContent = "Save";
      });
    });
  }

  modalElement.addEventListener("show.bs.modal", function () {
    loadPanel(false);
  });

  modalElement.addEventListener("hidden.bs.modal", function () {
    const countryMenu = contentElement.querySelector("#countryCurrencyCountryMenu");
    const countryToggle = contentElement.querySelector("#countryCurrencyCountryButton");

    if (countryMenu) countryMenu.classList.add("d-none");
    if (countryToggle) countryToggle.setAttribute("aria-expanded", "false");
  });

  contentElement.addEventListener("click", function (event) {
    if (event.target && event.target.id === "countryCurrencyRetry") {
      loadPanel(true);
    }
  });
});
</script>
<%
End Sub
%>