Filter Items

Treatments By Breeds

vvgfd' />/g, '>') .replace(/"/g, '"').replace(/'/g, '''); } function highlight(haystack, needle) { if (!haystack) return ''; if (!needle) return escapeHtml(haystack); var lh = String(haystack).toLowerCase(); var ln = String(needle).toLowerCase(); var i = lh.indexOf(ln); if (i < 0) return escapeHtml(haystack); return escapeHtml(haystack.slice(0, i)) + '' + escapeHtml(haystack.slice(i, i + needle.length)) + '' + escapeHtml(haystack.slice(i + needle.length)); } function ensurePanel(form) { var panel = form.querySelector('[data-ashop-search-results]'); if (panel) return panel; panel = document.createElement('div'); panel.setAttribute('data-ashop-search-results', ''); panel.className = 'ashop-search-results'; panel.setAttribute('role', 'listbox'); panel.hidden = true; // Anchor under the form so the panel inherits its width when CSS // positions it absolutely. form.appendChild(panel); return panel; } function renderResults(panel, query, results) { if (!results || results.length === 0) { panel.innerHTML = '
No products match \u201C' + escapeHtml(query) + '\u201D.
'; return; } var html = ''; html += 'View all results for \u201C' + escapeHtml(query) + '\u201D'; panel.innerHTML = html; } function bindForm(form) { if (form.__ashopBound) return; if (form.getAttribute('data-live-search') === 'off') return; var input = form.querySelector('input[type="search"], input[name="q"]'); if (!input) return; form.__ashopBound = true; // Make sure the form is a positioned ancestor so the panel anchors // to the input row. var pos = window.getComputedStyle(form).position; if (pos === 'static') form.style.position = 'relative'; var panel = ensurePanel(form); var debounce = null; var lastController = null; var activeIndex = -1; function open() { panel.hidden = false; input.setAttribute('aria-expanded', 'true'); } function close() { panel.hidden = true; input.setAttribute('aria-expanded', 'false'); activeIndex = -1; } function highlightActive() { var items = panel.querySelectorAll('li'); items.forEach(function (li, i) { if (i === activeIndex) li.setAttribute('aria-selected', 'true'); else li.removeAttribute('aria-selected'); }); var active = items[activeIndex]; if (active) active.scrollIntoView({ block: 'nearest' }); } function fetchSuggestions(q) { if (lastController) lastController.abort(); lastController = new AbortController(); panel.classList.add('is-loading'); open(); fetch('/api/search?q=' + encodeURIComponent(q) + '&limit=8', { signal: lastController.signal, headers: { Accept: 'application/json' }, }) .then(function (r) { return r.ok ? r.json() : Promise.reject(r); }) .then(function (data) { panel.classList.remove('is-loading'); renderResults(panel, q, data.results || []); }) .catch(function (err) { if (err && err.name === 'AbortError') return; panel.classList.remove('is-loading'); panel.innerHTML = '
Search is unavailable right now.
'; }); } input.addEventListener('input', function () { var q = input.value.trim(); if (debounce) clearTimeout(debounce); if (q.length < MIN_CHARS) { close(); panel.innerHTML = ''; return; } debounce = setTimeout(function () { fetchSuggestions(q); }, DEBOUNCE_MS); }); input.addEventListener('focus', function () { if (input.value.trim().length >= MIN_CHARS && panel.children.length) open(); }); input.addEventListener('keydown', function (e) { var items = panel.querySelectorAll('li > a'); if (panel.hidden || items.length === 0) return; if (e.key === 'ArrowDown') { e.preventDefault(); activeIndex = (activeIndex + 1) % items.length; highlightActive(); } else if (e.key === 'ArrowUp') { e.preventDefault(); activeIndex = (activeIndex - 1 + items.length) % items.length; highlightActive(); } else if (e.key === 'Enter' && activeIndex >= 0) { e.preventDefault(); items[activeIndex].click(); } else if (e.key === 'Escape') { close(); } }); document.addEventListener('click', function (e) { if (!form.contains(e.target)) close(); }); } function bindAll() { // Standard Shopify-shape: any form posting to /search. var forms = document.querySelectorAll('form[data-live-search], form[action="/search"], form[action$="/search"]'); forms.forEach(bindForm); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bindAll); else bindAll(); // Re-scan on DOM changes so themes that mount the header asynchronously // (drawer search, mobile menu, etc.) still pick up the behaviour. if (typeof MutationObserver !== 'undefined') { new MutationObserver(bindAll).observe(document.documentElement, { childList: true, subtree: true }); } })();