PageSourceSearch

https://dragononline.com.au/store.js

js dragononline.com.au collected 2026-10-02 13:32:06 UTC 6,763 bytes, 156 lines download raw bytes

1const menuButton = document.querySelector('.menu-toggle');
2const menu = document.querySelector('#main-nav');
3function setMenu(open) {
4  menu.classList.toggle('is-open', open);
5  menuButton.setAttribute('aria-expanded', String(open));
6  menuButton.querySelector('span').textContent = open ? 'Close' : 'Menu';
7}
8menuButton.addEventListener('click', () => setMenu(menuButton.getAttribute('aria-expanded') !== 'true'));
9menu.addEventListener('click', event => { if (event.target.closest('a')) setMenu(false); });
10document.addEventListener('keydown', event => {
11  if (event.key === 'Escape' && menuButton.getAttribute('aria-expanded') === 'true') {
12    setMenu(false); menuButton.focus();
13  }
14});
15document.addEventListener('click', event => { if (!event.target.closest('header')) setMenu(false); });
16window.matchMedia('(min-width:701px)').addEventListener('change', () => setMenu(false));
17
18// Settings are local to this embed. The original Ecwid storefront is unchanged.
19window.ec = window.ec || {};
20window.ec.config = window.ec.config || {};
21window.ec.config.chameleon = {
22  colors: {
23    'color-background': '#f2f3f4',
24    'color-foreground': '#111110',
25    'color-link': '#111110',
26    'color-button': '#ed3028',
27    'color-price': '#111110'
28  },
29  font: {'font-family': 'DM Sans, Arial, sans-serif'}
30};
31window.ec.storefront = Object.assign(window.ec.storefront || {}, {
32  product_list_title_behavior: 'SHOW',
33  product_list_price_behavior: 'SHOW',
34  product_list_sku_behavior: 'HIDE',
35  product_list_product_info_layout: 'LEFT',
36  product_list_category_title_behavior: 'SHOW_BELOW_IMAGE',
37  product_list_show_frame: false,
38  product_list_image_size: 'LARGE',
39  product_list_image_aspect_ratio: 'SQUARE',
40  product_list_image_position: 'FIT',
41  product_list_show_additional_image_on_hover: false,
42  productListCardSpacingType: 'wide',
43  product_details_layout: 'TWO_COLUMNS_SIDEBAR_ON_THE_RIGHT',
44  product_details_gallery_image_position: 'FIT',
45  show_breadcrumbs: true,
46  show_signin_link: true,
47  show_footer_menu: true
48});
49const status = document.getElementById('store-status');
50const storefront = document.getElementById('my-store-749064');
51// Keep Ecwid's own buttons and purchase handlers; change only their labels.
52const optionProductSelector = '.grid-product--id-810735753, .grid-product--id-810733276';
53let pendingBagButton = null;
54const addedButtons = new WeakSet();
55function updateShopButtons() {
56  storefront.querySelectorAll('button .form-control__button-text').forEach(label => {
57    const button = label.closest('button');
58    const current = label.textContent.trim();
59    if (!/^(Buy Now|Add to (Bag|bag|Cart|cart)|Choose Options|Added ✓)$/.test(current)) return;
60    const next = addedButtons.has(button) ? 'Added ✓'
61      : button.closest(optionProductSelector) ? 'Choose Options' : 'Add to Bag';
62    if (current !== next) label.textContent = next;
63  });
64}
65new MutationObserver(updateShopButtons).observe(storefront, {
66  childList: true, subtree: true, characterData: true
67});
68storefront.addEventListener('click', event => {
69  const button = event.target.closest('button');
70  if (button?.querySelector('.form-control__button-text')?.textContent.trim() === 'Add to Bag') {
71    pendingBagButton = {button, clickedAt: Date.now()};
72  } else {
73    pendingBagButton = null;
74  }
75}, true);
76function confirmBagButton() {
77  const pending = pendingBagButton;
78  pendingBagButton = null;
79  if (!pending || Date.now() - pending.clickedAt > 15000 || !pending.button.isConnected) return;
80  addedButtons.add(pending.button);
81  updateShopButtons();
82  setTimeout(() => {
83    addedButtons.delete(pending.button);
84    updateShopButtons();
85  }, 1800);
86}
87const loadingTimeout = setTimeout(() => {
88  status.textContent = 'The shop is taking longer to load. You can also use the original store below.';
89}, 20000);
90const script = document.createElement('script');
91script.src = 'https://app.ecwid.com/script.js?749064&data_platform=code';
92script.charset = 'utf-8';
93script.dataset.cfasync = 'false';
94script.onload = () => {
95  if (typeof window.xProductBrowser !== 'function') { showLoadError(); return; }
96  function applyCutouts() {
97    const cutouts = {
98      '731834809': 'assets/tote-cutout.png',
99      '704089559': 'assets/cooler-cutout.png',
100      '810735753': 'assets/tee-cutout.png',
101      '810733276': 'assets/singlet-transparent.png',
102      '128660098': 'assets/life-transparent.png',
103      '7096831': 'assets/happy-transparent.png',
104      '33020117': 'assets/trilogy-transparent.png',
105      '7096841': 'assets/beautiful-transparent.png',
106      '7096839': 'assets/remembers-transparent.png',
107      '14378270': 'assets/great-divide-transparent.png',
108      '656506917': 'assets/dragon-50-transparent.png'
109    };
110    for (const [id, source] of Object.entries(cutouts)) {
111      document.querySelectorAll(`.grid-product--id-${id} img.grid-product__picture`).forEach(img => {
112        if (img.dataset.dragonCutout) return;
113        img.dataset.dragonCutout = 'true';
114        const original = img.src;
115        img.addEventListener('error', () => { img.src = original; }, {once: true});
116        img.removeAttribute('srcset');
117        img.src = source;
118      });
119    }
120    const cds = ['656506917', '14378270', '33020117', '7096831', '7096841', '7096839', '128660098'];
121    for (const id of cds) {
122      document.querySelectorAll(`.grid-product--id-${id}`).forEach(card => card.classList.add('dragon-cd'));
123    }
124  }
125  if (window.Ecwid?.OnPageLoaded) {
126    window.Ecwid.OnPageLoaded.add(() => { clearTimeout(loadingTimeout); status.hidden = true; applyCutouts(); updateShopButtons(); });
127  }
128  window.xProductBrowser('id=my-store-749064');
129  window.Ecwid.OnAPILoaded.add(() => {
130    window.Ecwid.refreshConfig();
131    let lastQuantity = null;
132    let noticeTimer;
133    function updateBag(cart) {
134      const quantity = Number(cart.productsQuantity) || 0;
135      document.getElementById('bag-count').textContent = quantity;
136      document.querySelector('.shop-bag').setAttribute('aria-label', `Open shopping bag, ${quantity} items`);
137      if (lastQuantity !== null && quantity > lastQuantity) {
138        confirmBagButton();
139        const notice = document.getElementById('bag-notice');
140        document.getElementById('bag-message').textContent = 'Added to your bag.';
141        notice.hidden = false;
142        clearTimeout(noticeTimer);
143        noticeTimer = setTimeout(() => { notice.hidden = true; }, 6500);
144      }
145      lastQuantity = quantity;
146    }
147    window.Ecwid.Cart.get(updateBag);
148    window.Ecwid.OnCartChanged.add(updateBag);
149  });
150};
151function showLoadError() {
152  clearTimeout(loadingTimeout);
153  status.textContent = 'The shop could not load here. Please open the original Dragon store below.';
154}
155script.onerror = showLoadError;
156document.body.appendChild(script);

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.