1<!doctype html> 2<html lang="en"> 3<head > 4 <meta charset="utf-8"/>
4<script type="text/javascript">(window.NREUM||(NREUM={})).init={ajax:{deny_list:["bam.nr-data.net"]}};(window.NREUM||(NREUM={})).loader_config={licenseKey:"8185b07d0f",applicationID:"154432994",browserID:"155173439"};;/*! For license information please see nr-loader-rum-1.322.0.min.js.LICENSE.txt */ 5(()=>{var e={8122(e,t,r){"use strict";r.d(t,{a:()=>i});var n=r(944);function i(e,t){try{if(!e||"object"!=typeof e)return(0,n.R)(3);if(!t||"object"!=typeof t)return(0,n.R)(4);const r=Object.create(Object.getPrototypeOf(t),Object.getOwnPropertyDescriptors(t)),a=0===Object.keys(r).length?e:r;for(let s in a)if(void 0!==e[s])try{if(null===e[s]){r[s]=null;continue}Array.isArray(e[s])&&Array.isArray(t[s])?r[s]=Array.from(new Set([...e[s],...t[s]])):e[s]instanceof Map||e[s]instanceof Set||e[s]instanceof Date||e[s]instanceof RegExp?r[s]=e[s]:"object"==typeof e[s]&&null!==t[s]&&"object"==typeof t[s]?r[s]=i(e[s],t[s]):r[s]=e[s]}catch(e){r[s]||(0,n.R)(1,e)}return r}catch(e){(0,n.R)(2,e)}}},2555(e,t,r){"use strict";r.d(t,{f:()=>s});var n=r(384),i=r(8122);const a={beacon:n.NT.beacon,errorBeacon:n.NT.errorBeacon,licenseKey:void 0,applicationID:void 0,sa:void 0,queueTime:void 0,applicationTime:void 0,ttGuid:void 0,user:void 0,account:void 0,product:void 0,extra:void 0,jsAttributes:{},userAttributes:void 0,atts:void 0,transactionName:void 0,tNamePlain:void 0};function s(e){try{return!!e.licenseKey&&!!e.errorBeacon&&!!e.applicationID}catch(e){return!1}}r.d(t,["D",0,e=>(0,i.a)(e,a)])},7699(e,t,r){"use strict";var n=r(860);const i={[n.K7.logging]:!0,[n.K7.genericEvents]:!0,[n.K7.jserrors]:!0,[n.K7.ajax]:!0};r.d(t,["It",0,1e6,"KC",0,i,"qh",0,"SESSION_ERROR"])},9324(e,t,r){"use strict";r.d(t,["xv",0,"1.322.0"])},981(e,t,r){"use strict";r.d(t,["R",0,{AJAX:"AjaxRequest",PA:"PageAction",UA:"UserAction",BP:"BrowserPerformance",WS:"WebSocket",SPV:"SecurityPolicyViolation",JSE:"JavaScriptError",LOG:"Log",PVE:"PageView",PVT:"PageViewTiming",SR:"SessionReplay",ST:"SessionTrace",BI:"BrowserInteraction"}])},6154(e,t,r){"use strict";var n=r(1863);const i="undefined"!=typeof window&&!!window.document,a="undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self.navigator instanceof WorkerNavigator||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis.navigator instanceof WorkerNavigator),s=i?window:"undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis),o=Boolean("hidden"===s?.document?.visibilityState),c=""+s?.location,u=/iPad|iPhone|iPod/.test(s.navigator?.userAgent),d=u&&"undefined"==typeof SharedWorker,l=((()=>{const e=s.navigator?.userAgent?.match(/Firefox[/\s](\d+\.\d+)/);Array.isArray(e)&&e.length>=2&&e[1]})(),Date.now()-(0,n.t)());r.d(t,["OF",0,u,"RI",0,i,"WN",0,l,"bv",0,a,"gm",0,s,"m",0,c,"mw",0,o,"sb",0,d,"zk",0,()=>{const e=s?.performance?.getEntriesByType?.("navigation")?.[0];if(e&&e.responseStart>0&&e.responseStart<s.performance.now())return e}])},3241(e,t,r){"use strict";r.d(t,{W:()=>i});var n=r(6154);function i(e={}){try{n.gm.dispatchEvent(new CustomEvent("newrelic",{detail:e}))}catch(e){}}},1687(e,t,r){"use strict";r.d(t,{Ak:()=>o,Ze:()=>u,x3:()=>c});var n=r(3241),i=r(3606),a=r(860),s=r(2646);function o(e,t){if(!e)return;const r={staged:!1,priority:a.P3[t]||0};e.runtime.drainRegistry.get(t)||e.runtime.drainRegistry.set(t,r)}function c(e,t){if(!e)return;const r=e.runtime.drainRegistry;r&&(r.get(t)&&r.delete(t),l(e,t,!1),r.size&&d(e))}function u(e,t="feature",r=!1){if(e){if(!e.runtime.drainRegistry.get(t)||r)return l(e,t);e.runtime.drainRegistry.get(t).staged=!0,d(e)}}function d(e){if(!e)return;const t=Array.from(e.runtime.drainRegistry);t.every(([e,t])=>t.staged)&&(t.sort((e,t)=>e[1].priority-t[1].priority),t.forEach(([t])=>{e.runtime.drainRegistry.delete(t),l(e,t)}))}function l(e,t,r=!0){if(!e)return;const a=e.ee,o=i.i.handlers;if(a&&!a.aborted&&a.backlog&&o){if((0,n.W)({type:"lifecycle",name:"drain",feature:t}),r){const e=a.backlog[t],r=o[t];if(r){for(let t=0;e&&t<e.length;++t)f(e[t],r);Object.entries(r).forEach(([e,t])=>{Object.values(t||{}
5).forEach(t=>{t[0]?.on&&t[0].context()instanceof s.y&&!t[0].listeners(e).includes(t[1])&&t[0].on(e,t[1])})})}}a.isolatedBacklog||delete o[t],a.backlog[t]=null,a.emit("drain-"+t,[])}}function f(e,t){var r=e[1];Object.values(t[r]||{}).forEach(t=>{var r=e[0];if(t[0]===r){var n=t[1],i=e[3],a=e[2];n.apply(i,a)}})}},7836(e,t,r){"use strict";var n=r(384),i=r(8990),a=r(2646),s=r(5607);const o="nr@context:".concat(s.W),c=function e(t,r){var n={},s={},d={},l=!1;try{l=16===r.length&&u.initializedAgents?.[r]?.runtime.isolatedBacklog}catch(e){}var f={on:p,addEventListener:p,removeEventListener:function(e,t){var r=n[e];if(!r)return;for(var i=0;i<r.length;i++)r[i]===t&&r.splice(i,1)},emit:function(e,r,n,i,a){!1!==a&&(a=!0);if(c.aborted&&!i)return;t&&a&&t.emit(e,r,n);var o=g(n);m(e).forEach(e=>{e.apply(o,r)});var u=v()[s[e]];u&&u.push([f,e,r,o]);return o},get:h,listeners:m,context:g,buffer:function(e,t){const r=v();if(t=t||"feature",f.aborted)return;Object.entries(e||{}).forEach(([e,n])=>{s[n]=t,t in r||(r[t]=[])})},abort:function(){f._aborted=!0,Object.keys(f.backlog).forEach(e=>{delete f.backlog[e]})},isBuffering:function(e){return!!v()[s[e]]},debugId:r,backlog:l?{}:t&&"object"==typeof t.backlog?t.backlog:{},isolatedBacklog:l};return Object.defineProperty(f,"aborted",{get:()=>{let e=f._aborted||!1;return e||(t&&(e=t.aborted),e)}}),f;function g(e){return e&&e instanceof a.y?e:e?(0,i.I)(e,o,()=>new a.y(o)):new a.y(o)}function p(e,t){n[e]=m(e).concat(t)}function m(e){return n[e]||[]}function h(t){return d[t]=d[t]||e(f,t)}function v(){return f.backlog}}(void 0,"globalEE"),u=(0,n.Zm)();u.ee||(u.ee=c),r.d(t,["P",0,o,"ee",0,c])},2646(e,t,r){"use strict";r.d(t,{y:()=>n});class n{constructor(e){this.contextId=e}}},9908(e,t,r){"use strict";r.d(t,{d:()=>n,p:()=>i});var n=r(7836).ee.get("handle");function i(e,t,r,i,a){a?(a.buffer([e],i),a.emit(e,t,r)):(n.buffer([e],i),n.emit(e,t,r))}},3606(e,t,r){"use strict";r.d(t,{i:()=>a});var n=r(9908);a.on=s;var i=a.handlers={};function a(e,t,r,a){s(a||n.d,i,e,t,r)}function s(e,t,r,i,a){a||(a="feature"),e||(e=n.d);var s=t[a]=t[a]||{};(s[r]=s[r]||[]).push([e,i])}},3878(e,t,r){"use strict";function n(e,t){return{capture:e,passive:!1,signal:t}}function i(e,t,r=!1,i){window.addEventListener(e,t,n(r,i))}function a(e,t,r=!1,i){document.addEventListener(e,t,n(r,i))}r.d(t,{DD:()=>a,jT:()=>n,sp:()=>i})},5607(e,t,r){"use strict";const n=(0,r(9566).bz)();r.d(t,["W",0,n])},9566(e,t,r){"use strict";r.d(t,{LA:()=>s,bz:()=>a});var n=r(6154);function i(e,t){return e?15&e[t]:16*Math.random()|0}function a(){const e=n.gm?.crypto||n.gm?.msCrypto;let t,r=0;return e&&e.getRandomValues&&(t=e.getRandomValues(new Uint8Array(30))),"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".split("").map(e=>"x"===e?i(t,r++).toString(16):"y"===e?(3&i()|8).toString(16):e).join("")}function s(e){const t=n.gm?.crypto||n.gm?.msCrypto;let r,a=0;t&&t.getRandomValues&&(r=t.getRandomValues(new Uint8Array(e)));const s=[];for(var o=0;o<e;o++)s.push(i(r,a++).toString(16));return s.join("")}},2614(e,t,r){"use strict";r.d(t,["BB",0,18e5,"Wt",0,"NRBA_SESSION::","iL",0,{SAME_TAB:"same-tab",CROSS_TAB:"cross-tab"},"tS",0,{STARTED:"session-started",PAUSE:"session-pause",RESET:"session-reset",RESUME:"session-resume",UPDATE:"session-update"},"wk",0,144e5])},1863(e,t,r){"use strict";function n(){return Math.floor(performance.now())}r.d(t,{t:()=>n})},944(e,t,r){"use strict";r.d(t,{R:()=>i});var n=r(3241);function i(e,t){"function"==typeof console.debug&&(console.debug("New Relic Warning: https://github.com/newrelic/newrelic-browser-agent/blob/main/docs/warning-codes.md#".concat(e),t),(0,n.W)({drained:null,type:"data",name:"warn",feature:"warn",data:{code:e,secondary:t}}))}},8990(e,t,r){"use strict";r.d(t,{I:()=>i});var n=Object.prototype.hasOwnProperty;function i(e,t,r){if(n.call(e,t))return e[t];var i=r();if(Object.defineProperty&&Object.keys)try{return Object.defineProperty(e,t,{value:i,writable:!0,enumerable:!1}),i}catch(e){}return e[t]=i,i}},6389(e,t,r){"use strict";function n(e,t=500,r={}){const n=r?.leading||!1;let i;return(...r)=>{n&&void 0===i&&(e.apply(this,r),i=setTimeout(()=>{i=clearTimeout(i)},t)),n||(clearTimeout(i),i=setTimeout(()=>{e.apply(this,r)},t))}}function i(e){let t=!1;return(...r)=>{t||(t=!0,e.apply(this,r))}}r.d(t,{J:()=>i,s:()=>n})},1910(e,t,r){"use strict";r.d(t,{i:()=>a});var n=r(944);const i=new Map;function a(...e){return e.every(e=>{if(i.has(e))return i.get(e);const t="function"==typeof e?e.toString():"",r=t.includes("[native code]"),a=t.includes("nrWrapper");return r||a||(0,n.R)(64,e?.name||t),i.set(e,r),r})}},5289(e,t,r){"use strict";r.d(t,{GG:()=>s,Qr:()=>c,sB:()=>o});var n=r(3878),i=r(6389);function a(){return"undefined"==typeof document||"complete"===document.readyState}function s(e,t){if(a())return e();const r=(0,i.J)(e),s=setInterval(()=>
5{a()&&(clearInterval(s),r())},500);(0,n.sp)("load",r,t)}function o(e){if(a())return e();(0,n.DD)("DOMContentLoaded",e)}function c(e){if(a())return e();(0,n.sp)("popstate",e)}},384(e,t,r){"use strict";r.d(t,{Zm:()=>c,bQ:()=>d,dV:()=>u,pV:()=>l});var n=r(6154),i=r(1863),a=r(944),s=r(1910);const o={beacon:"bam.nr-data.net",errorBeacon:"bam.nr-data.net"};function c(){return n.gm.NREUM||(n.gm.NREUM={}),void 0===n.gm.newrelic&&(n.gm.newrelic=n.gm.NREUM),n.gm.NREUM}function u(){let e=c();return e.o||(e.o={ST:n.gm.setTimeout,SI:n.gm.setImmediate||n.gm.setInterval,CT:n.gm.clearTimeout,XHR:n.gm.XMLHttpRequest,REQ:n.gm.Request,EV:n.gm.Event,PR:n.gm.Promise,MO:n.gm.MutationObserver,FETCH:n.gm.fetch,WS:n.gm.WebSocket},(0,s.i)(...Object.values(e.o))),e}function d(e,t){let r=c();r.initializedAgents??={},t.initializedAt={ms:(0,i.t)(),date:new Date},r.initializedAgents[e]=t,2===Object.keys(r.initializedAgents).length&&(0,a.R)(69)}function l(){return function(){let e=c();const t=e.info||{};e.info={beacon:o.beacon,errorBeacon:o.errorBeacon,...t}}(),function(){let e=c();const t=e.init||{};e.init={...t}}(),u(),function(){let e=c();const t=e.loader_config||{};e.loader_config={...t}}(),c()}r.d(t,["NT",0,o])},2843(e,t,r){"use strict";r.d(t,{G:()=>a,u:()=>i});var n=r(3878);function i(e,t=!1,r,i){(0,n.DD)("visibilitychange",function(){if(t)return void("hidden"===document.visibilityState&&e());e(document.visibilityState)},r,i)}function a(e,t,r){(0,n.sp)("pagehide",e,t,r)}},9300(e,t,r){"use strict";r(860).K7.ajax;r.d(t,["mo",0,{NONE:"none",FAILURES:"failures",ALL:"all"}])},3969(e,t,r){"use strict";const n=r(860).K7.metrics;r.d(t,["TZ",0,n,"XG",0,"storeEventMetrics","xV",0,"storeSupportabilityMetrics"])},6630(e,t,r){"use strict";const n=r(860).K7.pageViewEvent;r.d(t,["T",0,n])},782(e,t,r){"use strict";const n=r(860).K7.pageViewTiming;r.d(t,["T",0,n])},4234(e,t,r){"use strict";r.d(t,{W:()=>i});var n=r(1687);class i{constructor(e,t){this.agentRef=e,this.ee=e?.ee,this.featureName=t,this.blocked=!1}deregisterDrain(){(0,n.x3)(this.agentRef,this.featureName)}}},7767(e,t,r){"use strict";var n=r(6154);r.d(t,["V",0,e=>n.RI&&!0===e?.privacy.cookies_enabled])},8362(e,t,r){"use strict";r.d(t,{d:()=>a});var n=r(9566),i=r(1741);class a extends i.W{agentIdentifier=(0,n.LA)(16)}},1741(e,t,r){"use strict";r.d(t,{W:()=>a});var n=r(944),i=r(4261);class a{#e(e,...t){if(this[e]!==a.prototype[e])return this[e](...t);(0,n.R)(35,e)}addPageAction(e,t){return this.#e(i.hG,e,t)}register(e){return this.#e(i.eY,e)}recordCustomEvent(e,t){return this.#e(i.fF,e,t)}setPageViewName(e,t){return this.#e(i.Fw,e,t)}setCustomAttribute(e,t,r){return this.#e(i.cD,e,t,r)}noticeError(e,t){return this.#e(i.o5,e,t)}setUserId(e,t=!1){return this.#e(i.Dl,e,t)}setApplicationVersion(e){return this.#e(i.nb,e)}setErrorHandler(e){return this.#e(i.bt,e)}addRelease(e,t){return this.#e(i.k6,e,t)}log(e,t){return this.#e("log",e,t)}start(){return this.#e("start")}finished(e){return this.#e(i.BL,e)}recordReplay(){return this.#e(i.CH)}pauseReplay(){return this.#e(i.Tb)}addToTrace(e){return this.#e(i.U2,e)}setCurrentRouteName(e){return this.#e(i.PA,e)}interaction(e){return this.#e(i.dT,e)}wrapLogger(e,t,r){return this.#e(i.Wb,e,t,r)}measure(e,t){return this.#e(i.V1,e,t)}consent(e){return this.#e(i.Pv,e)}}},4261(e,t,r){"use strict";r.d(t,["BL",0,"finished","CH",0,"recordReplay","Dl",0,"setUserId","Fw",0,"setPageViewName","PA",0,"setCurrentRouteName","Pv",0,"consent","Tb",0,"pauseReplay","U2",0,"addToTrace","V1",0,"measure","Wb",0,"wrapLogger","bt",0,"setErrorHandler","cD",0,"setCustomAttribute","dT",0,"interaction","eY",0,"register","fF",0,"recordCustomEvent","hG",0,"addPageAction","k6",0,"addRelease","nb",0,"setApplicationVersion","o5",0,"noticeError"])},1738(e,t,r){"use strict";r.d(t,{U:()=>l,Y:()=>d});var n=r(3241),i=r(9908),a=r(1863),s=r(944),o=r(3969),c=r(8362),u=r(860);function d(e,t,r,a){const d=a||r;!d||d[e]&&d[e]!==c.d.prototype[e]||(d[e]=function(){(0,i.p)(o.xV,["API/"+e+"/called"],void 0,u.K7.metrics,r.ee),(0,n.W)({drained:!!r.runtime?.activatedFeatures,type:"data",name:"api",feature:"api-"+e,data:{}});try{return t.apply(this,arguments)}catch(e){(0,s.R)(23,e)}})}function l(e,t,r,n,s){const o=e.info;null===r?delete o.jsAttributes[t]:o.jsAttributes[t]=r,(s||null===r)&&(0,i.p)("api-"+n,[(0,a.t)(),t,r],void 0,"session",e.ee)}},8374(e,t,r){r.nc=(()=>{try{return document?.currentScript?.nonce}catch(e){}return""})()},860(e,t,r){"use strict";const n="events",i="jserrors",a="browser/blobs",s="browser/logs",o={ajax:"ajax",genericEvents:"generic_events",jserrors:i,logging:"logging",metrics:"metrics",pageAction:"page_action",pageViewEvent:"page_view_event",pageViewTiming:"page_view_timing",sessionReplay:"session_replay",sessionTrace:"session_trace",softNav:"soft_navigations"},c={[o.pageViewEvent]:1,[o.pageViewTiming]:2,[o.metrics]:3,[o.jserrors]:4,[o.softNav]:5,[o.ajax]:6,[o.sessionTrace]:7,[o.sessionReplay]:8,[o.logging]:9,[o.genericEvents]:10},u={[o.pageViewEvent]:"rum",[o.pageViewTiming]:n,[o.ajax]:n,[o.softNav]:n,[o.metrics]:i,[o.jserrors]:i,[o.sessionTrace]:a,[o.sessionReplay]:a,[o.logging]:s,[o.genericEvents]:"ins"};r.d(t,["$J",0,u,"K7",0,o,"P3",0,c,"XX",0,i,"Yy",0,s,"df",0,a,"hg",0,"connect"])}};const t={};function r(n){const i=t[n];if(void 0!==i)return i.exports;const a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}r.m=e,r.d=(e,t)=>{if(Array.isArray(t))for(var n=0;n<t.length;){var i=t[n++],a=t[n++];r.o(e,i)?0===a&&n++:0===a?Object.defineProperty(e,i,{enumerable:!0,value:t[n++]}):Object.defineProperty(e,i,{enumerable:!0,get:a})}else for(var i in t)r.o(t,i)&&!r.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((t,n)=>(r.f[n](e,t),t),[])),r.u=e=>"nr-rum-1.322.0.min.js",r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{const e={},t="NRBA-1.322.0.PROD:";r.l=(n,i,a,s)=>{if(e[n])return void e[n].push(i);let o,c;if(void 0!==a){const e=document.getElementsByTagName("script");for(var u=0;u<e.length;u++){const r=e[u];if(r.getAttribute("src")==n||r.getAttribute("data-webpack")==t+a){o=r;break}}}if(!o){c=!0;var d={296:"sha512-/59P7qAoMYQDJAZerTRPChdYcdrlcoEAw2TwA1wz6Y0/XLmt3sblL
5I5JCXAuxG0YxsW7iqJzgrcO7NJWO58EfQ=="};o=document.createElement("script"),o.charset="utf-8",r.nc&&o.setAttribute("nonce",r.nc),o.setAttribute("data-webpack",t+a),o.src=n,0!==o.src.indexOf(window.location.origin+"/")&&(o.crossOrigin="anonymous"),d[s]&&(o.integrity=d[s])}e[n]=[i];const l=(t,r)=>{o.onerror=o.onload=null,clearTimeout(f);const i=e[n];if(delete e[n],o.parentNode?.removeChild(o),i?.forEach(e=>e(r)),t)return t(r)},f=setTimeout(l.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=l.bind(null,o.onerror),o.onload=l.bind(null,o.onload),c&&document.head.appendChild(o)}})(),r.r=e=>{Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="https://js-agent.newrelic.com/",(()=>{const e={374:0,840:0};r.f.j=(t,n)=>{let i=r.o(e,t)?e[t]:void 0;if(0!==i)if(i)n.push(i[2]);else{const a=new Promise((r,n)=>i=e[t]=[r,n]);n.push(i[2]=a);const s=r.p+r.u(t),o=new Error,c=n=>{if(r.o(e,t)&&(i=e[t],0!==i&&(e[t]=void 0),i)){const e=n&&("load"===n.type?"missing":n.type),r=n&&n.target&&n.target.src;o.message="Loading chunk "+t+" failed: ("+e+": "+r+")",o.name="ChunkLoadError",o.type=e,o.request=r,i[1](o)}};r.l(s,c,"chunk-"+t,t)}};const t=(t,n)=>{let[i,a,s]=n;var o,c,u=0;if(i.some(t=>0!==e[t])){for(o in a)r.o(a,o)&&(r.m[o]=a[o]);if(s)s(r)}for(t&&t(n);u<i.length;u++)c=i[u],r.o(e,c)&&e[c]&&e[c][0](),e[c]=0},n=self["webpackChunk:NRBA-1.322.0.PROD"]=self["webpackChunk:NRBA-1.322.0.PROD"]||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})(),(()=>{"use strict";r(8374);var e=r(8362),t=r(860);const n=Object.values(t.K7);var i=r(384),a=r(1741);var s=r(2555),o=r(981);t.K7.genericEvents,o.R.PA,o.R.UA,o.R.BP;const c={RESOURCES:"experimental.resources",REGISTER:"register"};var u=r(9300);const d=e=>{if(!e||"string"!=typeof e)return!1;try{document.createDocumentFragment().querySelector(e)}catch{return!1}return!0};var l=r(2614),f=r(944),g=r(8122);const p="[data-nr-mask]",m=e=>(0,g.a)(e,(()=>{const e={feature_flags:[],experimental:{register:!1,resources:!1,iframe_bridge:!1,iframe_domains:[]},mask_selector:"*",block_selector:"[data-nr-block]",mask_input_options:{color:!1,date:!1,"datetime-local":!1,email:!1,month:!1,number:!1,range:!1,search:!1,tel:!1,text:!1,time:!1,url:!1,week:!1,textarea:!1,select:!1,password:!0}};return{ajax:{deny_list:void 0,block_internal:!0,enabled:!0,autoStart:!0,capture_payloads:u.mo.NONE},api:{register:{get enabled(){return e.feature_flags.includes(c.REGISTER)||e.experimental.register},set enabled(t){e.experimental.register=t},duplicate_data_to_container:!1,get allow_iframe_bridge(){return e.feature_flags.includes(c.IFRAME_BRIDGE)||e.experimental.iframe_bridge},set allow_iframe_bridge(t){e.experimental.iframe_bridge=t},get iframe_domains(){return e.experimental.iframe_domains},set iframe_domains(t){Array.isArray(t)?e.experimental.iframe_domains=t:(0,f.R)(1,t)}}},browser_consent_mode:{enabled:!1},distributed_tracing:{enabled:void 0,exclude_newrelic_header:void 0,cors_use_newrelic_header:void 0,cors_use_tracecontext_headers:void 0,allowed_origins:void 0},get feature_flags(){return e.feature_flags},set feature_flags(t){e.feature_flags=t},generic_events:{enabled:!0,autoStart:!0},harvest:{interval:30},jserrors:{enabled:!0,autoStart:!0},logging:{enabled:!0,autoStart:!0},metrics:{enabled:!0,autoStart:!0},obfuscate:void 0,page_action:{enabled:!0},page_view_event:{enabled:!0,autoStart:!0},page_view_timing:{enabled:!0,autoStart:!0},performance:{capture_marks:!1,capture_measures:!1,capture_detail:!0,resources:{get enabled(){return e.feature_flags.includes(c.RESOURCES)||e.experimental.resources},set enabled(t){e.experimental.resources=t},asset_types:[],first_party_domains:[],ignore_newrelic:!0}},privacy:{cookies_enabled:!0},proxy:{assets:void 0,beacon:void 0},session:{expiresMs:l.wk,inactiveMs:l.BB},session_replay:{autoStart:!0,enabled:!1,preload:!1,sampling_rate:10,error_sampling_rate:100,collect_fonts:!1,inline_images:!1,fix_stylesheets:!0,mask_all_inputs:!0,get mask_text_selector(){return e.mask_selector},set mask_text_selector(t){d(t)?e.mask_selector="".concat(t,",").concat(p):""===t||null===t?e.mask_selector=p:(0,f.R)(5,t)},get block_class(){return"nr-block"},get ignore_class(){return"nr-ignore"},get mask_text_class(){return"nr-mask"},get block_selector(){return e.block_selector},set block_selector(t){d(t)?e.block_selector+=",".concat(t):""!==t&&(0,f.R)(6,t)},get mask_input_options(){return e.mask_input_options},set mask_input_options(t){t&&"object"==typeof t?e.mask_input_options={...t,password:!0}:(0,f.R)(7,t)}},session_trace:{enabled:!0,autoStart:!0},soft_navigations:{enabled:!0,autoStart:!0},ssl:void 0,user_actions:{enabled:!0,elementAttributes:["id","className","tagName","type"]},web_sockets:{enabled:!1}}})());var h=r(6154),v=r(9324);let b=0;const y={buildEnv:"PROD",distMethod:"CDN",version:v.xv,originTime:h.WN},_={consented:!1},w={activatedFeatures:void 0,appMetadata:{},configured:!1,get consented(){return this.session?.state?.consent||_.consented},set consented(e){_.consented=e}
5,customTransaction:void 0,denyList:[],disabled:!1,drainRegistry:new Map,connector:void 0,harvester:void 0,v2Target:void 0,isolatedBacklog:!1,isRecording:!1,loaderType:void 0,maxBytes:3e4,obfuscator:void 0,onerror:void 0,ptid:void 0,releaseIds:{},session:void 0,timeKeeper:void 0,registeredEntities:[],jsAttributesMetadata:{bytes:0},get harvestCount(){return++b},listeningForIframeMessages:!1},R="BA";var A=r(7836),x=r(3241);const E={accountID:void 0,trustKey:void 0,agentID:void 0,licenseKey:void 0,applicationID:void 0,xpid:void 0};var S=r(9908);const k="newrelic-iframe-";function T(e,t={},n,o){let{init:c,info:u,loader_config:d,runtime:l={},exposed:f=!0}=t;if(!u){const e=(0,i.pV)();c=e.init,u=e.info,d=e.loader_config}var p;e.init=m(c||{}),e.loader_config=(p=d||{},(0,g.a)(p,E)),u.jsAttributes??={},h.bv&&(u.jsAttributes.isWorker=!0),e.info=(0,s.D)(u);const v=e.init;e.runtime??=(e=>{const t=(0,g.a)(e,w),r=Object.keys(y).reduce((e,t)=>(e[t]={value:y[t],writable:!1,configurable:!0,enumerable:!0},e),{});return Object.defineProperties(t,r)})(l),e.runtime.v2Target??={type:R,instance:e.agentIdentifier,get id(){return e.runtime.appMetadata?.agents?.[0]?.entityGuid},get attributes(){return{"entity.guid":this.id,appId:e.info.applicationID}}},v.proxy.assets&&(e=>{const t=e.startsWith("http");e+="/",r.p=t?e:"https://"+e})(v.proxy.assets),e.runtime.configured||(Object.defineProperty(e,"beacons",{get:()=>[e.info.beacon,e.info.errorBeacon,e.init.proxy.assets,e.init.proxy.beacon].filter(Boolean)}),Object.defineProperty(e.runtime,"denyList",{get:()=>[...e.init.ajax.deny_list||[],...e.init.ajax.block_internal?e.beacons:[]]}),e.runtime.ptid=e.agentIdentifier,function(e){const t=(0,i.pV)();Object.getOwnPropertyNames(a.W.prototype).forEach(r=>{const n=a.W.prototype[r];if("function"!=typeof n||"constructor"===n)return;let i=t[r];e[r]&&!1!==e.exposed&&"micro-agent"!==e.runtime?.loaderType&&(t[r]=(...t)=>{const n=e[r](...t);return i?i(...t):n})})}(e),e.runtime.loaderType=n,e.ee=A.ee.get(e.agentIdentifier),e.exposed=f,(0,x.W)({drained:!!e.runtime.activatedFeatures,type:"lifecycle",name:"initialize",feature:void 0,data:e.config}),e.init.api.register.allow_iframe_bridge&&h.gm.addEventListener("message",t=>{"string"==typeof t.data?.type&&t.data.type.startsWith(k)&&(0,S.p)("iframe-message",[t],void 0,"IFRAME",e.ee)}),e.runtime.configured=!0)}var j=r(1863),P=r(4261),N=r(1738);
5var O=r(1687),M=r(4234),I=r(5289),D=r(7767);function V(e){return!!(0,i.dV)().o.MO&&(0,D.V)(e)&&!0===e?.session_trace.enabled}var W=r(6389),B=r(7699);const C=new WeakSet,K=new WeakMap;class U extends M.W{constructor(e,t){super(e,t),this.abortHandler=void 0,this.featAggregate=void 0,this.loadedSuccessfully=void 0,this.onAggregateImported=new Promise(e=>{this.loadedSuccessfully=e}),this.deferred=Promise.resolve(),!1===e.init[this.featureName].autoStart?this.deferred=new Promise((t,r)=>{this.ee.on("manual-start-all",(0,W.J)(()=>{(0,O.Ak)(e,this.featureName),t()}))}):(0,O.Ak)(e,t)}importAggregator(e,t,n={}){if(this.featAggregate)return;const i=async()=>{if(await this.deferred,this.#t(e),!(0,s.f)(e.info))return(0,f.R)(43),e.ee.abort(),void this.loadedSuccessfully(!1);try{await async function(e,t,n){if(K.has(e))return K.get(e);const i=(async()=>{if((0,D.V)(e.init))try{const{setupAgentSession:t}=await r.e(296).then(r.bind(r,1768));t(e)}catch(e){(0,f.R)(20,e),t.emit("internal-error",[e]),(0,S.p)(B.qh,[e],void 0,n,t)}if(e.init.api.register.allow_iframe_bridge)try{const{setupIframeMFEMessageListener:t}=await Promise.resolve().then(function(){const e=new Error("Cannot find module '../../loaders/configure/iframe-message-handler'");throw e.code="MODULE_NOT_FOUND",e});t(e)}catch(e){(0,f.R)(23,e)}const[{Connector:i},{Harvester:a}]=await Promise.all([r.e(296).then(r.bind(r,6589)),r.e(296).then(r.bind(r,5237))]);e.runtime.connector=new i(e),e.runtime.harvester=new a(e);const s=Object.values(e.features).filter(t=>e.runtime.drainRegistry.has(t.featureName));Promise.all(s.map(e=>e.onAggregateImported)).then(()=>e.runtime.harvester.startTimer())})();K.set(e,i),await i}(e,this.ee,this.featureName)}catch(e){return(0,f.R)(79,e),this.ee.abort(),void this.loadedSuccessfully(!1)}try{if(!this.#r(this.featureName,e.runtime.session,e.init))return this.abortHandler?.(),(0,O.Ze)(this.agentRef,this.featureName),void this.loadedSuccessfully(!1);const{Aggregate:r}=await t();this.featAggregate=new r(e,n),e.runtime.harvester.initializedAggregates.push(this.featAggregate),this.loadedSuccessfully(!0)}catch(e){(0,f.R)(34,e),this.abortHandler?.(),(0,O.Ze)(this.agentRef,this.featureName,!0),this.loadedSuccessfully(!1)}};h.RI?(0,I.GG)(()=>i(),!0):i()}#r(e,r,n){if(this.blocked)return!1;switch(e){case t.K7.sessionReplay:return V(n)&&!!r;case t.K7.sessionTrace:return!!r;default:return!0}}#t(e){if(!C.has(e)&&(C.add(e),!(0,s.f)(e.info))){const t=(0,i.pV)();let r={...t.info?.jsAttributes};try{r={...r,...e.info?.jsAttributes}}catch(e){}T(e,{...t,info:{...t.info,jsAttributes:r},runtime:e.runtime},e.runtime.loaderType)}}}var L=r(6630);class F extends U{static featureName=L.T;constructor(e){var t;super(e,L.T),this.setupInspectionEvents(),t=e,(0,N.Y)(P.Fw,function(e,r){"string"==typeof e&&("/"!==e.charAt(0)&&(e="/"+e),t.runtime.customTransaction=(r||"http://custom.transaction")+e,(0,S.p)("api-"+P.Fw,[(0,j.t)()],void 0,void 0,t.ee))},t),this.importAggregator(e,()=>e.init.feature_flags.includes("rum_v2")?r.e(296).then(r.bind(r,908)):r.e(296).then(r.bind(r,7927)))}setupInspectionEvents(){const e=(e,t)=>{e&&(0,x.W)({timeStamp:e.timeStamp,loaded:"complete"===e.target.readyState,type:"window",name:t,data:e.target.location+""})};(0,I.sB)(t=>{e(t,"DOMContentLoaded")}),(0,I.GG)(t=>{e(t,"load")}),(0,I.Qr)(t=>{e(t,"navigate")}),this.ee.on(l.tS.UPDATE,(e,t)=>{(0,x.W)({type:"lifecycle",name:"session",data:t})})}}class G extends e.d{constructor(e){var t;(super(),h.gm)?(this.features={},(0,i.bQ)(this.agentIdentifier,this),this.desiredFeatures=new Set(e.features||[]),this.desiredFeatures.add(F),T(this,e,e.loaderType||"agent"),t=this,(0,N.Y)(P.cD,function(e,r,n=!1){if("string"==typeof e){if(["string","number","boolean"].includes(typeof r)||null===r)return(0,N.U)(t,e,r,P.cD,n);(0,f.R)(40,typeof r)}else(0,f.R)(39,typeof e)},t),function(e){(0,N.Y)(P.Dl,function(t,r=!1){if("string"!=typeof t&&null!==t)return void(0,f.R)(41,typeof t);const n=e.info.jsAttributes["enduser.id"];r&&null!=n&&n!==t?(0,S.p)("api-setUserIdAndResetSession",[t],void 0,"session",e.ee):(0,N.U)(e,"enduser.id",t,P.Dl,!0)},e)}(this),function(e){(0,N.Y)(P.nb,function(t){if("string"==typeof t||null===t)return(0,N.U)(e,"application.version",t,P.nb,!1);(0,f.R)(42,typeof t)},e)}(this),function(e){(0,N.Y)("start",function(){e.ee.emit("manual-start-all")},e)}(this),function(e){(0,N.Y)(P.Pv,function(t=!0){if("boolean"==typeof t){if((0,S.p)("api-"+P.Pv,[t],void 0,"session",e.ee),e.runtime.consented=t,t){const t=e.features.page_view_event;t.onAggregateImported.then(e=>{const r=t.featAggregate;e&&!r.sentRum&&r.sendRum?.()})}}else(0,f.R)(65,typeof t)},e)}(this),this.run()):(0,f.R)(21)}get config(){return{info:this.info,init:this.init,loader_config:this.loader_config,runtime:this.runtime}}get api(){return this}run(){try{const e=function(e){const t={};
5return n.forEach(r=>{t[r]=!!e[r]?.enabled}),t}(this.init),r=[...this.desiredFeatures],i=this.init.feature_flags.includes("rum_v2");r.sort((e,r)=>t.P3[e.featureName]-t.P3[r.featureName]),r.forEach(r=>{if(!e[r.featureName]&&(i||r.featureName!==t.K7.pageViewEvent))return;const n=function(e){switch(e){case t.K7.ajax:return[t.K7.jserrors];case t.K7.sessionTrace:return[t.K7.ajax,t.K7.pageViewEvent];case t.K7.sessionReplay:return[t.K7.sessionTrace];case t.K7.pageViewTiming:return[t.K7.pageViewEvent];default:return[]}}(r.featureName).filter(e=>!(e in this.features));n.length>0&&(0,f.R)(36,{targetFeature:r.featureName,missingDependencies:n}),this.features[r.featureName]=new r(this)})}catch(e){(0,f.R)(22,e);for(const e in this.features)this.features[e].abortHandler?.();const t=(0,i.Zm)();delete t.initializedAgents[this.agentIdentifier]?.features,delete this.sharedAggregator;return t.ee.get(this.agentIdentifier).abort(),!1}}}var H=r(2843),z=r(782);class Y extends U{static featureName=z.T;constructor(e){super(e,z.T),h.RI&&((0,H.u)(()=>(0,S.p)("docHidden",[(0,j.t)()],void 0,z.T,this.ee),!0),(0,H.G)(()=>(0,S.p)("winPagehide",[(0,j.t)()],void 0,z.T,this.ee)),this.importAggregator(e,()=>r.e(296).then(r.bind(r,9981))))}}var Z=r(3969);class q extends U{static featureName=Z.TZ;constructor(e){super(e,Z.TZ),this.importAggregator(e,()=>r.e(296).then(r.bind(r,9623)))}}new G({features:[F,Y,q],loaderType:"lite"})})()})();</script>
5 6<meta name="title" content="R27 Clean Air Premium Pet: Best Vacuum for Pet Owners"/> 7<meta name="keywords" content="Riccar Vacuums"/> 8<meta name="robots" content="index, follow"/> 9<meta name="viewport" content="width=device-width, initial-scale=1"/> 10<meta name="msapplication-TileColor" content="#da532c"/> 11<meta name="theme-color" content="#ffffff"/> 12<title>R27 Clean Air Premium Pet: Best Vacuum for Pet Owners</title> 13<link rel="stylesheet" type="text/css" media="all" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/css/styles.css" /> 14<link rel="stylesheet" type="text/css" media="all" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Amasty_Storelocator/vendor/chosen/chosen.min.css" /> 15<link rel="stylesheet" type="text/css" media="all" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Ves_Trackorder/css/style.css" /> 16<link rel="stylesheet" type="text/css" media="all" href="https://cloud.typography.com/7437156/7175012/css/fonts.css" /> 17<link rel="shortcut icon" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/images/favicons/favicon.ico" />
18<script type="text/javascript" defer="defer" src="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Hyva_MagentoDataServices/js/storefront-event-collector.min.js"></script>
vendor: 1 bytes, line 18
18
19<script type="text/javascript" defer="defer" src="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Hyva_MagentoDataServices/js/storefront-events-sdk.min.js"></script>
vendor: 1 bytes, line 19
19
20<script type="text/javascript" defer="defer" src="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Hyva_MagentoLiveSearch/js/sdk.min.js"></script>
vendor: 1 bytes, line 20
20
21<script type="text/javascript" defer="defer" src="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Hyva_MagentoProductRecommendations/js/recs-sdk.min.js"></script>
21 22<link rel="preload" as="font" crossorigin="anonymous" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/images/favicons/safari-pinned-tab.svg" /> 23<link rel="apple-touch-icon" sizes="180x180" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/images/favicons/apple-touch-icon.png" /> 24<link rel="icon" type="image/png" sizes="32x32" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/images/favicons/favicon-32x32.png" /> 25<link rel="icon" type="image/png" sizes="16x16" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/images/favicons/favicon-16x16.png" /> 26<link rel="manifest" href="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/images/favicons/site.webmanifest" /> 27<link rel="canonical" href="https://www.riccar.com/blog/r27-clean-air-premium-pet-best-vacuum-for-pet-owners.html" /> 28<link rel="icon" type="image/x-icon" href="https://www.riccar.com/media/favicon/stores/17/Favicon_500x500.png" /> 29<link rel="shortcut icon" type="image/x-icon" href="https://www.riccar.com/media/favicon/stores/17/Favicon_500x500.png" /> 30<meta name="p:domain_verify" content="8fcdd0a0b5b9e8fc1b8fa28e75a560c8"/> 31 32<!-- Hotjar Tracking Code for https://riccar.com/ -->
33<script>
vendor: 125 bytes, lines 33-36
33 34 (function(h,o,t,j,a,r){ 35 h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)}; 36 h._hjSettings={hjid:
361882948
vendor: 259 bytes, lines 36-41
36,hjsv:6}; 37 a=o.getElementsByTagName('head')[0]; 38 r=o.createElement('script');r.async=1; 39 r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv; 40 a.appendChild(r); 41 })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
42</script>
42 43 44<meta name="google-site-verification" content="rsaMORtFa-d7RhKri2FDIMK9r2eLMf6x50fD0y6tj_8" /> 45 46 47<!-- BEGIN MerchantWidget Code --> 48
49<script id='merchantWidgetScript' 50 51 src="https://www.gstatic.com/shopping/merchant/merchantwidget.js" 52 53 defer> 54 55</script>
55 56
57<script type="text/javascript"> 58 59 merchantWidgetScript.addEventListener('load', function () { 60 61 merchantwidget.start({ 62 63 position: 'LEFT_BOTTOM' 64 65 }); 66 67 }); 68 69</script>
69 70 71<!-- END MerchantWidget Code --> 72 73 74<style> 75.catalog-product-view .pdp-description div[data-content-type="row"]:last-child .pagebuilder-column-group .pagebuilder-column { 76 align-items: center; 77 gap: 16px; 78} 79 80.minicart-old-price { 81 text-decoration:line-through; 82} 83 84#product-key-features .attributes-list__value ul { 85 list-style: disc; 86 margin-left: 40px; 87} 88</style> 89 90<!-- Fix BazaarVoice styles -->
91<script type="text/javascript"> 92 window.addEventListener('load', function () { 93 if (document.getElementById("html-body").classList.contains("catalog-product-view")) { 94 let reviewsTab = document.getElementById("bazaarvoice.reviews.tab"); 95 96 if (reviewsTab.children.length > 1) { 97 reviewsTab.children[1].setAttribute(':class', "isCollapsed ? 'block' : 'hidden'"); 98 } 99 } 100 }); 101</script>
101
102<script src="https://polyfill-fastly.io/v2/polyfill.min.js?features=Promise" crossorigin></script>
102 103 104 105
105<script> 106 "use strict"; 107 const script = document.createElement('script'); 108 script.src = 'https://browser.sentry-cdn.com/7.109.0/bundle.tracing.replay.min.js'; 109 script.async = true; 110 script.crossOrigin = 'anonymous'; 111 script.onload = function () { 112 Sentry.init({ 113 dsn: 'https://81f24570f2e794c597a8a384e9f92eab@o4506385148739584.ingest.us.sentry.io/4506977471561728', 114 release: '0.0.0', 115 environment: 'Production', 116 integrations: [ 117 118 new Sentry.BrowserTracing(), 119 120 new Sentry.Replay({ 121 blockAllMedia: false, 122 maskAllText: false, 123 mask: ['address, .shipping-address-items, .shipping-information__content, .dashboard-content'], 124 }) 125 126 ], 127 128 tracesSampleRate: '0.25', 129 130 replaysSessionSampleRate: '0.1', 131 replaysOnErrorSampleRate: '0.5', 132 133 ignoreErrors: null, 134 }); 135 function sentryErrorInfo(event) { 136 const sectionData = event.detail.data; 137 138 if (sectionData.customer && sectionData.customer.firstname) { 139 Sentry.setUser({ 140 email: sectionData.customer.email 141 }) 142 } 143 } 144 145 window.addEventListener('private-content-loaded', sentryErrorInfo); 146} 147 document.head.appendChild(script);</script>
147<script type="text/javascript" data-routing="commerce=rum" defer="defer" src="https://rum.hlx.page/.rum/@adobe/helix-rum-js@^2/dist/rum-standalone.js"></script>
147 148
149<script type="text/javascript"> 150 tacoData = window.tacoData || []; 151 jsonProducts = window.jsonProducts || {}; 152 prePageLoadEvent = window.prePageLoadEvent || []; 153 if(typeof tacoTrackEvent == 'undefined'){ 154 window.tacoTrackEvent = function(){ 155 }; 156 } 157</script>
vendor: 1 bytes, line 157
157
158<script type="text/javascript">
vendor: 486 bytes, lines 158-171
158(function (w, d, s, l, i) { 159 160 w[l] = w[l] || []; 161 w[l].push({ 162 'gtm.start': 163 new Date().getTime(), event: 'gtm.js' 164 }); 165 var f = d.getElementsByTagName(s)[0], 166 j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; 167 j.async = true; 168 j.src = 169 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; 170 f.parentNode.insertBefore(j, f); 171 })(window, document, 'script', 'tacoData', "
171GTM-M9VGW8K
vendor: 4 bytes, line 171
171");
172</script>
vendor: 1 bytes, line 172
172
173<script src='https://www.dwin1.com/19038.js' defer='defer'></script>
173<script> 174 var BASE_URL = 'https://www.riccar.com/'; 175 var THEME_PATH = 'https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US'; 176 var COOKIE_CONFIG = { 177 "expires": null, 178 "path": "\u002F", 179 "domain": ".www.riccar.com", 180 "secure": true, 181 "lifetime": "2592000", 182 "cookie_restriction_enabled": false }; 183 var CURRENT_STORE_CODE = 'rv_store_view'; 184 var CURRENT_WEBSITE_ID = '17'; 185 186 window.hyva = window.hyva || {} 187 188 window.cookie_consent_groups = window.cookie_consent_groups || {} 189 window.cookie_consent_groups['necessary'] = true; 190 191 window.cookie_consent_config = window.cookie_consent_config || {}; 192 window.cookie_consent_config['necessary'] = [].concat( 193 window.cookie_consent_config['necessary'] || [], 194 [ 195 'user_allowed_save_cookie', 196 'form_key', 197 'mage-messages', 198 'private_content_version', 199 'mage-cache-sessid', 200 'last_visited_store', 201 'section_data_ids' 202 ] 203 ); 204 //# sourceURL=hyva-variables.js 205</script>
vendor: 1 bytes, line 205
205
206<script> 207 (function( hyva, undefined ) { 208 209 function lifetimeToExpires(options, defaults) { 210 211 const lifetime = options.lifetime || defaults.lifetime; 212 213 if (lifetime) { 214 const date = new Date; 215 date.setTime(date.getTime() + lifetime * 1000); 216 return date; 217 } 218 219 return null; 220 } 221 222 function generateRandomString() { 223 224 const allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 225 length = 16; 226 227 let formKey = '', 228 charactersLength = allowedCharacters.length; 229 230 for (let i = 0; i < length; i++) { 231 formKey += allowedCharacters[Math.round(Math.random() * (charactersLength - 1))] 232 } 233 234 return formKey; 235 } 236 237 const sessionCookieMarker = {noLifetime: true} 238 239 const cookieTempStorage = {}; 240 241 const internalCookie = { 242 get(name) { 243 const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)'); 244 return v ? v[2] : null; 245 }, 246 set(name, value, days, skipSetDomain) { 247 let expires, 248 path, 249 domain, 250 secure, 251 samesite; 252 253 const defaultCookieConfig = { 254 expires: null, 255 path: '/', 256 domain: null, 257 secure: false, 258 lifetime: null, 259 samesite: 'lax' 260 }; 261 262 const cookieConfig = window.COOKIE_CONFIG || {}; 263 264 expires = days && days !== sessionCookieMarker 265 ? lifetimeToExpires({lifetime: 24 * 60 * 60 * days, expires: null}, defaultCookieConfig) 266 : lifetimeToExpires(window.COOKIE_CONFIG, defaultCookieConfig) || defaultCookieConfig.expires; 267 268 path = cookieConfig.path || defaultCookieConfig.path; 269 domain = !skipSetDomain && (cookieConfig.domain || defaultCookieConfig.domain); 270 secure = cookieConfig.secure || defaultCookieConfig.secure; 271 samesite = cookieConfig.samesite || defaultCookieConfig.samesite; 272 273 document.cookie = name + "=" + encodeURIComponent(value) + 274 (expires && days !== sessionCookieMarker ? '; expires=' + expires.toGMTString() : '') + 275 (path ? '; path=' + path : '') + 276 (domain ? '; domain=' + domain : '') + 277 (secure ? '; secure' : '') + 278 (samesite ? '; samesite=' + samesite : 'lax'); 279 }, 280 isWebsiteAllowedToSaveCookie() { 281 const allowedCookies = this.get('user_allowed_save_cookie'); 282 if (allowedCookies) { 283 const allowedWebsites = JSON.parse(unescape(allowedCookies)); 284 285 return allowedWebsites[CURRENT_WEBSITE_ID] === 1; 286 } 287 return false; 288 }, 289 getGroupByCookieName(name) { 290 const cookieConsentConfig = window.cookie_consent_config || {}; 291 let group = null; 292 for (let prop in cookieConsentConfig) { 293 if (!cookieConsentConfig.hasOwnProperty(prop)) continue; 294 if (cookieConsentConfig[prop].includes(name)) { 295 group = prop; 296 break; 297 } 298 } 299 return group; 300 }, 301 isCookieAllowed(name) { 302 const cookieGroup = this.getGroupByCookieName(name); 303 return cookieGroup 304 ? window.cookie_consent_groups[cookieGroup] 305 : this.isWebsiteAllowedToSaveCookie(); 306 }, 307 saveTempStorageCookies() { 308 for (const [name, data] of Object.entries(cookieTempStorage)) { 309 if (this.isCookieAllowed(name)) { 310 this.set(name, data['value'], data['days'], data['skipSetDomain']); 311 delete cookieTempStorage[name]; 312 } 313 } 314 } 315 }; 316 317 hyva.getCookie = (name) => { 318 const cookieConfig = window.COOKIE_CONFIG || {}; 319 320 if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) { 321 return cookieTempStorage[name] ? cookieTempStorage[name]['value'] : null; 322 } 323 324 return internalCookie.get(name); 325 } 326 327 hyva.setCookie = (name, value, days, skipSetDomain) => { 328 const cookieConfig = window.COOKIE_CONFIG || {}; 329 330 if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) { 331 cookieTempStorage[name] = {value, days, skipSetDomain}; 332 return; 333 } 334 return internalCookie.set(name, value, days, skipSetDomain); 335 } 336 337 338 hyva.setSessionCookie = (name, value, skipSetDomain) => { 339 return hyva.setCookie(name, value, sessionCookieMarker, skipSetDomain) 340 } 341 342 hyva.getBrowserStorage = () => { 343 const browserStorage = window.localStorage || window.sessionStorage; 344 if (!browserStorage) { 345 console.warn('Browser Storage is unavailable'); 346 return false;
347 } 348 try { 349 browserStorage.setItem('storage_test', '1'); 350 browserStorage.removeItem('storage_test'); 351 } catch (error) { 352 console.warn('Browser Storage is not accessible', error); 353 return false; 354 } 355 return browserStorage; 356 } 357 358 hyva.postForm = (postParams) => { 359 const form = document.createElement("form"); 360 361 let data = postParams.data; 362 363 if (! postParams.skipUenc && ! data.uenc) { 364 data.uenc = btoa(window.location.href); 365 } 366 form.method = "POST"; 367 form.action = postParams.action; 368 369 Object.keys(postParams.data).map(key => { 370 const field = document.createElement("input"); 371 field.type = 'hidden' 372 field.value = postParams.data[key]; 373 field.name = key; 374 form.appendChild(field); 375 }); 376 377 const form_key = document.createElement("input"); 378 form_key.type = 'hidden'; 379 form_key.value = hyva.getFormKey(); 380 form_key.name="form_key"; 381 form.appendChild(form_key); 382 383 document.body.appendChild(form); 384 385 form.submit(); 386 } 387 388 hyva.getFormKey = function () { 389 let formKey = hyva.getCookie('form_key'); 390 391 if (!formKey) { 392 formKey = generateRandomString(); 393 hyva.setCookie('form_key', formKey); 394 } 395 396 return formKey; 397 } 398 399 hyva.formatPrice = (value, showSign, options = {}) => { 400 const groupSeparator = options.groupSeparator; 401 const decimalSeparator = options.decimalSeparator 402 delete options.groupSeparator; 403 delete options.decimalSeparator; 404 const formatter = new Intl.NumberFormat( 405 'en\u002DUS', 406 Object.assign({ 407 style: 'currency', 408 currency: 'USD', 409 signDisplay: showSign ? 'always' : 'auto' 410 }, options) 411 ); 412 return (typeof Intl.NumberFormat.prototype.formatToParts === 'function') ? 413 formatter.formatToParts(value).map(({type, value}) => { 414 switch (type) { 415 case 'currency': 416 return '\u0024' || value; 417 case 'minusSign': 418 return '- '; 419 case 'plusSign': 420 return '+ '; 421 case 'group': 422 return groupSeparator !== undefined ? groupSeparator : value; 423 case 'decimal': 424 return decimalSeparator !== undefined ? decimalSeparator : value; 425 default : 426 return value; 427 } 428 }).reduce((string, part) => string + part) : 429 formatter.format(value); 430 } 431 432 const formatStr = function (str, nStart) { 433 const args = Array.from(arguments).slice(2); 434 435 return str.replace(/(%+)([0-9]+)/g, (m, p, n) => { 436 const idx = parseInt(n) - nStart; 437 438 if (args[idx] === null || args[idx] === void 0) { 439 return m; 440 } 441 return p.length % 2 442 ? p.slice(0, -1).replace('%%', '%') + args[idx] 443 : p.replace('%%', '%') + n; 444 }) 445 } 446 447 hyva.str = function (string) { 448 const args = Array.from(arguments); 449 args.splice(1, 0, 1); 450 451 return formatStr.apply(undefined, args); 452 } 453 454 hyva.strf = function () { 455 const args = Array.from(arguments); 456 args.splice(1, 0, 0); 457 458 return formatStr.apply(undefined, args); 459 } 460 461 /** 462 * Take a html string as `content` parameter and 463 * extract an element from the DOM to replace in 464 * the current page under the same selector, 465 * defined by `targetSelector` 466 */ 467 hyva.replaceDomElement = (targetSelector, content) => { 468 // Parse the content and extract the DOM node using the `targetSelector` 469 const parser = new DOMParser(); 470 const doc = parser.parseFromString(content, 'text/html');
471 const contentNode = doc.querySelector(targetSelector); 472 473 // Bail if content or target can't be found 474 if (!contentNode || !document.querySelector(targetSelector)) { 475 return; 476 } 477 478 hyva.activateScripts(contentNode); 479 480 // Replace the old DOM node with the new content 481 document.querySelector(targetSelector).replaceWith(contentNode); 482 483 // Reload customerSectionData and display cookie-messages if present 484 window.dispatchEvent(new CustomEvent("reload-customer-section-data")); 485 hyva.initMessages(); 486 } 487 488 hyva.removeScripts = (contentNode) => { 489 const scripts = contentNode.getElementsByTagName('script'); 490 for (let i = 0; i < scripts.length; i++) { 491 scripts[i].parentNode.removeChild(scripts[i]); 492 } 493 const templates = contentNode.getElementsByTagName('template'); 494 for (let i = 0; i < templates.length; i++) { 495 const container = document.createElement('div'); 496 container.innerHTML = templates[i].innerHTML; 497 hyva.removeScripts(container); 498 templates[i].innerHTML = container.innerHTML; 499 } 500 } 501 502 hyva.activateScripts = (contentNode) => { 503 // Create new array from HTMLCollection to avoid mutation of collection while manipulating the DOM. 504 const scripts = Array.from(contentNode.getElementsByTagName('script')); 505 506 // Iterate over all script tags to duplicate+inject each into the head 507 for (const original of scripts) { 508 const script = document.createElement('script'); 509 original.type && (script.type = original.type); 510 script.innerHTML = original.innerHTML; 511 512 // Remove the original (non-executing) script from the contentNode 513 original.parentNode.removeChild(original) 514 515 // Add script to head 516 document.head.appendChild(script); 517 } 518 519 return contentNode; 520 } 521 522 const replace = {['+']: '-', ['/']: '_', ['=']: ','}; 523 hyva.getUenc = () => btoa(window.location.href).replace(/[+/=]/g, match => replace[match]); 524 525 let currentTrap; 526 527 const focusableElements = (rootElement) => { 528 const selector = 'button, [href], input, select, textarea, details, [tabindex]:not([tabindex="-1"]'; 529 return Array.from(rootElement.querySelectorAll(selector)) 530 .filter(el => { 531 return el.style.display !== 'none' 532 && !el.disabled 533 && el.tabIndex !== -1 534 && (el.offsetWidth || el.offsetHeight || el.getClientRects().length) 535 }) 536 } 537 538 const focusTrap = (e) => { 539 const isTabPressed = e.key === 'Tab' || e.keyCode === 9; 540 if (!isTabPressed) return; 541 542 const focusable = focusableElements(currentTrap) 543 const firstFocusableElement = focusable[0] 544 const lastFocusableElement = focusable[focusable.length - 1] 545 546 e.shiftKey 547 ? document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), e.preventDefault()) 548 : document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), e.preventDefault()) 549 }; 550 551 hyva.releaseFocus = (rootElement) => { 552 if (currentTrap && (!rootElement || rootElement === currentTrap)) { 553 currentTrap.removeEventListener('keydown', focusTrap) 554 currentTrap = null 555 } 556 } 557 hyva.trapFocus = (rootElement) => { 558 if (!rootElement) return; 559 hyva.releaseFocus() 560 currentTrap = rootElement 561 rootElement.addEventListener('keydown', focusTrap) 562 const firstElement = focusableElements(rootElement)[0] 563 firstElement && firstElement.focus() 564 } 565 566 hyva.safeParseNumber = (rawValue) => { 567 const number = rawValue ? parseFloat(rawValue) : null; 568 569 return Array.isArray(number) || isNaN(number) ? rawValue : number; 570 } 571 572 const toCamelCase = s => s.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(''); 573 hyva.createBooleanObject = (name, value = false, additionalMethods = {}) => { 574 575 const camelCase = toCamelCase(name);
576 const key = '__hyva_bool_' + name 577 578 return new Proxy(Object.assign( 579 additionalMethods, 580 { 581 [key]: !!value, 582 [name]() {return !!this[key]}, 583 ['!' + name]() {return !this[key]}, // @deprecated This does not work with non-CSP Alpine 584 ['not' + camelCase]() {return !this[key]}, 585 ['toggle' + camelCase]() {this[key] = !this[key]}, 586 [`set${camelCase}True`]() {this[key] = true}, 587 [`set${camelCase}False`]() {this[key] = false}, 588 } 589 ), { 590 set(target, prop, value) { 591 return prop === name 592 ? (target[key] = !!value) 593 : Reflect.set(...arguments); 594 } 595 }) 596 } 597 598 hyva.alpineInitialized = (fn) => window.addEventListener('alpine:initialized', fn, {once: true}) 599 window.addEventListener('alpine:init', () => Alpine.data('{}', () => ({})), {once: true}); 600 window.addEventListener('user-allowed-save-cookie', () => internalCookie.saveTempStorageCookies()) 601 602 }( window.hyva = window.hyva || {} )); 603 //# sourceURL=hyva.js 604</script>
vendor: 1 bytes, line 604
604
605<script type="speculationrules"> 606{ 607 "tag": "Hyva Theme", 608 "prefetch": [{ 609 "source": "document", 610 "where": { 611 "and": [ 612 { "href_matches": "/*" }, 613 { "not": { 614 "href_matches": ["/customer/*","/search/*","/sales/*","/wishlist/*","/checkout/*","/paypal/*","/newsletter/*","/stores/store/redirect/*"] }}, 615 { "not": { 616 "selector_matches": [".no-preload", ".do-not-prerender", "[download]", "[rel~=nofollow]", "[target]"] 617 }} 618 ] 619 }, 620 "eagerness": "moderate" 621 }] 622} 623</script>
623 624 625
626<script> 627 (function () { 628 let amSwiperProcessed = false; 629 630 window.addEventListener('load-amswiper', () => { 631 if (amSwiperProcessed) { 632 window?.Swiper && window.dispatchEvent(new CustomEvent('amswiper-loaded', {})); 633 return; 634 } 635 636 const script = document.createElement('script'); 637 script.src = 'https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Amasty_LibSwiperJs/js/vendor/swiper/swiper.min.js'; 638 script.async = true; 639 document.body.appendChild(script); 640 641 amSwiperProcessed = true; 642 643 script.onload = () => { 644 window.dispatchEvent(new CustomEvent('amswiper-loaded', {})); 645 } 646 647 const stylesHref = 'https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Amasty_LibSwiperJs/vendor/swiper/swiper.min.css'; 648 649 if (document.querySelector(`link[href="${stylesHref}"]`)) { 650 return; 651 } 652 653 const styles = document.createElement('link'); 654 styles.rel = 'stylesheet'; 655 styles.type = 'text/css'; 656 styles.href = stylesHref; 657 658 document.head.appendChild(styles); 659 }); 660 }()); 661</script>
661 662
663<script> 664 window.addEventListener('load', function () { 665 window.magentoStorefrontEvents = magentoStorefrontEvents; 666 magentoStorefrontEvents.context.setStorefrontInstance( 667 {"storeUrl":"https:\/\/www.riccar.com\/","websiteId":17,"websiteCode":"rv","storeId":17,"storeCode":"rv_store","storeViewId":17,"storeViewCode":"rv_store_view","websiteName":"Riccar Vacuums","storeName":"Riccar Vacuums Store","storeViewName":"Riccar Vacuums Store View","baseCurrencyCode":"USD","storeViewCurrencyCode":"USD","catalogExtensionVersion":"103.4.25","environmentId":"180b553f-20dd-47e9-914e-ceca7d950e45","environment":"Production","storefrontTemplate":"Hyva"} ); 668 magentoStorefrontEvents.context.setMagentoExtension({ 669 magentoExtensionVersion: "8.0.1", 670 }); 671 magentoStorefrontEvents.context.setDataServicesExtension({ 672 version: "8.0.1", 673 }); 674 magentoStorefrontEvents.context.setPage({ 675 pageType: "Default" 676 }); 677 magentoStorefrontEvents.context.setContext("pageExtended", { 678 action: "page-view" 679 }); 680 681 let shopperId = "guest"; 682 magentoStorefrontEvents.context.setShopper({ shopperId: shopperId }); 683 684 685 magentoStorefrontEvents.publish.pageView(); 686 }); 687 688 function getCustomerIdFromDataServices() { 689 let customerId = hyva.getCookie("dataservices_customer_id"); 690 return customerId ? decodeURI(customerId).replace(/[^\w\s]/gi, "") : null; 691 } 692 693 function getCustomerGroupFromDataServices() { 694 try { 695 const decodedString = decodeURIComponent(hyva.getCookie("dataservices_customer_group")); 696 return decodedString ? JSON.parse(decodedString) : null; 697 } catch (error) { 698 console.error("Failed to parse customer group data:", error); 699 return null; 700 } 701 } 702</script>
702 703</head> 704<body class="pl-thm-snowdog pl-thm-snowdog-riccar amblog-index-post page-layout-2columns-left" id="html-body"> 705 706 707 708 <!--suppress HtmlUnknownTarget --> 709 <!-- BV | Magento Extension 9.1.8 --> 710
710<script async type="text/javascript" src="//apps.bazaarvoice.com/deployments/riccar/main_site/production/en_US/bv.js"></script>
710 711<input name="form_key" type="hidden" value="p2wmkuQgiVuquLwx" /> 712 <noscript> 713 <section class="message global noscript border-b-2 border-blue-500 bg-blue-50 shadow-none m-0 px-0 rounded-none font-normal"> 714 <div class="container text-center"> 715 <p> 716 <strong>JavaScript seems to be disabled in your browser.</strong> 717 <span> 718 For the best experience on our site, be sure to turn on Javascript in your browser. </span> 719 </p> 720 </div> 721 </section> 722 </noscript> 723 724
725<script> 726 document.body.addEventListener('touchstart', () => {}, {passive: true}) 727</script>
727 728<div class="widget block block-static-block"> 729 </div> 730 <!-- GOOGLE TAG MANAGER -->
vendor: 81 bytes, lines 730-732
730 731 <noscript> 732 <iframe src="https://www.googletagmanager.com/ns.html?id=
732GTM-M9VGW8K
vendor: 108 bytes, lines 732-735
732" 733 height="0" width="0" style="display:none;visibility:hidden"></iframe> 734 </noscript> 735
735<!-- END GOOGLE TAG MANAGER -->
736<script> 737 'use strict'; 738 739 (() => { 740 window.addEventListener( 741 'ga-initialized', 742 () => { 743 window.addEventListener('cart-item-added', (event) => { 744 let products = []; 745 746 event.detail.forEach((item) => { 747 products.push({ 748 id: item['product_sku'], 749 name: item['product_name'], 750 price: item['product_price_value'], 751 quantity: item['qty'], 752 }); 753 }); 754 755 dataLayer.push({ 756 event: 'addToCart', 757 ecommerce: { 758 currencyCode: 'USD', 759 add: { 760 products: products, 761 }, 762 }, 763 }); 764 }); 765 }, 766 { once: true } 767 ); 768 })(); 769</script>
vendor: 1 bytes, line 769
769
770<script> 771 'use strict'; 772 773 (() => { 774 window.addEventListener( 775 'ga-initialized', 776 () => { 777 window.addEventListener('cart-item-removed', (event) => { 778 let products = []; 779 780 event.detail.forEach((item) => { 781 products.push({ 782 id: item['product_sku'], 783 name: item['product_name'], 784 price: item['product_price_value'], 785 quantity: item['qty'], 786 }); 787 }); 788 789 dataLayer.push({ 790 event: 'removeFromCart', 791 ecommerce: { 792 currencyCode: 'USD', 793 remove: { 794 products: products, 795 }, 796 }, 797 }); 798 }); 799 }, 800 { once: true } 801 ); 802 })(); 803</script>
vendor: 1 bytes, line 803
803
804<script> 805 'use strict'; 806 807 (() => { 808 window.addEventListener( 809 'ga-initialized', 810 () => { 811 const banners = document.querySelectorAll('\u005Bdata\u002Dbanner\u002Did\u005D'); 812 let promotions = []; 813 814 banners.forEach((banner) => { 815 banner.addEventListener('click', () => { 816 window.dataLayer.push({ 817 event: 'promotionClick', 818 ecommerce: { 819 promoClick: { 820 promotions: [{ 821 id: banner.dataset.bannerId, 822 name: banner.dataset.bannerName, 823 creative: '', 824 position: 'amblog_index_post', 825 }], 826 }, 827 }, 828 }); 829 }); 830 831 promotions.push({ 832 id: banner.dataset.bannerId, 833 name: banner.dataset.bannerName, 834 creative: '', 835 position: 'amblog_index_post', 836 }); 837 }); 838 839 if (promotions.length) { 840 window.dataLayer.push({ 841 event: 'promotionView', 842 ecommerce: { 843 promoView: { 844 promotions: promotions, 845 }, 846 }, 847 }); 848 } 849 }, 850 { once: true } 851 ); 852 })(); 853</script>
853 854<div class="page-wrapper"><header class="page-header"><a class="action skip sr-only focus:not-sr-only focus:absolute focus:z-40 focus:bg-white 855 contentarea" 856 href="#contentarea"> 857 <span> 858 Skip to Content </span> 859</a>
860<script type="application/javascript" async 861 src="https://static.klaviyo.com/onsite/js/klaviyo.js?company_id=SFYXXU"></script>
861 862<div x-data="initKlaviyoCustomerTracking()" 863 @private-content-loaded.window="sendCustomerDataToKlaviyo(event.detail.data)"></div> 864
864<script> 865 function initKlaviyoCustomerTracking() { 866 return { 867 sendCustomerDataToKlaviyo(data) { 868 const _learnq = window._learnq || []; 869 const customer = data.customer; 870 871 if (customer && customer.email) { 872 _learnq.push(['identify', { 873 $email: customer.email, 874 $first_name: customer.firstname ? customer.firstname : '', 875 $last_name: customer.lastname ? customer.lastname : '' 876 }]); 877 } 878 } 879 } 880 } 881 </script>
vendor: 1 bytes, line 881
881
882<script> 883 function initHeader () { 884 return { 885 searchOpen: false, 886 cart: {}, 887 isCartOpen: false, 888 getData(data) { 889 if (data.cart) { this.cart = data.cart } 890 }, 891 isCartEmpty() { 892 return !this.cart.summary_count 893 }, 894 toggleCart(event) { 895 if (event.detail && event.detail.isOpen !== undefined) { 896 this.isCartOpen = event.detail.isOpen 897 if (!this.isCartOpen && this.$refs && this.$refs.cartButton) { 898 this.$refs.cartButton.focus() 899 } 900 } else { 901 this.isCartOpen = true 902 } 903 } 904 } 905 } 906 function initCompareHeader() { 907 return { 908 compareProducts: null, 909 itemCount: 0, 910 receiveCompareData(data) { 911 if (data['compare-products']) { 912 this.compareProducts = data['compare-products']; 913 this.itemCount = this.compareProducts.count; 914 } 915 } 916 } 917 } 918</script>
918 919<div 920 id="header" 921 class="relative z-30 w-full bg-container-lighter border-container-lighter shadow-md" 922 x-data="initHeader()" 923 @private-content-loaded.window="getData(event.detail.data)" 924> 925 926<div class="hidden bg-black sm:block"> 927 <div class="container py-2.5 flex text-white justify-end text-base"> 928 <a class="" href="/where-to-buy"> 929 Find a Retailer </a> 930 <div class="ml-9"> 931 932<div> 933 <a onclick="hyva.setCookie && hyva.setCookie( 934 'login_redirect', 935 window.location.href, 936 1 937 )" 938 href="https://www.riccar.com/customer/account/index/"> 939 Login / 940 Register </a> 941 </div> 942 </div> 943 <a class="ml-9" href="/contact-form"> 944 Contact Us </a> 945 </div> 946</div> 947 948 <div 949 class=" 950 container flex items-center justify-between w-full px-6 py-2 mx-auto mt-0 951 sm:justify-start sm:py-5 952 " 953 > 954 <!--Mobile Navigation--> 955 956 957 <nav 958 x-data="initMenuMobile_6ab60e46966fd()" 959 class="flex z-20 p-3 navigation sm:mr-4 lg:hidden" 960 aria-label="Site navigation" 961 role="navigation" 962 > 963 <!-- mobile --> 964 <button 965 x-ref="open-menu-button" 966 @click="openMenu()" 967 class="flex items-center justify-center" 968 type="button" 969 aria-label="Open menu" 970 aria-haspopup="menu" 971 :aria-expanded="open" 972 :hidden="open" 973 title="Open menu" 974 > 975 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 25 24" fill="currentColor" class="w-6 h-6 stroke-[0.5]" aria-hidden="true"><path fill-rule="evenodd" d="M3.271 4.5h18V6h-18V4.5Zm0 13.5h18v1.5h-18V18Zm18-9h-18v1.5h18V9Zm-18 4.5h18V15h-18v-1.5Z" clip-rule="evenodd" stroke="currentColor"/></svg> 976 977 </button> 978 <div 979 class="backdrop" 980 x-show="open" 981 x-transition:enter="ease-in-out duration-500" 982 x-transition:enter-start="opacity-0" 983 x-transition:enter-end="opacity-100" 984 x-transition:leave="ease-in-out duration-500" 985 x-transition:leave-start="opacity-100" 986 x-transition:leave-end="opacity-0" 987 @click="closeMenu" 988 x-cloak 989 ></div> 990 991 <div 992 class=" 993 fixed hidden top-0 left-0 right-0 h-full 994 duration-150 ease-in-out transform transition-display 995 z-30 overflow-y-auto overflow-x-hidden bg-white 996 " 997 x-cloak 998 x-ref="menu-dialog" 999 :class="{ 'hidden' : !open }" 1000 :aria-hidden="open ? 'false' : 'true'" 1001 role="dialog" 1002 aria-modal="true" 1003 > 1004 <div class="relative flex flex-col flex-1 mt-4 mx-6"> 1005 1006 <div class="sm:hidden order-2"> 1007 <span class="block text-lg font-Gotham font-medium mb-2 px-4 pb-2"> 1008 Search: 1009 </span> 1010
1010<script> 1011 'use strict'; 1012 1013 function initMiniSearch() { 1014 return { 1015 minSearchLength: 3, 1016 suggestions: [], 1017 suggest() { 1018 const search = this.$refs.searchInput; 1019 if (search.value.length >= this.minSearchLength) { 1020 search.setCustomValidity(''); 1021 search.reportValidity(); 1022 this.fetchSuggestions(search.value); 1023 } else { 1024 this.suggestions = []; 1025 } 1026 }, 1027 fetchSuggestions(term) { 1028 fetch( 1029 window.BASE_URL + 'search/ajax/suggest?' + new URLSearchParams({q: term}), 1030 { 1031 headers: { 1032 'X-Requested-With': 'XMLHttpRequest' 1033 } 1034 } 1035 ) 1036 .then(response => response.json()) 1037 .then(result => this.suggestions = result); 1038 }, 1039 search(term) { 1040 const search = this.$refs.searchInput; 1041 term = term || search.value; 1042 if (term.length < this.minSearchLength) { 1043 search.setCustomValidity('Minimum\u0020Search\u0020query\u0020length\u0020is\u00203'); 1044 search.reportValidity(); 1045 } else { 1046 search.setCustomValidity(''); 1047 search.value = term; 1048 this.$refs.form.submit(); 1049 } 1050 }, 1051 focusElement(element) { 1052 if (element && element.nodeName === "DIV") { 1053 element.focus(); 1054 return true; 1055 } else { 1056 return false; 1057 } 1058 } 1059 } 1060 } 1061</script>
1061 1062<div class="container py-2 mx-auto text-black" x-data="initMiniSearch()"> 1063 <form 1064 class="form minisearch relative" 1065 id="search_mini_form" 1066 x-ref="form" 1067 @submit.prevent="search()" 1068 action="https://www.riccar.com/catalogsearch/result/" 1069 method="get" 1070 role="search" 1071 > 1072 <label 1073 class="hidden" 1074 for="search" 1075 data-role="minisearch-label" 1076 > 1077 <span> 1078 Search </span> 1079 </label> 1080 <input 1081 id="search" 1082 x-ref="searchInput" 1083 type="search" 1084 autocomplete="off" 1085 name="q" 1086 value="" 1087 placeholder="Search entire store here..." 1088 maxlength="128" 1089 class=" 1090 w-full p-2 text-lg leading-normal transition appearance-none text-grey-800 1091 focus:outline-none focus:border-transparent lg:text-xl 1092 " 1093 @focus.once="suggest" 1094 @input.debounce.300="suggest" 1095 @keydown.arrow-down.prevent="focusElement($root.querySelector('[tabindex]'))" 1096 @search-open.window.debounce.10=" 1097 $el.focus() 1098 $el.select() 1099 " 1100 /> 1101 <template x-if="suggestions.length > 0"> 1102 <div 1103 class=" 1104 w-full leading-normal transition appearance-none text-grey-800 flex flex-col mt-1 1105 absolute bg-white z-30 md:static 1106 " 1107 > 1108 <template x-for="(suggestion, index) in suggestions"> 1109 <div 1110 class=" 1111 flex justify-between p-2 bg-container-lighter mb-1 cursor-pointer 1112 border border-container hover:bg-container" 1113 :class="(index + 1) === suggestions.length ? 'mobileLastItem' : ''" 1114 tabindex="0" 1115 @click="search(suggestion.title)" 1116 @keydown.enter="search(suggestion.title)" 1117 @keydown.escape="suggestions = []" 1118 @keydown.arrow-up.prevent=" 1119 focusElement($event.target.previousElementSibling) || $refs.searchInput.focus() 1120 " 1121 @keydown.arrow-down.prevent="focusElement($event.target.nextElementSibling)" 1122 @keydown.tab="(index + 1) === suggestions.length && !$event.shiftKey ? $refs.searchInput.focus() : ''" 1123 > 1124 <span x-text="suggestion.title"></span> 1125 <span x-text="suggestion.num_results"></span> 1126 </div> 1127 </template> 1128 </div> 1129 </template> 1130 <button 1131 type="submit" 1132 title="Search" 1133 class="action search sr-only" 1134 aria-label="Search" 1135 > 1136 Search </button> 1137 </form> 1138</div> 1139 </div> 1140 1141 <ul 1142 x-ref="mobileMenuNavLinks" 1143 class="mobileMenuNavLinks flex flex-col order-4" 1144 aria-label="Site navigation links" 1145 > 1146 <li 1147 x-data="{'node767': false }" 1148 class=" 1149 " 1150 > 1151 <button 1152 class=" 1153 flex items-center justify-between w-full p-4 my-2 1154 text-primary font-medium font-Gotham leading-4 1155 " 1156 @click="toggleSubmenu('node767')" 1157 aria-label="Toggle submenu for Vacuums" 1158 :aria-expanded="node767 === true" 1159 type="button" 1160 >
1161 <span> 1162 Vacuums </span> 1163 <div class="transition-transform" 1164 :class="{'rotate-180' : node767 === true}" 1165 > 1166 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-gray-500" width="20" height="20" aria-hidden="true"> 1167 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 1168</svg> 1169 </div> 1170 </button> 1171 <ul 1172 x-ref="submenu-node767" 1173 class="pb-2 pl-4" 1174 x-show="node767" 1175 :aria-hidden="node767 === false ? 'true' : 'false'" 1176 title="Vacuums" 1177 > 1178 <li 1179 class=" 1180 flex items-center w-full cursor-pointer 1181 text-primary text-sm font-Gotham leading-4 px-4 py-3 1182 " 1183 > 1184 1185 <!-- view all --> 1186 <a 1187 href="https://www.riccar.com/vacuum-cleaners" 1188 title="View All" 1189 class="font-medium" 1190 > 1191 View All </a> 1192 </li> 1193 <li 1194 class=" 1195 " 1196 x-data="{ 'node770': false }" 1197 > 1198 <div class="group"> 1199 1200 <div class="relative"> 1201 <!-- toggle --> 1202 <a 1203 class=" 1204 flex items-center w-full cursor-pointer 1205 level-1 text-primary text-sm font-Gotham leading-4 px-4 py-3 1206 " 1207 href="https://www.riccar.com/vacuum-cleaners/stick-vacuums-handheld-vacuums" 1208 title="Handheld Vacuums" 1209 > 1210 Handheld Vacuums </a> 1211 </div> 1212 </div> 1213 </li> 1214 1215 <li 1216 class=" 1217 " 1218 x-data="{ 'node773': false }" 1219 > 1220 <div class="group"> 1221 1222 <div class="relative"> 1223 <!-- toggle --> 1224 <a 1225 class=" 1226 flex items-center w-full cursor-pointer 1227 level-1 text-primary text-sm font-Gotham leading-4 px-4 py-3 1228 " 1229 href="https://www.riccar.com/vacuum-cleaners/upright-vacuums" 1230 title="Upright Vacuums" 1231 > 1232 Upright Vacuums </a> 1233 </div> 1234 </div> 1235 </li> 1236 1237 <li 1238 class=" 1239 " 1240 x-data="{ 'node776': false }" 1241 > 1242 <div class="group"> 1243 1244 <div class="relative"> 1245 <!-- toggle --> 1246 <a 1247 class=" 1248 flex items-center w-full cursor-pointer 1249 level-1 text-primary text-sm font-Gotham leading-4 px-4 py-3 1250 " 1251 href="https://www.riccar.com/vacuum-cleaners/canister-vacuums" 1252 title="Bagged Canister Vacuums" 1253 > 1254 Bagged Canister Vacuums </a> 1255 </div> 1256 </div> 1257 </li> 1258 1259 <li 1260 class=" 1261 " 1262 x-data="{ 'node779': false }" 1263 > 1264 <div class="group"> 1265 1266 <div class="relative"> 1267 <!-- toggle --> 1268 <a 1269 class=" 1270 flex items-center w-full cursor-pointer 1271 level-1 text-primary text-sm font-Gotham leading-4 px-4 py-3 1272 " 1273 href="https://www.riccar.com/vacuum-cleaners/central-vacuums" 1274 title="Central Vacuums" 1275 > 1276 Central Vacuums </a> 1277 </div> 1278 </div> 1279 </li> 1280 1281 </ul> 1282 1283 </li> 1284 <li 1285 x-data="{'node782': false }" 1286 class=" 1287 " 1288 > 1289 <button 1290 class=" 1291 flex items-center justify-between w-full p-4 my-2 1292 text-primary font-medium font-Gotham leading-4 1293 " 1294 @click="toggleSubmenu('node782')" 1295 aria-label="Toggle submenu for Parts & Accessories" 1296 :aria-expanded="node782 === true" 1297 type="button" 1298 >
1299 <span> 1300 Parts & Accessories </span> 1301 <div class="transition-transform" 1302 :class="{'rotate-180' : node782 === true}" 1303 > 1304 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-gray-500" width="20" height="20" aria-hidden="true"> 1305 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 1306</svg> 1307 </div> 1308 </button> 1309 <ul 1310 x-ref="submenu-node782" 1311 class="pb-2 pl-4" 1312 x-show="node782" 1313 :aria-hidden="node782 === false ? 'true' : 'false'" 1314 title="Parts & Accessories" 1315 > 1316 <li 1317 class=" 1318 flex items-center w-full cursor-pointer 1319 text-primary text-sm font-Gotham leading-4 px-4 py-3 1320 " 1321 > 1322 1323 <!-- view all --> 1324 <a 1325 href="https://www.riccar.com/tools-accessories" 1326 title="View All" 1327 class="font-medium" 1328 > 1329 View All </a> 1330 </li> 1331 <li 1332 class=" 1333 " 1334 x-data="{ 'node785': false }" 1335 > 1336 <div class="group"> 1337 1338 <div class="relative"> 1339 <!-- toggle --> 1340 <a 1341 class=" 1342 flex items-center w-full cursor-pointer 1343 level-1 text-primary text-sm font-Gotham leading-4 px-4 py-3 1344 " 1345 href="https://www.riccar.com/tools-accessories/central-vacuum-accessories" 1346 title="Central Vacuum Accessories" 1347 > 1348 Central Vacuum Accessories </a> 1349 </div> 1350 </div> 1351 </li> 1352 1353 <li 1354 class=" 1355 " 1356 x-data="{ 'node788': false }" 1357 > 1358 <div class="group"> 1359 1360 <div class="relative"> 1361 <!-- toggle --> 1362 <a 1363 class=" 1364 flex items-center w-full cursor-pointer 1365 level-1 text-primary text-sm font-Gotham leading-4 px-4 py-3 1366 " 1367 href="https://www.riccar.com/tools-accessories/vacuum-tools-attachments" 1368 title="Vacuum Tools & Attachments" 1369 > 1370 Vacuum Tools & Attachments </a> 1371 </div> 1372 </div> 1373 </li> 1374 1375 <li 1376 class=" 1377 " 1378 x-data="{ 'node791': false }" 1379 > 1380 <div class="group"> 1381 1382 <div class="relative"> 1383 <!-- toggle --> 1384 <a 1385 class=" 1386 flex items-center w-full cursor-pointer 1387 level-1 text-primary text-sm font-Gotham leading-4 px-4 py-3 1388 " 1389 href="https://www.riccar.com/tools-accessories/carpet-care-cleaning-supplies-floor-pads" 1390 title="Floor Cleaning Pads" 1391 > 1392 Floor Cleaning Pads </a> 1393 </div> 1394 </div> 1395 </li> 1396 1397 </ul> 1398 1399 </li> 1400 <li 1401 x-data="{'node794': false }" 1402 class=" 1403 " 1404 > 1405 <div class="group"> 1406 1407<a 1408 href="https://www.riccar.com/support" 1409 class=" 1410 flex items-center w-full cursor-pointer my-2 1411 text-primary font-medium font-Gotham leading-4 p-4 1412 __link " 1413 data-menu="menu-794"> 1414 Support</a> 1415 </div> 1416 </li> 1417 <li 1418 x-data="{'node797': false }" 1419 class=" 1420 " 1421 > 1422 <div class="group"> 1423 1424<a 1425 href="https://www.riccar.com/about-us" 1426 class=" 1427 flex items-center w-full cursor-pointer my-2 1428 text-primary font-medium font-Gotham leading-4 p-4 1429 __link " 1430 data-menu="menu-797"> 1431 Why Riccar?</a> 1432 </div> 1433 </li> 1434 </ul> 1435 <div class="sm:hidden order-5"> 1436 1437<div> 1438 <ul> 1439 <li 1440 class=" 1441 flex items-center w-full cursor-pointer 1442 text-primary font-medium font-Gotham leading-4 p-4 my-2 1443 __link 1444 " 1445 > 1446 <a 1447 onclick="hyva.setCookie && hyva.setCookie( 1448 'login_redirect', 1449 window.location.href, 1450 1 1451 ) 1452 " 1453 href="https://www.riccar.com/customer/account/index/" 1454 > 1455 Login </a> 1456 </li> 1457 <li 1458 class=" 1459 flex items-center w-full cursor-pointer 1460 text-primary font-medium font-Gotham leading-4 p-4 my-2 1461 __link 1462 " 1463 > 1464 <a 1465 href="https://www.riccar.com/customer/account/create/" 1466 > 1467 Register </a> 1468 </li> 1469 </ul> 1470 </div> 1471 </div> 1472 1473 <div class="separator-block separator-block--small my-6 order-3 sm:hidden"></div> 1474 1475 <div class="flex justify-end px-3 order-1"> 1476 <button 1477 @click="closeMenu" 1478 class="flex justify-center items-center w-16 h-16" 1479 aria-label="Close menu" 1480 type="button" 1481 > 1482 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true"> 1483 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/> 1484</svg> 1485 </button> 1486 </div> 1487 1488 </div> 1489 </div> 1490 </nav> 1491 1492
1492<script> 1493 'use strict'; 1494 1495 const initMenuMobile_6ab60e46966fd = () => ({ 1496 open: false, 1497 openMenu(event) { 1498 this.open = true 1499 this.$nextTick(() => hyva.trapFocus(this.$refs['menu-dialog'])) 1500 // Prevent from body scrolling while mobile menu opened 1501 document.body.classList.add('fixed', 'w-full') 1502 }, 1503 closeMenu(event) { 1504 event.stopPropagation() 1505 document.body.classList.remove('fixed', 'w-full') 1506 this.open = false 1507 this.$nextTick(() => this.$refs['open-menu-button'].focus() || hyva.releaseFocus()) 1508 }, 1509 toggleSubmenu(index) { 1510 this[index] = !this[index] 1511 1512 if (this[index]) { 1513 const focusableElements = 'button:not([disabled]), a[href]:not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])' 1514 this.$nextTick(() => { 1515 this.$refs['submenu-' + index]?.querySelector(focusableElements)?.focus() 1516 }) 1517 } 1518 }, 1519 }) 1520 </script>
1520 1521 1522 <!--Logo--> 1523 <div class=""> 1524 <a 1525 class="flex items-center justify-center max-w-[150px]" 1526 href="https://www.riccar.com/" 1527 aria-label="Go to Home page" 1528 > 1529 <img 1530 src="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/images/logo.svg" 1531 alt="Store logo" 1532 width="189" height="64" /> 1533 </a> 1534</div> 1535 1536 <!--Main Navigation--> 1537 1538<div 1539 x-data="initMenuDesktop_6ab60e469e529()" 1540 x-ref="nav-desktop" 1541 class="navigation navigation-desktop hidden lg:flex" 1542> 1543 <nav 1544 class="snowdog-topmenu-desktop flex" 1545 aria-label="Main menu" 1546 > 1547 <ul class="flex justify-start px-4 font-Gotham"> 1548 1549 <li 1550 @mouseenter="hoverPanelActiveId = '845'" 1551 @mouseleave="hoverPanelActiveId = 0" 1552 @keyup.escape="hoverPanelActiveId = 0" 1553 @blur="closeMenuOnBlur" 1554 class="text-sm flex font-medium uppercase p-2.5 2xl:px-4.5 2xl:text-base" 1555 > 1556 1557<a 1558 href="https://www.riccar.com/vacuum-cleaners" 1559 class="__link" 1560 data-menu="menu-845" @focus="hoverPanelActiveId = 0"> 1561 Vacuums</a> 1562 <button 1563 class="flex justify-center items-center ml-1" 1564 @click="openMenuOnClick('845')" 1565 :aria-expanded="hoverPanelActiveId === '845'" 1566 > 1567 <span class="sr-only"> 1568 Toggle Vacuums submenu </span> 1569 <span> 1570 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-gray-500" width="20" height="20" aria-hidden="true"> 1571 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 1572</svg> 1573 </span> 1574 </button> 1575 <div class="desktop-sub-menu-845"> 1576 <div 1577 class=" 1578 absolute left-0 top-[calc(100%_-_24px)] w-full z-20 hidden bg-white 1579 py-4 shadow-md 1580 " 1581 :class="{ 1582 'hidden' : hoverPanelActiveId !== '845', 1583 'flex' : hoverPanelActiveId === '845', 1584 }" 1585 > 1586 <div class="mt-2 w-full pb-6 pt-2"> 1587 <div class="container grid grid-cols-2 lg:px-6"> 1588 <ul class="flex flex-col"> 1589 <li class="flex py-2"> 1590 1591<a 1592 href="https://www.riccar.com/vacuum-cleaners/upright-vacuums" 1593 class="__inner-link" 1594 data-menu="menu-851"> 1595 Upright Vacuums</a> 1596 </li> 1597 <li class="flex py-2"> 1598 1599<a 1600 href="https://www.riccar.com/vacuum-cleaners/cordless-vacuums" 1601 class="__inner-link" 1602 data-menu="menu-896"> 1603 Cordless Vacuums</a> 1604 </li> 1605 <li class="flex py-2"> 1606 1607<a 1608 href="https://www.riccar.com/vacuum-cleaners/stick-vacuums-handheld-vacuums" 1609 class="__inner-link" 1610 data-menu="menu-848"> 1611 Stick & Handheld Vacuums</a> 1612 </li> 1613 <li class="flex py-2"> 1614 1615<a 1616 href="https://www.riccar.com/vacuum-cleaners/canister-vacuums" 1617 class="__inner-link" 1618 data-menu="menu-854"> 1619 Bagged Canister Vacuums</a> 1620 </li> 1621 </ul> 1622 <div> 1623 <style>#html-body [data-pb-style=WRRFB1B]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}</style><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-element="inner" data-pb-style="WRRFB1B"><div data-content-type="text" data-appearance="default" data-element="main"><p style="text-align: center;"><span style="font-size: 20px;">Why Riccar Vacuums?</span></p></div><div class="my-4" data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><div class="separator-block separator-block--small"></div></div><div class="px-10 normal-case" data-content-type="text" data-appearance="default" data-element="main"><p style="text-align: center;"><span style="font-size: 14px;">We are driven by one passion: making world-class vacuums. Every product is designed and engineered with the goal of creating machines that truly last, all while keeping the healthiest home possible.</span></p></div></div></div> </div> 1624 </div> 1625 </div> 1626 </div> 1627 1628 </div> 1629 </li> 1630 <li 1631 @mouseenter="hoverPanelActiveId = '860'" 1632 @mouseleave="hoverPanelActiveId = 0" 1633 @keyup.escape="hoverPanelActiveId = 0" 1634 @blur="closeMenuOnBlur" 1635 class="text-sm flex font-medium uppercase p-2.5 2xl:px-4.5 2xl:text-base" 1636 > 1637 1638<a 1639 href="https://www.riccar.com/bags-belts-filters" 1640 class="__link" 1641 data-menu="menu-860" @focus="hoverPanelActiveId = 0"> 1642 Bags Belts & Filters</a> 1643 <button 1644 class="flex justify-center items-center ml-1" 1645 @click="openMenuOnClick('860')" 1646 :aria-expanded="hoverPanelActiveId === '860'" 1647 >
1648 <span class="sr-only"> 1649 Toggle Bags Belts & Filters submenu </span> 1650 <span> 1651 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-gray-500" width="20" height="20" aria-hidden="true"> 1652 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 1653</svg> 1654 </span> 1655 </button> 1656 <div class="desktop-sub-menu-860"> 1657 <div 1658 class=" 1659 absolute left-0 top-[calc(100%_-_24px)] w-full z-20 hidden bg-white 1660 py-4 shadow-md 1661 " 1662 :class="{ 1663 'hidden' : hoverPanelActiveId !== '860', 1664 'flex' : hoverPanelActiveId === '860', 1665 }" 1666 > 1667 <div class="mt-2 w-full pb-6 pt-2"> 1668 <div class="container grid grid-cols-2 lg:px-6"> 1669 <ul class="flex flex-col"> 1670 <li class="flex py-2"> 1671 1672<a 1673 href="https://www.riccar.com/bags-belts-filters/vacuum-bags" 1674 class="__inner-link" 1675 data-menu="menu-863"> 1676 Vacuum Bags</a> 1677 </li> 1678 <li class="flex py-2"> 1679 1680<a 1681 href="https://www.riccar.com/bags-belts-filters/vacuum-filters" 1682 class="__inner-link" 1683 data-menu="menu-866"> 1684 Filters</a> 1685 </li> 1686 <li class="flex py-2"> 1687 1688<a 1689 href="https://www.riccar.com/bags-belts-filters/vacuum-belts" 1690 class="__inner-link" 1691 data-menu="menu-869"> 1692 Belts</a> 1693 </li> 1694 </ul> 1695 <div> 1696 <style>#html-body [data-pb-style=WRRFB1B]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}</style><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-element="inner" data-pb-style="WRRFB1B"><div data-content-type="text" data-appearance="default" data-element="main"><p style="text-align: center;"><span style="font-size: 20px;">Why Riccar Vacuums?</span></p></div><div class="my-4" data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><div class="separator-block separator-block--small"></div></div><div class="px-10 normal-case" data-content-type="text" data-appearance="default" data-element="main"><p style="text-align: center;"><span style="font-size: 14px;">We are driven by one passion: making world-class vacuums. Every product is designed and engineered with the goal of creating machines that truly last, all while keeping the healthiest home possible.</span></p></div></div></div> </div> 1697 </div> 1698 </div> 1699 </div> 1700 1701 </div> 1702 </li> 1703 <li 1704 @mouseenter="hoverPanelActiveId = '872'" 1705 @mouseleave="hoverPanelActiveId = 0" 1706 @keyup.escape="hoverPanelActiveId = 0" 1707 @blur="closeMenuOnBlur" 1708 class="text-sm flex font-medium uppercase p-2.5 2xl:px-4.5 2xl:text-base" 1709 > 1710 1711<a 1712 href="https://www.riccar.com/tools-accessories" 1713 class="__link"
1714 data-menu="menu-872" @focus="hoverPanelActiveId = 0"> 1715 Parts & Accessories</a> 1716 <button 1717 class="flex justify-center items-center ml-1" 1718 @click="openMenuOnClick('872')" 1719 :aria-expanded="hoverPanelActiveId === '872'" 1720 > 1721 <span class="sr-only"> 1722 Toggle Parts & Accessories submenu </span> 1723 <span> 1724 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-gray-500" width="20" height="20" aria-hidden="true"> 1725 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 1726</svg> 1727 </span> 1728 </button> 1729 <div class="desktop-sub-menu-872"> 1730 <div 1731 class=" 1732 absolute left-0 top-[calc(100%_-_24px)] w-full z-20 hidden bg-white 1733 py-4 shadow-md 1734 " 1735 :class="{ 1736 'hidden' : hoverPanelActiveId !== '872', 1737 'flex' : hoverPanelActiveId === '872', 1738 }" 1739 > 1740 <div class="mt-2 w-full pb-6 pt-2"> 1741 <div class="container grid grid-cols-2 lg:px-6"> 1742 <ul class="flex flex-col"> 1743 <li class="flex py-2"> 1744 1745<a 1746 href="https://www.riccar.com/tools-accessories/central-vacuum-accessories" 1747 class="__inner-link" 1748 data-menu="menu-875"> 1749 Central Vacuum Accessories</a> 1750 </li> 1751 <li class="flex py-2"> 1752 1753<a 1754 href="https://www.riccar.com/tools-accessories/vacuum-tools-attachments" 1755 class="__inner-link" 1756 data-menu="menu-878"> 1757 Vacuum Tools & Attachments</a> 1758 </li> 1759 <li class="flex py-2"> 1760 1761<a 1762 href="https://www.riccar.com/tools-accessories/carpet-care-cleaning-supplies-floor-pads" 1763 class="__inner-link" 1764 data-menu="menu-881"> 1765 Carpet Care Cleaning Supplies & Floor Pads</a> 1766 </li> 1767 <li class="flex py-2"> 1768 1769<a 1770 href="https://www.riccar.com/tools-accessories/batteries-chargers" 1771 class="__inner-link" 1772 data-menu="menu-890"> 1773 Batteries & Chargers</a> 1774 </li> 1775 </ul> 1776 <div> 1777 <style>#html-body [data-pb-style=WRRFB1B]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}</style><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-element="inner" data-pb-style="WRRFB1B"><div data-content-type="text" data-appearance="default" data-element="main"><p style="text-align: center;"><span style="font-size: 20px;">Why Riccar Vacuums?</span></p></div><div class="my-4" data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><div class="separator-block separator-block--small"></div></div><div class="px-10 normal-case" data-content-type="text" data-appearance="default" data-element="main"><p style="text-align: center;"><span style="font-size: 14px;">We are driven by one passion: making world-class vacuums. Every product is designed and engineered with the goal of creating machines that truly last, all while keeping the healthiest home possible.</span></p></div></div></div> </div> 1778 </div> 1779 </div> 1780 </div> 1781 1782 </div> 1783 </li> 1784 <li 1785 @mouseenter="hoverPanelActiveId = '884'" 1786 @mouseleave="hoverPanelActiveId = 0" 1787 @keyup.escape="hoverPanelActiveId = 0" 1788 @blur="closeMenuOnBlur" 1789 class="text-sm flex font-medium uppercase p-2.5 2xl:px-4.5 2xl:text-base" 1790 > 1791 1792<a 1793 href="https://www.riccar.com/support" 1794 class="__link" 1795 data-menu="menu-884" @focus="hoverPanelActiveId = 0"> 1796 Support</a> 1797 </li> 1798 <li 1799 @mouseenter="hoverPanelActiveId = '887'" 1800 @mouseleave="hoverPanelActiveId = 0" 1801 @keyup.escape="hoverPanelActiveId = 0" 1802 @blur="closeMenuOnBlur" 1803 class="text-sm flex font-medium uppercase p-2.5 2xl:px-4.5 2xl:text-base" 1804 > 1805 1806<a 1807 href="https://www.riccar.com/about-us" 1808 class="__link" 1809 data-menu="menu-887" @focus="hoverPanelActiveId = 0"> 1810 Why Riccar?</a> 1811 </li> 1812 </ul> 1813 </nav> 1814</div>
1815<script> 1816 'use strict'; 1817 1818 const initMenuDesktop_6ab60e469e529 = () => { 1819 return { 1820 hoverPanelActiveId: null, 1821 openMenuOnClick(menuNode) { 1822 if (menuNode === this.hoverPanelActiveId) { 1823 this.hoverPanelActiveId = 0; 1824 } else { 1825 this.hoverPanelActiveId = menuNode 1826 1827 } 1828 }, 1829 closeMenuOnBlur (event) { 1830 if (!this.$refs['nav-desktop'].contains(event.relatedTarget)) { 1831 this.hoverPanelActiveId = 0; 1832 } 1833 }, 1834 } 1835 } 1836</script>
1836 1837 1838 <div class="flex items-center sm:ml-auto"> 1839 1840 <!--Search Icon--> 1841 <button 1842 id="menu-search-icon" 1843 class="hidden p-3 sm:inline-block" 1844 @click.prevent=" 1845 searchOpen = !searchOpen; 1846 $dispatch('search-open'); 1847 " 1848 aria-label="Toggle search form" 1849 aria-haspopup="true" 1850 :aria-expanded="searchOpen" 1851 x-ref="searchButton" 1852 > 1853 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 25 24" fill="currentColor" class="w-6 h-6 stroke-[0.5]" aria-hidden="true"><path d="m22.022 20.69-5.664-5.665a8.264 8.264 0 1 0-1.061 1.06l5.664 5.665 1.06-1.06ZM3.272 9.75a6.75 6.75 0 1 1 6.75 6.75 6.757 6.757 0 0 1-6.75-6.75Z" stroke="currentColor"/></svg> 1854 </button> 1855 1856 <div class="hidden sm:block mx-1.5 h-12 border-black border-r" 1857 ></div> 1858 1859 <!--Cart Icon--> 1860 <button 1861 id="menu-cart-icon" 1862 class="relative inline-block no-underline p-3" 1863 x-ref="cartButton" 1864 :aria-disabled="isCartEmpty()" 1865 title="Cart" 1866 @click.prevent.stop="() => { 1867 $dispatch('toggle-cart', { isOpen: true }) 1868 }" 1869 @toggle-cart.window="toggleCart($event)" 1870 :aria-expanded="isCartOpen" 1871 aria-haspopup="dialog" 1872 > 1873 <span 1874 class="sr-only label" 1875 x-text="` 1876 Toggle minicart, 1877 ${isCartEmpty() ? 1878 'Cart is empty' : 1879 hyva.str( 1880 'You have %1 product%2 in your cart.', 1881 cart.summary_count, 1882 cart.summary_count === 1 ? '' : 's' 1883 )}` 1884 " 1885 > 1886 </span> 1887 1888 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 25 24" fill="currentColor" class="w-6 h-6 stroke-[0.5]" aria-hidden="true"><g clip-path="url(#a)"><path d="M7.771 22.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM18.271 22.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM21.271 5.25H4.636L4.021 2.1a.75.75 0 0 0-.75-.6h-3V3h2.385l2.865 14.4a.75.75 0 0 0 .75.6h13.5v-1.5H6.886l-.615-3h13.5a.75.75 0 0 0 .75-.585l1.5-6.75a.751.751 0 0 0-.75-.915Zm-2.1 6.75H5.987l-1.05-5.25h15.398L19.172 12Z" stroke="currentColor"/></g><defs><clipPath id="a"><path d="M.271 0h24v24h-24z" stroke="currentColor"/></clipPath></defs></svg> 1889 1890 <div 1891 x-show="!isCartEmpty()" 1892 x-cloak 1893 class="absolute top-3 right-4 w-1" 1894 > 1895 <span 1896 class=" 1897 w-2 h-2 block rounded-full bg-secondary 1898 " 1899 ></span> 1900 <span 1901 x-cloak 1902 class=" 1903 w-2 h-2 block animate-ping rounded-full bg-secondary 1904 relative bottom-2 1905 " 1906 aria-hidden="true" 1907 ></span> 1908 </div> 1909 </button> 1910 </div> 1911 </div> 1912 <!--Search--> 1913 <div 1914 class="absolute z-10 w-full border-t shadow-sm bg-container-lighter border-container-lighter" 1915 id="search-content" 1916 x-cloak x-show="searchOpen" 1917 @click.outside="searchOpen = false" 1918 @keydown.escape=" 1919 searchOpen = false; 1920 $refs.searchButton.focus(); 1921 " 1922 > 1923 <div x-data="initLiveSearch" 1924 x-init="initPopover" 1925 @close-search.window="closePopover" 1926 @open-search.window="openPopover"> 1927 <div class="container py-2 mx-auto text-black"> 1928 <form class="form minisearch" 1929 id="search_mini_form" 1930 action="https://www.riccar.com/catalogsearch/result/" 1931 method="get" 1932 > 1933 <div> 1934 <div class="relative group"> 1935 <div class="flex"> 1936 <label class="hidden" for="search" data-role="minisearch-label">
1937 <span>Search</span> 1938 </label> 1939 <input id="search" 1940 class="w-full p-2 text-lg leading-normal transition appearance-none text-grey-800 focus:outline-none focus:border-transparent lg:text-xl" 1941 type="text" 1942 x-model="queryPhrase" 1943 name="q" 1944 value="" 1945 placeholder="Search entire store here..." 1946 maxlength="128" 1947 role="combobox" 1948 aria-haspopup="false" 1949 aria-autocomplete="both" 1950 autocomplete="off" 1951 aria-expanded="false" 1952 @input="handleInput" 1953 @click.away="closePopover" 1954 /> 1955 </div> 1956 <div class="absolute flex-col z-50 shadow-xl mt-1 bg-white w-full search-autocomplete" 1957 :class="getSearchClasses" 1958 x-show="true" 1959 > 1960 <div class="flex"> 1961 <template x-if="showSuggestions"> 1962 <div> 1963 <h3 class="font-bold p-4 pb-2 pt-6"> 1964 Suggestions </h3> 1965 <div class="grid grid-cols-1"> 1966 <template x-for="suggestion in liveSearchSuggestions"> 1967 <button x-text="suggestion" @click="searchSuggestion" 1968 type="button" 1969 class="p-2 text-left m-1 ml-2 hover:bg-gray-200"></button> 1970 </template> 1971 </div> 1972 </div> 1973 </template> 1974 <template x-if="showResults"> 1975 <div class="grid grid-cols-2 gap-x-8 gap-y-2 mr-8 pl-4 pt-14"> 1976 <template x-for="product in liveSearchProducts"> 1977 <a class="flex p-2 hover:bg-gray-200 cursor-pointer" 1978 @click="handleProductClick"> 1979 <div class="w-12 h-12"> 1980 <img :src="product.image" :alt="product.name"/> 1981 </div> 1982 <div class="flex-col ml-4"> 1983 <div x-text="product.name" class="font-bold"></div> 1984 <template x-if="product.price"> 1985 <div class="flex"> 1986 <div x-text="showProductPrice"></div> 1987 </div> 1988 </template> 1989 </div> 1990 </a> 1991 </template> 1992 </div> 1993 </template> 1994 </div> 1995 <template x-if="showResults"> 1996 <button class="bg-gray-100 hover:bg-gray-200 w-full p-2 text-sm hover:font-semibold 1997 mt-4 text-center" type="submit"> 1998 View All </button> 1999 </template> 2000 </div> 2001 </div> 2002 </div> 2003 </form> 2004 </div> 2005</div> 2006
2007<script> 2008 'use strict'; 2009 window.addEventListener( 2010 'alpine:init', 2011 () => Alpine.data('initLiveSearch', () => ({ 2012 queryPhrase: '', 2013 liveSearchProducts: [], 2014 liveSearchSuggestions: [], 2015 minQueryLength: 3, 2016 pageSize: 8, 2017 searchOpen: false, 2018 search: null, 2019 searchId: "180b553f-20dd-47e9-914e-ceca7d950e45_" + 2020 "rv_" + 2021 "rv_store_" + 2022 "rv_store_view", 2023 2024 initPopover() { 2025 this.search = this.buildSearch(); 2026 this.initTogglePopover(); 2027 }, 2028 2029 buildSearch() { 2030 window.magentoStorefrontEvents.context.setSearchExtension({ 2031 version: "4.7.2" 2032 }); 2033 return new MagentoLiveSearch({ 2034 environmentId: "180b553f-20dd-47e9-914e-ceca7d950e45", 2035 websiteCode: "rv", 2036 storeCode: "rv_store", 2037 storeViewCode: "rv_store_view", 2038 apiKey: "search_gql", 2039 }); 2040 }, 2041 2042 // this will open the popover, whenever the search-input has focus 2043 initTogglePopover() { 2044 const popover = document.getElementById('search'); 2045 2046 popover.addEventListener('focus', () => { 2047 if (this.isQueryLengthValid()) { 2048 this.openPopover(); 2049 } else { 2050 this.closePopover(); 2051 } 2052 }); 2053 }, 2054 2055 closePopover() { 2056 this.searchOpen = false; 2057 }, 2058 2059 openPopover() { 2060 this.searchOpen = true; 2061 }, 2062 2063 handleInput() { 2064 if (!this.isQueryLengthValid()) { 2065 if (this.searchOpen){ 2066 this.closePopover(); 2067 } 2068 return; 2069 } 2070 2071 this.getProducts(); 2072 this.$nextTick(() => { 2073 this.openPopover(); 2074 }); 2075 }, 2076 2077 showProductPrice(){ 2078 return this.product.price ? hyva.formatPrice(this.product.price) : ''; 2079 }, 2080 2081 handleProductClick() { 2082 window.magentoStorefrontEvents.context.setSearchResults( 2083 window.magentoStorefrontEvents.context.getSearchResults() 2084 ); 2085 2086 window.magentoStorefrontEvents.publish.searchProductClick("search-bar", `${this.product.sku}`); 2087 2088 // Timeout to prevent submission before event has fired. 2089 setTimeout(() => window.location.href = this.product.url, 500); 2090 }, 2091 2092 // this will submit the form with the clicked suggestion as the search-phrase 2093 searchSuggestion() { 2094 document.getElementById('search').value = this.suggestion; 2095 document.getElementById('search_mini_form').submit(); 2096 }, 2097 2098 showResults(){ 2099 return this.liveSearchProducts.length >= 1 && this.isQueryLengthValid(); 2100 }, 2101 2102 showSuggestions(){ 2103 return this.liveSearchSuggestions.length >= 1 && this.isQueryLengthValid(); 2104 }, 2105 2106 isQueryLengthValid() { 2107 return this.queryPhrase.length >= this.minQueryLength; 2108 }, 2109 2110 getSearchClasses() { 2111 return this.searchOpen ? 'block' : 'hidden'; 2112 }, 2113 2114 // get products from fetch-request and update liveSearchProducts and liveSearchSuggestions 2115 async getProducts() { 2116 this.searchOpen = true; 2117 const result = await this.getLiveSearchProducts(); 2118 let products = []; 2119 2120 this.liveSearchProducts = result.data.productSearch.items.map(item => ({ 2121 name: item.product.name, 2122 price: item.product.price_range.maximum_price.regular_price.value, 2123 currency: item.product.price_range.maximum_price.regular_price.currency, 2124 image: item.product.image ? item.product.image.url : 'https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Magento_Catalog/images/product/placeholder/small_image.jpg', 2125 url: item.product.canonical_url, 2126 id: item.product.id, 2127 sku: item.product.sku 2128 })); 2129 2130 this.liveSearchSuggestions = result.data.productSearch.suggestions; 2131 //search-results-view 2132 }, 2133 2134 // retrieve products from magento live search service 2135 async getLiveSearchProducts() { 2136 this.searchRequestId = Math.random().toString(16).slice(2); 2137 2138 if (!this.search) { 2139 return []; 2140 } 2141 2142 const searchCtx = { 2143 units: [{ 2144 searchUnitId: "search-bar", 2145 queryTypes: ["products"], 2146 phrase: this.queryPhrase, 2147 currentPage: 1, 2148 pageSize: this.pageSize, 2149 filter:[ 2150 {attribute:"visibility",in:["Search","Catalog, Search"]}, 2151 {attribute:"inStock",eq:"true"} 2152 ], 2153 sort: [{attribute: "relevance", direction: "DESC"}], 2154 searchRequestId: this.searchRequestId 2155 }] 2156 }; 2157 2158 window.magentoStorefrontEvents.context.setSearchInput(searchCtx); 2159 window.magentoStorefrontEvents.publish.searchRequestSent("search-bar"); 2160 2161 const before = Date.now(); 2162 2163 const result = await this.search.productSearch({ 2164 phrase: this.queryPhrase, 2165 page_size: this.pageSize, 2166 sort: [{attribute: "relevance", direction: "DESC"}], 2167 filter:[ 2168 {attribute:"visibility",in:["Search","Catalog, Search"]}, 2169 {attribute:"inStock",eq:"true"} 2170 ], 2171 current_page: 1, 2172 data: { 2173 products: true, 2174 facets: true, 2175 suggestions: true 2176 }, 2177 context: { 2178 customerGroup: "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c" 2179 } 2180 }); 2181 2182 const after = Date.now(); 2183 2184 const productItems = result.data.productSearch.items || []; 2185 const suggestions = result.data.productSearch.suggestions || []; 2186 const facets = result.data.productSearch.facets || []; 2187 2188 const formattedProductItems = productItems.map((item, key) => ({ 2189 name: item.product.name, 2190 sku: item.product.sku, 2191 url: item.product.canonical_url, 2192 imageUrl: item.product.image ? item.product.image.url : 'https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Magento_Catalog/images/product/placeholder/small_image.jpg', 2193 price: item.product.price_range.minimum_price.final_price.value, 2194 rank: key, 2195 })); 2196 2197 const formattedSuggestions = suggestions.map((item, key) => ({ 2198 suggestion: item, 2199 rank: key, 2200 })); 2201 2202 const formattedFacets = facets.map((facet) => ({ 2203 attribute: facet.attribute, 2204 title: facet.title, 2205 type: facet.type || "PINNED", 2206 buckets: facet.buckets.map((bucket) => bucket), 2207 })); 2208 2209 const searchCtxUpdated = { 2210 units: [{ 2211 searchUnitId: "search-bar", 2212 searchRequestId: this.searchRequestId, 2213 executionTime: after - before, 2214 products: formattedProductItems, 2215 categories: [], 2216 suggestions: formattedSuggestions, 2217 page: result.data.productSearch.page_info.current_page, 2218 perPage: result.data.productSearch.page_info.page_size, 2219 facets: formattedFacets 2220 }] 2221 }; 2222 2223 window.magentoStorefrontEvents.context.setSearchResults(searchCtxUpdated); 2224 window.magentoStorefrontEvents.publish.searchResponseReceived("search-bar"); 2225 2226 return result; 2227 } 2228 })), 2229 {once: true} 2230 ) 2231</script>
2231 2232 </div> 2233 2234 <!--Cart Drawer--> 2235
2235<script> 2236 function initCartDrawer() { 2237 return { 2238 open: false, 2239 isLoading: false, 2240 cart: {}, 2241 maxItemsToDisplay: 10, 2242 itemsCount: 0, 2243 updatingItemIds: [], 2244 getData(data) { 2245 if (data.cart) { 2246 this.cart = data.cart; 2247 this.itemsCount = data.cart.items && data.cart.items.length || 0; 2248 this.setCartItems(); 2249 this.updatingItemIds = []; 2250 } 2251 this.isLoading = false; 2252 }, 2253 cartItems: [], 2254 getItemCountTitle() { 2255 return hyva.strf('\u00250\u0020of\u0020\u00251\u0020products\u0020in\u0020cart\u0020displayed', this.maxItemsToDisplay, this.itemsCount) 2256 }, 2257 setCartItems() { 2258 this.cartItems = this.cart.items && this.cart.items.sort((a, b) => b.item_id - a.item_id) || []; 2259 2260 if (this.maxItemsToDisplay > 0) { 2261 this.cartItems = this.cartItems.slice(0, parseInt(this.maxItemsToDisplay, 10)); 2262 } 2263 }, 2264 getItemQty(item) { 2265 const itemQty = parseFloat(item.qty); 2266 2267 return Number.isFinite(itemQty) ? itemQty : 1; 2268 }, 2269 isItemUpdating(itemId) { 2270 return this.updatingItemIds.includes(itemId); 2271 }, 2272 setItemUpdating(itemId, isUpdating) { 2273 if (isUpdating) { 2274 this.updatingItemIds = [...new Set([...this.updatingItemIds, itemId])]; 2275 return; 2276 } 2277 2278 this.updatingItemIds = this.updatingItemIds.filter((updatingItemId) => updatingItemId !== itemId); 2279 }, 2280 changeItemQty(item, change) { 2281 const currentQty = this.getItemQty(item); 2282 const itemQty = Math.max(1, currentQty + change); 2283 2284 if (itemQty === currentQty || this.isItemUpdating(item.item_id)) { 2285 return; 2286 } 2287 2288 this.updateItemQty(item, itemQty); 2289 }, 2290 updateItemQty(item, itemQty) { 2291 this.setItemUpdating(item.item_id, true); 2292 2293 const formKey = hyva.getFormKey(); 2294 const postUrl = BASE_URL + 'checkout/sidebar/updateItemQty/'; 2295 const body = new URLSearchParams({ 2296 form_key: formKey, 2297 item_id: item.item_id, 2298 item_qty: itemQty 2299 }); 2300 2301 fetch(postUrl, { 2302 headers: { 2303 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 2304 'X-Requested-With': 'XMLHttpRequest' 2305 }, 2306 body, 2307 method: 'POST', 2308 mode: 'cors', 2309 credentials: 'include' 2310 }).then(response => { 2311 if (response.redirected) { 2312 window.location.href = response.url; 2313 } else if (response.ok) { 2314 return response.json(); 2315 } else { 2316 window.dispatchMessages && window.dispatchMessages([{ 2317 type: 'warning', 2318 text: 'Could\u0020not\u0020update\u0020item\u0020quantity.' 2319 }]); 2320 this.setItemUpdating(item.item_id, false); 2321 } 2322 }).then(result => { 2323 if (!result) { 2324 return; 2325 } 2326 2327 window.dispatchEvent(new CustomEvent('clear-messages')); 2328 document.cookie = 'mage-messages=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 2329 2330 if (result.success) { 2331 item.qty = itemQty; 2332 window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 2333 this.setItemUpdating(item.item_id, false); 2334 return; 2335 } 2336 2337 this.setItemUpdating(item.item_id, false); 2338 window.dispatchMessages && window.dispatchMessages([{ 2339 type: 'error', 2340 text: result.error_message 2341 }], 0) 2342 }).catch(() => { 2343 this.setItemUpdating(item.item_id, false); 2344 window.dispatchMessages && window.dispatchMessages([{ 2345 type: 'error', 2346 text: 'Could\u0020not\u0020update\u0020item\u0020quantity.' 2347 }], 0) 2348 }); 2349 }, 2350 deleteItemFromCart(itemId) { 2351 this.isLoading = true; 2352 2353 const itemData = this.cart.items.filter((item) => item['item_id'] === itemId); 2354 const formKey = hyva.getFormKey(); 2355 const postUrl = BASE_URL + 'checkout/sidebar/removeItem/'; 2356 2357 fetch(postUrl, { 2358 "headers": { 2359 "content-type": "application/x-www-form-urlencoded; charset=UTF-8", 2360 }, 2361 "body": "form_key=" + formKey + "&item_id=" + itemId, 2362 "method": "POST", 2363 "mode": "cors", 2364 "credentials": "include" 2365 }).then(response => { 2366 if (response.redirected) { 2367 window.location.href = response.url; 2368 } else if (response.ok) { 2369 return response.json(); 2370 } else { 2371 window.dispatchMessages && window.dispatchMessages([{ 2372 type: 'warning',
2373 text: 'Could\u0020not\u0020remove\u0020item\u0020from\u0020quote.' 2374 }]); 2375 this.isLoading = false; 2376 } 2377 }).then(result => { 2378 window.dispatchMessages && window.dispatchMessages([{ 2379 type: result.success ? 'success' : 'error', 2380 text: result.success 2381 ? 'You\u0020removed\u0020the\u0020item.' 2382 : result.error_message 2383 }], result.success ? 5000 : 0); 2384 2385 if (result.success && itemData) { 2386 window.dispatchEvent(new CustomEvent('cart-item-removed', { detail: itemData })); 2387 } 2388 2389 window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 2390 }); 2391 }, 2392 scrollLock(use = true) { 2393 document.body.style.overflow = use ? "hidden" : ""; 2394 }, 2395 toggleCartDrawer(event) { 2396 if (event.detail && event.detail.isOpen !== undefined) { 2397 if (event.detail.isOpen) { 2398 this.openCartDrawer(); 2399 } else { 2400 this.open = false; 2401 this.scrollLock(false); 2402 this.$refs && this.$refs.cartDialogContent && hyva.releaseFocus(this.$refs.cartDialogContent); 2403 } 2404 } else { 2405 this.openCartDrawer() 2406 } 2407 }, 2408 openCartDrawer() { 2409 this.open = true; 2410 this.scrollLock(true); 2411 this.$nextTick(() => { 2412 this.$refs && this.$refs.cartDialogContent && hyva.trapFocus(this.$refs.cartDialogContent) 2413 }) 2414 }, 2415 closeCartDrawer() { 2416 this.$dispatch('toggle-cart', { isOpen: false }) 2417 }, 2418 getSectionDataExtraActions() { 2419 if (!this.cart.extra_actions) { 2420 return ''; 2421 } 2422 2423 const contentNode = document.createElement('div'); 2424 contentNode.innerHTML = this.cart.extra_actions; 2425 2426 hyva.activateScripts(contentNode); 2427 2428 return contentNode.innerHTML; 2429 } 2430 } 2431 } 2432</script>
2432 2433<section x-cloak 2434 x-show="cart" 2435 id="cart-drawer" 2436 x-data="initCartDrawer()" 2437 @private-content-loaded.window="getData($event.detail.data)" 2438 @toggle-cart.window="toggleCartDrawer($event)" 2439 @keydown.escape="closeCartDrawer" 2440> 2441 <div role="dialog" 2442 aria-labelledby="cart-drawer-title" 2443 aria-modal="true" 2444 :aria-hidden="!open" 2445 class="fixed inset-y-0 right-0 z-30 flex max-w-full"> 2446 <div class="backdrop" 2447 x-show="open" 2448 x-transition:enter="ease-in-out duration-500" 2449 x-transition:enter-start="opacity-0" 2450 x-transition:enter-end="opacity-100" 2451 x-transition:leave="ease-in-out duration-500" 2452 x-transition:leave-start="opacity-100" 2453 x-transition:leave-end="opacity-0" 2454 role="button" 2455 @click="closeCartDrawer" 2456 aria-label="Close minicart"></div> 2457 <div class="relative w-screen max-w-md shadow-2xl" 2458 x-show="open" 2459 x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700" 2460 x-transition:enter-start="translate-x-full" 2461 x-transition:enter-end="translate-x-0" 2462 x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700" 2463 x-transition:leave-start="translate-x-0" 2464 x-transition:leave-end="translate-x-full" 2465 x-ref="cartDialogContent" 2466 role="region" 2467 :tabindex="open ? 0 : -1" 2468 aria-label="My Cart" 2469 2470 > 2471 <div class="flex flex-col h-full max-h-screen bg-white shadow-xl"> 2472 2473 <header class="relative px-4 py-6 sm:px-6"> 2474 <p id="cart-drawer-title" class="text-lg font-medium leading-7 text-gray-900"> 2475 <strong>My Cart</strong> 2476 <span class="items-total text-xs" 2477 x-show="maxItemsToDisplay && maxItemsToDisplay < itemsCount" 2478 x-text="getItemCountTitle()"> 2479 </span> 2480 </p> 2481 </header> 2482 2483 2484 <template x-if="!itemsCount"> 2485 <div class="relative px-4 py-6 bg-white border-bs sm:px-6 border-container"> 2486 Cart is empty </div> 2487 </template> 2488 2489 <template x-if="itemsCount"> 2490 <div class="relative grid gap-6 sm:gap-8 px-1 py-3 sm:px-3 bg-white border-b border-container overflow-y-auto overscroll-y-contain"> 2491 <template x-for="item in cartItems"> 2492 <div class="flex items-start p-3 space-x-4 transition duration-150 ease-in-out rounded-lg hover:bg-gray-100"> 2493 <template x-if="item.product_has_url && item.is_visible_in_site_visibility"> 2494 <a :href="item.product_url" 2495 class="w-1/4 !ml-0" 2496 :aria-label="hyva.strf('Product\u0020\u0022\u00250\u0022', item.product_name)" 2497 > 2498 <img 2499 :src="item.product_image.src" 2500 :width="item.product_image.width" 2501 :height="item.product_image.height" 2502 loading="lazy" 2503 :alt="item.product_name" 2504 /> 2505 </a> 2506 </template> 2507 <template x-if="!item.product_has_url || !item.is_visible_in_site_visibility"> 2508 <div class="w-1/4 !ml-0"> 2509 <img 2510 :src="item.product_image.src" 2511 :width="item.product_image.width" 2512 :height="item.product_image.height" 2513 loading="lazy" 2514 :alt="item.product_name" 2515 /> 2516 </div> 2517 </template> 2518 <div class="w-3/4 space-y-2"> 2519 <div> 2520 <p class="text-xl">
2521 <span x-html="item.product_name"></span> 2522 </p> 2523 <p class="text-sm"><span x-html="item.product_sku"></span></p> 2524 </div> 2525 <template x-for="option in item.options"> 2526 <div class="pt-2"> 2527 <p class="font-semibold" x-text="option.label + ':'"></p> 2528 <p class="text-secondary" x-html="option.value"></p> 2529 </div> 2530 </template> 2531 <div 2532 class="inline-flex items-center border border-gray-300" 2533 :aria-label="hyva.strf('Quantity\u0020controls\u0020for\u0020\u0022\u00250\u0022', item.product_name)" 2534 > 2535 <button 2536 type="button" 2537 class="flex h-10 w-10 items-center justify-center text-xl leading-none" 2538 :class="{ 'cursor-not-allowed opacity-50': getItemQty(item) <= 1 || isItemUpdating(item.item_id) }" 2539 @click="changeItemQty(item, -1)" 2540 :disabled="getItemQty(item) <= 1 || isItemUpdating(item.item_id)" 2541 :aria-label="hyva.strf('Decrease\u0020quantity\u0020for\u0020\u0022\u00250\u0022', item.product_name)" 2542 > 2543 <span aria-hidden="true">-</span> 2544 </button> 2545 <span 2546 class="w-10 px-3 text-center text-sm" 2547 aria-live="polite" 2548 x-text="getItemQty(item)" 2549 ></span> 2550 <button 2551 type="button" 2552 class="flex h-10 w-10 items-center justify-center text-xl leading-none" 2553 :class="{ 'cursor-not-allowed opacity-50': isItemUpdating(item.item_id) }" 2554 @click="changeItemQty(item, 1)" 2555 :disabled="isItemUpdating(item.item_id)" 2556 :aria-label="hyva.strf('Increase\u0020quantity\u0020for\u0020\u0022\u00250\u0022', item.product_name)" 2557 > 2558 <span aria-hidden="true">+</span> 2559 </button> 2560 </div> 2561 <p><span x-html="item.product_price"></span></p> 2562 <div class="pt-4"> 2563 <a :href="item.configure_url" 2564 x-show="item.product_type !== 'grouped' && item.is_visible_in_site_visibility" 2565 class="inline-flex p-2 mr-2 btn btn-primary" 2566 :aria-label="hyva.strf('Edit\u0020product\u0020\u0022\u00250\u0022', item.product_name)" 2567 > 2568 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20" aria-hidden="true"> 2569 <path stroke-linecap="round" stroke-linejoin="round" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/> 2570</svg> 2571 </a> 2572 <button type="button" 2573 class="inline-flex p-2 btn btn-primary" 2574 @click="deleteItemFromCart(item.item_id)" 2575 :aria-label="hyva.strf('Remove\u0020product\u
25750020\u0022\u00250\u0022\u0020from\u0020cart', item.product_name)" 2576 > 2577 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20" aria-hidden="true"> 2578 <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/> 2579</svg> 2580 </button> 2581 </div> 2582 2583 </div> 2584 </div> 2585 </template> 2586 </div> 2587 </template> 2588 2589 <template x-if="itemsCount"> 2590 <div> 2591 2592 <div class="relative grid gap-6 sm:gap-8 py-3 px-1 sm:px-3 bg-white"> 2593 <div class="w-full p-3 space-x-4 transition duration-150 ease-in-out rounded-lg hover:bg-gray-100"> 2594 <p>Subtotal: <span x-html="cart.subtotal"></span></p> 2595 </div> 2596 <div class="w-full p-3 space-x-4 transition duration-150 ease-in-out rounded-lg hover:bg-gray-100"> 2597 <a @click.prevent.stop="closeCartDrawer; $dispatch('toggle-authentication', 2598 {url: 'https://www.riccar.com/checkout/'});" 2599 href="https://www.riccar.com/checkout/" 2600 class="inline-flex btn btn-primary" 2601 > 2602 Checkout </a> 2603 <span>or</span> 2604 <a href="https://www.riccar.com/checkout/cart/" 2605 class="underline" 2606 > 2607 View and Edit Cart </a> 2608 </div> 2609 <div x-html="getSectionDataExtraActions()"></div> 2610 </div> 2611 </div> 2612 </template> 2613 2614 </div> 2615 2616 <button 2617 type="button" 2618 @click="closeCartDrawer" 2619 aria-label="Close minicart" 2620 class="absolute top-0 right-2 p-4 mt-2 text-gray-300 transition-colors hover:text-black" 2621 > 2622 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true"> 2623 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/> 2624</svg> 2625 </button> 2626 </div> 2627 <div 2628 class="z-50 fixed inset-0 grid place-items-center bg-white/70 text-slate-800" 2629 x-cloak 2630 x-show="isLoading" 2631 x-transition.opacity.duration.200ms 2632> 2633 <div class="flex gap-10 items-center p-4"> 2634 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57 57" width="57" height="57" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"> 2635 <style> 2636 @keyframes spinner-ball-triangle1 { 2637 0% { transform: translate(0%, 0%); } 2638 33% { transform: translate(38%, -79%); } 2639 66% { transform: translate(77%, 0%); } 2640 100% { transform: translate(0%, 0%); } 2641 } 2642 2643 @keyframes spinner-ball-triangle2 { 2644 0% { transform: translate(0%, 0%); } 2645 33% { transform: translate(38%, 79%); } 2646 66% { transform: translate(-38%, 79%); } 2647 100% { transform: translate(0%, 0%); } 2648 } 2649 2650 @keyframes spinner-ball-triangle3 { 2651 0% { transform: translate(0%, 0%); } 2652 33% { transform: translate(-77%, 0%); } 2653 66% { transform: translate(-38%, -79%); } 2654 100% { transform: translate(0%, 0%); } 2655 } 2656 </style> 2657 <circle cx="5" cy="50" r="5" style="animation: spinner-ball-tr
2657iangle1 2.2s linear infinite"/> 2658 <circle cx="27" cy="5" r="5" style="animation: spinner-ball-triangle2 2.2s linear infinite"/> 2659 <circle cx="49" cy="50" r="5" style="animation: spinner-ball-triangle3 2.2s linear infinite"/> 2660</svg> 2661 <span class="text-xl select-none"> 2662 Loading... </span> 2663 </div> 2664</div> 2665 </div> 2666 2667</section> 2668 2669 <!--Authentication Pop-Up--> 2670
2670<script> 2671 function initAuthentication() { 2672 return { 2673 open: false, 2674 close() { 2675 this.open = false; 2676 }, 2677 forceAuthentication: false, 2678 checkoutUrl: 'https://www.riccar.com/checkout/index/', 2679 errors: 0, 2680 hasCaptchaToken: 0, 2681 displayErrorMessage: false, 2682 errorMessages: [], 2683 setErrorMessages(message) { 2684 this.errorMessages = [message]; 2685 this.displayErrorMessage = true; 2686 }, 2687 submitForm() { 2688 // Do not rename $form, the variable is expected to be declared in the recaptcha output 2689 const $form = document.querySelector('#login-form'); 2690 2691 if (this.errors === 0) { 2692 this.dispatchLoginRequest($form); 2693 } 2694 }, 2695 onPrivateContentLoaded() { 2696 const data = this.$event.detail.data; 2697 const isLoggedIn = data.customer && data.customer.firstname; 2698 if (data.cart && !isLoggedIn) { 2699 this.forceAuthentication = !data.cart.isGuestCheckoutAllowed; 2700 } 2701 }, 2702 redirectIfAuthenticated() { 2703 const event = this.$event; 2704 this.open = this.forceAuthentication; 2705 2706 if (event.detail && event.detail.url) { 2707 this.checkoutUrl = event.detail.url; 2708 } 2709 if (!this.forceAuthentication) { 2710 window.location.href = this.checkoutUrl; 2711 } 2712 }, 2713 resetErrors() { 2714 this.errors = 0; 2715 }, 2716 dispatchLoginRequest(form) { 2717 this.isLoading = true; 2718 const username = this.$refs['customer-email'].value; 2719 const password = this.$refs['customer-password'].value; 2720 const formKey = hyva.getFormKey(); 2721 const bodyFields = { 2722 'username': username, 2723 'password': password, 2724 'formKey': formKey 2725 }; 2726 const fieldName = ''; 2727 const recaptchaField = fieldName && form[fieldName]; 2728 if (recaptchaField) { 2729 bodyFields[fieldName] = recaptchaField.value; 2730 } 2731 fetch('https://www.riccar.com/customer/ajax/login/', { 2732 method: 'POST', 2733 headers: { 2734 'Content-Type': 'application/json', 2735 'X-Requested-With': 'XMLHttpRequest' 2736 }, 2737 body: JSON.stringify(bodyFields) 2738 } 2739 ).then(response => { 2740 return response.json() 2741 } 2742 ).then(data => { 2743 this.isLoading = false; 2744 if (data.errors) { 2745 this.setErrorMessages(data.message); 2746 this.errors = 1; 2747 this.hasCaptchaToken = 0; 2748 } else { 2749 window.location.href = this.checkoutUrl; 2750 } 2751 }); 2752 } 2753 } 2754 } 2755 2756 window.addEventListener('alpine:init', () => Alpine.data('initAuthentication', initAuthentication), {once: true}) 2757</script>
2757 2758<section id="authentication-popup" 2759 x-data="initAuthentication" 2760 @private-content-loaded.window="onPrivateContentLoaded" 2761 @toggle-authentication.window="redirectIfAuthenticated" 2762 @keydown.window.escape="close" 2763> 2764 <div 2765 class="backdrop" 2766 aria-hidden="true" 2767 x-cloak 2768 x-show="open" 2769 x-transition:enter="ease-in-out duration-500" 2770 x-transition:enter-start="opacity-0" 2771 x-transition:enter-end="opacity-100" 2772 x-transition:leave="ease-in-out duration-500" 2773 x-transition:leave-start="opacity-100" 2774 x-transition:leave-end="opacity-0" 2775 @click="close" 2776 ></div> 2777 <div role="dialog" 2778 aria-modal="true" 2779 @click.outside="close" 2780 class="inset-y-0 right-0 z-30 flex max-w-full fixed" 2781 x-cloak 2782 x-show="open" 2783 > 2784 <div class="relative w-screen max-w-md pt-16 bg-container-lighter" 2785 x-show="open" 2786 x-cloak 2787 x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700" 2788 x-transition:enter-start="translate-x-full" 2789 x-transition:enter-end="translate-x-0" 2790 x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700" 2791 x-transition:leave-start="translate-x-0" 2792 x-transition:leave-end="translate-x-full" 2793 > 2794 <div 2795 x-show="open" 2796 x-cloak 2797 x-transition:enter="ease-in-out duration-500" 2798 x-transition:enter-start="opacity-0" 2799 x-transition:enter-end="opacity-100" 2800 x-transition:leave="ease-in-out duration-500" 2801 x-transition:leave-start="opacity-100" 2802 x-transition:leave-end="opacity-0" class="absolute top-0 right-2 flex p-2 mt-2"> 2803 <button 2804 type="button" 2805 @click="close" 2806 aria-label="Close panel" 2807 class="p-2 text-gray-300 transition duration-150 ease-in-out hover:text-black" 2808 > 2809 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true"> 2810 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/> 2811</svg> 2812 </button> 2813 </div> 2814 <template x-if="open"> 2815 <div class="flex flex-col h-full py-6 space-y-6 bg-white shadow-xl overflow-y-auto"> 2816 <div class="mx-4"> 2817 <div class="message error mb-0" x-show="errors" x-cloak> 2818 <template x-for="(message, index) in errorMessages" :key="index"> 2819 <div> 2820 <template x-if="message"> 2821 <span x-html="message"></span> 2822 </template> 2823 </div> 2824 </template> 2825 </div> 2826 </div> 2827 <div class="block-customer-login bg-container border border-container mx-4 p-4 shadow-sm"> 2828 <p id="authenticate-customer-login" class="text-lg leading-7 text-gray-900"> 2829 <strong class="font-medium">Checkout using your account</strong> 2830 </p> 2831 2832 <form class="form form-login" 2833 method="post" 2834 @submit.prevent="submitForm" 2835 id="login-form" 2836 > 2837 <div class="fieldset login"> 2838 <div class="field email required"> 2839 <label class="label" for="form-login-username" form="login-form" > 2840 <span>Email Address</span> 2841 </label> 2842 <div class="control"> 2843 <input name="username" 2844 id="form-login-username" 2845 x-ref="customer-email" 2846 @change="resetErrors" 2847 type="email" 2848 required 2849 autocomplete="off" 2850 class="form-input" 2851 > 2852 </div> 2853 </div> 2854 <div class="field password required"> 2855 <label for="form-login-password" class="label" form="login-form">
2856 <span>Password</span> 2857 </label> 2858 <div class="control"> 2859 <input name="password" 2860 id="form-login-password" 2861 type="password" 2862 class="form-input" 2863 required 2864 x-ref="customer-password" 2865 autocomplete="off" 2866 @change="resetErrors" 2867 > 2868 </div> 2869 </div> 2870 2871 <input name="context" type="hidden" value="checkout" /> 2872 <div class="actions-toolbar pt-6 pb-2"> 2873 <button type="submit" class="inline-flex btn btn-primary disabled:opacity-75" 2874 > 2875 Sign In </button> 2876 <a href="https://www.riccar.com/customer/account/forgotpassword/" 2877 > 2878 Forgot Your Password? </a> 2879 </div> 2880 2881 </div> 2882 </form> 2883 </div> 2884 <div class="mx-4"> 2885 </div> 2886 <div class="block-new-customer bg-container border border-container mx-4 p-4 shadow-sm"> 2887 <p id="authenticate-new-customer" class="text-lg mb-2 leading-7 text-gray-900"> 2888 <strong class="font-medium">Checkout as a new customer</strong> 2889 </p> 2890 2891 <div class="block-content"> 2892 <p class="mb-1"> 2893 Creating an account has many benefits: </p> 2894 <ul class="list-disc pl-5"> 2895 <li> See order and shipping status</li> 2896 <li> Track order history</li> 2897 <li> Check out faster</li> 2898 </ul> 2899 <div class="actions-toolbar mt-6 mb-2"> 2900 <a href="https://www.riccar.com/customer/account/create/" 2901 class="inline-flex btn btn-primary"> 2902 Create an Account </a> 2903 </div> 2904 </div> 2905 </div> 2906 </div> 2907 </template> 2908 </div> 2909 </div> 2910</section> 2911</div> 2912 2913 2914</header><div class="top-container"><nav class="breadcrumbs" aria-label="Breadcrumb"> 2915 <div class="container"> 2916 <ol class="items list-reset py-4 rounded flex flex-wrap text-black-80"> 2917 <li 2918 class=" 2919 item 2920 home " 2921 > 2922 <a 2923 href="https://www.riccar.com/" 2924 class="no-underline" 2925 title="Home" 2926 > 2927 Home </a> 2928 </li> 2929 <li 2930 class=" 2931 item 2932 blog " 2933 > 2934 <span aria-hidden="true" class="separator text-black-80 px-1">/</span> 2935 <a 2936 href="https://www.riccar.com/blog.html" 2937 class="no-underline" 2938 title="Blog" 2939 > 2940 Blog </a> 2941 </li> 2942 <li 2943 class=" 2944 item 2945 post " 2946 >
2947 <span aria-hidden="true" class="separator text-black-80 px-1">/</span> 2948 <span aria-current="page"> 2949 R27 Clean Air Premium Pet: Best Vacuum for Pet Owners </span> 2950 </li> 2951 </ol> 2952 </div> 2953</nav> 2954</div><main id="maincontent" class="page-main"><div id="contentarea" tabindex="-1"></div> 2955<div class="page messages">
2955<script> 2956 function initMessages() { 2957 "use strict"; 2958 return { 2959 messages: window.mageMessages || [], 2960 isEmpty() { 2961 return this.messages.reduce( 2962 function (isEmpty, message) { 2963 return isEmpty && message === undefined 2964 }, true 2965 ) 2966 }, 2967 hasMessages() { 2968 return !this.isEmpty(); 2969 }, 2970 hasMessage() { 2971 return !!this.message; 2972 }, 2973 removeMessage() { 2974 this.messages[this.index] = undefined; 2975 }, 2976 addMessages(messages, hideAfter) { 2977 messages.map((message) => { 2978 this.messages = this.messages.concat(message); 2979 if (hideAfter === undefined && message.type === 'success' && window.defaultSuccessMessageTimeout) { 2980 hideAfter = window.defaultSuccessMessageTimeout; 2981 } 2982 if (hideAfter) { 2983 this.setHideTimeOut(this.messages.length -1, hideAfter); 2984 } 2985 }); 2986 }, 2987 setHideTimeOut(messageIndex, hideAfter) { 2988 setTimeout((messageIndex) => { 2989 this.messages[messageIndex] = undefined; 2990 }, hideAfter, messageIndex); 2991 }, 2992 eventListeners: { 2993 ['@messages-loaded.window'](event) { 2994 this.addMessages(event.detail.messages, event.detail.hideAfter) 2995 }, 2996 ['@private-content-loaded.window'](event) { 2997 const data = event.detail.data; 2998 if ( 2999 data.messages && 3000 data.messages.messages && 3001 data.messages.messages.length 3002 ) { 3003 this.addMessages(data.messages.messages); 3004 } 3005 }, 3006 ['@clear-messages.window']() { 3007 this.messages = []; 3008 } 3009 }, 3010 getMessageUiId() { 3011 return 'message-' + this.message.type; 3012 } 3013 } 3014 } 3015 3016 window.addEventListener('alpine:init', () => Alpine.data('initMessages', initMessages), {once: true}) 3017</script>
3017 3018<section id="messages" 3019 x-data="initMessages" 3020 x-bind="eventListeners" 3021 role="alert" 3022> 3023 <template x-if="hasMessages"> 3024 <div class="w-full"> 3025 <div class="messages container mx-auto py-3"> 3026 <template x-for="(message, index) in messages" :key="index"> 3027 <div> 3028 <template x-if="hasMessage"> 3029 <div class="message" 3030 :class="message.type" 3031 :ui-id="getMessageUiId" 3032 > 3033 <span x-html="message.text"></span> 3034 <button 3035 type="button" 3036 class="text-gray-600 hover:text-black" 3037 aria-label="Close message" 3038 @click.prevent="removeMessage" 3039 > 3040 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="stroke-current" width="18" height="18" aria-hidden="true"> 3041 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/> 3042</svg> 3043 </button> 3044 </div> 3045 </template> 3046 </div> 3047 </template> 3048 </div> 3049 </div> 3050 </template> 3051</section> 3052</div> <div class="container flex flex-col flex-wrap my-6 md:flex-row lg:mt-8"> 3053 <h1 3054 class="text-4xl tracking-wide font-light md:text-6xl md:font-normal" 3055 > 3056 <span data-ui-id="page-title-wrapper" >R27 Clean Air Premium Pet: Best Vacuum for Pet Owners</span> </h1> 3057 </div> 3058<div class="columns"><aside class="sidebar sidebar-main"> 3059 <div data-amblog-js="element-block" class="desktop-block amblog-element-block" 3060 data-set="sidebar-recentpost"> 3061 <div class="amblog-element-block mb-12 relative"> 3062 <div 3063 class="amblog-post-list amblog-widget-container -recent-posts" 3064 x-data="amblogWidgetAccData_6ab6254aead1d()" 3065 x-init="initAccordion()" 3066 @resize.window.debounce="checkIsMobileResolution()" 3067 > 3068 <h3 3069 class=" 3070 flex justify-between items-center cursor-pointer 3071 md:cursor-default md:pb-2 3072 " 3073 @click="accordionOpen()" 3074 > 3075 <span class="title text-xl font-medium uppercase font-Gotham"> 3076 Recent posts </span> 3077 <span class="py-1 px-1 rounded border border-container md:hidden"> 3078 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="transition-transform transform duration-300 ease-in-out" width="24" height="24" :class="{ 'rotate-180': open }" role="img"> 3079 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 3080<title>chevron-down</title></svg> 3081 </span> 3082 </h3> 3083 <div 3084 class=" 3085 amblog-list pt-4 pb-1 items-start flex flex-col 3086 sm:grid sm:grid-cols-2 sm:gap-4 3087 lg:flex lg:flex-col 3088 " 3089 x-show="open" 3090 > 3091 <div 3092 class=" 3093 post-item-info mb-4 last:mb-0 3094 amblog-recent-post-517 " 3095 > 3096 <a 3097 href="https://www.riccar.com/blog/barefoot-season-is-here.html" 3098 title="Barefoot Season is Here" 3099 aria-label="Barefoot Season is Here" 3100 class="post-image" 3101 > 3102 <img 3103 src="https://www.riccar.com/media/amasty/blog/cache/R/i/300/300/Riccar-0921.jpg" 3104 alt="Barefoot Season is Here" 3105 > 3106 </a> 3107 <div class="post-item-details"> 3108 <div class="amblog-date text-black-80 uppercase mb-1 text-xs font-Gotham font-medium"> 3109 </div> 3110 <a 3111 class=" 3112 post-title font-Gotham text-sm font-medium 3113 hover:text-blue hover:underline 3114 " 3115 href="https://www.riccar.com/blog/barefoot-season-is-here.html" 3116 title="Barefoot Season is Here" 3117 aria-label="Barefoot Season is Here" 3118 > 3119 Barefoot Season is Here </a> 3120 3121 </div> 3122 </div> 3123 <div 3124 class=" 3125 post-item-info mb-4 last:mb-0 3126 amblog-recent-post-311 " 3127 > 3128 <a 3129 href="https://www.riccar.com/blog/understanding-riccar-service-parts.html" 3130 title="Understanding Riccar Service Parts" 3131 aria-label="Understanding Riccar Service Parts" 3132 class="post-image" 3133 > 3134 <img 3135 src="https://www.riccar.com/media/amasty/blog/cache/R/1/300/300/R10P_SupraLiteP_DT_BrushRoll.jpg" 3136 alt="Understanding Riccar Service Parts" 3137 > 3138 </a> 3139 <div class="post-item-details"> 3140 <div class="amblog-date text-black-80 uppercase mb-1 text-xs font-Gotham font-medium"> 3141 </div> 3142 <a 3143 class=" 3144 post-title font-Gotham text-sm font-medium 3145 hover:text-blue hover:underline 3146 " 3147 href="https://www.riccar.com/blog/understanding-riccar-service-parts.html" 3148 title="Understanding Riccar Service Parts" 3149 aria-label="Understanding Riccar Service Parts" 3150 > 3151 Understanding Riccar Service Parts </a> 3152 3153 </div> 3154 </div> 3155 <div 3156 class=" 3157 post-item-info mb-4 last:mb-0 3158 amblog-recent-post-308 " 3159 > 3160 <a 3161 href="https://www.riccar.com/blog/top-10-clean-home-health-benefits.html" 3162 title="Top 10 Health Benefits of a Clean Home" 3163 aria-label="Top 10 Health Benefits of a Clean Home" 3164 class="post-image" 3165 > 3166 <img 3167 src="https://www.riccar.com/media/amasty/blog/cache/I/T/300/300/ITLT_2_0I0A4761-min_1_-99.jpg" 3168 alt="Top 10 Health Benefits of a Clean Home" 3169 > 3170 </a> 3171 <div class="post-item-details"> 3172 <div class="amblog-date text-black-80 uppercase mb-1 text-xs font-Gotham font-medium"> 3173 </div> 3174 <a 3175 class=" 3176 post-title font-Gotham text-sm font-medium 3177 hover:text-blue hover:underline 3178 " 3179 href="https://www.riccar.com/blog/top-10-clean-home-health-benefits.html" 3180 title="Top 10 Health Benefits of a Clean Home" 3181 aria-label="Top 10 Health Benefits of a Clean Home" 3182 > 3183 Top 10 Health Benefits of a Clean Home </a> 3184 3185 </div> 3186 </div> 3187 <div 3188 class=" 3189 post-item-info mb-4 last:mb-0 3190 amblog-recent-post-305 " 3191 > 3192 <a 3193 href="https://www.riccar.com/blog/r27-clean-air-premium-pet-best-vacuum-for-pet-owners.html" 3194 title="R27 Clean Air Premium Pet: Best Vacuum for Pet Owners" 3195 aria-label="R27 Clean Air Premium Pet: Best Vacuum for Pet Owners" 3196 class="post-image" 3197 > 3198 <img 3199 src="https://www.riccar.com/media/amasty/blog/cache/R/2/300/300/R27P.jpg" 3200 alt="R27 Clean Air Premium Pet: Best Vacuum for Pet Owners" 3201 > 3202 </a> 3203 <div class="post-item-details"> 3204 <div class="amblog-date text-black-80 uppercase mb-1 text-xs font-Gotham font-medium"> 3205 </div> 3206 <a 3207 class=" 3208 post-title font-Gotham text-sm font-medium 3209 hover:text-blue hover:underline 3210 " 3211 href="https://www.riccar.com/blog/r27-clean-air-premium-pet-best-vacuum-for-pet-owners.html" 3212 title="R27 Clean Air Premium Pet: Best Vacuum for Pet Owners" 3213 aria-label="R27 Clean Air Premium Pet: Best Vacuum for Pet Owners" 3214 > 3215 R27 Clean Air Premium Pet: Best V
3215acuum for Pet Owners </a> 3216 3217 </div> 3218 </div> 3219 <div 3220 class=" 3221 post-item-info mb-4 last:mb-0 3222 amblog-recent-post-57 " 3223 > 3224 <a 3225 href="https://www.riccar.com/blog/youre-protected.html" 3226 title="You're Protected" 3227 aria-label="You're Protected" 3228 class="post-image" 3229 > 3230 <img 3231 src="https://www.riccar.com/media/amasty/blog/cache/R/1/300/300/R17_Campaign2.jpg" 3232 alt="You're Protected" 3233 > 3234 </a> 3235 <div class="post-item-details"> 3236 <div class="amblog-date text-black-80 uppercase mb-1 text-xs font-Gotham font-medium"> 3237 </div> 3238 <a 3239 class=" 3240 post-title font-Gotham text-sm font-medium 3241 hover:text-blue hover:underline 3242 " 3243 href="https://www.riccar.com/blog/youre-protected.html" 3244 title="You're Protected" 3245 aria-label="You're Protected" 3246 > 3247 You're Protected </a> 3248 3249 </div> 3250 </div> 3251 </div> 3252 </div> 3253 3254
3255<script> 3256 function amblogWidgetAccData_6ab6254aead1d() { 3257 return { 3258 open: true, 3259 isMobile: false, 3260 initAccordion() { 3261 this.checkIsMobileResolution(); 3262 this.open = !this.isMobile; 3263 this.$watch('isMobile', (state) => { 3264 this.open = !state 3265 }) 3266 }, 3267 accordionOpen() { 3268 if (this.isMobile) { 3269 this.open = !this.open 3270 } 3271 }, 3272 checkIsMobileResolution() { 3273 this.isMobile = window.matchMedia('(max-width: 767px)').matches; 3274 } 3275 } 3276 } 3277</script>
3277 3278 </div> </div> 3279 </aside><div class="column main"> 3280 <div data-amblog-js="element-block" class="desktop-block amblog-element-block" 3281 data-set="sidebar-post"> 3282 <div class="amblog-post-container -post-page mb-4"> 3283 <img 3284 class="mb-4" 3285 src="https://www.riccar.com/media/amasty/blog/R27P.jpg" 3286 alt="R27 Clean Air Premium Pet: Best Vacuum for Pet Owners" 3287 /> 3288 <div class="amblog-content"> 3289 <div class="tags my-6"> 3290 </div> 3291 <div class="amblog-post-content"> 3292 <style>#html-body [data-pb-style=D5KI13T],#html-body [data-pb-style=FTTLS8P],#html-body [data-pb-style=N9U4LA4],#html-body [data-pb-style=PK56E45],#html-body [data-pb-style=R62LSO3],#html-body [data-pb-style=Y5Q3B5P]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}</style><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="" data-element="inner" data-pb-style="FTTLS8P"><h2 data-content-type="heading" data-appearance="default" data-element="main">Riccar R27 Clean Air Premium Pet Upright: The Best Vacuum for Pet Owners Who Want a Cleaner, Healthier Home</h2></div></div><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="" data-element="inner" data-pb-style="R62LSO3"><h3 data-content-type="heading" data-appearance="default" data-element="main">Looking for the best vacuum for pet hair and allergies? </h3><div data-content-type="text" data-appearance="default" data-element="main"><p>The Riccar R27 Clean Air Premium Pet Upright is designed for households with pets, offering powerful Clean AirTechnology, HEPA media filtration, and a self-cleaning Fur Get It® tool to remove stubborn pet hair. Unlike bagless vacuums, the R27’s bagged system locks in dust and allergens for cleaner air. Built for durability and supported by Riccar’s Red Carpet Service and warranty, the R27 is ideal for multi-surface homes, allergy sufferers, and busy families. Available for purchase online and at authorized Riccar retailers, where you can also see a live demo.</p> 3293<p> </p></div></div></div><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="" data-element="inner" data-pb-style="Y5Q3B5P"><h3 data-content-type="heading" data-appearance="default" data-element="main">Who Should Choose the Riccar R27 Premium Pet Upright?</h3><div data-content-type="text" data-appearance="default" data-element="main"><p>The Riccar R27 Clean Air Premium Pet Upright is designed for households with pets, offering powerful Clean AirTechnology, HEPA media filtration, and a self-cleaning Fur Get It® tool to remove stubborn pet hair. Unlike bagless vacuums, the R27’s bagged system locks in dust and allergens for cleaner air. Built for durability and supported by Riccar’s Red Carpet Service and warranty, the R27 is ideal for multi-surface homes, allergy sufferers, and busy families. Available for purchase online and at authorized Riccar retailers, where you can also see a live demo.</p> 3294<p> </p></div></div></div><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="" data-element="inner" data-pb-style="N9U4LA4"><h3 data-content-type="heading" data-appearance="default" data-element="main">Features at a Glance</h3><div data-content-type="text" data-appearance="default" data-element="main"><p>Powerful Suction & Airflow –
3294 Cleans deeply into carpets and efficiently on hard floors.<br>HEPA Media Filtration – Traps 99.97% (down to 0.3 microns) of particles for cleaner indoor air.<br>Fur Get It® Pet Tool – Self-cleaning attachment designed specifically for pet hair.<br>Large Capacity Bagged System – Hygienic disposal with no dust clouds.<br>Onboard Tools & Long Hose – Easy to clean stairs, upholstery, and hard-to-reach spots.<br>Adjustable Height Settings – Customizable for different floor types.<br>Durability – Riccar’s craftsmanship ensures years of reliable performance.</p> 3295<p> </p></div></div></div><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="" data-element="inner" data-pb-style="D5KI13T"><h3 data-content-type="heading" data-appearance="default" data-element="main">R27 vs. Other Vacuums: Why Riccar Wins</h3><div data-content-type="text" data-appearance="default" data-element="main"><p>Powerful Suction & Airflow – Cleans deeply into carpets and efficiently on hard floors.<br>HEPA Media Filtration – Traps 99.97% (down to 0.3 microns) of particles for cleaner indoor air.<br>Fur Get It® Pet Tool – Self-cleaning attachment designed specifically for pet hair.<br>Large Capacity Bagged System – Hygienic disposal with no dust clouds.<br>Onboard Tools & Long Hose – Easy to clean stairs, upholstery, and hard-to-reach spots.<br>Adjustable Height Settings – Customizable for different floor types.<br>Durability – Riccar’s craftsmanship ensures years of reliable performance.</p> 3296<p> </p></div></div></div><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-background-type="image" data-video-loop="true" data-video-play-only-visible="true" data-video-lazy-load="true" data-video-fallback-src="" data-background-lazy-load="" data-element="inner" data-pb-style="PK56E45"><h3 data-content-type="heading" data-appearance="default" data-element="main">Pro Tips for Pet Owners</h3><div data-content-type="text" data-appearance="default" data-element="main"><p>Powerful Suction & Airflow – Cleans deeply into carpets and efficiently on hard floors.<br>HEPA Media Filtration – Traps 99.97% (down to 0.3 microns) of particles for cleaner indoor air.<br>Fur Get It® Pet Tool – Self-cleaning attachment designed specifically for pet hair.<br>Large Capacity Bagged System – Hygienic disposal with no dust clouds.<br>Onboard Tools & Long Hose – Easy to clean stairs, upholstery, and hard-to-reach spots.<br>Adjustable Height Settings – Customizable for different floor types.<br>Durability – Riccar’s craftsmanship ensures years of reliable performance.</p> 3297<p> </p></div></div></div> </div> 3298 </div> 3299 <div class="amblog-footer"> 3300 3301 <div class="amblog-dates text-gray-400 font-light text-sm flex mt-4"> 3302 <span class="amblog-date text-black-80 uppercase mb-2 text-md font-Gotham font-medium"> 3303 January 20, 2026 </span> 3304 </div> 3305 </div> 3306 3307 </div> 3308 3309 3310 3311 3312<div class="amblog-overlay" data-amblog-js="overlay"></div> 3313
3314<script> 3315 'use strict'; 3316 3317 function dataComments() { 3318 return { 3319 replyCount: 0, 3320 isLoading: false, 3321 isShowViews: false, 3322 3323 options: { 3324 form_selector: '.amblog-comment-reply', 3325 form_url: 'https://www.riccar.com/amblog/index/form/reply_to/%7B%7Breply_to%7D%7D/post_id/%7B%7Bpost_id%7D%7D/session_id/%7B%7Bsession_id%7D%7D/', 3326 update_url: 'https://www.riccar.com/amblog/index/updateComments/', 3327 post_url: 'https://www.riccar.com/amblog/index/postForm/reply_to/%7B%7Breply_to%7D%7D/post_id/%7B%7Bpost_id%7D%7D/', 3328 post_id: '305', 3329 session_id: '5191ce0200a587967d8ddd9a091b7534', 3330 maxDeep: 2 3331 }, 3332 3333 selectors: { 3334 topCommentsWrapper: '.top-comments-wrapper', 3335 gdpr: '[name="gdpr_agree"]', 3336 viewsCounter: 'amblog-views-counter', 3337 commentsWrapper: '.comments_wrapper', 3338 shortComments: '#short_comments', 3339 commentsForm: '#comments-form', 3340 replies: '.amblog-replies', 3341 }, 3342 3343 classes: { 3344 deepReply: 'deep-reply', 3345 pointer: 'pointer-events-none', 3346 fillGrey: 'fill-amb_grey', 3347 fillBlue: 'fill-amb_blue_icon', 3348 textGrey: 'text-amb_grey', 3349 textBlue: 'text-amb_blue_icon' 3350 }, 3351 3352 windowReplace: window.location.href.replace(/:[^:].*$/i, ''), 3353 3354 initComments() { 3355 this.checkLocation(); 3356 this.postViewStatistic(); 3357 this.loadCommentsByAjax(); 3358 }, 3359 3360 getReplyCount(el) { 3361 return el.closest('.comment-item') 3362 .querySelectorAll('.comment-item').length; 3363 }, 3364 3365 getReplyForm(el) { 3366 const container = el.getAttribute('href').replace('#', ''), 3367 id = el.getAttribute('data-id'); 3368 3369 this.showForm(container, id); 3370 }, 3371 3372 innerElements(elementSelector, data) { 3373 const tmpElement = document.createElement('div'); 3374 const element = document.querySelector(elementSelector); 3375 tmpElement.innerHTML = data; 3376 const commentsWrapper = tmpElement.querySelector(elementSelector) 3377 3378 if (element && commentsWrapper && commentsWrapper.firstChild) { 3379 element.innerHTML = commentsWrapper.innerHTML; 3380 } 3381 3382 if (element && !commentsWrapper) { 3383 element.innerHTML = data; 3384 } 3385 }, 3386 3387 parents(el, selector) { 3388 const parents = []; 3389 while ((el = el.parentNode) && el !== document) { 3390 if (!selector || el.matches(selector)) parents.push(el); 3391 } 3392 return parents; 3393 }, 3394 3395 loadCommentsByAjax() { 3396 fetch(this.options.update_url+ '?form_key=' + hyva.getFormKey() + 3397 '&post_id=305', 3398 { 3399 method: 'GET', 3400 headers: { 3401 'Content-type': 'application/json', 3402 'X-Requested-With': 'XMLHttpRequest' 3403 } 3404 } 3405 ) 3406 .then(response => response.json()) 3407 .then(result => { 3408 if (result.content) { 3409 this.innerElements(this.selectors.commentsWrapper, result.content); 3410 3411 if (result.short_content) { 3412 this.innerElements(this.selectors.shortComments, result.short_content); 3413 } 3414 3415 if (result.comments_form) { 3416 this.innerElements(this.selectors.commentsForm, result.comments_form); 3417 } 3418 3419 this.setDeepReplyClass(); 3420 } else if (data.error) { 3421 console.warn(data.error); 3422 } 3423 }); 3424 }, 3425 3426 setDeepReplyClass() { 3427 const commentsWrapper = document.querySelector(this.selectors.commentsWrapper), 3428 replies = commentsWrapper.querySelectorAll(this.selectors.replies); 3429
3430 replies.forEach(reply => { 3431 if (this.parents(reply, this.selectors.replies).length >= this.options.maxDeep) { 3432 reply.classList.add(this.classes.deepReply); 3433 } 3434 }); 3435 }, 3436 3437 checkLocation() { 3438 // Redirect to form after login 3439 if (window.location.hash) { 3440 if (window.location.hash === '#add-comment') { 3441 this.showForm('amblog-comment-form', 0); 3442 } else if (window.location.hash.indexOf('#reply-to-') !== -1) { 3443 const replyTo = window.location.hash.replace('#reply-to-', ''); 3444 this.showForm('am-comment-form-' + replyTo, replyTo); 3445 } 3446 } 3447 }, 3448 3449 hideForm(el) { 3450 const container = el.closest('.amblog-comment-reply'); 3451 3452 container.innerHTML = ''; 3453 container.style.display = 'none'; 3454 }, 3455 3456 showForm(container, id) { 3457 const formContainer = document.getElementById(container), 3458 formID = formContainer.getAttribute('id'); 3459 3460 if (formContainer && formContainer.style.display === 'none') { 3461 document.querySelectorAll('.amblog-comment-reply').forEach(containerReply => { 3462 if (containerReply !== formContainer) { 3463 containerReply.innerHTML = ''; 3464 containerReply.style.display = 'none'; 3465 } 3466 }); 3467 3468 formContainer.style.display = 'block'; 3469 3470 this.loadFormToContainer(container, id, formID); 3471 } 3472 3473 return false; 3474 }, 3475 3476 loadFormToContainer: function (container, id, formID) { 3477 let url = decodeURI( 3478 this.options.form_url.replace(/^http[s]{0,1}/, 3479 this.windowReplace) 3480 ); 3481 3482 this.isLoading = true; 3483 fetch(this.getFormattedUrl(url, id), { 3484 headers: { 3485 'Content-type': 'application/json', 3486 'X-Requested-With': 'XMLHttpRequest' 3487 } 3488 } 3489 ) 3490 .then(response => response.json()) 3491 .then(result => { 3492 if (result.form) { 3493 document.getElementById(container).innerHTML = result.form; 3494 3495 if (formID) { 3496 this.addFormHash(formID); 3497 } 3498 } 3499 }) 3500 .catch(this.displayError) 3501 .finally(() => { 3502 this.isLoading = false; 3503 }); 3504 }, 3505 3506 addFormHash(formID) { 3507 window.location.hash = '#' + formID; 3508 document.querySelector('#' + formID).scrollIntoView({block: 'start', behavior: 'smooth'}); 3509 }, 3510 3511 getReplyLabel(el, isShow) { 3512 if (isShow) { 3513 return 'Hide replies'; 3514 } 3515 3516 const repliesCount = this.getReplyCount(el), 3517 replyText = repliesCount > 1 ? 3518 'replies' : 3519 'reply'; 3520 3521 return repliesCount + ' ' + replyText; 3522 }, 3523 3524 showReply(el) { 3525 let display = 'none'; 3526 const replys = el.closest('.amblog-comment') 3527 .querySelector('.amblog-replies').children, 3528 isShow = replys[0].style.display === display; 3529 3530 if (isShow) { 3531 display = 'block'; 3532 } 3533 3534 for (const reply of replys) { 3535 reply.style.display = display; 3536 } 3537 3538 el.innerHTML = this.getReplyLabel(el, isShow); 3539 }, 3540 3541 sendForm(form) { 3542 let url = decodeURI(this.options.post_url), 3543 values = this.serializeForm(form), 3544 replyTo = values.filter(val => val.name === 'reply_to' ); 3545 3546 if (form.querySelectorAll(this.selectors.gdpr).length 3547 && !form.querySelectorAll(this.selectors.gdpr + ':checked').length 3548 ) { 3549 values.email = ''; 3550 values.name = ''; 3551 values['customer_id'] = 0; 3552 } 3553 3554 if (!('name' in values)) { 3555 values.name = ''; 3556 } 3557 3558 this.isLoading = true; 3559 fetch(this.getClearUrlParams(this.getFormattedUrl(url, replyTo[0].value), values), { 3560 method: 'POST', 3561 headers: { 3562 'Content-type': 'application/json', 3563 'X-Requested-With': 'XMLHttpRequest' 3564 } 3565 } 3566 ) 3567 .then(response => response.json()) 3568 .then(result => { 3569 form.querySelector('textarea').value = ''; 3570 3571 let commentsBlock = document.querySelector('.amblog-comments-block'); 3572 3573 if (form.classList.contains('reply-form')) { 3574 commentsBlock = form 3575 .closest('.amblog-replies-block') 3576 .querySelector('.amblog-replies'); 3577 3578 commentsBlock.style.display = 'block'; 3579 } 3580 3581 this.insertBeforeElement(commentsBlock, result.message); 3582 commentsBlock.querySelector('div > .comment-item').style.display = 'block'; 3583 3584 const commentItem = commentsBlock.closest('.comment-item'); 3585 if (commentItem) { 3586 const commentBtn = commentItem 3587 .querySelector('.amblog-comment-content button.replies-button'), 3588 commentBtnLabel = commentBtn.querySelector('span'), 3589 commentBtnSVG = commentBtn.querySelector('svg'); 3590 3591 commentBtnLabel.innerHTML = this.getReplyLabel(commentBtnLabel, true); 3592 3593 commentBtn.classList.remove(this.classes.pointer); 3594 commentBtnLabel.classList.remove(this.classes.textGrey); 3595 commentBtnLabel.classList.add(this.classes.textBlue);; 3596 commentBtnSVG.classList.remove(this.classes.fillGrey); 3597 commentBtnSVG.classList.add(this.classes.fillBlue); 3598 } 3599 }) 3600 .catch(this.displayError) 3601 .finally(() => { 3602 this.isLoading = false;
3603 }); 3604 }, 3605 3606 getClearUrlParams(url, data) { 3607 let params = ''; 3608 3609 url = url.replace('#', ''); 3610 3611 data.map(param => { 3612 if (params) { 3613 params += '&'; 3614 } 3615 3616 params += param.name + '=' + param.value; 3617 }); 3618 3619 if (~url.indexOf('?')) { 3620 url += '&'; 3621 } else { 3622 url += '?'; 3623 } 3624 3625 return url + params; 3626 }, 3627 3628 getFormattedUrl(url, replyTo) { 3629 return url.replace('{{post_id}}', this.options.post_id) 3630 .replace('{{session_id}}', this.options.session_id) 3631 .replace('{{reply_to}}', replyTo) 3632 .replace(/^http[s]{0,1}/, this.windowReplace); 3633 }, 3634 3635 insertBeforeElement(parent, message) { 3636 const before = parent.querySelector('div'), 3637 div = document.createElement('div'); 3638 3639 div.innerHTML = message; 3640 3641 parent.insertBefore(div, before); 3642 }, 3643 3644 serializeForm(form) { 3645 const data = new FormData(form) 3646 let array = []; 3647 for (let [key, value] of data) { 3648 array.push({ 3649 name: key, 3650 value: value 3651 }); 3652 } 3653 3654 return array; 3655 }, 3656 3657 displayError(error) { 3658 if (error.name === 'AbortError') { 3659 console.log('Fetch aborted'); 3660 } else { 3661 console.error(error); 3662 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 3663 [{ 3664 type: "error", 3665 text: "Something\u0020went\u0020wrong.\u0020Please\u0020try\u0020again." 3666 }], 10000 3667 ); 3668 } 3669 }, 3670 3671 postViewStatistic() { 3672 fetch(BASE_URL + 'amblog/index/view?form_key=' + hyva.getFormKey() + 3673 '&post_id=305', 3674 { 3675 method: 'GET', 3676 headers: { 3677 'Content-type': 'application/json', 3678 'X-Requested-With': 'XMLHttpRequest' 3679 } 3680 } 3681 ) 3682 .then(response => response.json()) 3683 .then(result => { 3684 const viewsCount = result.views_count; 3685 3686 if (!isNaN(viewsCount) && this.isShowViews) { 3687 document.getElementById(this.selectors.viewsCounter).innerHTML = 3688 '%1 view(s)'.replace('%1', viewsCount); 3689 } 3690 }); 3691 } 3692 } 3693 } 3694</script>
3694 3695 3696
3697<script> 3698 'use strict'; 3699 3700 function HumanizeDateComponent() { 3701 return { 3702 now: new Date(), 3703 timeData: '', 3704 dateString: '', 3705 formattedDate: '', 3706 3707 /** 3708 * Renders a date in the local timezone, including day of the week. 3709 * e.g. 'Fri, 22 May 2020' 3710 */ 3711 dateFormatter: new Intl.DateTimeFormat([], { 3712 'year': 'numeric', 3713 'month': 'long', 3714 'day': 'numeric', 3715 'weekday': 'short' 3716 }), 3717 3718 /** 3719 * Renders an HH:MM time in the local timezone, including timezone info. 3720 * e.g. '12:17 BST' 3721 */ 3722 timeFormatter: new Intl.DateTimeFormat([], { 3723 'hour': 'numeric', 3724 'minute': 'numeric', 3725 'timeZoneName': 'short' 3726 }), 3727 3728 /** 3729 * @returns {void} 3730 */ 3731 initializeDates(dateString) { 3732 this._prepareNowDate(); 3733 this._processDateString(dateString); 3734 this._setTimeData(); 3735 this._setDate(); 3736 }, 3737 3738 /** 3739 * Convert current date to UTC. 3740 * @private 3741 * @returns {void} 3742 */ 3743 _prepareNowDate() { 3744 this.now = new Date( 3745 this.now.getUTCFullYear(), 3746 this.now.getUTCMonth(), 3747 this.now.getUTCDate(), 3748 this.now.getUTCHours(), 3749 this.now.getUTCMinutes(), 3750 this.now.getUTCSeconds(), 3751 this.now.getUTCMilliseconds() 3752 ); 3753 }, 3754 3755 /** 3756 * For iOS devices is need to replace the 'space' with a 'T' to conform to a simplified version of ISO-8601. 3757 * @private 3758 * @returns {void} 3759 */ 3760 _processDateString(dateString) { 3761 this.parsedDate = new Date(Date.parse(dateString.replace(' ', 'T'))); 3762 }, 3763 3764 /** 3765 * @private 3766 * @returns {void} 3767 */ 3768 _setTimeData() { 3769 const delta = this.now - this.parsedDate, 3770 seconds = Math.floor(delta / 1000), 3771 minutes = Math.floor(seconds / 60), 3772 hours = Math.floor(minutes / 60), 3773 days = Math.floor(hours / 24), 3774 months = Math.floor(days / 30), 3775 years = Math.floor(days / 365); 3776 3777 this.timeData = { 3778 seconds: { 3779 value: seconds, 3780 label: 'second' 3781 }, 3782 minutes: { 3783 value: minutes, 3784 label: 'minute' 3785 }, 3786 hours: { 3787 value: hours, 3788 label: 'hour' 3789 }, 3790 days: { 3791 value: days, 3792 label: 'day' 3793 }, 3794 months: { 3795 value: months, 3796 label: 'month' 3797 }, 3798 years: { 3799 value: years, 3800 label: 'year' 3801 } 3802 }; 3803 }, 3804 3805 /** 3806 * @private 3807 * @returns {Boolean} 3808 */ 3809 _isToday() { 3810 return this.dateFormatter.format(this.parsedDate) === this.dateFormatter.format(this.now); 3811 }, 3812 3813 /** 3814 * @private 3815 * @returns {Boolean} 3816 */ 3817 _isYesterday() { 3818 const yesterday = new Date().setDate(this.now.getDate() - 1); 3819 3820 return this.dateFormatter.format(this.parsedDate) === this.dateFormatter.format(yesterday); 3821 }, 3822 3823 /** 3824 * @private 3825 * @returns {String} 3826 */ 3827 _getFormattedDate() { 3828 const timeData = this.timeData; 3829 3830 if (timeData.seconds.value < 5) { 3831 return 'just now'; 3832 } 3833 3834 if (timeData.seconds.value < 60) { 3835 return this._getFormattedValue(timeData.seconds); 3836 } 3837 3838 if (timeData.minutes.value < 60) { 3839 return this._getFormattedValue(timeData.minutes); 3840 } 3841 3842 if (timeData.hours.value < 24) { 3843 return this._getFormattedValue(timeData.hours); 3844 } 3845 3846 if (timeData.days.value < 30) { 3847 return this._getFormattedValue(timeData.days); 3848 } 3849 3850 if (timeData.months.value < 12) { 3851 return this._getFormattedValue(timeData.months); 3852 } 3853 3854 return this._getFormattedValue(timeData.years); 3855 }, 3856 3857 /** 3858 * @private 3859 * @param {Object} data 3860 * @returns {String} 3861 */ 3862 _getFormattedValue(data) { 3863 const postfix = this._getPostfix(data.value); 3864 let formatted = '%1' + ' ' + data.label + postfix + ' ago'; 3865 3866 3867 return this._getDateTranslate(formatted).replace('%1', data.value); 3868 }, 3869 3870 /** 3871 * @private 3872 * @param {Number} value 3873 * @returns {String} 3874 */ 3875 _getPostfix(value) { 3876 return value === 1 ? '' : 's'; 3877 }, 3878 3879 /** 3880 * @private 3881 * @returns {void} 3882 */ 3883 _setDate() { 3884 this.formattedDate = this._getFormattedDate(); 3885 }, 3886 3887 /** 3888 * @public 3889 * @returns {String} 3890 */ 3891 getDate() { 3892 return this.formattedDate; 3893 }, 3894 3895 /** 3896 * @private 3897 * @param {String} string 3898 * @returns {String} 3899 */ 3900 _getDateTranslate(string) { 3901 const translate = { 3902 '%1 second ago': '%1 second ago', 3903 '%1 seconds ago': '%1 seconds ago', 3904 '%1 minute ago': '%1 minute ago', 3905 '%1 minutes ago': '%1 minutes ago', 3906 '%1 day ago': '%1 day ago', 3907 '%1 days ago': '%1 days ago', 3908 '%1 month ago': '%1 month ago', 3909 '%1 months ago': '%1 months ago', 3910 '%1 year ago': '%1 year ago', 3911 '%1 years ago': '%1 years ago' 3912 } 3913
3914 return translate[string] || string; 3915 }, 3916 3917 /** 3918 * Returns formatted date 3919 * @public 3920 * @returns {String} 3921 */ 3922 getHumanizeDate() { 3923 return this.formattedDate; 3924 } 3925 } 3926 } 3927</script>
3927 3928 3929
3929<script type="application/ld+json">{"@context":"http:\/\/schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"undefined"},"datePublished":"2026-01-20 20:23:00","dateModified":"2026-01-27 19:48:35","name":"R27 Clean Air Premium Pet: Best Vacuum for Pet Owners","description":"","image":"https:\/\/www.riccar.com\/media\/amasty\/blog\/R27P.jpg","mainEntityOfPage":"https:\/\/www.riccar.com\/blog\/r27-clean-air-premium-pet-best-vacuum-for-pet-owners.html","headline":"R27 Clean Air Premium Pet: Best Vacuum for Pet Owners"}</script>
3929 3930
3930<script type="application/ld+json">{"@context":"http:\/\/schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"https:\/\/www.riccar.com\/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"https:\/\/www.riccar.com\/blog.html","name":"Blog"}}]}</script>
3930 </div> 3931 3932 <div 3933 class="z-10 fixed bottom-4 inset-x-4 sm:w-96 max-w-prose mx-auto p-4 rounded shadow-2xl bg-container-lighter 3934 lg:absolute lg:bottom-auto lg:right-auto lg:top-[var(--msrp-block-offset)] lg:left-[var(--msrp-inline-offset)] lg:shadow-lg lg:max-w-xs" 3935 :style="setPosition()" 3936 x-data="initMsrpPopover()" 3937 x-cloak 3938 x-show="open" 3939 x-transition:enter="transition ease-out duration-300 opacity-0 translate-y-full lg:-translate-y-0" 3940 x-transition:enter-end="transition ease-out duration-300 opacity-100 translate-y-0" 3941 x-transition:leave="transition ease-in duration-150 opacity-0 translate-y-full lg:-translate-y-0" 3942 @click.outside="closePopover($event)" 3943 @msrp-popover.window="showPopover($event.detail)" 3944 @resize.window.debounce="closePopover()" 3945 @keydown.window.escape="closePopover()" 3946 > 3947 <div class="flex justify-between gap-2 mb-2"> 3948 <strong id="map-popup-heading-price" class="font-bold" x-text="title"></strong> 3949 <button 3950 type="button" 3951 @click="closePopover()" 3952 aria-label="Close panel" 3953 title="Close panel" 3954 > 3955 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true"> 3956 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/> 3957</svg> 3958 </button> 3959 </div> 3960 3961 <template x-if="type !== 'help'"> 3962 <div class="mb-4 text-sm"> 3963 <dl class="price-box"> 3964 <div class="flex gap-2"> 3965 <dt class="font-semibold whitespace-nowrap">Price:</dt> 3966 <dd x-html="msrpPrice" class="flex flex-col"></dd> 3967 </div> 3968 <div class="flex gap-2"> 3969 <dt class="font-semibold whitespace-nowrap">Actual Price:</dt> 3970 <dd x-html="actualPrice" class="flex flex-col"></dd> 3971 </div> 3972 </dl> 3973 </div> 3974 </template> 3975 3976 <div class="text-sm" x-html="content"></div> 3977 3978
3978<script> 3979 function initMsrpPopover() { 3980 return { 3981 open: false, 3982 type: "price", // price or help 3983 title: '', 3984 content: 'Our price is lower than the manufacturer's "minimum advertised price." As a result, we cannot show you the price in catalog or the product page. <br><br> You have no obligation to purchase the product once you know the price. You can simply remove the item from your cart.', 3985 isSaleable: false, 3986 actualPrice: null, 3987 msrpPrice: null, 3988 productId: null, 3989 anchor: null, 3990 position: ['0', '0'], 3991 isInViewport() { 3992 const pageWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; 3993 const offset = this.anchor.offsetLeft + this.$root.offsetWidth; 3994 return pageWidth > offset; 3995 }, 3996 setPosition() { 3997 return { 3998 '--msrp-block-offset': this.position[0], 3999 '--msrp-inline-offset': this.position[1] 4000 } 4001 }, 4002 calcPosition() { 4003 const target = this.anchor; 4004 const pageTop = target.getBoundingClientRect().top + window.scrollY; 4005 const pageLeft = target.getBoundingClientRect().left + window.scrollX; 4006 const positionBlock = `${pageTop + target.clientHeight}px`; 4007 const positionInline = this.isInViewport() 4008 ? `${pageLeft}px` 4009 : `${(pageLeft - (this.$root.offsetWidth - target.offsetWidth))}px`; 4010 this.position = [positionBlock, positionInline] 4011 }, 4012 closePopover(event) { 4013 if (event && event.target === this.anchor) return; 4014 this.open = false; 4015 }, 4016 showPopover(event) { 4017 const data = event.msrpData; 4018 if (!data) return; 4019 4020 this.open = true; 4021 this.type = data.type; 4022 this.productId = data.id; 4023 this.isSaleable = data.isSaleable; 4024 this.actualPrice = data.realPrice; 4025 this.msrpPrice = data.msrpPrice; 4026 this.title = this.type === 'help' 4027 ? '' 4028 : data.productName; 4029 this.content = this.type === 'help' 4030 ? 'Our price is lower than the manufacturer's "minimum advertised price." As a result, we cannot show you the price in catalog or the product page. <br><br> You have no obligation to purchase the product once you know the price. You can simply remove the item from your cart.' 4031 : 'Our price is lower than the manufacturer's "minimum advertised price." As a result, we cannot show you the price in catalog or the product page. <br><br> You have no obligation to purchase the product once you know the price. You can simply remove the item from your cart.'; 4032 4033 if (event.target) { 4034 this.anchor = event.target; 4035 this.$nextTick(() => this.calcPosition()); 4036 } 4037 } 4038 } 4039 } 4040 </script>
4040 4041 </div> 4042
4042<script nonce="OGF6cnd0b3FqaXhvOTVsbTJ0Mno1Zmd2ajh4a2QyMHE="> 4043 function hasWebP() { 4044 var elem = document.createElement('canvas'); 4045 4046 if (!!(elem.getContext && elem.getContext('2d'))) { 4047 return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0; 4048 } 4049 return false; 4050 } 4051 4052 if (hasWebP()) { 4053 document.body.classList.add("webp"); 4054 } else { 4055 document.body.classList.add("no-webp"); 4056 }</script>
4056<script type="text/javascript"> 4057 require(['jquery'], function ($) { 4058 $(document).ready(function () { 4059 $("img").each(function () { 4060 if (!$(this).attr("alt")) { 4061 var src = $(this).attr("src"); 4062 var fileName = src.substring(src.lastIndexOf('/')); 4063 /** 4064 * Replace .jpg|.png|.bmp|.svg|/|-| of filename equal whitespace 4065 * @type {string} 4066 */ 4067 var alt = fileName.replace(/.jpg|.png|.gif|.bmp|.svg|\/|-/gi, ''); 4068 $(this).attr("alt", alt.trim()); 4069 } 4070 }); 4071 }); 4072 }); 4073</script>
4073 4074
4075<script> 4076 const rawRequest = ""; 4077 const searchRequest = rawRequest ? JSON.parse(rawRequest) : null; 4078 4079 const rawResponse = ""; 4080 const searchResponse = rawResponse ? JSON.parse(rawResponse) : null; 4081 4082 const rawExecutionTime = "0"; 4083 const executionTime = rawExecutionTime ? parseFloat(rawExecutionTime) : null; 4084 4085 const requestId = "c7ecef0b\u002D3a36\u002D4ae8\u002D9817\u002Dd5315bf93c74"; 4086 4087 const rawAttributes = ""; 4088 const attributes = rawAttributes ? JSON.parse(rawAttributes) : null; 4089 4090 const rawPageSize = "24"; 4091 const pageSize = rawPageSize ? parseInt(rawPageSize) : null; 4092 4093 const customerGroup = "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c"; 4094 4095 window.LiveSearchMetrics = { 4096 searchRequest, 4097 searchResponse, 4098 requestId, 4099 executionTime, 4100 attributes, 4101 pageSize, 4102 context: { 4103 'customerGroup' : customerGroup 4104 } 4105 }; 4106 4107 window.addEventListener('load', function () { 4108 magentoStorefrontEvents.context.setSearchExtension({ 4109 version: "4.7.2" 4110 }); 4111 }) 4112</script>
4112 4113</div></div></main><footer class="page-footer"><div class="footer content">
4113<script> 4114 addEventListener('DOMContentLoaded', () => { 4115 for (const [selector, label] of Object.entries({"aside.sidebar-main":"Sidebar Main","aside.sidebar-additional":"Sidebar Additional"})) { 4116 const target = document.querySelector(selector); 4117 target && target.setAttribute('aria-label', label); 4118 } 4119 }, {once: true}) 4120</script>
4120 4121<div class="bg-primary-darker pt-14 text-white"> 4122 <div class="container"> 4123 <div class="border-b border-white pb-14 mb-14 grid md2:grid-cols-3"> 4124 4125 <div class="text-white mb-14 md2:col-span-2 md2:mb-0"> 4126 <form 4127 class="form subscribe grid sm:grid-cols-2 sm:gap-x-8" 4128 action="https://www.riccar.com/newsletter/subscriber/new/" 4129 method="post" 4130 x-data="initNewsletterForm()" 4131 @submit.prevent="submitForm()" 4132 id="newsletter-validate-detail" 4133 aria-label="Subscribe to Newsletter" 4134 > 4135 <div class="mb-6"> 4136 <h2 4137 class="font-Gotham text-xl uppercase mb-5 font-medium" 4138 id="footer-newsletter-heading" 4139 > 4140 Join our email list: 4141 </h2> 4142 <p class="text-black-20"> 4143 Sign up for savings and product announcements. </p> 4144 </div> 4145 4146 <div class="flex flex-col"> 4147 <div class="relative mb-6"> 4148 <label for="newsletter-subscribe" class="sr-only"> 4149 Email Address </label> 4150 <input 4151 name="email" 4152 type="email" 4153 required 4154 id="newsletter-subscribe" 4155 class="form-input inline-flex w-full text-primary rounded-none" 4156 placeholder="Enter your email" 4157 aria-describedby="footer-newsletter-heading" 4158 > 4159 <input name="form_key" type="hidden" value="eWVZzr6eztTWwg5P" /> <button 4160 class=" 4161 absolute right-0 top-0 bottom-0 btn btn-quaternary 4162 rounded-none !outline-orange-500 4163 " 4164 > 4165 Sign up </button> 4166 </div> 4167 <div class="text-white flex items-center"> 4168 <input 4169 name="newsletter-agreements" 4170 class="mr-4 !outline-orange-500" 4171 required 4172 id="newsletter-agreements" 4173 type="checkbox" 4174 /> 4175 <label for="newsletter-agreements" class="text-white text-xs mb-0"> 4176 I agree to the <a href="https://www.tacony.com/terms-of-use.html" class="font-medium underline leading-4">Terms & Conditions</a> and wish to receive promotional emails and updates from Riccar. </label> 4177 </div> 4178 <div class="newsletter-hcaptcha mt-4 flex justify-start"> 4179 4180 <input type="hidden" name="hcaptcha_marker" value="1"> 4181 <div class="captcha-wrapper my-4"> 4182 <div class="h-captcha" id="h-captcha-newsletter" 4183 data-sitekey="4940c24a-6722-48aa-812a-e40c333435c0" 4184 data-page-type="newsletter" 4185 data-form-selector="#newsletter-validate-detail"> 4186 </div> 4187 <div id="h-captcha-newsletter-error" class="text-red-600 mt-1" style="display:none;"> 4188 <span> 4189 This is a required field. </span> 4190 </div> 4191 </div> 4192 4193
4193<script> 4194 (function () { 4195 'use strict'; 4196 4197 const pageType = 'newsletter'; 4198 const containerId = 'h\u002Dcaptcha\u002Dnewsletter'; 4199 const formSelector = '\u0023newsletter\u002Dvalidate\u002Ddetail'; 4200 const isInvisible = false; 4201 4202 window.hCaptchaInstances = window.hCaptchaInstances || {}; 4203 window.hCaptchaRendered = window.hCaptchaRendered || {}; 4204 4205 const config = { 4206 siteKey: '4940c24a-6722-48aa-812a-e40c333435c0', 4207 theme: 'light', 4208 size: 'normal' 4209 }; 4210 4211 /** Check if hCaptcha is already rendered in container */ 4212 function isAlreadyRendered(containerId) { 4213 const container = document.getElementById(containerId); 4214 if (!container) { 4215 return false; 4216 } 4217 if (window.hCaptchaRendered[containerId]) { 4218 return true; 4219 } 4220 if (container.querySelector('iframe[src*="hcaptcha.com"]')) { 4221 window.hCaptchaRendered[containerId] = true; 4222 return true; 4223 } 4224 if (window.hCaptchaInstances[containerId] !== undefined) { 4225 return true; 4226 } 4227 return false; 4228 } 4229 4230 function renderHcaptcha(type, containerId) { 4231 if (isAlreadyRendered(containerId)) { 4232 return; 4233 } 4234 const container = document.getElementById(containerId); 4235 if (!container) { 4236 return; 4237 } 4238 if (typeof hcaptcha === 'undefined') { 4239 return; 4240 } 4241 try { 4242 const existingIframe = container.querySelector('iframe'); 4243 if (existingIframe) { 4244 return; 4245 } 4246 const widgetId = hcaptcha.render(container, { 4247 sitekey: config.siteKey, 4248 theme: config.theme, 4249 size: config.size, 4250 callback: function (token) { 4251 onHcaptchaSuccess(containerId, token); 4252 }, 4253 'expired-callback': function () { 4254 onHcaptchaExpired(containerId); 4255 }, 4256 'error-callback': function () { 4257 console.error('hCaptcha error occurred'); 4258 } 4259 }); 4260 window.hCaptchaInstances[containerId] = widgetId; 4261 window.hCaptchaRendered[containerId] = true; 4262 } catch (e) { 4263 console.error('hCaptcha render error:', e); 4264 window.hCaptchaRendered[containerId] = false; 4265 } 4266 } 4267 4268 /** 4269 * Callback when hCaptcha is successfully completed 4270 */ 4271 function onHcaptchaSuccess(containerId, token) { 4272 const form = document.querySelector(formSelector); 4273 if (form) { 4274 const checkboxes = form.querySelectorAll('input[type=checkbox].required-captcha'); 4275 checkboxes.forEach(checkbox => checkbox.checked = true); 4276 } 4277 hideError(); 4278 if (isInvisible && form) { 4279 // Remove js event prevention temporarily 4280 const alpineSubmitAttr = form.getAttribute('@submit.prevent'); 4281 if (alpineSubmitAttr) { 4282 form.removeAttribute('@submit.prevent'); 4283 } 4284 setTimeout(function () { 4285 HTMLFormElement.prototype.submit.call(form); 4286 }, 100); 4287 } 4288 } 4289 4290 /** Callback when hCaptcha expires */ 4291 function onHcaptchaExpired(containerId) { 4292 const form = document.querySelector(formSelector); 4293 if (form) { 4294 const checkboxes = form.querySelectorAll('input[type=checkbox].required-captcha');
4295 checkboxes.forEach(checkbox => checkbox.checked = false); 4296 } 4297 } 4298 4299 /** Show error message */ 4300 function showError() { 4301 const errorElement = document.getElementById(containerId + '-error'); 4302 if (errorElement) { 4303 errorElement.style.display = 'block'; 4304 } 4305 } 4306 4307 /** Hide error message */ 4308 function hideError() { 4309 const errorElement = document.getElementById(containerId + '-error'); 4310 if (errorElement) { 4311 errorElement.style.display = 'none'; 4312 } 4313 } 4314 4315 /** Validate hCaptcha before form submission */ 4316 function validateHcaptcha() { 4317 const container = document.getElementById(containerId); 4318 if (!container) { 4319 return true; 4320 } 4321 const hcaptchaResponse = container.querySelector('textarea[name="h-captcha-response"]'); 4322 // For invisible captcha, check if response exists 4323 if (isInvisible) { 4324 if (!hcaptchaResponse || hcaptchaResponse.value === '') { 4325 // Execute invisible captcha 4326 executeInvisibleCaptcha(); 4327 return false; 4328 } 4329 hideError(); 4330 return true; 4331 } 4332 // For visible captcha, show error if not completed 4333 if (!hcaptchaResponse || hcaptchaResponse.value === '') { 4334 showError(); 4335 container.scrollIntoView({ behavior: 'smooth', block: 'center' }); 4336 return false; 4337 } 4338 hideError(); 4339 return true; 4340 } 4341 4342 /** Execute invisible captcha */ 4343 function executeInvisibleCaptcha() { 4344 if (typeof hcaptcha === 'undefined' || window.hCaptchaInstances[containerId] === undefined) { 4345 // Try to render first if not rendered 4346 if (!isAlreadyRendered(containerId)) { 4347 renderHcaptcha(pageType, containerId); 4348 setTimeout(executeInvisibleCaptcha, 200); 4349 } 4350 return; 4351 } 4352 try { 4353 hcaptcha.execute(window.hCaptchaInstances[containerId]); 4354 } catch (e) { 4355 console.error('hCaptcha execute error:', e); 4356 } 4357 } 4358 4359 /** Reset hCaptcha */ 4360 function resetHcaptcha() { 4361 if (typeof hcaptcha !== 'undefined' && window.hCaptchaInstances[containerId] !== undefined) { 4362 try { 4363 hcaptcha.reset(window.hCaptchaInstances[containerId]); 4364 hideError(); 4365 } catch (e) { 4366 console.error('hCaptcha reset error:', e); 4367 } 4368 } 4369 } 4370 4371 // Expose validation and reset functions globally 4372 window['validateHcaptcha_' + pageType] = validateHcaptcha; 4373 window['resetHcaptcha_' + pageType] = resetHcaptcha; 4374 4375 /** Intercept Alpine.js form submission*/ 4376 function interceptAlpineSubmit() { 4377 let form = document.querySelector(formSelector); 4378 if (pageType === 'custom_form' || !form) { 4379 const container = document.getElementById(containerId); 4380 if (container) { 4381 const closestForm = container.closest('form'); 4382 if (closestForm) { 4383 form = closestForm; 4384 } 4385 } 4386 } 4387 4388 if (!form) { 4389 return; 4390 } 4391 let alpineComponent = form.__x; 4392 if (!alpineComponent && typeof Alpine !== 'undefined') { 4393 alpineComponent = Alpine.$data(form); 4394 } 4395 if (!alpineComponent) { 4396 return; 4397 } 4398 const alpineData = alpineComponent.$data || alpineComponent; 4399 if (!alpineData || typeof alpineData.submitForm !== 'function') { 4400 return; 4401 } 4402 if (alpineData._hcaptchaIntercepted) { 4403 return; 4404 } 4405 const originalSubmitForm = alpineData.submitForm; 4406 alpineData.submitForm = function () { 4407 if (!validateHcaptcha()) { 4408 return false;
4409 } 4410 return originalSubmitForm.call(this); 4411 }; 4412 alpineData._hcaptchaIntercepted = true; 4413 } 4414 4415 /** Alternative: Intercept form submit event (fallback) */ 4416 function interceptFormSubmit() { 4417 let form = document.querySelector(formSelector); 4418 if (pageType === 'custom_form' || !form) { 4419 const container = document.getElementById(containerId); 4420 if (container) { 4421 const closestForm = container.closest('form'); 4422 if (closestForm) { 4423 form = closestForm; 4424 } 4425 } 4426 } 4427 4428 if (!form || form.hasAttribute('data-hcaptcha-attached')) { 4429 return; 4430 } 4431 4432 form.setAttribute('data-hcaptcha-attached', 'true'); 4433 4434 // Listen to submit event 4435 form.addEventListener('submit', function (e) { 4436 if (!validateHcaptcha()) { 4437 e.preventDefault(); 4438 e.stopPropagation(); 4439 e.stopImmediatePropagation(); 4440 return false; 4441 } 4442 }, true); // Use capture phase 4443 } 4444 4445 /** Watch for Alpine.js initialization */ 4446 function waitForAlpine() { 4447 let form = document.querySelector(formSelector); 4448 if (pageType === 'custom_form' || !form) { 4449 const container = document.getElementById(containerId); 4450 if (container) { 4451 const closestForm = container.closest('form'); 4452 if (closestForm) { 4453 form = closestForm; 4454 } 4455 } 4456 } 4457 4458 if (!form) { 4459 // Try again in case form is rendered late 4460 setTimeout(waitForAlpine, 500); 4461 return; 4462 } 4463 let checkCount = 0; 4464 const maxChecks = 20; 4465 const checkAlpine = function () { 4466 checkCount++; 4467 if (form.__x && form.__x.$data) { 4468 interceptAlpineSubmit(); 4469 return; 4470 } 4471 if (checkCount < maxChecks) { 4472 requestAnimationFrame(checkAlpine); 4473 } else { 4474 // Timeout reached, use fallback 4475 interceptFormSubmit(); 4476 } 4477 }; 4478 checkAlpine(); 4479 } 4480 4481 /** Global callback when hCaptcha API loads */ 4482 if (!window.initAllHcaptchas) { 4483 window.initAllHcaptchas = function () { 4484 document.querySelectorAll('.h-captcha').forEach(function (element) { 4485 const type = element.getAttribute('data-page-type'); 4486 const id = element.getAttribute('id'); 4487 4488 if (id && !isAlreadyRendered(id)) { 4489 renderHcaptcha(type, id); 4490 } 4491 }); 4492 }; 4493 } 4494 4495 /** Load and initialize hCaptcha */ 4496 function initHcaptcha() { 4497 // Check if already rendered 4498 if (isAlreadyRendered(containerId)) { 4499 return; 4500 } 4501 // Load hCaptcha script if not already loaded 4502 if (typeof hcaptcha === 'undefined' && !window.hCaptchaLoading) { 4503 window.hCaptchaLoading = true; 4504 const script = document.createElement('script'); 4505 script.src = 'https://hcaptcha.com/1/api.js?onload=initAllHcaptchas&render=explicit'; 4506 script.async = true; 4507 script.defer = true; 4508 script.onload = function () { 4509 window.hCaptchaLoading = false;
4510 }; 4511 script.onerror = function () { 4512 console.error('Failed to load hCaptcha script'); 4513 window.hCaptchaLoading = false; 4514 }; 4515 document.head.appendChild(script); 4516 } else if (typeof hcaptcha !== 'undefined') { 4517 if (!isAlreadyRendered(containerId)) { 4518 renderHcaptcha(pageType, containerId); 4519 } 4520 } 4521 } 4522 /** Initialize everything */ 4523 function init() { 4524 initHcaptcha(); 4525 waitForAlpine(); 4526 } 4527 // Initialize 4528 if (document.readyState === 'loading') { 4529 document.addEventListener('DOMContentLoaded', init); 4530 } else { 4531 init(); 4532 } 4533 })(); 4534 </script>
4534 4535 </div> 4536 </div> 4537 <div> 4538 <template x-if="displayErrorMessage"> 4539 <p class="flex items-center text-red"> 4540 <span class="inline-block w-8 h-8 mr-3"> 4541 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" role="img"> 4542 <path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/> 4543<title>exclamation-circle</title></svg> 4544 </span> 4545 <template x-for="errorMessage in errorMessages"> 4546 <span x-html="errorMessage"></span> 4547 </template> 4548 </p> 4549 </template> 4550 </div> 4551 </form> 4552
4552<script> 4553 function initNewsletterForm() { 4554 return { 4555 errors: 0, 4556 hasCaptchaToken: 0, 4557 displayErrorMessage: false, 4558 errorMessages: [], 4559 setErrorMessages(messages) { 4560 this.errorMessages = [messages] 4561 this.displayErrorMessage = this.errorMessages.length 4562 }, 4563 submitForm() { 4564 // Do not rename $form, the variable is expected to be declared in the recaptcha output 4565 const $form = document.querySelector('#newsletter-validate-detail'); 4566 4567 if (this.errors === 0) { 4568 $form.submit(); 4569 } 4570 } 4571 } 4572 } 4573 </script>
4573 4574</div> 4575 4576 <div class="flex flex-col md2:ml-[34px] md2:pl-[34px] md2:border-l md2:border-white"> 4577 <h2 class="font-Gotham text-xl uppercase mb-8 font-medium"> 4578 Let's get social! </h2> 4579 <div class="flex gap-2"> 4580 <a 4581 href="https://www.facebook.com/RiccarVacuums" 4582 target="_blank" 4583 rel="noopener noreferer" 4584 class="!outline-orange-500" 4585 > 4586 <div class="btn btn-icon"> 4587 <span class="sr-only"> 4588 Link to the facebook fanpage </span> 4589 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="w-6 h-6" width="24" height="24" aria-hidden="true"><path fill="currentColor" fill-rule="evenodd" d="m16.65 13.252.555-3.62h-3.473V7.285c0-.99.485-1.956 2.04-1.956h1.58V2.247s-1.433-.245-2.803-.245c-2.86 0-4.73 1.734-4.73 4.872v2.759H6.64v3.62h3.18v8.75h3.912v-8.75h2.918Z" clip-rule="evenodd"/></svg> 4590 </div> 4591 </a> 4592 <a 4593 href="https://www.youtube.com/channel/UC6Je7052xu5kl92QxQ1C5RQ" 4594 target="_blank" 4595 rel="noopener noreferer" 4596 class="!outline-orange-500" 4597 > 4598 <div class="btn btn-icon"> 4599 <span class="sr-only"> 4600 Link to the youtube channel </span> 4601 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="w-6 h-6" width="24" height="24" aria-hidden="true"><path fill="currentColor" fill-rule="evenodd" d="M22.468 6.723a2.745 2.745 0 0 0-1.931-1.944c-1.704-.459-8.535-.459-8.535-.459s-6.83 0-8.534.46c-.94.252-1.68.997-1.932 1.943-.456 1.715-.456 5.292-.456 5.292s0 3.578.456 5.292c.252.946.992 1.66 1.932 1.913 1.703.46 8.534.46 8.534.46s6.831 0 8.535-.46a2.704 2.704 0 0 0 1.931-1.913c.457-1.714.457-5.292.457-5.292s0-3.577-.457-5.292Zm-12.7 8.54V8.767l5.71 3.248-5.71 3.248Z" clip-rule="evenodd"/></svg> 4602 </div> 4603 </a> 4604 <a 4605 href="https://www.instagram.com/riccarvacuums/" 4606 target="_blank" 4607 rel="noopener noreferer" 4608 class="!outline-orange-500" 4609 > 4610 <div class="btn btn-icon"> 4611 <span class="sr-only"> 4612 Link to the instagram profile </span> 4613 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="w-6 h-6" width="24" height="24" aria-hidden="true"><path fill="currentColor" fill-rule="evenodd" d="M12.005 6.872A5.12 5.12 0 0 0 6.877 12a5.12 5.12 0 0 0 5.128 5.128A5.12 5.12 0 0 0 17.131 12a5.12 5.12 0 0 0-5.128-5.128Zm0 8.462A3.34 3.34 0 0 1 8.67 12a3.337 3.337 0 0 1 3.334-3.334A3.337 3.337 0 0 1 15.338 12a3.34 3.34 0 0 1-3.333 3.334Zm6.533-8.671c0 .664-.535 1.196-1.196 1.196a1.196 1.196 0 1 1 1.196-1.196Zm3.396 1.213c-.076-1.602-.442-3.02-1.615-4.19-1.17-1.17-2.589-1.535-4.19-1.616-1.652-.093-6.601-.093-8.253 0-1.597.076-3.016.442-4.19 1.611C2.512 4.851 2.15 6.27 2.07 7.871c-.093 1.652-.093 6.601 0 8.253.076 1.602.442 3.02 1.616 4.19 1.174 1.17 2.588 1.535 4.19 1.616 1.652.093 6.6.093 8.252 0 1.602-.076 3.021-.442 4.19-1.616 1.17-1.17 1.536-2.588 1.616-4.19.094-1.652.094-6.596 0-8.248Zm-2.133 10.02a3.375 3.375 0 0 1-1.901 1.9c-1.317.523-4.44.402-5.895.402-1.455 0-4.584.116-5.896-.401a3.375 3.375 0 0 1-1.901-1.902c-.522-1.316-.402-4.44-.402-5.895 0-1.455-.116-4.583.402-5.895a3.375 3.375 0 0 1 1.901-1.902c1.317-.522 4.44-.401 5.896-.401 1.454 0 4.583-.116 5.895.401A3.375 3.375 0 0 1 19.8 6.106c.522 1.316.402 4.44.402 5.895 0 1.455.12 4.583-.402 5.895Z" clip-rule="evenodd"/></svg> 4614 </div> 4615 </a> 4616 </div> 4617 </div> 4618 </div> 4619 4620 <div class="mb-14"> 4621 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 170 36" class="w-[170px] h-9" width="170" height="36" aria-hidden="true"><g clip-path="url(#a_2)"><path fill="#fff" d="m16.876 31.751 4.97-4.855V8.87l-4.777-4.737H4.777L0 8.869v18.027l4.979 4.855h11.897Z"/>
4621<path fill="#00548E" d="M10.8 12.268H7.377a3.462 3.462 0 0 0-2.565.894 3.381 3.381 0 0 0-.806 1.118c-.188.424-.287.88-.29 1.343.004.819.3 1.61.835 2.235a3.534 3.534 0 0 0 2.094 1.182C5.31 20.984 2.838 24.21 1.21 24.618v.081h1.07c2.518-.75 5.748-5.298 5.995-5.867h-.521c-1.904-.108-2.746-1.582-2.746-3.2a2.682 2.682 0 0 1 .778-2.062 2.777 2.777 0 0 1 2.069-.814h1.134v9.945a.977.977 0 0 1-.43.742h2.206a.989.989 0 0 1-.43-.742v-9.773c0-.388.476-.623.476-.623l-.01-.037Zm4.503 6.808a3.534 3.534 0 0 0 2.095-1.182 3.455 3.455 0 0 0 .834-2.235 3.346 3.346 0 0 0-.29-1.343 3.382 3.382 0 0 0-.805-1.117 3.462 3.462 0 0 0-2.566-.894h-3.423s.476.235.476.623v9.782a.976.976 0 0 1-.43.742H13.4a.989.989 0 0 1-.43-.742v-9.944h1.143a2.775 2.775 0 0 1 2.063.817 2.684 2.684 0 0 1 .775 2.058c0 1.618-.824 3.092-2.746 3.2h-.522c.247.57 3.478 5.117 5.995 5.867h1.08v-.08c-1.638-.408-4.11-3.617-5.446-5.579"/><path fill="#fff" d="M31.83 0h-1.263v36h1.263V0ZM169.643 29.988a1.468 1.468 0 0 1-.266.816 1.5 1.5 0 0 1-.679.534 1.52 1.52 0 0 1-1.627-.338 1.475 1.475 0 0 1 .24-2.273c.246-.163.535-.249.831-.249a1.503 1.503 0 0 1 1.074.441 1.466 1.466 0 0 1 .427 1.069Zm-3.359 0c0 .357.108.707.309 1.004.201.298.487.53.821.666a1.853 1.853 0 0 0 1.995-.392 1.797 1.797 0 0 0-.277-2.782 1.847 1.847 0 0 0-2.312.225c-.343.34-.536.8-.536 1.279Zm1.474.145h.357l.567.904h.357l-.604-.904a.545.545 0 0 0 .518-.353.52.52 0 0 0 .031-.217c0-.407-.247-.588-.75-.588h-.806v2.08h.33v-.922Zm0-.905h.439c.366 0 .467.118.467.317s-.128.343-.522.343h-.384v-.66ZM68.613 6.681h-4.65s.99.48.99 1.284v20.16a1.99 1.99 0 0 1-.28.865 2.02 2.02 0 0 1-.636.655h4.576a2.019 2.019 0 0 1-.636-.655 1.99 1.99 0 0 1-.28-.864V7.965a1.714 1.714 0 0 1 .915-1.284ZM127.004 19.13l3.322-7.802 3.66 9.04.339.905c.293.623.595 1.274.915 1.944a13.734 13.734 0 0 0-8.172-4.078l-.064-.009Zm13.27 9.267c-3.313-7.757-5.921-14.149-9.381-22.511l-.668.958-.513.832-.741 1.139s.366.162.439.37l.403 1.004c-1.446 3.336-2.663 6.139-3.816 8.814h-.742c-1.764.027-3.51.354-5.161.968l1.134.542a10.045 10.045 0 0 1 4.027-.605h.357a1313.138 1313.138 0 0 1-3.761 8.597c-.259.48-.629.891-1.08 1.203h2.572c-.138-.398-.678-.461-.366-1.203 1.382-3.345 3.111-7.232 3.111-7.232l.376-.904.173-.407a12.893 12.893 0 0 1 6.773 2.819 12.647 12.647 0 0 1 4.091 6.032 1.158 1.158 0 0 1-.503.904h4.466a4.934 4.934 0 0 1-1.254-1.338M49.723 20.884c3.972-.443 7.257-4.285 7.257-8.462 0-4.737-3.724-8.29-9.152-8.29h-8.475s1.19.56 1.19 1.537v24.229c-.03.361-.14.712-.326 1.025-.186.313-.44.58-.745.783h5.492a2.427 2.427 0 0 1-.74-.785 2.392 2.392 0 0 1-.322-1.023V5.262h2.828c4.915 0 7.038 3.562 7.038 7.115 0 4.005-2.04 7.657-6.754 7.938l-1.3.063c.613 1.41 8.622 12.657 14.845 14.52h2.663v-.2c-4.054-1.003-10.159-8.995-13.472-13.814"/><path fill="#fff" d="M154.332 20.884c3.963-.443 7.248-4.285 7.248-8.462 0-4.737-3.724-8.29-9.152-8.29h-8.484s1.19.56 1.19 1.537v24.229a2.397 2.397 0 0 1-1.062 1.808h5.446a2.415 2.415 0 0 1-1.062-1.808V5.262h2.819c4.915 0 7.047 3.562 7.047 7.115 0 4.005-2.05 7.657-6.754 7.938l-1.3.063c.614 1.41 8.613 12.657 14.845 14.52h2.654v-.2c-4.045-1.003-10.159-8.995-13.462-13.814M87.092 7.576a10.506 10.506 0 0 1 7.047 2.965l.147-.063-.577-3.028h-1.19c-1.062 0-2.791-1.05-6.644-1.05-6.81 0-12.548 5.29-12.548 11.862v.163c0 6.563 5.739 11.445 12.548 11.445 3.853 0 5.582-1.04 6.644-1.04h1.19l.576-3.028-.146-.063a10.506 10.506 0 0 1-7.047 2.965c-7.001 0-10.983-4.818-10.983-10.387-.04-1.434.216-2.86.754-4.193a10.504 10.504 0 0 1 2.376-3.553 10.657 10.657 0 0 1 3.606-2.33 10.76 10.76 0 0 1 4.247-.728M110.457 7.576a10.541 10.541 0 0 1 7.056 2.965l.146-.063-.576-3.028h-1.19c-1.062 0-2.8-1.05-6.644-1.05-6.819 0-12.548 5.29-12.548 11.862v.163c0 6.563 5.729 11.445 12.548 11.445 3.844 0 5.582-1.04 6.644-1.04h1.19l.576-3.028-.146-.063a10.541 10.541 0 0 1-7.056 2.965c-6.992 0-10.983-4.818-10.983-10.387-.04-1.434.216-2.86.754-4.193a10.513 10.513 0 0 1 2.375-3.553 10.657 10.657 0 0 1 3.607-2.33 10.763 10.763 0 0 1 4.247-.728"/></g><defs><clipPath id="a_2"><path fill="#fff" d="M0 0h170v36H0z"/></clipPath></defs></svg> 4622 </div> 4623 4624 <div class="pb-14"> 4625 4626 4627 <nav 4628 id="footer-navigation" 4629 aria-label="Footer site navigation" 4630 class=" 4631 flex flex-col gap-4 md2:grid 4632 md2:grid md2:grid-cols-3 md2:grid-rows-2 4633 xl:grid-cols-4 xl:grid-rows-1 xl:gap-8 4634 " 4635 > 4636 <div 4637 class=" 4638 md2:row-span-2 xl:col-span-1 xl:col-start-auto xl:row-start-auto 4639 " 4640 > 4641 4642<div 4643 class="flex flex-col"
4644 x-data="initCollapsible()" 4645> 4646 <button 4647 class="flex justify-between items-center w-full py-2 !outline-orange-500 md2:hidden" 4648 @click="isCollapsed = !isCollapsed" 4649 :aria-expanded="!isCollapsed" 4650 > 4651 <span class="sr-only md2:hidden"> 4652 Toggle menu item - </span> 4653 <h2 4654 class="font-Gotham text-xl uppercase font-medium" 4655 > 4656 Customer care </h2> 4657 4658 <span 4659 class="transition-all md2:hidden" 4660 x-cloak 4661 :class="isCollapsed ? 'rotate-180' : 'rotate-0'" 4662 > 4663 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-6 h-6" width="24" height="24" aria-hidden="true"> 4664 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 4665</svg> 4666 </span> 4667 </button> 4668 4669 <div class="hidden justify-between items-center w-full py-2 md2:flex"> 4670 <h2 4671 class="font-Gotham text-xl uppercase font-medium" 4672 > 4673 Customer care </h2> 4674 </div> 4675 4676 <div 4677 class="flex-col mb-4 lg:mb-0" 4678 :class="isCollapsed ? 'flex' : 'hidden md2:flex'" 4679 x-cloak 4680 > 4681 <ul class="flex flex-col py-8 text-black-20 gap-4 md2:pb-0"> 4682 <li> 4683 4684 4685<a 4686 href="/support" 4687 data-menu="menu-623" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4688 Support</a> </li> 4689 <li> 4690 4691 4692<a 4693 href="customer/account/login" 4694 data-menu="menu-626" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4695 Log in</a> </li> 4696 <li> 4697 4698 4699<a 4700 href="/customer/account/create/" 4701 data-menu="menu-629" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4702 Create an Account</a> </li> 4703 <li> 4704 4705 4706<a 4707 href="/warranty-information" 4708 data-menu="menu-893" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4709 Warranty Information</a> </li> 4710 <li> 4711 4712 4713<a 4714 href="/register-warranty" 4715 data-menu="menu-632" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4716 Register a Warranty</a> </li> 4717 <li> 4718 4719 4720<a 4721 href="/shipping-returns" 4722 data-menu="menu-635" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4723 Shipping & Returns</a> </li> 4724 <li> 4725 4726 4727<a 4728 href="/where-to-buy" 4729 data-menu="menu-638" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4730 Find a retailer</a> </li> 4731 <li> 4732 4733 4734<a 4735 href="/contact-form" 4736 data-menu="menu-641" class="__inner-link text-xl !outline-orange-500 hover:text-white"> 4737 Contact Us</a> </li> 4738 </ul> 4739 </div> 4740</div> 4741
4742<script> 4743 function initCollapsible() { 4744 return { 4745 isCollapsed: false, 4746 } 4747 } 4748</script>
4748 4749 </div> 4750 <div 4751 class=" 4752 xl:col-span-1 xl:col-start-auto xl:row-start-auto 4753 " 4754 > 4755 4756<div 4757 class="flex flex-col" 4758 x-data="initCollapsible()" 4759> 4760 <button 4761 class="flex justify-between items-center w-full py-2 !outline-orange-500 md2:hidden" 4762 @click="isCollapsed = !isCollapsed" 4763 :aria-expanded="!isCollapsed" 4764 > 4765 <span class="sr-only md2:hidden"> 4766 Toggle menu item - </span> 4767 <h2 4768 class="font-Gotham text-xl uppercase font-medium" 4769 > 4770 Vacuums </h2> 4771 4772 <span 4773 class="transition-all md2:hidden" 4774 x-cloak 4775 :class="isCollapsed ? 'rotate-180' : 'rotate-0'" 4776 > 4777 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-6 h-6" width="24" height="24" aria-hidden="true"> 4778 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 4779</svg> 4780 </span> 4781 </button> 4782 4783 <div class="hidden justify-between items-center w-full py-2 md2:flex"> 4784 <h2 4785 class="font-Gotham text-xl uppercase font-medium" 4786 > 4787 Vacuums </h2> 4788 </div> 4789 4790 <div 4791 class="flex-col mb-4 lg:mb-0" 4792 :class="isCollapsed ? 'flex' : 'hidden md2:flex'" 4793 x-cloak 4794 > 4795 <ul class="flex flex-col py-8 text-black-20 gap-4 md2:pb-0"> 4796 <li> 4797 4798 4799<a 4800 href="https://www.riccar.com/vacuum-cleaners/upright-vacuums" 4801 class=" 4802 text-xl !outline-orange-500 hover:text-white 4803 " 4804> 4805 Upright vacuums</a> 4806 </li> 4807 <li> 4808 4809 4810<a 4811 href="https://www.riccar.com/vacuum-cleaners/canister-vacuums" 4812 class=" 4813 text-xl !outline-orange-500 hover:text-white 4814 " 4815> 4816 Canister Vacuums</a> 4817 </li> 4818 <li> 4819 4820 4821<a 4822 href="https://www.riccar.com/vacuum-cleaners/stick-vacuums-handheld-vacuums" 4823 class=" 4824 text-xl !outline-orange-500 hover:text-white 4825 " 4826> 4827 Handheld Vacuums</a> 4828 </li> 4829 </ul> 4830 </div> 4831</div> 4832
4833<script> 4834 function initCollapsible() { 4835 return { 4836 isCollapsed: false, 4837 } 4838 } 4839</script>
4839 4840 </div> 4841 <div 4842 class=" 4843 md2:col-start-2 xl:col-span-1 xl:col-start-auto xl:row-start-auto 4844 " 4845 > 4846 4847<div 4848 class="flex flex-col" 4849 x-data="initCollapsible()" 4850> 4851 <button 4852 class="flex justify-between items-center w-full py-2 !outline-orange-500 md2:hidden" 4853 @click="isCollapsed = !isCollapsed" 4854 :aria-expanded="!isCollapsed" 4855 > 4856 <span class="sr-only md2:hidden"> 4857 Toggle menu item - </span> 4858 <h2 4859 class="font-Gotham text-xl uppercase font-medium" 4860 > 4861 Accessories </h2> 4862 4863 <span 4864 class="transition-all md2:hidden" 4865 x-cloak 4866 :class="isCollapsed ? 'rotate-180' : 'rotate-0'" 4867 > 4868 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-6 h-6" width="24" height="24" aria-hidden="true"> 4869 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 4870</svg> 4871 </span> 4872 </button> 4873 4874 <div class="hidden justify-between items-center w-full py-2 md2:flex"> 4875 <h2 4876 class="font-Gotham text-xl uppercase font-medium" 4877 > 4878 Accessories </h2> 4879 </div> 4880 4881 <div 4882 class="flex-col mb-4 lg:mb-0" 4883 :class="isCollapsed ? 'flex' : 'hidden md2:flex'" 4884 x-cloak 4885 > 4886 <ul class="flex flex-col py-8 text-black-20 gap-4 md2:pb-0"> 4887 <li> 4888 4889 4890<a 4891 href="https://www.riccar.com/tools-accessories/vacuum-tools-attachments" 4892 class=" 4893 text-xl !outline-orange-500 hover:text-white 4894 " 4895> 4896 Tools & Attachments</a> 4897 </li> 4898 <li> 4899 4900 4901<a 4902 href="https://www.riccar.com/tools-accessories/carpet-care-cleaning-supplies-floor-pads" 4903 class=" 4904 text-xl !outline-orange-500 hover:text-white 4905 " 4906> 4907 Floor Cleaning Pads</a> 4908 </li> 4909 <li> 4910 4911 4912<a 4913 href="https://www.riccar.com/tools-accessories/central-vacuum-accessories" 4914 class=" 4915 text-xl !outline-orange-500 hover:text-white 4916 " 4917> 4918 Central Vacuum Accessories</a> 4919 </li> 4920 </ul> 4921 </div> 4922</div> 4923
4924<script> 4925 function initCollapsible() { 4926 return { 4927 isCollapsed: false, 4928 } 4929 } 4930</script>
4930 4931 </div> 4932 <div 4933 class=" 4934 md2:row-start-1 md2:col-start-3 xl:col-span-1 xl:col-start-auto xl:row-start-auto 4935 " 4936 > 4937 4938<div 4939 class="flex flex-col" 4940 x-data="initCollapsible()" 4941> 4942 <button 4943 class="flex justify-between items-center w-full py-2 !outline-orange-500 md2:hidden" 4944 @click="isCollapsed = !isCollapsed" 4945 :aria-expanded="!isCollapsed" 4946 > 4947 <span class="sr-only md2:hidden"> 4948 Toggle menu item - </span> 4949 <h2 4950 class="font-Gotham text-xl uppercase font-medium" 4951 > 4952 Bags Belts & Filters </h2> 4953 4954 <span 4955 class="transition-all md2:hidden" 4956 x-cloak 4957 :class="isCollapsed ? 'rotate-180' : 'rotate-0'" 4958 > 4959 <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-6 h-6" width="24" height="24" aria-hidden="true"> 4960 <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/> 4961</svg> 4962 </span> 4963 </button> 4964 4965 <div class="hidden justify-between items-center w-full py-2 md2:flex"> 4966 <h2 4967 class="font-Gotham text-xl uppercase font-medium" 4968 > 4969 Bags Belts & Filters </h2> 4970 </div> 4971 4972 <div 4973 class="flex-col mb-4 lg:mb-0" 4974 :class="isCollapsed ? 'flex' : 'hidden md2:flex'" 4975 x-cloak 4976 > 4977 <ul class="flex flex-col py-8 text-black-20 gap-4 md2:pb-0"> 4978 <li> 4979 4980 4981<a 4982 href="https://www.riccar.com/bags-belts-filters/vacuum-bags" 4983 class=" 4984 text-xl !outline-orange-500 hover:text-white 4985 " 4986> 4987 Vacuum bags</a> 4988 </li> 4989 <li> 4990 4991 4992<a 4993 href="https://www.riccar.com/bags-belts-filters/vacuum-filters" 4994 class=" 4995 text-xl !outline-orange-500 hover:text-white 4996 " 4997> 4998 Vacuum filters</a> 4999 </li> 5000 <li> 5001 5002 5003<a 5004 href="https://www.riccar.com/bags-belts-filters/vacuum-belts" 5005 class=" 5006 text-xl !outline-orange-500 hover:text-white 5007 " 5008> 5009 Vacuum belts</a> 5010 </li> 5011 </ul> 5012 </div> 5013</div> 5014
5015<script> 5016 function initCollapsible() { 5017 return { 5018 isCollapsed: false, 5019 } 5020 } 5021</script>
5021 5022 </div> 5023 </nav> 5024 </div> 5025 </div> 5026 5027 <style>.cmsb869-container { 5028width: 100%; 5029margin-right: auto; 5030margin-left: auto; 5031padding-right: 1.5rem; 5032padding-left: 1.5rem 5033} 5034@media (min-width: 704px) { 5035.cmsb869-container { 5036max-width: 704px 5037} 5038} 5039@media (min-width: 928px) { 5040.cmsb869-container { 5041max-width: 928px 5042} 5043} 5044@media (min-width: 1376px) { 5045.cmsb869-container { 5046max-width: 1376px 5047} 5048} 5049.cmsb869-block { 5050display: block 5051} 5052.cmsb869-flex { 5053display: flex 5054} 5055.cmsb869-w-full { 5056width: 100% 5057} 5058.cmsb869-items-center { 5059align-items: center 5060} 5061.cmsb869-justify-between { 5062justify-content: space-between 5063} 5064.cmsb869-border { 5065border-width: 1px 5066} 5067.cmsb869-border-white { 5068--tw-border-opacity: 1; 5069border-color: rgb(255 255 255 / var(--tw-border-opacity)) 5070} 5071.cmsb869-bg-black { 5072--tw-bg-opacity: 1; 5073background-color: rgb(15 14 13 / var(--tw-bg-opacity)) 5074} 5075.cmsb869-px-5 { 5076padding-left: 1.25rem; 5077padding-right: 1.25rem 5078} 5079.cmsb869-py-2 { 5080padding-top: 0.5rem; 5081padding-bottom: 0.5rem 5082} 5083.cmsb869-py-4 { 5084padding-top: 1rem; 5085padding-bottom: 1rem 5086} 5087.cmsb869-py-9 { 5088padding-top: 2.25rem; 5089padding-bottom: 2.25rem 5090} 5091.cmsb869-text-xl { 5092font-size: 1.25rem; 5093line-height: 1.75rem 5094} 5095.cmsb869-text-xs { 5096font-size: 0.75rem; 5097line-height: 1rem 5098} 5099.cmsb869-uppercase { 5100text-transform: uppercase 5101} 5102.cmsb869-tracking-\[0\.3em\] { 5103letter-spacing: 0.3em 5104} 5105.cmsb869-text-white { 5106--tw-text-opacity: 1; 5107color: rgb(255 255 255 / var(--tw-text-opacity)) 5108} 5109.cmsb869-underline { 5110text-decoration-line: underline 5111}</style> 5112<style>#html-body [data-pb-style=PU4ATEK]{border-style:none;border-width:0;border-radius:0;margin:0;padding:0}</style><div data-content-type="html" data-appearance="default" data-element="main" data-pb-style="PU4ATEK" data-decoded="true"><div class="cmsb869-w-full cmsb869-bg-black cmsb869-py-2"> 5113 <div class="cmsb869-container cmsb869-flex cmsb869-justify-between cmsb869-items-center cmsb869-py-9"> 5114 <a href="https://riccardealers.com/" target="_blank" rel="noopener noreferer" class="cmsb869-block cmsb869-tracking-[0.3em] cmsb869-text-xs cmsb869-uppercase cmsb869-text-white cmsb869-px-5 cmsb869-py-4 cmsb869-border cmsb869-border-white"> 5115 Retailer site 5116 </a> 5117<a href="/accessibility" rel="noopener noreferer" class="cmsb869-block cmsb869-text-white cmsb869-text-xl cmsb869-underline">Accessibility</a> 5118 <a href="https://www.tacony.com/privacy-policy.html" target="_blank" rel="noopener noreferer" class="cmsb869-block cmsb869-text-white cmsb869-text-xl cmsb869-underline"> 5119 Privacy Policy 5120 </a> 5121 </div> 5122 </div></div> 5123 <p class="w-full flex justify-center bg-black p-2 text-white"> 5124 Copyright 2026 Riccar© Vacuums. All rights reserved.</p> 5125</div> 5126
5127<script> 5128 'use strict'; 5129 5130 function amBrandsPopup() { 5131 let cached = false; 5132 5133 const displayError = (error) => { 5134 console.error(error); 5135 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 5136 [{ 5137 type: "error", 5138 text: "Something\u0020went\u0020wrong.\u0020Please\u0020try\u0020again." 5139 }], 10000 5140 ); 5141 }; 5142 5143 let letters = [ 5144 "A","B","C","D", 5145 "E","F","G","H","I","J","K","L","M", 5146 "N","O","P","Q","R","S","T","U","V","W","X","Y","Z","#" 5147 ]; 5148 5149 return { 5150 hoverPanelActiveId: null, 5151 selectedLetter: null, 5152 items: [], 5153 letters: [], 5154 showCount: null, 5155 showFilter: null, 5156 showImages: true, 5157 showSearch: null, 5158 loading: false, 5159 label: 'Brands', 5160 isPopupEnabled: false, 5161 isTopMenuItemEnabled: false, 5162 cache: false, 5163 isMobile: false, 5164 5165 initErrorMessages(errors) { 5166 const messages = []; 5167 for (let error in Object.keys(errors)) { 5168 messages.push({type: 'error', text: errors[error].message}); 5169 } 5170 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(messages, 10000); 5171 }, 5172 5173 chooseLetter(letter) { 5174 this.selectedLetter = this.selectedLetter === letter ? null : letter; 5175 }, 5176 5177 getQuery() { 5178 return "query BrandsPopupQuery { ambrandlist(\n showCount: true\n displayZero: true\n ) {\n all_letters,\n items {\n alt\n brandId\n cnt\n image\n img\n label\n letter\n url\n }\n }\n storeConfig {\n amshopby_brand_general_brands_brands_popup,\n amshopby_brand_general_menu_item_label,\n amshopby_brand_general_brands_page,\n amshopby_brand_general_topmenu_enabled,\n amshopby_brand_general_brands_popup_config {\n show_images,\n display_zero,\n filter_display_all,\n image_width,\n image_height,\n show_filter,\n show_count\n }\n } }" }, 5179 5180 /** 5181 * Retrieve media url for given path 5182 * 5183 * @param path 5184 * @returns {string} 5185 */ 5186 getMediaUrl(path) { 5187 const baseUrl = BASE_URL.replace('index.php/', ''); 5188 if (path.includes('://')) { 5189 return path; 5190 } 5191 5192 let productImageUrl = `${baseUrl}${path}`; 5193 const regexDuplicateDomain = new RegExp(`^(https?:\/\/[^/]+).*\\1`); 5194 productImageUrl = productImageUrl.replace(regexDuplicateDomain, '$1'); 5195 5196 return productImageUrl.includes('/product/placeholder/') 5197 ? productImageUrl.replace(/\/media(?=\/static)/, '') 5198 : productImageUrl; 5199 }, 5200 5201 checkIsMobileResolution() { 5202 this.isMobile = window.matchMedia('(max-width: 1023px)').matches; 5203 }, 5204 5205 getBrandUrl(url){ 5206 return BASE_URL + url; 5207 }, 5208 5209 init() { 5210 this.checkIsMobileResolution(); 5211 5212 this.$watch('hoverPanelActiveId', (value) => { 5213 if (value === 'am-brand') { 5214 this.sendRequest(); 5215 } 5216 }); 5217 }, 5218 5219 /** 5220 * Get brands by letter 5221 * 5222 * @param result 5223 * @returns {{imageWidth: *, isTopMenuItemEnabled: *, showCount: *, displayAll: *, showFilter: *, showImages: *, isPopupEnabled: *, label: *, imageHeight: *, filterDisplayAll: *, brandsPage: *}} 5224 */ 5225 settingsMapper(result) { 5226 const config = result.data.storeConfig?.amshopby_brand_general_brands_popup_config; 5227 return { 5228 showImages: config.show_images, 5229 showCount: config.show_count, 5230 showFilter: config.show_filter, 5231 imageWidth: config.image_width, 5232 imageHeight: config.image_height, 5233 filterDisplayAll: config.filter_display_all, 5234 displayAll: config.display_zero, 5235 isPopupEnabled: result.data.storeConfig?.amshopby_brand_general_brands_brands_popup, 5236 label: result.data.storeConfig?.amshopby_brand_general_menu_item_label, 5237 isTopMenuItemEnabled: result.data.storeConfig?.amshopby_brand_general_topmenu_enabled, 5238 brandsPage: result.data.storeConfig?.amshopby_brand_general_brands_page, 5239 } 5240 }, 5241 5242 /** 5243 * Send request to graphql 5244 * 5245 * @returns {Promise<any>} 5246 */ 5247 async sendRequest() { 5248 if (this.isMobile) { 5249 return false;
5250 } 5251 5252 this.loading = true; 5253 5254 try { 5255 if (cached) { 5256 this.loading = false; 5257 return false; 5258 } 5259 5260 const response = await fetch('https://www.riccar.com/graphql', { 5261 method: 'POST', 5262 headers: { 5263 'Content-Type': 'application/json', 5264 'Store': 'rv_store_view' 5265 }, 5266 credentials: 'include', 5267 body: JSON.stringify({query: this.getQuery(), variables: {}}) 5268 }); 5269 5270 const result = await response.json(); 5271 5272 if (result?.errors) { 5273 this.initErrorMessages(result.errors); 5274 return; 5275 } 5276 5277 const data = result.data?.ambrandlist; 5278 const mapper = this.settingsMapper(result); 5279 5280 // Update component settings 5281 Object.keys(mapper).forEach(config => { 5282 this[config] = mapper[config]; 5283 }); 5284 5285 if (!this.filterDisplayAll) { 5286 letters = data.all_letters.split(','); 5287 } 5288 5289 const items = data.items.map(brand => { 5290 brand.image = brand.img 5291 ? this.getMediaUrl(brand.img) : (brand.image ? this.getMediaUrl(brand.image) : null); 5292 return brand; 5293 }); 5294 5295 this.letters = letters.map(letter => ({ 5296 letter, 5297 brands: this.getLetterItems(items, letter), 5298 })); 5299 5300 this.items = this.letters.filter(row => row.brands?.length > 0); 5301 5302 cached = true; 5303 } catch (error) { 5304 displayError(error); 5305 } finally { 5306 this.loading = false; 5307 } 5308 }, 5309 5310 /** 5311 * Get brands by letter 5312 * 5313 * @param items 5314 * @param letter 5315 * @returns {*} 5316 */ 5317 getLetterItems(items, letter) { 5318 return items.filter(row => row.letter === letter); 5319 }, 5320 5321 convertHtml(text) { 5322 let textField = document.createElement("textarea"); 5323 textField.innerHTML = text; 5324 return textField.value; 5325 } 5326 } 5327 } 5328 5329 function amBrandsPopupData() { 5330 return Object.assign( 5331 amBrandsPopup(), 5332 { 5333 brandPopupClass() { 5334 return { 5335 'hover:border-primary data-[active]:border-primary': !this.isPopupEnabled 5336 } 5337 }, 5338 labelPopupClass() { 5339 return {'w-14 opacity-0': this.label === ''} 5340 }, 5341 popupcontentClass() { 5342 return { 5343 'hidden' : this.hoverPanelActiveId !== 'am-brand', 5344 'left-0' : `${this.$el.dataset.first}`, 5345 'right-0' : `${this.$el.dataset.last}` 5346 } 5347 }, 5348 panelActiveMouseenterEvent() { 5349 return this.hoverPanelActiveId = 'am-brand' 5350 }, 5351 panelActiveMouseleaveEvent() { 5352 return this.hoverPanelActiveId = null 5353 }, 5354 isPopupShow() { 5355 return this.hoverPanelActiveId === 'am-brand' 5356 }, 5357 labelText(){ 5358 return this.label 5359 }, 5360 isEnabledPopup(){ 5361 return this.isPopupEnabled 5362 }, 5363 showExtMessage(){ 5364 return false 5365 }, 5366 notLoading() { 5367 return !this.loading 5368 }, 5369 brandLabel() { 5370 return this.brand.label 5371 }, 5372 letterClass() { 5373 return { 5374 'border-blue-400 text-blue-400 bg-blue-100': this.selectedLetter === this.letter.letter, 5375 'bg-gray-200 text-gray-700 cursor-default pointer-events-none': !this.letter.brands || this.letter.brands.length === 0 5376 } 5377 }, 5378 letterClickEvent(event) { 5379 return this.chooseLetter(this.letter.letter) 5380 }, 5381 letterBrands() { 5382 return this.letter.brands 5383 }, 5384 brandUrl() { 5385 return this.getBrandUrl(this.brand.url) 5386 }, 5387 brandImage() { 5388 return this.brand.image 5389 },
5390 notBrandImage() { 5391 return !this.brand.image 5392 }, 5393 letterLetter() { 5394 return this.letter.letter 5395 }, 5396 brandBrandId() { 5397 return this.brand.brandId 5398 }, 5399 isLetterShow() { 5400 return !this.selectedLetter || this.selectedLetter === this.letter.letter 5401 }, 5402 brandImageMediaUrl() { 5403 return this.getMediaUrl(this.brand.image) 5404 }, 5405 brandImageStyle() { 5406 return `max-width: ${this.imageWidth ? this.imageWidth + 'px' : '100px' };max-height: ${this.imageHeight ? this.imageHeight + 'px' : 'inherit'}` 5407 }, 5408 brandsLabelStyle() { 5409 return `min-width: ${this.imageWidth}px` 5410 }, 5411 brandLabelFilter() { 5412 return this.brand.label.charAt(0) 5413 }, 5414 brandCnt() { 5415 return '(' + this.brand.cnt + ')' 5416 } 5417 } 5418 ) 5419 } 5420 window.addEventListener('alpine:init', () => Alpine.data('amBrandsPopupData', amBrandsPopupData), {once: true}); 5421</script>
5421 5422</div></footer>
5423<script> 5424 function dataServicesShoppingCartContextData() { 5425 return { 5426 initContext(cartData) { 5427 let contextCartItems = []; 5428 5429 if (cartData && cartData.items) { 5430 cartData.items.forEach(function (item) { 5431 contextCartItems.push({ 5432 id: item.item_id, 5433 formattedPrice: parseFloat(item.product_price_value ? item.product_price_value : 0), 5434 quantity: item.qty, 5435 product: { 5436 productType: item.product_type, 5437 productId: item.product_id, 5438 name: item.product_name, 5439 sku: item.product_sku, 5440 mainImageUrl: item.product_image.src 5441 }, 5442 prices: { 5443 price: { 5444 value: parseFloat(item.product_price_value ? item.product_price_value : 0) 5445 } 5446 } 5447 }); 5448 }); 5449 5450 magentoStorefrontEvents.context.setShoppingCart({ 5451 id: cartData.dsCartId, 5452 totalQuantity: cartData.summary_count, 5453 prices: { 5454 subtotalExcludingTax: { 5455 value: parseFloat(cartData.subtotalAmountExclTax ? cartData.subtotalAmountExclTax : 0) 5456 }, 5457 subtotalIncludingTax: { 5458 value: parseFloat(cartData.subtotalAmount ? cartData.subtotalAmount : 0) 5459 } 5460 }, 5461 items: contextCartItems, 5462 possibleOnepageCheckout: cartData.possible_onepage_checkout, 5463 giftMessageSelected : false, 5464 giftWrappingSelected : false 5465 }); 5466 } 5467 5468 window.dispatchEvent(new Event("shoppingCartContextSet")); 5469 } 5470 } 5471 } 5472</script>
5472 5473 5474<div x-data="dataServicesShoppingCartContextData()" 5475 @private-content-loaded.window="initContext($event.detail.data.cart)"></div> 5476 5477
5478<script> define( 5479 'signifyd-fingerprint-module', 5480 [ 5481 'uiComponent', 5482 'Magento_Customer/js/customer-data', 5483 'jquery' 5484 ], function (Component, customerData, $) { 5485 'use strict'; 5486 var SignifydFingerprint = function() { 5487 return { 5488 initialize: function () { 5489 var me = this; 5490 if (jQuery('.checkout-onepage-success').length > 0) { 5491 customerData.reload(['signifyd-fingerprint']); 5492 } else { 5493 me.data = customerData.get('signifyd-fingerprint'); 5494 me.sent = false; 5495 5496 if (Object.entries(me.data()).length === 0 && 5497 window.location.href.indexOf('checkout') > -1 5498 ) { 5499 customerData.reload(['signifyd-fingerprint']); 5500 } 5501 5502 me.sent = me.checkSessionId(me.data().dataOrderSessionId); 5503 if (me.sent === false) { 5504 me.observing = me.data.subscribe(function (newData) { 5505 me.sent = me.checkSessionId(newData.dataOrderSessionId); 5506 }); 5507 } 5508 } 5509 }, 5510 checkSessionId: function(dataOrderSessionId) { 5511 var me = this; 5512 5513 if ( 5514 typeof dataOrderSessionId !== 'undefined' && dataOrderSessionId.length > 0 5515 ) { 5516 if (typeof $.cookie('signifyd-' + dataOrderSessionId) !== 'undefined' && 5517 $.cookie('signifyd-' + dataOrderSessionId) !== null && 5518 $.cookie('signifyd-' + dataOrderSessionId) !== 'null' 5519 ) { 5520 console.log('Fingerprint already sent'); 5521 } else { 5522 console.log('Sending fingerprint...'); 5523 5524 $.cookie('signifyd-' + dataOrderSessionId, true, { 5525 expires: 0.5, 5526 path: '/' 5527 }); 5528 5529 me.callScript(dataOrderSessionId); 5530 if (typeof me.observing != "undefined") { 5531 me.observing.dispose(); 5532 } 5533 return true; 5534 } 5535 } else { 5536 console.log('Will not send fingerprint'); 5537 console.log(dataOrderSessionId); 5538 return false; 5539 } 5540 }, 5541 callScript: function(dataOrderSessionId) { 5542 var signifydScript = document.createElement('script'); 5543 signifydScript.setAttribute('async', true); 5544 signifydScript.setAttribute('type', 'text/javascript'); 5545 signifydScript.setAttribute('id', 'sig-api'); 5546 signifydScript.setAttribute('data-order-session-id', dataOrderSessionId); 5547 signifydScript.setAttribute('src', 'https://cdn-scripts.signifyd.com/api/script-tag.js'); 5548 $("head").append(signifydScript); 5549 } 5550 } 5551 }; 5552 jQuery(function() { 5553 SignifydFingerprint().initialize(); 5554 }); 5555 } 5556 ); 5557 require(['signifyd-fingerprint-module']);</script>
5557
5557<script> 5558 window.openMinicart = '1'; 5559 window.shouldOpenMinicart = '1'; 5560 window.openMinicartDisplayOptions = 'both'; 5561 requirejs(['jquery', 'weltpixel_quickcart' ], function($, quickcart) { 5562 $(document).ready(function() { 5563 var mobileBreakpoint = 768; 5564 quickcart.initialize(mobileBreakpoint); 5565 }); 5566 }); 5567 </script>
5567 5568
5569<script> 5570 let SnapSlider = class { 5571 constructor(el, { 5572 labelSepparator = 'of', 5573 autoPager, 5574 groupPager, 5575 loop, 5576 forcePager 5577 } = {}) { 5578 this.el = el; 5579 this.track = this.el.querySelector("[data-track]"); 5580 if (!this.track) { 5581 console.warn( 5582 "No Slider track defined, reverting back to CSS slider.\nPlease create a wrapper for your slides with the attribute data-track", 5583 this.el 5584 ); 5585 return; 5586 } 5587 this.initialLoad = true; 5588 this.slides = []; 5589 this.inViewObserver; 5590 this.mutationObserver; 5591 this.resizeObserver; 5592 this.pager = this.el.querySelector("[data-pager]"); 5593 this.navBtns = Array.from( 5594 this.el.querySelectorAll("[data-next], [data-prev]") 5595 ); 5596 this.slideLabelSepparator = this.el.dataset.slideLabelSepparator || labelSepparator; 5597 this.useAutoPager = autoPager || this.el.hasAttribute("data-auto-pager") || false; 5598 this.useGroupPager = groupPager || this.el.hasAttribute("data-group-pager") || false; 5599 this.useLoop = loop || this.el.hasAttribute("data-loop") || false; 5600 this.forcePager = forcePager || this.el.hasAttribute("data-force-pager") || false; 5601 this.sliderLabel = this.el.hasAttribute("aria-label") && this.el.getAttribute("aria-label").toLowerCase().trim().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, ""); 5602 this.sliderId = this.el.id || this.sliderLabel || "slider"; 5603 this.markerIdName = "data-target-id"; 5604 this.pagerClasses = this.el.dataset.pagerClass || "snap-pager"; 5605 this.markerClasses = this.el.dataset.markerClass || "snap-marker"; 5606 this.init(); 5607 } 5608 init() { 5609 this.setupSlides(); 5610 this.setupNav(); 5611 if (this.useAutoPager) { 5612 this.createPager(); 5613 } else { 5614 this.setupPager(); 5615 } 5616 this.setupObservers(); 5617 this.setupMutationObserver(); 5618 this.setupResizeObserver(); 5619 this.el.addEventListener("click", this.eventHandler.bind(this)); 5620 this.el.addEventListener("keydown", this.eventHandler.bind(this)); 5621 if ("onscrollend" in window) { 5622 this.track.addEventListener("scrollend", () => { 5623 this.isNavigating = false; 5624 }); 5625 } else { 5626 this.track.addEventListener("scroll", () => { 5627 clearTimeout(this.scrollEndTimer); 5628 this.scrollEndTimer = setTimeout(() => { 5629 this.isNavigating = false; 5630 }, 100); 5631 }); 5632 } 5633 } 5634 destroy() { 5635 this.inViewObserver?.disconnect(); 5636 this.mutationObserver?.disconnect(); 5637 this.resizeObserver?.disconnect(); 5638 this.el.removeEventListener("click", this.eventHandler.bind(this)); 5639 this.el.removeEventListener("keydown", this.eventHandler.bind(this)); 5640 } 5641 roundUpIfGreaterThan(number, min = 8) { 5642 const decimalPart = number - Math.floor(number); 5643 return decimalPart >= min ? Math.ceil(number) : Math.floor(number); 5644 } 5645 getInViewItems() { 5646 const inViewSlides = Array.from(this.track.querySelectorAll("[data-in-view]")).filter((el) => this.slides.includes(el)); 5647 const firstInViewSlide = inViewSlides[0] || null; 5648 const lastInViewSlide = inViewSlides[inViewSlides.length - 1] || null; 5649 const isAtStart = firstInViewSlide === this.slides[0]; 5650 const isAtEnd = lastInViewSlide === this.slides[this.slides.length - 1]; 5651 return { 5652 inViewSlides, 5653 totalInViewSlides: inViewSlides.length, 5654 firstInViewSlide, 5655 lastInViewSlide, 5656 isAtStart, 5657 isAtEnd, 5658 hasNoOverflow: isAtStart && isAtEnd 5659 }; 5660 } 5661 groupPagerMarkers() { 5662 if (this.slides.length === 0 || !this.pager || !this.useGroupPager) return; 5663 const totalVisibleSlides = this.roundUpIfGreaterThan( 5664 this.track.offsetWidth / this.slides[0].offsetWidth 5665 ); 5666 const markers = Array.from(this.pager.querySelectorAll("a, button"));
5667 markers.forEach((marker, index) => { 5668 marker.style.display = index % totalVisibleSlides === 0 ? null : "none"; 5669 }); 5670 } 5671 handleInView(entries) { 5672 entries.forEach((entry) => { 5673 const marker = this.pager && (this.pager.querySelector(`[href="#${entry.target.id}"]`) || this.pager.querySelector( 5674 `[${this.markerIdName}="${entry.target.id}"]` 5675 )); 5676 entry.target.toggleAttribute("data-in-view", entry.isIntersecting); 5677 entry.target.toggleAttribute("inert", !entry.isIntersecting); 5678 marker?.setAttribute("aria-current", entry.isIntersecting); 5679 marker?.setAttribute("tabindex", entry.isIntersecting ? "0" : "-1"); 5680 }); 5681 const { isAtStart, isAtEnd, hasNoOverflow } = this.getInViewItems(); 5682 this.navBtns.forEach((btn) => { 5683 if (btn.hasAttribute("data-next")) { 5684 btn.style.visibility = hasNoOverflow ? "hidden" : null; 5685 isAtEnd && !this.useLoop ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled"); 5686 } 5687 if (btn.hasAttribute("data-prev")) { 5688 btn.style.visibility = hasNoOverflow ? "hidden" : null; 5689 isAtStart && !this.useLoop ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled"); 5690 } 5691 }); 5692 if (this.pager) { 5693 const hidePager = hasNoOverflow && !this.forcePager; 5694 this.pager.style.visibility = hidePager ? "hidden" : null; 5695 this.pager.toggleAttribute("inert", hidePager); 5696 } 5697 if (!this.initialLoad) { 5698 this.el.dispatchEvent( 5699 new CustomEvent("slideChange", { 5700 detail: this.getInViewItems() 5701 }) 5702 ); 5703 } else { 5704 this.initialLoad = false; 5705 } 5706 if (document.activeElement.parentElement.hasAttribute("data-pager")) { 5707 const activeItems = this.pager.querySelectorAll('[tabindex="0"]'); 5708 if (activeItems.length) { 5709 activeItems[0].focus({ preventScroll: true }); 5710 } 5711 } 5712 } 5713 getSlides() { 5714 if (!this.track) return []; 5715 return Array.from(this.track.children).filter( 5716 (child) => child.tagName.toLowerCase() !== "template" && child.tagName.toLowerCase() !== "style" && child.tagName.toLowerCase() !== "script" && child.style.display !== "none" 5717 ); 5718 } 5719 refreshSlides() { 5720 this.initialLoad = true; 5721 this.slides = this.getSlides(); 5722 this.setupSlides(); 5723 if (this.useAutoPager) { 5724 this.createPager(); 5725 } else { 5726 this.setupPager(); 5727 } 5728 this.groupPagerMarkers(); 5729 this.setupObservers(); 5730 } 5731 setupSlides() { 5732 this.slides = this.getSlides(); 5733 this.slides.forEach((slide, index) => { 5734 const totalSlides = this.slides.length; 5735 const currentSlide = index + 1; 5736 const existingLabel = slide.getAttribute("aria-label") || ""; 5737 const isImage = slide.tagName.toLowerCase() === "img" || slide.tagName.toLowerCase() === "picture"; 5738 const slideLabelTag = isImage ? "alt" : "aria-label"; 5739 const hasAutoLabel = existingLabel.startsWith( 5740 `${currentSlide} ${this.slideLabelSepparator} ` 5741 ); 5742 if (!slide.hasAttribute("id")) { 5743 slide.setAttribute( 5744 "id", 5745 `${this.sliderId}-item-${currentSlide}` 5746 ); 5747 } 5748 if (!slide.hasAttribute(slideLabelTag) || slide.getAttribute(slideLabelTag) === "" || hasAutoLabel) { 5749 slide.setAttribute( 5750 slideLabelTag, 5751 `${currentSlide} ${this.slideLabelSepparator} ${totalSlides}` 5752 ); 5753 } 5754 if (slide.tagName.toLowerCase() === "div" && !slide.hasAttribute("role")) { 5755 slide.setAttribute("role", "group"); 5756 } 5757 if (this.pager && !isImage) { 5758 slide.setAttribute("role", "tabpanel"); 5759 } 5760 if (slide.getAttribute("role") === "group") { 5761 slide.setAttribute("aria-roledescription", "item"); 5762 } 5763 }); 5764 if (!this.el.hasAttribute("role") && this.el.tagName !== "SECTION") { 5765 this.el.setAttribute("role", "region"); 5766 } 5767 if (!this.el.hasAttribute("aria-roledescription")) { 5768 this.el.setAttribute("aria-roledescription", "carousel"); 5769 } 5770 if (!this.track.hasAttribute("tabindex")) { 5771 this.track.setAttribute("tabindex", 0); 5772 } 5773 this.track.setAttribute("aria-live", "polite"); 5774 } 5775 setupNav() { 5776 this.navBtns.forEach((btn) => { 5777 btn.setAttribute("disabled", ""); 5778 btn.removeAttribute("hidden"); 5779 btn.classList.remove("invisible"); 5780 btn.style.visibility = null; 5781 }); 5782 } 5783 createPager() { 5784 const newPager = document.createElement("nav"); 5785 newPager.setAttribute("data-pager", ""); 5786 newPager.setAttribute("role", "tablist"); 5787 newPager.classList.add(...this.pagerClasses.split(" "));
5788 this.slides.forEach((slide, index) => { 5789 const marker = document.createElement("button"); 5790 const slideId = slide.id || `${this.sliderId}-item-${index + 1}`; 5791 marker.setAttribute(this.markerIdName, slideId); 5792 marker.classList.add(...this.markerClasses.split(" ")); 5793 this.setupPagerMarker(marker, index); 5794 newPager.appendChild(marker); 5795 if (slide.tagName.toLowerCase() !== "img" && slide.tagName.toLowerCase() !== "picture") { 5796 slide.removeAttribute("aria-roledescription"); 5797 slide.setAttribute("role", "tabpanel"); 5798 } 5799 }); 5800 if (this.pager) { 5801 this.pager.setAttribute("role", "tablist"); 5802 this.pager.replaceChildren(...newPager.children); 5803 } else { 5804 this.track.after(newPager); 5805 this.pager = this.el.querySelector("[data-pager]"); 5806 } 5807 } 5808 setupPager() { 5809 if (!this.pager) return; 5810 this.pager.setAttribute("role", "tablist"); 5811 const items = Array.from(this.pager.querySelectorAll("a, button")); 5812 items.forEach((marker, index) => this.setupPagerMarker(marker, index)); 5813 } 5814 setupPagerMarker(marker, index) { 5815 const markerId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(this.markerIdName); 5816 const slideId = markerId || `${this.sliderId}-item-${index + 1}`; 5817 if (!markerId) { 5818 marker.setAttribute(this.markerIdName, slideId); 5819 } 5820 marker.setAttribute("role", "tab"); 5821 marker.setAttribute("aria-controls", slideId); 5822 marker.setAttribute("aria-posinset", index + 1); 5823 marker.setAttribute("aria-setsize", this.slides.length); 5824 marker.setAttribute("tabindex", "-1"); 5825 if (!marker.hasAttribute("aria-label")) { 5826 marker.setAttribute("aria-label", `Slide ${index + 1}`); 5827 } 5828 } 5829 setupObservers() { 5830 if (this.inViewObserver) { 5831 this.inViewObserver.disconnect(); 5832 } 5833 this.inViewObserver = new IntersectionObserver( 5834 this.handleInView.bind(this), { 5835 root: this.track, 5836 threshold: 0.8 5837 } 5838 ); 5839 this.slides.forEach((slide) => this.inViewObserver.observe(slide)); 5840 } 5841 setupMutationObserver() { 5842 this.mutationObserver = new MutationObserver((mutations) => { 5843 if (mutations.some((m) => m.type === "childList" || m.target.parentElement === this.track)) { 5844 this.refreshSlides(); 5845 } 5846 }); 5847 this.mutationObserver.observe(this.track, { 5848 childList: true, 5849 subtree: true, 5850 attributeFilter: ["style"] 5851 }); 5852 } 5853 setupResizeObserver() { 5854 this.resizeObserver = new ResizeObserver( 5855 this.groupPagerMarkers.bind(this) 5856 ); 5857 this.resizeObserver.observe(this.el); 5858 } 5859 goToSlideDir(dir = "next") { 5860 if (this.isNavigating) return; 5861 const { firstInViewSlide, lastInViewSlide } = this.getInViewItems(); 5862 const isPrev = dir === "prev"; 5863 const referenceSlide = isPrev ? firstInViewSlide : lastInViewSlide; 5864 const currentIndex = this.slides.indexOf(referenceSlide); 5865 let targetIndex = isPrev ? currentIndex - 1 : currentIndex + 1; 5866 if (targetIndex < 0 || targetIndex >= this.slides.length) { 5867 if (!this.useLoop) return; 5868 targetIndex = isPrev ? this.slides.length - 1 : 0; 5869 } 5870 const targetSlide = this.slides[targetIndex]; 5871 if (!targetSlide) return; 5872 this.isNavigating = true; 5873 targetSlide.scrollIntoView({ 5874 block: "nearest", 5875 inline: isPrev ? "end" : "start" 5876 }); 5877 } 5878 pagerToSlide(event) { 5879 if (!event.target.closest("[data-pager]")) return; 5880 const marker = event.target.closest("a, button"); 5881 if (!marker) return; 5882 event.preventDefault(); 5883 const slideId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(this.markerIdName); 5884 const targetSlide = this.track.querySelector(`#${slideId}`);
5885 targetSlide?.scrollIntoView({ block: "nearest", inline: "start" }); 5886 } 5887 eventHandler(event) { 5888 const target = event.target.closest( 5889 "[data-next], [data-prev], [data-pager]" 5890 ); 5891 if (!target) return; 5892 if (event.type === "click") { 5893 if (target.hasAttribute("data-next")) { 5894 this.goToSlideDir("next"); 5895 } else if (target.hasAttribute("data-prev")) { 5896 this.goToSlideDir("prev"); 5897 } else if (target.closest("[data-pager]")) { 5898 this.pagerToSlide(event); 5899 } 5900 } 5901 if (event.type === "keydown" && target.closest("[data-pager]")) { 5902 if (event.key === "ArrowRight" || event.key === "ArrowDown") { 5903 event.preventDefault(); 5904 this.goToSlideDir("next"); 5905 } else if (event.key === "ArrowLeft" || event.key === "ArrowUp") { 5906 event.preventDefault(); 5907 this.goToSlideDir("prev"); 5908 } 5909 } 5910 } 5911 }; 5912 5913 (() => { 5914 function alpineSnapSlider(Alpine) { 5915 Alpine.directive("snap-slider", (el, { 5916 modifiers 5917 }, { 5918 cleanup 5919 }) => { 5920 const slider = new SnapSlider(el, { 5921 autoPager: modifiers.includes("auto-pager"), 5922 groupPager: modifiers.includes("group-pager"), 5923 loop: modifiers.includes("loop"), 5924 forcePager: modifiers.includes("force-pager") 5925 }); 5926 cleanup(() => { 5927 slider.destroy(); 5928 }); 5929 }); 5930 } 5931 5932 document.addEventListener("alpine:init", () => { 5933 window.Alpine.plugin(alpineSnapSlider); 5934 }); 5935 })(); 5936 //# sourceURL=alpine-snap-slider.js 5937</script>
vendor: 1 bytes, line 5937
5937
5938<script> 5939 (() => { 5940 // src/dialog.js 5941 function dialog_default(Alpine) { 5942 Alpine.directive("htmldialog", fylgjaAlpineDialog); 5943 function fylgjaAlpineDialog(el, { expression, modifiers }, { evaluateLater, cleanup }) { 5944 const evaluate = expression.length ? evaluateLater(expression) : () => {}; 5945 const lockPageScroll = modifiers.includes("noscroll"); 5946 const isModeless = modifiers.includes("modeless"); 5947 const closeBy = el.getAttribute("closeby") || modifierValue(modifiers, "closeby", "closerequest"); 5948 el.style.display = null; 5949 el.style.length === 0 && el.removeAttribute("style"); 5950 if (el._x_isShown) { 5951 open(); 5952 } 5953 const closeBySupported = (() => { 5954 return "closedBy" in HTMLDialogElement.prototype; 5955 })(); 5956 function scrollLock(use = true) { 5957 document.body.style.overflow = use ? "hidden" : ""; 5958 } 5959 function dialogSubmit(event) { 5960 if (event.target.getAttribute("method") === "dialog" || event.submitter?.getAttribute("formmethod") === "dialog") { 5961 event.preventDefault(); 5962 evaluate(); 5963 } 5964 } 5965 function escapeDialog(event) { 5966 if (event.key !== "Escape") return; 5967 event.preventDefault(); 5968 if (closeBy === "none") return; 5969 evaluate(); 5970 } 5971 function handleCloseByEvent(event) { 5972 if (event.target !== el) return; 5973 const rect = el.getBoundingClientRect(); 5974 const isInDialog = rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width; 5975 if (!isInDialog) { 5976 if (closeBy === "any") { 5977 if (closeBySupported) { 5978 event.preventDefault(); 5979 } 5980 evaluate(); 5981 } 5982 } 5983 } 5984 function handleCloseEvent() { 5985 evaluate(); 5986 } 5987 function open() { 5988 if (el.hasAttribute("open")) return; 5989 isModeless ? el.show() : el.showModal(); 5990 scrollLock(lockPageScroll); 5991 } 5992 function close() { 5993 if (!el.hasAttribute("open")) return; 5994 el.close(); 5995 scrollLock(false); 5996 } 5997 el._x_doShow = () => open(); 5998 el._x_doHide = () => close(); 5999 el.addEventListener("keydown", escapeDialog); 6000 el.addEventListener("submit", dialogSubmit); 6001 el.addEventListener("click", handleCloseByEvent); 6002 el.addEventListener("cancel", handleCloseEvent); 6003 cleanup(() => { 6004 el.removeEventListener("keydown", escapeDialog); 6005 el.removeEventListener("submit", dialogSubmit); 6006 el.removeEventListener("click", handleCloseByEvent); 6007 el.removeEventListener("cancel", handleCloseEvent); 6008 scrollLock(false); 6009 }); 6010 } 6011 } 6012 function modifierValue(modifiers, key, fallback) { 6013 if (modifiers.indexOf(key) === -1) return fallback; 6014 const rawValue = modifiers[modifiers.indexOf(key) + 1]; 6015 if (!rawValue) return fallback; 6016 if (key === "closeby") { 6017 const allowedValues = ["auto", "none", "closerequest", "any"]; 6018 const options = allowedValues.join(", "); 6019 if (!allowedValues.includes(rawValue)) { 6020 console.warn( 6021 `"${rawValue}" is not one of the allowed values for closeby: ${options}` 6022 ); 6023 return fallback; 6024 } 6025 } 6026 return rawValue; 6027 } 6028 6029 // src/cdn.js 6030 document.addEventListener("alpine:init", () => { 6031 window.Alpine.plugin(dialog_default); 6032 }); 6033 })(); 6034 //# sourceURL=alpine-htmldialog.js 6035</script>
vendor: 1 bytes, line 6035
6035
6036<script> 6037 (() => { 6038 function src_default(Alpine) { 6039 Alpine.directive("intersect", Alpine.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => { 6040 let evaluate = evaluateLater(expression); 6041 let options = { 6042 rootMargin: getRootMargin(modifiers), 6043 threshold: getThreshold(modifiers) 6044 }; 6045 let observer = new IntersectionObserver((entries) => { 6046 entries.forEach((entry) => { 6047 if (entry.isIntersecting === (value === "leave")) 6048 return; 6049 evaluate(); 6050 modifiers.includes("once") && observer.disconnect(); 6051 }); 6052 }, options); 6053 observer.observe(el); 6054 cleanup(() => { 6055 observer.disconnect(); 6056 }); 6057 })); 6058 } 6059 function getThreshold(modifiers) { 6060 if (modifiers.includes("full")) 6061 return 0.99; 6062 if (modifiers.includes("half")) 6063 return 0.5; 6064 if (!modifiers.includes("threshold")) 6065 return 0; 6066 let threshold = modifiers[modifiers.indexOf("threshold") + 1]; 6067 if (threshold === "100") 6068 return 1; 6069 if (threshold === "0") 6070 return 0; 6071 return Number(`.${threshold}`); 6072 } 6073 function getLengthValue(rawValue) { 6074 let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/); 6075 return match ? match[1] + (match[2] || "px") : void 0; 6076 } 6077 function getRootMargin(modifiers) { 6078 const key = "margin"; 6079 const fallback = "0px 0px 0px 0px"; 6080 const index = modifiers.indexOf(key); 6081 if (index === -1) 6082 return fallback; 6083 let values = []; 6084 for (let i = 1; i < 5; i++) { 6085 values.push(getLengthValue(modifiers[index + i] || "")); 6086 } 6087 values = values.filter((v) => v !== void 0); 6088 return values.length ? values.join(" ").trim() : fallback; 6089 } 6090 6091 document.addEventListener("alpine:init", () => { 6092 window.Alpine.plugin(src_default); 6093 }); 6094 })(); 6095 //# sourceURL=alpine-intersect.js 6096</script>
6096 6097
6098<script> 6099 for (const [selector, deferUntil] of Object.entries({".product-slider section[x-data]:not([x-data] [x-data])":"intersect",".product-info [x-data]:not([x-data] [x-data])":"intersect","#filters-content [x-data]:not([x-data] [x-data])":"intersect","#review_form":"intersect","section[x-data^=initRecentlyViewedProductsComponent]":"intersect","div[x-data^=initBundleOptions]":"intersect","#product_addtocart_form [x-data]:not([x-data] [x-data])":"intersect","#notice-cookie-block":"idle"})) { 6100 document.querySelectorAll(selector).forEach(el => el.setAttribute('x-defer', `${deferUntil}`)); 6101 } 6102 //# sourceURL=alpine-defer-rules.js 6103</script>
vendor: 1 bytes, line 6103
6103
6104<script> 6105 (() => { 6106 const hasAlpine = new Promise(resolve => { 6107 window.addEventListener('alpine:initialized', resolve, {once: true, passive: true}); 6108 }); 6109 6110 const hasInteract = new Promise(resolve => { 6111 (events => { 6112 const onInteract = () => { 6113 resolve(); 6114 events.forEach(type => window.removeEventListener(type, onInteract)); 6115 } 6116 events.forEach(type => window.addEventListener(type, onInteract, {once: true, passive: true})) 6117 })(['touchstart', 'mouseover', 'wheel', 'scroll', 'keydown']) 6118 }); 6119 6120 const onIntersect = (el) => { 6121 return new Promise(resolve => { 6122 const observer = new IntersectionObserver(entries => { 6123 for (const entry of entries) { 6124 if (entry.isIntersecting) { 6125 observer.disconnect() 6126 resolve(); 6127 } 6128 } 6129 }, {}); 6130 observer.observe(el); 6131 }); 6132 } 6133 6134 function runComponent(el) { 6135 hasAlpine.then(() => { 6136 el.removeAttribute('x-ignore'); 6137 queueMicrotask(() => Alpine.initTree(el)); 6138 }); 6139 } 6140 6141 function initDeferredComponents() { 6142 document.querySelectorAll('[x-data][x-defer]').forEach(el => { 6143 el.setAttribute('x-ignore', ''); 6144 const deferUntil = (el.getAttribute('x-defer') || '').trim(); 6145 switch (deferUntil) { 6146 case 'interact': 6147 hasInteract.then(() => runComponent(el)); 6148 break; 6149 case 'intersect': 6150 onIntersect(el).then(() => runComponent(el)) 6151 break; 6152 case 'idle': 6153 window.requestIdleCallback 6154 ? window.requestIdleCallback(() => runComponent(el), {timeout: 4000}) 6155 : setTimeout(() => runComponent(el), 4000); 6156 break; 6157 case 'eager': 6158 runComponent(el); 6159 break; 6160 default: 6161 if (deferUntil.startsWith('event:') && deferUntil.length > 6) { 6162 window.addEventListener(deferUntil.substring(6), () => runComponent(el), {once: true, passive: true}); 6163 } 6164 } 6165 }); 6166 } 6167 6168 window.addEventListener('alpine:init', initDeferredComponents, {once: true, passive: true}); 6169 })(); 6170 //# sourceURL=alpine-defer.js 6171</script>
6171 6172
vendor: 1,455 bytes, lines 6173-6175
6173<script> 6174(()=>{function g(n){n.directive("collapse",e),e.inline=(t,{modifiers:i})=>{i.includes("min")&&(t._x_doShow=()=>{},t._x_doHide=()=>{})};function e(t,{modifiers:i}){let r=l(i,"duration",250)/1e3,u=l(i,"min",0),h=!i.includes("min");t._x_isShown||(t.style.height=`${u}px`),!t._x_isShown&&h&&(t.hidden=!0),t._x_isShown||(t.style.overflow="hidden");let c=(d,s)=>{let o=n.setStyles(d,s);return s.height?()=>{}:o},f={transitionProperty:"height",transitionDuration:`${r}s`,transitionTimingFunction:"cubic-bezier(0.4, 0.0, 0.2, 1)"};t._x_transition={in(d=()=>{},s=()=>{}){h&&(t.hidden=!1),h&&(t.style.display=null);let o=t.getBoundingClientRect().height;t.style.height="auto";let a=t.getBoundingClientRect().height;o===a&&(o=u),n.transition(t,n.setStyles,{during:f,start:{height:o+"px"},end:{height:a+"px"}},()=>t._x_isShown=!0,()=>{t.getBoundingClientRect().height==a&&(t.style.overflow=null)})},out(d=()=>{},s=()=>{}){let o=t.getBoundingClientRect().height;n.transition(t,c,{during:f,start:{height:o+"px"},end:{height:u+"px"}},()=>t.style.overflow="hidden",()=>{t._x_isShown=!1,t.style.height==`${u}px`&&h&&(t.style.display="none",t.hidden=!0)})}}}}function l(n,e,t){if(n.indexOf(e)===-1)return t;let i=n[n.indexOf(e)+1];if(!i)return t;if(e==="duration"){let r=i.match(/([0-9]+)ms/);if(r)return r[1]}if(e==="min"){let r=i.match(/([0-9]+)px/);if(r)return r[1]}return i}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(g)});})(); 6175</script>
vendor: 1 bytes, line 6175
6175
6176<script> 6177// x-teleport implementation 6178(_ => { 6179 document.addEventListener('DOMContentLoaded', event => { 6180 // x-teleport available only for template 6181 if (!Alpine.version.startsWith('2')) { 6182 return; 6183 } 6184 6185 const teleportDirective = (el, expression) => { 6186 let target = document.querySelector(expression) 6187 let clone = el.content.cloneNode(true).firstElementChild; 6188 6189 target.appendChild(clone); 6190 setTimeout(() => { 6191 target.querySelectorAll('[x-data]') 6192 .forEach(el => Alpine.initializeComponent(el)); 6193 }, 0) 6194 }; 6195 6196 document.querySelectorAll('template').forEach(el => { 6197 if (!el.hasAttribute('x-teleport')) { 6198 return; 6199 } 6200 6201 teleportDirective(el, el.getAttribute('x-teleport')); 6202 }); 6203 6204 document.querySelectorAll('[x-data]').forEach(el => { 6205 if (el.hasAttribute('x-init')) { 6206 return; 6207 } 6208 6209 setTimeout(() => { 6210 Alpine.initializeComponent(el); 6211 }, 0); 6212 }); 6213 }); 6214})() 6215</script>
6215 6216
6217<script type="module" 6218 src="https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Hyva_Theme/js/alpine3.min.js" 6219 defer 6220 crossorigin 6221></script>
vendor: 1 bytes, line 6221
6221
6222<script> 6223 function dispatchMessages(messages, hideAfter) { 6224 const messagesEvent = new CustomEvent("messages-loaded", { 6225 detail: { 6226 messages: messages, 6227 hideAfter: hideAfter 6228 } 6229 }); 6230 window.dispatchEvent(messagesEvent); 6231 } 6232 6233 if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) { 6234 console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script"); 6235 } 6236 6237 (function( hyva, undefined ) { 6238 6239 hyva.initFormKey = () => { 6240 if (typeof hyva.getFormKey !== 'function') return; 6241 6242 const formKey = hyva.getFormKey(); 6243 if (!formKey) return; 6244 6245 document.querySelectorAll('input[name="form_key"]').forEach((input) => { 6246 input.value = formKey; 6247 }); 6248 } 6249 6250 hyva.initMessages = () => { 6251 try { 6252 const messages = hyva.getCookie('mage-messages'); 6253 window.mageMessages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : []; 6254 6255 dispatchMessages(window.mageMessages); 6256 6257 // empty `mage-messages` cookie 6258 const skipSetDomain = true; 6259 hyva.setCookie('mage-messages','', -1, skipSetDomain); 6260 6261 } catch (error) { 6262 console.warn('Error parsing Cookie Messages:', error); 6263 } 6264 } 6265 6266 window.addEventListener('DOMContentLoaded', hyva.initFormKey); 6267 6268 window.addEventListener('pageshow', (event) => { 6269 if (event.persisted) { 6270 hyva.initFormKey(); 6271 } 6272 }); 6273 6274 hyva.alpineInitialized(hyva.initMessages) 6275 }( window.hyva = window.hyva || {} )); 6276 //# sourceURL=hyva-cookies.js 6277</script>
vendor: 1 bytes, line 6277
6277
6278<script> 6279 (() => { 6280 const private_content_key = 'mage-cache-storage'; 6281 const private_content_expire_key = 'mage-cache-timeout'; 6282 const private_content_version_key = 'private_content_version'; 6283 const section_data_ids_key = 'section_data_ids'; 6284 const mage_cache_session_id_key = 'mage-cache-sessid'; 6285 const last_visited_store_key = 'last_visited_store'; 6286 6287 const ttl = 2592000; 6288 6289 if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) { 6290 console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script"); 6291 } 6292 6293 function loadSectionData () { 6294 const browserStorage = hyva.getBrowserStorage(); 6295 if (!browserStorage) { 6296 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 6297 [{ 6298 type: "warning", 6299 text: "Please enable LocalStorage in your browser." 6300 }] 6301 ); 6302 return; 6303 } 6304 try { 6305 let isInvalid = false; 6306 6307 if (hyva.getCookie(last_visited_store_key) !== CURRENT_STORE_CODE) { 6308 isInvalid = true; 6309 } 6310 hyva.setCookie(last_visited_store_key, CURRENT_STORE_CODE, false, false); 6311 6312 if (!hyva.getCookie(mage_cache_session_id_key)) { 6313 isInvalid = true; 6314 browserStorage.removeItem(private_content_key); 6315 const skipSetDomain = true; 6316 const days = false; 6317 hyva.setCookie(mage_cache_session_id_key, true, days, skipSetDomain) 6318 } 6319 6320 const cookieVersion = hyva.getCookie(private_content_version_key); 6321 const storageVersion = browserStorage.getItem(private_content_version_key); 6322 6323 if (cookieVersion && !storageVersion || cookieVersion !== storageVersion) { 6324 isInvalid = true; 6325 } 6326 6327 const privateContentExpires = browserStorage.getItem(private_content_expire_key); 6328 if (privateContentExpires && new Date(privateContentExpires) < new Date()) { 6329 browserStorage.removeItem(private_content_key); 6330 } 6331 6332 if (isInvalid && cookieVersion) { 6333 fetchPrivateContent([]); 6334 } else if (cookieVersion && storageVersion && cookieVersion === storageVersion) { 6335 const privateContent = JSON.parse(browserStorage.getItem(private_content_key)); 6336 if ( 6337 privateContent && 6338 privateContentExpires && 6339 privateContent.cart && 6340 privateContent.customer 6341 ) { 6342 dispatchPrivateContent(privateContent); 6343 } else { 6344 fetchPrivateContent([]); 6345 } 6346 } else { 6347 if (document.getElementById('default-section-data')) { 6348 const privateContent = JSON.parse(document.getElementById('default-section-data').textContent.trim()); 6349 dispatchPrivateContent(privateContent); 6350 } else { 6351 dispatchPrivateContent({}); 6352 } 6353 } 6354 6355 } catch (error) { 6356 console.warn('Error retrieving Private Content:', error); 6357 } 6358 } 6359 6360 hyva.alpineInitialized(loadSectionData) 6361 window.addEventListener('reload-customer-section-data', loadSectionData); 6362 6363 window.processSectionDataBeforeDispatch = window.processSectionDataBeforeDispatch || (data => data); 6364 6365 function dispatchPrivateContent(data) { 6366 6367 const privateContentEvent = new CustomEvent("private-content-loaded", { 6368 detail: { 6369 data: window.processSectionDataBeforeDispatch(data) 6370 } 6371 }); 6372 window.dispatchEvent(privateContentEvent); 6373 } 6374 6375 function fetchPrivateContent(sections) { 6376 fetch(`${BASE_URL}customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`, { 6377 method: 'GET', 6378 headers: { 6379 'Content-Type': 'application/json', 6380 'X-Requested-With': 'XMLHttpRequest' 6381 } 6382 }) 6383 .then(response => response.ok && response.json()) 6384 .then( 6385 data => { 6386 if (data) { 6387 try { 6388 const browserStorage = hyva.getBrowserStorage(); 6389 6390 // merge new data preserving non-invalidated sections 6391 const oldSectionData = JSON.parse(browserStorage.getItem(private_content_key) || '{}') || {}; 6392 6393 if ((! data.cart || ! data.cart.cartId) && oldSectionData['checkout-data']) { 6394 delete oldSectionData['checkout-data']; 6395 } 6396 const newSectionData = Object.assign(oldSectionData, data); 6397 6398 dispatchPrivateContent(newSectionData); 6399 6400 // don't persist messages, they've been dispatched already 6401 if (newSectionData.messages && newSectionData.messages.messages ) { 6402 newSectionData.messages.messages = []; 6403 } 6404 6405 browserStorage.setItem(private_content_key, JSON.stringify(newSectionData)); 6406 6407 const expiresAt = new Date(Date.now() + (ttl * 1000)).toISOString(); 6408 browserStorage.setItem(private_content_expire_key, expiresAt); 6409 6410 const newCookieVersion = hyva.getCookie(private_content_version_key); 6411 browserStorage.setItem(private_content_version_key, newCookieVersion); 6412 6413 // We don't need the section_data_ids in Hyvä, but we store them for compatibility 6414 // with Luma Fallback. Otherwise, not all sections are loaded in Luma Checkout 6415 hyva.setCookie( 6416 section_data_ids_key, 6417 JSON.stringify( 6418 Object.keys(data).reduce((sectionDataIds, sectionKey) => { 6419 sectionDataIds[sectionKey] = data[sectionKey]['data_id']; 6420 return sectionDataIds; 6421 }, {}) 6422 ), 6423 false, 6424 true 6425 ); 6426 } catch (error) { 6427 console.warn("Couldn't store privateContent", error); 6428 } 6429 } 6430 } 6431 ) 6432 .catch(error => { 6433 console.warn("Couldn't fetch privateContent", error); 6434 }); 6435 } 6436 })(); 6437 //# sourceURL=hyva-private-content.js 6438</script>
vendor: 1 bytes, line 6438
6438
6439<script> 6440 (() => { 6441 document.addEventListener('submit', event => event.target.action = event.target.action.replace('%25uenc%25', hyva.getUenc())); 6442 })() 6443</script>
vendor: 1 bytes, line 6443
6443
6444<script> 6445 (events => { 6446 const dispatchUserInteractionEvent = () => { 6447 events.forEach(type => window.removeEventListener(type, dispatchUserInteractionEvent)) 6448 window.dispatchEvent(new Event('init-external-scripts')) 6449 }; 6450 events.forEach(type => window.addEventListener(type, dispatchUserInteractionEvent, {once: true, passive: true})) 6451 })(['touchstart', 'mousemove', 'wheel', 'scroll', 'keydown']); 6452 //# sourceURL=hyva-init-external-scripts.js 6453</script>
vendor: 1 bytes, line 6453
6453
6454<script> 6455 function initConfigurableOptions(productId, optionConfig) { 6456 6457 function findPathParam(key) { 6458 const baseUrl = (BASE_URL.substring(0, 2) === '//' ? 'http:' : '') + BASE_URL; 6459 const baseUrlParts = (new URL(baseUrl)).pathname.replace(/\/$/, '').split('/'); 6460 const pathParts = window.location.pathname.split('/').slice(baseUrlParts.length + 3); 6461 for (let i = 0; i < pathParts.length; i += 2) { 6462 if (pathParts[i] === key && pathParts.length > i) { 6463 return pathParts[i + 1]; 6464 } 6465 } 6466 } 6467 6468 return { 6469 optionConfig, 6470 productId, 6471 itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'), 6472 allowedAttributeOptions: [], 6473 selectedValues: [], 6474 init() { 6475 this.findAllowedAttributeOptions(); 6476 this.$nextTick(() => { 6477 if (typeof this.optionConfig.defaultValues === 'object') { 6478 for (const [attributeId, value] of Object.entries(this.optionConfig.defaultValues)) { 6479 this.changeOption(attributeId, value + ''); 6480 } 6481 } 6482 this.preselectQuerystringItems(); 6483 this.preselectLocationHashItems(); 6484 }); 6485 }, 6486 productIndex: 0, 6487 productIndexForPrice: 0, 6488 optionIsActive(attributeId, optionId) { 6489 return !!this.getAllowedAttributeOptions(attributeId).find( 6490 option => option.id === optionId 6491 ) 6492 }, 6493 optionIsEnabled(attributeId, optionId) { 6494 for (const productId in this.optionConfig.index) { 6495 if (this.optionConfig.index[productId][attributeId] === optionId) { 6496 return true; 6497 } 6498 } 6499 return false; 6500 }, 6501 findSimpleIndex() { 6502 this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues); 6503 this.productIndexForPrice = this.findCheapestProductForPartialSelection(this.selectedValues); 6504 }, 6505 calculateSimpleIndexForPartialSelection(selectedValues) { 6506 if (selectedValues.length === 0) return 0; 6507 return this.findProductIdsForPartialSelection(selectedValues)[0]; 6508 }, 6509 calculateSimpleIndexForFullSelection(selectedValues) { 6510 if (! this.isFullSelection(selectedValues)) return false; 6511 6512 const productIndexes = this.optionConfig.index; 6513 return Object.keys(productIndexes).find(productIndex => { 6514 const productCandidateOptions = productIndexes[productIndex]; 6515 6516 for (const productOption in productCandidateOptions) { 6517 if ( 6518 !selectedValues[productOption] || 6519 selectedValues[productOption] !== productCandidateOptions[productOption] 6520 ) { 6521 return false; 6522 } 6523 } 6524 return productIndex; 6525 }); 6526 }, 6527 findAllowedAttributeOptions() { 6528 this.allowedAttributeOptions = this.calculateAllowedAttributeOptions(this.selectedValues); 6529 }, 6530 calculateAllowedAttributeOptions(selectedValues) { 6531 const allAttributes = this.optionConfig.attributes; 6532 const allAttributesSorted = Object.values(allAttributes).sort((a,b) => { 6533 return a.position - b.position 6534 }); 6535 6536 const newAllowedAttributeOptions = []; 6537 6538 allAttributesSorted.forEach(attribute => { 6539 const selectionWithoutAttr = Object.assign({}, this.removeAttrFromSelection(selectedValues, attribute.id)); 6540 const availableIndexes = this.calculateAvailableProductIndexes(selectionWithoutAttr); 6541 newAllowedAttributeOptions[attribute.id] = allAttributes[attribute.id].options.filter(option => { 6542 return !!option.products.find(product => { 6543 return availableIndexes.includes(product); 6544 }) 6545 }); 6546 }); 6547 return newAllowedAttributeOptions; 6548 }, 6549 calculateAvailableProductIndexes(selectedOptions) { 6550 if (Object.keys(selectedOptions).length === 0) { 6551 if (Object.values(this.optionConfig.salable || {}).length) { 6552 return [].concat.apply([], [].concat.apply([], Object.values(this.optionConfig.salable).map(Object.values))).filter((x, i, a) => a.indexOf(x) === i) 6553 } 6554 return Object.keys(this.optionConfig.index); 6555 } 6556 6557 const selectedIds = Object.keys(selectedOptions); 6558 if (Object.values(this.optionConfig.salable || {}).length) { 6559 const selectedOptionIndexes = selectedIds.map(attrId => { 6560 const optionValue = selectedOptions[attrId]; 6561 return this.optionConfig.salable[attrId] && this.optionConfig.salable[attrId][optionValue] || [] 6562 }) 6563 return selectedOptionIndexes.reduce((acc, optionIndexes) => { 6564 return acc.filter(index => optionIndexes.includes(index)); 6565 }); 6566 } else { 6567 const productIndexes = this.optionConfig.index; 6568 return Object.keys(productIndexes).filter(index => { 6569 for (const attrId of selectedIds) { 6570 if (productIndexes[index][attrId] !== `${selectedOptions[attrId]}`) return false 6571 } 6572 return true 6573 }); 6574 } 6575 }, 6576 findAttributeByOptionId(optionId) { 6577 for (const attributeId in this.optionConfig.attributes) { 6578 const attributeOptions = this.optionConfig.attributes[attributeId].options || []; 6579 if (attributeOptions.find(option => option.id === optionId)) { 6580 return attributeId; 6581 } 6582 } 6583 }, 6584 getAllowedAttributeOptions(attributeId) { 6585 return this.allowedAttributeOptions[attributeId] || [] 6586 }, 6587 getAllAttributeOptions(attributeId) { 6588 return ( 6589 this.optionConfig.attributes[attributeId] && 6590 this.optionConfig.attributes[attributeId].options 6591 ) || [] 6592 }, 6593 getProductIdsForOption(option) { 6594 const attributeId = this.findAttributeByOptionId(option.id); 6595 const allOptions = this.optionConfig.attributes[attributeId]; 6596 const opt = (allOptions && allOptions.options || []).find(o => o.id === option.id); 6597 return opt && opt.products 6598 ? opt.products 6599 : []; 6600 }, 6601 findProductIdsForPartialSelection(optionSelection) { 6602 const candidateProducts = Object.values(optionSelection).reduce((candidates, optionId) => { 6603 const newCandidates = this.getProductIdsForOption({id: optionId}); 6604 return candidates === null 6605 ? newCandidates 6606 : candidates.filter(productId => newCandidates.includes(productId)); 6607 }, null); 6608 return candidateProducts || []; 6609 },
6610 findCheapestProductForPartialSelection(optionSelection) { 6611 const candidateProducts = this.findProductIdsForPartialSelection(optionSelection); 6612 return candidateProducts.reduce((cheapest, simpleIdx) => { 6613 // in the first iteration we start with simpleIdx as the currently cheapest product 6614 if (! this.optionConfig.optionPrices[cheapest]) return simpleIdx; 6615 const knownCheapestPrice = this.optionConfig.optionPrices[cheapest].finalPrice.amount; 6616 return knownCheapestPrice > this.optionConfig.optionPrices[simpleIdx].finalPrice.amount 6617 ? simpleIdx 6618 : cheapest; 6619 }, 0) 6620 }, 6621 findProductIdToUseForOptionPrice(option) { 6622 // try to find a product for a complete selection 6623 const attributeId = this.findAttributeByOptionId(option.id); 6624 const optionSelection = Object.assign({}, this.selectedValues, {[attributeId]: option.id}); 6625 const matchingSimpleIndex = this.calculateSimpleIndexForFullSelection(optionSelection); 6626 // if there is no complete selection, use the cheapest product for the option 6627 return matchingSimpleIndex || this.findCheapestProductForPartialSelection(optionSelection); 6628 }, 6629 getAttributeOptionLabel(option) { 6630 const optionProduct = this.findProductIdToUseForOptionPrice(option); 6631 6632 if ((! optionProduct) || (optionProduct === this.productIndexForPrice)) { 6633 return option.label; 6634 } 6635 6636 const currentPrice = this.getOptionPriceAdjustmentBasePrice(); 6637 6638 if (this.optionConfig.optionPrices[optionProduct]) { 6639 const optionPrice = this.optionConfig.optionPrices[optionProduct].finalPrice.amount; 6640 if (optionPrice !== currentPrice){ 6641 return option.label + ' ' + hyva.formatPrice(optionPrice - currentPrice, true); 6642 } 6643 } 6644 return option.label; 6645 }, 6646 getOptionPriceAdjustmentBasePrice() { 6647 if (this.optionConfig.optionPrices[this.productIndexForPrice]) { 6648 return this.optionConfig.optionPrices[this.productIndexForPrice].finalPrice.amount 6649 } 6650 return this.optionConfig.prices.finalPrice.amount; // default price if no option selection 6651 }, 6652 clearOptionIfActive(optionId, value) { 6653 if (this.selectedValues[optionId] === value) { 6654 this.blurLabel() 6655 this.changeOption(optionId, '') 6656 } 6657 }, 6658 removeAttrFromSelection(selectedValues, attributeId) { 6659 attributeId = parseInt(attributeId); 6660 return selectedValues.reduce((newSelection, val, attr) => { 6661 if (attr !== attributeId) { 6662 newSelection[attr] = val; 6663 } 6664 return newSelection; 6665 }, []); 6666 }, 6667 changeOption(attributeId, value) { 6668 if (value === '') { 6669 this.selectedValues = this.removeAttrFromSelection(this.selectedValues, attributeId) 6670 } else if (value && this.getAllowedAttributeOptions(attributeId).find(option => option.id === value)) { 6671 this.selectedValues[attributeId] = value; 6672 } 6673 this.findSimpleIndex(); 6674 this.findAllowedAttributeOptions(); 6675 this.updatePrices(); 6676 this.updateGallery(); 6677 6678 const candidates = this.findProductIdsForPartialSelection(this.selectedValues); 6679 6680 window.dispatchEvent( 6681 new CustomEvent( 6682 'configurable-selection-changed', 6683 { 6684 detail: { 6685 productId: this.productId, 6686 optionId: attributeId, 6687 value: value, 6688 productIndex: this.productIndex, 6689 selectedValues: this.selectedValues, 6690 candidates: candidates, 6691 skuCandidates: Object.values(candidates).map(id =>
6691 this.optionConfig.sku?.[id] ?? null).filter(Boolean), 6692 } 6693 } 6694 ) 6695 ); 6696 }, 6697 calculateIsMinimalPrice() { 6698 return ! this.isFullSelection(this.selectedValues); 6699 }, 6700 isFullSelection(selectedValues) { 6701 return Object.values(selectedValues).length === Object.keys(this.optionConfig.attributes).length; 6702 }, 6703 updatePrices() { 6704 const value = this.optionConfig.optionPrices[this.productIndexForPrice] || this.optionConfig.prices; 6705 window.dispatchEvent( 6706 new CustomEvent( 6707 "update-prices-" + this.productId, 6708 { 6709 detail: Object.assign( 6710 value, 6711 { isMinimalPrice: this.calculateIsMinimalPrice() } 6712 ) 6713 } 6714 ) 6715 ); 6716 }, 6717 updateGallery () { 6718 if (this.productIndex) { 6719 const images = this.optionConfig.images[this.productIndex]; 6720 images && window.dispatchEvent(new CustomEvent( 6721 "update-gallery", 6722 { detail: this.sortImagesByPosition(images) } 6723 )); 6724 } else { 6725 window.dispatchEvent(new Event("reset-gallery")); 6726 } 6727 }, 6728 sortImagesByPosition(images) { 6729 return images.sort((x, y) => { 6730 return x.position === y.position ? 0 : (parseInt(x.position) > parseInt(y.position) ? 1 : -1) 6731 }); 6732 }, 6733 onGetCartData(data) { 6734 }, 6735 preselectCartItems(data) { 6736 // pre-select options based on cart data for current (quote) itemId 6737 const cart = data && data.cart; 6738 if (cart && cart.items) { 6739 const cartItem = cart.items.find((item) => { 6740 return ( 6741 item.item_id === this.itemId 6742 && item.product_id === this.productId 6743 ) 6744 }); 6745 if (cartItem && cartItem.options && cartItem.options.length) { 6746 cartItem.options.map(option => { 6747 this.changeOption(option.option_id, option.option_value); 6748 }) 6749 } 6750 } 6751 }, 6752 preselectQuerystringItems() { 6753 // pre-select option like ?size=167 6754 const urlQueryParams = new URLSearchParams(window.location.search.replace('?','')); 6755 this.preselectItemsBasedOnLocation(attribute => urlQueryParams.get(attribute.code)); 6756 }, 6757 preselectLocationHashItems() { 6758 // pre-select option like #144=167 6759 const urlHashParams = new URLSearchParams(window.location.hash.replace('#','')); 6760 this.preselectItemsBasedOnLocation(attribute => urlHashParams.get(attribute.id)); 6761 }, 6762 preselectItemsBasedOnLocation(getLocationValue) { 6763 Object.values(this.optionConfig.attributes).map(attribute => { 6764 const v = getLocationValue(attribute); 6765 v && this.changeOption(attribute.id, v) 6766 }); 6767 } 6768 } 6769 } 6770</script>
vendor: 1 bytes, line 6770
6770
6771<script> 6772 function initSwatchOptions(swatchConfig) { 6773 return { 6774 swatchConfig, 6775 getAttributeSwatchData(attributeId) { 6776 const swatchConfig = Object.assign({}, this.swatchConfig[attributeId]); 6777 swatchConfig['details'] = JSON.parse(swatchConfig['additional_data']); 6778 6779 return swatchConfig; 6780 }, 6781 mapSwatchTypeNumberToTypeCode(typeNumber) { 6782 switch ("" + typeNumber) { 6783 case "1": 6784 return "color" 6785 case "2": 6786 return "image" 6787 case "3": 6788 return "empty" 6789 case "0": 6790 default: 6791 return "text" 6792 } 6793 }, 6794 getTypeOfFirstOption(attributeId) { 6795 for (const optionId in this.swatchConfig[attributeId]) { 6796 const option = this.swatchConfig[attributeId][optionId]; 6797 if (typeof option.type !== 'undefined') { 6798 return this.mapSwatchTypeNumberToTypeCode(option.type); 6799 } 6800 } 6801 }, 6802 getVisualSwatchType(attributeId, targetOptionId) { 6803 // If a type configuration is present for the given option id, use it 6804 const config = this.swatchConfig[attributeId]; 6805 if (config[targetOptionId] && typeof config[targetOptionId].type !== 'undefined') { 6806 return this.mapSwatchTypeNumberToTypeCode(config[targetOptionId].type); 6807 } 6808 6809 // Otherwise - if no config is present for the target option - use the type of the first option 6810 // with a type property from the attribute, thus assuming its the same type as the target option. 6811 // (This edge case condition can occur on single swatch products if some options are not salable) 6812 return this.getTypeOfFirstOption(attributeId); 6813 }, 6814 getSwatchType(attributeId, optionId) { 6815 // Deserialize the attribute details the first time they are used 6816 if (this.swatchConfig[attributeId] && ! this.swatchConfig[attributeId].details) { 6817 this.swatchConfig[attributeId] = this.getAttributeSwatchData(attributeId); 6818 } 6819 const type = this.swatchConfig[attributeId] && 6820 this.swatchConfig[attributeId].details && 6821 this.swatchConfig[attributeId].details.swatch_input_type || 6822 "empty"; 6823 return type === 'visual' ? this.getVisualSwatchType(attributeId, optionId) : type; 6824 }, 6825 isTextSwatch(attributeId, optionId) { 6826 return this.getSwatchType(attributeId, optionId) === 'text'; 6827 }, 6828 isVisualSwatch(attributeId, optionId) { 6829 const type = this.getSwatchType(attributeId, optionId); 6830 6831 return ['image', 'color'].includes(type); 6832 }, 6833 getSwatchBackgroundStyle(attributeId, optionId) { 6834 const config = this.getSwatchConfig(attributeId, optionId); 6835 const type = this.getSwatchType(attributeId, optionId); 6836 6837 if (type === "color") { 6838 return 'background-color:' + config.value; 6839 } else if (type === "image") { 6840 return "background: #fff url('" + config.value + "') no-repeat center"; 6841 } else { 6842 return ''; 6843 } 6844 }, 6845 getSwatchText(attributeId, optionId) { 6846 const config = this.getSwatchConfig(attributeId, optionId); 6847 return config.label || config.value || this.getOptionLabelFromOptionConfig(attributeId, optionId); 6848 }, 6849 getOptionLabelFromOptionConfig(attributeId, optionId) { 6850 // Fallback if no value is present in swatchConfig data 6851 // Reference issue https://gitlab.hyva.io/hyva-themes/magento2-default-theme/-/issues/190 6852 const option = this.getAllAttributeOptions(attributeId).filter(option => option.id === optionId); 6853 return option && option[0] && option[0].label ||''; 6854 }, 6855 getSwatchConfig(attributeId, optionId) { 6856 return this.swatchConfig[attributeId] && this.swatchConfig[attributeId][optionId] 6857 ? this.swatchConfig[attributeId][optionId] 6858 : false;
6859 }, 6860 activeTooltipItem: false, 6861 tooltipPositionElement: false, 6862 isTooltipVisible() { 6863 return this.activeTooltipItem && 6864 this.getSwatchConfig( 6865 this.activeTooltipItem.attribute, 6866 this.activeTooltipItem.item 6867 ); 6868 }, 6869 isFirstItemCol() { 6870 return this.activeTooltipItem.index === 0; 6871 }, 6872 getTooltipImageStyle(attributeId, optionId) { 6873 const config = this.getSwatchConfig(attributeId, optionId); 6874 const type = this.getSwatchType(attributeId, optionId); 6875 6876 if (type === "color") { 6877 return 'background-color:' + config.value + '; width: 110px; height: 90px;'; 6878 } else if (type === "image") { 6879 return "background: #ffffff url('" + config.thumb + 6880 "') center center no-repeat; width: 110px; height: 90px;"; 6881 } else { 6882 return 'display:none'; 6883 } 6884 }, 6885 getTooltipPosition() { 6886 return this.tooltipPositionElement ? 6887 `top: ${this.tooltipPositionElement.offsetTop}px;` + 6888 `left: ${ 6889 this.tooltipPositionElement.offsetLeft - ( 6890 this.tooltipPositionElement.closest('.snap') && 6891 this.tooltipPositionElement.closest('.snap').scrollLeft || 6892 0 6893 ) 6894 }px;` : '' 6895 }, 6896 getTooltipLabel() { 6897 return this.getSwatchConfig(this.activeTooltipItem.attribute, this.activeTooltipItem.item).label 6898 }, 6899 focusedLabel: false, 6900 focusLabel(optionId) { 6901 this.focusedLabel = optionId; 6902 }, 6903 blurLabel() { 6904 this.focusedLabel = false; 6905 }, 6906 showSwatches: false, 6907 initShowSwatchesIntersect() { 6908 if ('IntersectionObserver' in window && !window.scrollY) { 6909 let io = new IntersectionObserver( 6910 entries => { 6911 entries.map(entry => { 6912 if (entry.isIntersecting) { 6913 this.showSwatches = true; 6914 io.unobserve(this.$root); 6915 } 6916 }) 6917 } 6918 ); 6919 io.observe(this.$root); 6920 } else { 6921 this.showSwatches = true 6922 } 6923 } 6924 } 6925 } 6926</script>
vendor: 1 bytes, line 6926
6926
6927<script> 6928 (function () { 6929 const modals = []; 6930 let lastHide = 0; 6931 6932 function resolveElement($refs, value) { 6933 if (!value) return null; 6934 if (value instanceof Element) return value; 6935 if (typeof value === 'string') { 6936 try { 6937 return ($refs && $refs[value]) || document.querySelector(value) || null; 6938 } catch (e) {} 6939 } 6940 return null; 6941 } 6942 6943 function determineTrigger($refs, dialog, trigger) { 6944 if (!trigger && dialog?.target instanceof HTMLElement) { 6945 return dialog.target; 6946 } 6947 6948 if (typeof dialog === 'string' && trigger?.target instanceof HTMLElement) { 6949 return trigger.target; 6950 } 6951 6952 return resolveElement($refs, trigger); 6953 } 6954 6955 function setFocusFirstElement(dialogElement) { 6956 if (!dialogElement) return; 6957 6958 window.setTimeout(() => { 6959 const candidates = dialogElement.querySelectorAll('[x-focus-first]'); 6960 for (const candidate of candidates) { 6961 if (candidate.closest('dialog') === dialogElement) { 6962 candidate.focus(); 6963 return; 6964 } 6965 } 6966 }, 50); 6967 } 6968 6969 window.hyva.modal = function(options = {}) { 6970 if (this.$el && this.$el.dataset && this.$el.dataset.options) { 6971 try { 6972 options = Object.assign(options, JSON.parse(this.$el.dataset.options || '{}')); 6973 } catch (e) { 6974 throw new Error('Cannot read the dialog options from the data-options attribute: not valid JSON'); 6975 } 6976 } 6977 6978 const config = Object.assign({ 6979 dialog: 'dialog', duration: 300, transitionEnter: 'transition ease-out duration-300', 6980 transitionEnterStart: 'opacity-0', 6981 transitionEnterEnd: 'opacity-100', 6982 transitionLeave: 'transition ease-in duration-300', 6983 transitionLeaveStart: 'opacity-100', 6984 transitionLeaveEnd: 'opacity-0', 6985 }, options); 6986 6987 return { 6988 opened: {}, 6989 show(dialog, trigger) { 6990 const name = typeof dialog === 'string' ? dialog : config.dialog; 6991 if (!name || this.opened[name]) return; 6992 6993 this.opened[name] = true; 6994 const focusTarget = determineTrigger(this.$refs, dialog, trigger); 6995 const dialogEl = this.$refs && this.$refs[name]; 6996 const frame = { name, instance: this, focusTarget, time: Date.now() }; 6997 modals.push(frame); 6998 setFocusFirstElement(dialogEl); 6999 return new Promise(resolve => { frame.resolve = resolve; }); 7000 }, 7001 cancel() { 7002 this.hide(false); 7003 }, 7004 ok() { 7005 this.hide(true); 7006 }, 7007 hide(value) { 7008 if (Date.now() - lastHide < config.duration) return; 7009 lastHide = Date.now(); 7010 7011 const modal = modals.pop(); 7012 if (!modal) return; 7013 7014 modal.instance.opened[modal.name] = false; 7015 7016 const focusTarget = modal.focusTarget; 7017 focusTarget && window.setTimeout(() => focusTarget.focus(), config.duration + 50); 7018 modal.resolve && modal.resolve(value); 7019 }, 7020 /** 7021 * @deprecated Use dialogConfig() instead, which is used by the default modal-container.phtml template. 7022 * This method is kept for backwards compatibility with custom container templates. 7023 */ 7024 overlay(dialog) { 7025 dialog = this.$el.dataset.dialogRefName || dialog; 7026 const name = typeof dialog === 'string' ? dialog : config.dialog; 7027 if (this.$el.tagName !== 'DIALOG' && ! window.hyva.modal.legacyModalCompatibility) { 7028 console.warn( 7029 '[hyva] Deprecated modal markup detected (x-bind="overlay" on a non-dialog element' + 7030 (name ? ` for "${name}"` : '') + ').\n' + 7031 'Escape and click-outside closing are not available for such dialogs anymore.\n' + 7032 'Install hyva-themes/magento2-legacy-modal-compatibility or migrate to the native <dialog> markup.' 7033 ); 7034 } 7035 return Object.assign({}, this.dialogConfig(name), { 7036 ['@hyva-modal-show.window'](event) { 7037 event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide) 7038 } 7039 }); 7040 }, 7041 dialogConfig(name) { 7042 name = name || this.$el.dataset.dialogRefName || config.dialog; 7043 return { 7044 ['x-show']: () => name ? this.opened[name] : false, 7045 ['x-transition:enter']: config.transitionEnter, 7046 ['x-transition:enter-start']: config.transitionEnterStart, 7047 ['x-transition:enter-end']: config.transitionEnterEnd, 7048 ['x-transition:leave']: config.transitionLeave, 7049 ['x-transition:leave-start']: config.transitionLeaveStart, 7050 ['x-transition:leave-end']: config.transitionLeaveEnd, 7051 ['@hyva-modal-show.window'](event) { 7052 event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide); 7053 }, 7054 }; 7055 },
7056 showDialogOnInit() { 7057 const name = this.$el.dataset.dialogRefName; 7058 if (name) { 7059 this.show(name); 7060 } 7061 } 7062 }; 7063 } 7064 7065 window.hyva.modal.peek = () => modals.length > 0 && modals[modals.length - 1] 7066 7067 window.hyva.modal.pop = function () { 7068 if (modals.length > 0) { 7069 modals[modals.length - 1].instance.hide(); 7070 } 7071 } 7072 7073 /** 7074 * @deprecated Native <dialog> handles focus trapping automatically. 7075 * Calling this function has no effect. Kept for backwards compatibility. 7076 */ 7077 window.hyva.modal.excludeSelectorsFromFocusTrap = function (selectors) {} 7078 7079 /** 7080 * @deprecated Native <dialog> with x-htmldialog handles ESC key and click-outside events. 7081 * These functions have no effect. Kept for backwards compatibility. 7082 */ 7083 window.hyva.modal.eventListeners = { 7084 keydown: event => {}, 7085 click: event => {} 7086 }; 7087 })(); 7088 7089 window.addEventListener('alpine:init', () => { 7090 Alpine.data('hyvaModal', window.hyva.modal); 7091 }, {once: true}); 7092</script>
vendor: 1 bytes, line 7092
7092
7093<script> 7094 'use strict'; 7095 7096 function initParentContainerProcessor() { 7097 const selectors = { 7098 labelContainer: '.amasty-label-container', 7099 galleryImg: '#gallery img:not(.amasty-label-image)' 7100 } 7101 7102 return { 7103 /** 7104 * @param {AmlabelComponent} label 7105 * @return {void} 7106 */ 7107 process: function (label) { 7108 this.moveLabelToParent(label); 7109 this.setParentStyles(label); 7110 }, 7111 7112 /** 7113 * @param {AmlabelComponent} label 7114 * @return {void} 7115 */ 7116 moveLabelToParent: function (label) { 7117 const newParent = this.getNewParent(label); 7118 7119 if (!newParent) { 7120 return; 7121 } 7122 7123 const wrapperElement = newParent.querySelector(label.wrapperClass); 7124 label.parent = newParent; 7125 7126 // if same wrapper already exists - move label there 7127 if (wrapperElement && !wrapperElement.isSameNode(label.element)) { 7128 this.insertLabelByPriority(label, wrapperElement); 7129 } else { 7130 newParent.prepend(label.element); 7131 } 7132 }, 7133 7134 /** 7135 * @param {AmlabelComponent} label 7136 * @return {HTMLElement|null} 7137 */ 7138 getNewParent: function (label) { 7139 // move label to container from settings 7140 let newParent = label.element.closest(label.config.path) 7141 || this.findPreviousNodeExcludingScriptsAndDifferentLabels(label.element)?.querySelector(label.config.path) 7142 || label.parent.querySelector(label.config.path); 7143 7144 // Try to find default gallery container on product page if none of the config selectors found 7145 if (!newParent && label.config.move !== 1 && label.config.mode === 'prod') { 7146 newParent = document.querySelector(selectors.galleryImg)?.parentElement; 7147 } 7148 7149 return newParent; 7150 }, 7151 7152 /** 7153 * @param {HTMLElement} element 7154 * @return {HTMLElement|null} 7155 */ 7156 findPreviousNodeExcludingScriptsAndDifferentLabels: function (element) { 7157 const previousElement = element?.previousElementSibling; 7158 if (!previousElement) { 7159 return null; 7160 } 7161 7162 if (previousElement?.tagName !== 'SCRIPT' 7163 && !previousElement?.className?.includes?.('amlabel-position-wrapper') 7164 ) { 7165 return previousElement; 7166 } 7167 7168 return this.findPreviousNodeExcludingScriptsAndDifferentLabels(previousElement); 7169 }, 7170 7171 /** 7172 * @param {AmlabelComponent} label 7173 * @param {HTMLElement} wrapperElement 7174 * @return {void} 7175 */ 7176 insertLabelByPriority: function (label, wrapperElement) { 7177 const labelContainers = wrapperElement.querySelectorAll(selectors.labelContainer); 7178 const currentLabelOrder = label.labelContainer.dataset.amlabelOrder; 7179 let insertAfterContainer = null; 7180 7181 // find the label behind which we want to insert current one by priority 7182 labelContainers.forEach(labelContainer => { 7183 if (labelContainer.dataset.amlabelOrder < currentLabelOrder) { 7184 insertAfterContainer = labelContainer; 7185 } 7186 }); 7187 7188 insertAfterContainer === null 7189 ? wrapperElement.prepend(label.labelContainer) 7190 : insertAfterContainer.after(label.labelContainer); 7191 7192 label.element.remove(); 7193 label.element = wrapperElement; 7194 }, 7195 7196 /** 7197 * @param {AmlabelComponent} label 7198 * @return {void} 7199 */ 7200 setParentStyles: function (label) { 7201 /* required for child position absolute */ 7202 !(label.parent.style.position === 'absolute') && (label.parent.style.position = 'relative'); 7203 !label.parent.style.width && label.parent.classList.add('w-fit-content'); 7204 !label.parent.style.marginLeft && label.parent.classList.add('ml-auto'); 7205 !label.parent.style.marginRight && label.parent.classList.add('mr-auto'); 7206 }, 7207 } 7208 } 7209</script>
vendor: 1 bytes, line 7209
7209
7210<script> 7211 'use strict'; 7212 7213 function initLabelItemProcessor() { 7214 /** 7215 * @typedef {Object} AmlabelComponent 7216 * 7217 * @property {HTMLElement} element Label wrapper element 7218 * @property {HTMLElement} parent Element where label should be placed 7219 * @property {boolean} initialized Is label initialized 7220 * @property {string} wrapperClass Dynamic class for label wrapper to place multiple labels properly by position 7221 * @property {HTMLElement} labelContainer Container for label text image and tooltip 7222 * @property {Config} config Label Configuration 7223 * @property {Object} parentContainerProcessor 7224 * @property {Object} labelItemProcessor 7225 */ 7226 7227 /** 7228 * @typedef {Object} AmLabelConfig 7229 * 7230 * @property {0|1} alignment Labels Alignment config value (0 - Horizontal| 1 - Vertical) 7231 * @property {number} label Label Id 7232 * @property {number} margin Margin between labels config value 7233 * @property {('cat'|'prod')} mode Label mode 7234 * @property {number} move 7235 * @property {number} order Label order 7236 * @property {string} path The css selector to which label should place 7237 * @property {string} position Label position 7238 * @property {string} product Product Id 7239 * @property {string} redirect_url 7240 * @property {string} size Label size 7241 * @property {{ 7242 * backgroundColor: string, 7243 * color: string, 7244 * content: string, 7245 * status: 1|2|3 7246 * }} tooltip 7247 */ 7248 7249 return { 7250 /** 7251 * @param {AmlabelComponent} label 7252 * @return {void} 7253 */ 7254 process: function(label) { 7255 this.setLabelSize(label); 7256 this.setLinkProps(label); 7257 }, 7258 7259 /** 7260 * @param {AmlabelComponent} label 7261 * @return {void} 7262 */ 7263 setLabelSize: function (label) { 7264 if (!label.config.size) { 7265 return; 7266 } 7267 7268 label.labelContainer.style.width = label.parent.offsetWidth * label.config.size / 100 + 'px'; 7269 }, 7270 7271 /** 7272 * 7273 * @param {Object} $event 7274 * @param {HTMLElement} tooltipNode 7275 */ 7276 placeTooltip: function($event, tooltipNode) { 7277 const labelNode = $event.target; 7278 const labelNodeRect = labelNode.getBoundingClientRect(); 7279 7280 tooltipNode.style.bottom = (window.innerHeight - labelNodeRect.top) + 'px'; 7281 tooltipNode.style.left = (labelNodeRect.left + labelNode.offsetWidth / 2 ) + 'px'; 7282 }, 7283 7284 /** 7285 * @param {AmlabelComponent} label 7286 * @return {void} 7287 */ 7288 setLinkProps: function (label) { 7289 !!label.config.redirect_url && label.labelContainer.classList.add('-link', 'cursor-pointer'); 7290 }, 7291 7292 /** 7293 * @param {Object} $event Click event 7294 * @param {string} redirectUrl 7295 */ 7296 openLink: function($event, redirectUrl) { 7297 if (redirectUrl.length === 0) { 7298 return; 7299 } 7300 7301 $event.preventDefault(); 7302 window.open(redirectUrl, '_blank'); 7303 } 7304 } 7305 } 7306</script>
7306 7307
7308<script> 7309 (function () { 7310 'use strict'; 7311 7312 const observedEvent = 'amlabel-swatch-product-changed'; 7313 const selectors = { 7314 swatchOptions: 'div[x-data^=initConfigurable][x-data*=Options]', 7315 addToCartFormOnListing: 'form.product_addtocart_form', 7316 galleryImage: '#gallery img:not(.amasty-label-image)', 7317 labelWrapper: '.amlabel-position-wrapper' 7318 } 7319 7320 /** 7321 * @return {void} 7322 */ 7323 const injectLabelObserver = function () { 7324 const swatches = document.querySelectorAll(selectors.swatchOptions); 7325 7326 swatches.forEach(swatch => { 7327 const isListing = !!swatch.closest(selectors.addToCartFormOnListing); 7328 const injectedDispatch = `$dispatch('${observedEvent}', ` 7329 + `{productIndex: productIndex, element: $el, optionConfig: optionConfig, isListing: ${isListing ? 1 : 0}})`; 7330 7331 let mutatedInitAttribute = swatch.getAttribute('x-init'); 7332 mutatedInitAttribute += `; $watch('productIndex', (productIndex) => { ${injectedDispatch} });`; 7333 swatch.setAttribute('x-init', mutatedInitAttribute); 7334 }); 7335 } 7336 7337 /** 7338 * @param {{ 7339 * productIndex: number, 7340 * element: HTMLElement, 7341 * optionConfig: Object, 7342 * isListing: 0|1 7343 * }} payload 7344 * @return {void} 7345 */ 7346 const updateLabel = function ({detail: payload}) { 7347 const {productIndex, element, optionConfig, isListing} = payload; 7348 7349 if (!productIndex) { 7350 return; 7351 } 7352 7353 const reloadUrl = optionConfig.label_reload; 7354 const headers = { 7355 "content-type": "application/x-www-form-urlencoded; charset=UTF-8", 7356 }; 7357 const body = new URLSearchParams({ 7358 product_ids: productIndex, 7359 in_product_list: isListing 7360 }); 7361 const labelContainerSelector = isListing ? optionConfig.label_category : optionConfig.label_product; 7362 7363 fetch(`${reloadUrl}?${body.toString()}`, {headers: headers, method: 'GET'}).then((response) => { 7364 if (response.ok) { 7365 return response.json(); 7366 } 7367 }).then((result) => { 7368 const labelHtml = result.labels && result.labels[productIndex]; 7369 let labelContainer = findClosest(element, labelContainerSelector); 7370 7371 // Try to find default gallery container on product page if none of the config selectors found 7372 if (labelContainer === null && isListing === 0) { 7373 labelContainer = document.querySelector(selectors.galleryImage)?.parentElement; 7374 } 7375 7376 if (!!labelContainer) { 7377 !!labelHtml ? replaceLabels(labelContainer, labelHtml) : clearLabelWrapper(labelContainer); 7378 } 7379 }).catch((error) => { 7380 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 7381 [{ 7382 type: 'error', 7383 text: error 7384 }], 7385 5000 7386 ); 7387 }); 7388 } 7389 7390 /** 7391 * We use approach from hyva.replaceDomElement method to replace labels and init components 7392 * 7393 * @param {HTMLElement} labelContainer 7394 * @param {string} labelHtml 7395 * @return {void} 7396 */ 7397 function replaceLabels(labelContainer, labelHtml) { 7398 const parser = new DOMParser(); 7399 const doc = parser.parseFromString(labelHtml, 'text/html'); 7400 const nodes = doc.querySelectorAll(selectors.labelWrapper); 7401 7402 if (!nodes) { 7403 return; 7404 } 7405 7406 clearLabelWrapper(labelContainer); 7407 7408 // Extract all the script tags from the new content. 7409 // Script tags won't execute when inserted into a dom-element directly, 7410 // therefore we need to inject them to the head of the document. 7411 const tmpScripts = doc.getElementsByTagName('script'); 7412 7413 if (tmpScripts.length > 0) { 7414 // Push all script tags into an array 7415 // (to prevent dom manipulation while iterating over dom nodes) 7416 const scripts = [...tmpScripts]; 7417 7418 // Iterate over all script tags and duplicate+inject each into the head
7419 scripts.forEach(script => { 7420 let scriptNode = document.createElement('script'); 7421 scriptNode.innerHTML = script.innerHTML; 7422 document.head.appendChild(scriptNode); 7423 7424 // Remove the original (non-executing) node from the page 7425 script.parentNode.removeChild(script); 7426 }); 7427 } 7428 7429 labelContainer.append(...nodes); 7430 } 7431 7432 /** 7433 * @param {HTMLElement} labelContainer 7434 * @return {void} 7435 */ 7436 function clearLabelWrapper(labelContainer) { 7437 labelContainer.querySelectorAll(selectors.labelWrapper).forEach(wrapper => wrapper.remove()); 7438 } 7439 7440 /** 7441 * @param {HTMLElement} currentElement 7442 * @param {string} selector 7443 * @return {HTMLElement|null} 7444 */ 7445 function findClosest(currentElement, selector) { 7446 // We need to limit parent searches to prevent labels from being associated with the wrong product. 7447 const maxDepth = 3; 7448 let counter = 0; 7449 let closest = null; 7450 7451 while (currentElement.parentNode && closest === null && counter < maxDepth) { 7452 ++counter; 7453 currentElement = currentElement.parentNode; 7454 closest = currentElement.querySelector(selector); 7455 } 7456 7457 return closest; 7458 } 7459 7460 injectLabelObserver(); 7461 window.addEventListener(observedEvent, updateLabel); 7462 })(); 7463</script>
vendor: 1 bytes, line 7463
7463
7464<script> 7465 (function () { 7466 'use strict'; 7467 7468 const selectors = { 7469 body: '.catalog-product-view', 7470 productItem: 'product-item', 7471 productGalleryImage: '#gallery img' 7472 } 7473 7474 window.addEventListener('alpine:init', () => { 7475 Alpine.directive('amintersect', (el, { expression }, { evaluate, cleanup }) => { 7476 const observer = new IntersectionObserver(entries => { 7477 entries.forEach(entry => { 7478 if (entry.isIntersecting) { 7479 evaluate(expression); 7480 observer.disconnect(); 7481 } 7482 }) 7483 }, { threshold: 0.5 }); 7484 7485 observer.observe(getElement()); 7486 7487 cleanup(() => { 7488 observer.disconnect() 7489 }); 7490 7491 function getElement() { 7492 return !!document.querySelector(selectors.body) ? getImageProductBlock(el) : getCategoryProductBlock(el); 7493 } 7494 7495 function getCategoryProductBlock(el) { 7496 if (el.previousElementSibling === null) { 7497 return el; 7498 } 7499 7500 if (!el.previousElementSibling.classList.contains(selectors.productItem)) { 7501 return getCategoryProductBlock(el.previousElementSibling); 7502 } 7503 7504 return el.previousElementSibling; 7505 } 7506 7507 function getImageProductBlock(el) { 7508 return el.parentNode.querySelector(selectors.productGalleryImage)?.parentNode ?? el.parentNode; 7509 } 7510 }); 7511 }); 7512 })(); 7513</script>
7513 7514
7515<script> 7516 'use strict'; 7517 7518 (() => { 7519 const browserStorage = hyva.getBrowserStorage(); 7520 const storageKey = 'mage-banners-cache-storage'; 7521 const cacheTimeoutKey = 'mage-banners-cache-timeout'; 7522 const storeIdKey = 'mage-banners-storeId'; 7523 const cartIdKey = 'mage-banners-cartDataId'; 7524 const options = { 7525 cacheTtl: 30000, 7526 sectionLoadUrl: 'https://www.riccar.com/banner/ajax/load/' 7527 }; 7528 7529 if (browserStorage && browserStorage.getItem(storageKey) === null) { 7530 browserStorage.setItem(storageKey, "{}"); 7531 } 7532 7533 async function initBanners(elements) { 7534 invalidateCacheBySessionTimeOut(); 7535 7536 const storageData = JSON.parse(browserStorage.getItem(storageKey)); 7537 let items = []; 7538 7539 if (storageData.data) { 7540 items = getFromStorage(); 7541 } else { 7542 items = await getFromServer(); 7543 } 7544 7545 populateDynamicBlocks(elements, items); 7546 } 7547 7548 // Cache invalidation. Banner cache ttl is 30 sec by default.
7549 function invalidateCacheBySessionTimeOut() { 7550 const cacheEol = new Date(browserStorage.getItem(cacheTimeoutKey)) 7551 const dateTo = new Date(Date.now() + options.cacheTtl); 7552 const globalStoreId = hyva.getCookie('store') || 'default'; 7553 const mageCacheStorage = JSON.parse(browserStorage.getItem('mage-cache-storage')); 7554 let cartDataId = null; 7555 7556 if (browserStorage.getItem(storeIdKey) === null) { 7557 browserStorage.setItem(storeIdKey, globalStoreId); 7558 } 7559 7560 if (mageCacheStorage !== null && 7561 mageCacheStorage.hasOwnProperty('cart')) { 7562 cartDataId = mageCacheStorage.cart['data_id']; 7563 } 7564 7565 if (cacheEol < new Date() || 7566 browserStorage.getItem(storeIdKey) !== globalStoreId || 7567 Number(browserStorage.getItem(cartIdKey)) !== cartDataId) 7568 { 7569 browserStorage.setItem(storageKey, "{}"); 7570 browserStorage.setItem(cacheTimeoutKey, dateTo); 7571 browserStorage.setItem(storeIdKey, globalStoreId); 7572 7573 if (cartDataId) { 7574 browserStorage.setItem(cartIdKey, cartDataId); 7575 } 7576 } 7577 } 7578 7579 async function getFromServer() { 7580 try { 7581 const url = new URL(options.sectionLoadUrl); 7582 url.searchParams.append('requesting_page_url', url.origin); 7583 url.searchParams.append('_', Date.now()); 7584 7585 const response = await fetch(url.href, { 7586 headers: { 7587 'Content-Type': 'application/json', 7588 'X-Requested-With': 'XMLHttpRequest' 7589 } 7590 }); 7591 const storageData = await response.json(); 7592 7593 browserStorage.setItem(storageKey, JSON.stringify(storageData)); 7594 7595 if (storageData.data && storageData.data.items) { 7596 return storageData.data.items.fixed ? storageData.data.items.fixed : []; 7597 } 7598 } catch (error) { 7599 console.warn(error); 7600 7601 return []; 7602 } 7603 } 7604 7605 function getFromStorage() { 7606 const storageData = JSON.parse(browserStorage.getItem(storageKey)); 7607 if (storageData.data && storageData.data.items) { 7608 return storageData.data.items.fixed || []; 7609 } 7610 } 7611 7612 function populateDynamicBlocks(elements, items) { 7613 if (!items || items.length === 0) { 7614 console.log(`No\u0020banners\u0020found`); 7615 7616 return; 7617 } 7618 7619 for (const element of elements) { 7620 // Filter IDs by those allowed for current customer segment 7621 const ids = element.getAttribute('data-ids').split(',').filter((id) => items.hasOwnProperty(id)); 7622 const config = { 7623 type: element.getAttribute('data-rotate'), 7624 dynamicBlockId: element.getAttribute('data-banner-id'), 7625 }; 7626 7627 getByType(config, element, items, ids); 7628 } 7629 } 7630 7631 function getByType(config = null, element, items, ids) { 7632 if (!config) return; 7633 7634 if (config.type === 'random') { 7635 ids = [ids[Math.floor(Math.random() * ids.length)]]; 7636 } 7637 7638 if (config.type === 'series' || config.type === 'shuffle') { 7639 ids = [getNextInOrder(config, ids)]; 7640 } 7641 7642 for (const id of ids) { 7643 if (items[id]) { 7644 element.insertAdjacentHTML('beforeend', items[id].content); 7645 } 7646 } 7647 } 7648 7649 function getNextInOrder(config, ids) { 7650 const dynamicBlockId = config.dynamicBlockId; 7651 const localStorageKey = 'dynamic-block-banner-rotator'; 7652 let localStorageData = JSON.parse(localStorage.getItem(localStorageKey)) || {}; 7653 let nextId; 7654 7655 if (localStorageData[dynamicBlockId] && localStorageData[dynamicBlockId].length > 0) { 7656 nextId = localStorageData[dynamicBlockId].shift(0); 7657 } else { 7658 if (config.type === 'shuffle') { 7659 ids.sort(() => Math.random() - 0.5); 7660 } 7661 nextId = ids.shift(0); 7662 localStorageData[dynamicBlockId] = ids; 7663 } 7664 7665 localStorage.setItem( 7666 localStorageKey, 7667 JSON.stringify(localStorageData) 7668 ); 7669 7670 return nextId; 7671 } 7672 7673 const elements = document.querySelectorAll('[data-banner-id][data-ids]'); 7674 if (elements.length > 0) { 7675 initBanners(elements); 7676 } 7677 })(); 7678</script>
7678 7679<style> 7680.is-loading > :not(.loader) { 7681 visibility: hidden; 7682} 7683</style>
7684<script> 7685(() => { 7686 const ajaxCartBoundAttribute = 'data-snowdog-ajax-cart-bound'; 7687 window.defaultSuccessMessageTimeout = window.defaultSuccessMessageTimeout || 3000; 7688 let shownMessageCount = 0; 7689 7690 function uniqueMessages(messages) { 7691 const seen = new Set(); 7692 7693 return messages.filter((message) => { 7694 const key = `${message.type || ''}:${message.text || ''}`; 7695 7696 if (seen.has(key)) { 7697 return false; 7698 } 7699 7700 seen.add(key); 7701 return true; 7702 }); 7703 } 7704 7705 window.addEventListener('private-content-loaded', (event) => { 7706 const messages = event.detail 7707 && event.detail.data 7708 && event.detail.data.messages 7709 && event.detail.data.messages.messages; 7710 7711 if (!Array.isArray(messages)) { 7712 return; 7713 } 7714 7715 // Reset if the backlog shrank (e.g. cleared by a full page load). 7716 if (messages.length < shownMessageCount) { 7717 shownMessageCount = 0; 7718 } 7719 7720 const freshMessages = messages.slice(shownMessageCount); 7721 shownMessageCount = messages.length; 7722 7723 event.detail.data.messages.messages = uniqueMessages(freshMessages); 7724 }, true); 7725 7726 window.setAjaxCart = (selectors = '.product_addtocart_form,\u0020\u0023product_addtocart_form', recursive = true) => { 7727 const forms = document.querySelectorAll(selectors); 7728 const delay = parseInt('1000', 10); 7729 7730 forms.forEach(form => { 7731 if (form.getAttribute(ajaxCartBoundAttribute) === 'true') { 7732 return; 7733 } 7734 7735 form.setAttribute(ajaxCartBoundAttribute, 'true'); 7736 7737 form.addEventListener('submit', async (e) => { 7738 e.preventDefault(); 7739 7740 const formData = new URLSearchParams(new FormData(form)); 7741 const button = form.querySelector('button') 7742 ? form.querySelector('button') 7743 : document.getElementById('product-addtocart-button'); 7744 const loader = document.createElement('div'); 7745 7746 loader.className = 'absolute inset-0 flex justify-center items-center loader'; 7747 loader.innerHTML = ` 7748 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" xml:space="preserve" width="32" height="32"> 7749 <path fill="#fff" 7750 d="M73 50c0-12.7-10.3-23-23-23S27 37.3 27 50m3.9 0c0-10.5 8.5-19.1 19.1-19.1S69.1 39.5 69.1 50"> 7751 <animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" 7752 from="0 50 50" to="360 50 50" 7753 repeatCount="indefinite"/> 7754 </path> 7755 </svg> 7756 `; 7757 7758 if (button) { 7759 button.prepend(loader); 7760 button.classList.add('relative', 'is-loading'); 7761 button.disabled = true; 7762 } 7763 7764 try { 7765 const response = await fetch(e.currentTarget.action, { 7766 method: 'POST', 7767 body: formData, 7768 headers: { 7769 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 7770 'X-Requested-With': 'XMLHttpRequest' 7771 } 7772 }); 7773 7774 if (!response.ok) { 7775 return form.submit(); 7776 } 7777 7778 if (response.redirected) { 7779 return window.location.href = response.url; 7780 } 7781 7782 const data = await response.json(); 7783 7784 if (data.backUrl) { 7785 return window.location.href = data.backUrl; 7786 } 7787 7788 window.dispatchEvent(new CustomEvent('clear-messages')); 7789 7790 // Avoid process the cookie and section data messages simultaneously 7791 document.cookie = 'mage-messages=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 7792 7793 // Show the add-to-cart messages from the response. The server-side 7794 if (Array.isArray(data.messages) && data.messages.length) { 7795 window.dispatchMessages 7796 && window.dispatchMessages(data.messages, window.defaultSuccessMessageTimeout); 7797 } 7798 7799 if (recursive) { 7800 window.dispatchEvent(new CustomEvent('product-addtocart-success')); 7801 } 7802 7803 let cartOpened = false;
7804 const openCart = () => { 7805 if (cartOpened) { 7806 return; 7807 } 7808 cartOpened = true; 7809 window.dispatchEvent(new CustomEvent('toggle-cart', { 7810 detail: { 7811 isOpen: true 7812 } 7813 })); 7814 window.dispatchEvent(new CustomEvent('open-cart')); 7815 }; 7816 7817 window.addEventListener('private-content-loaded', openCart, { once: true }); 7818 setTimeout(openCart, 1500); 7819 7820 return window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 7821 } catch (err) { 7822 console.warn(err); 7823 window.dispatchEvent(new CustomEvent('product-addtocart-error')); 7824 7825 setMessage({ 7826 text:'There\u0020was\u0020a\u0020problem\u0020adding\u0020your\u0020item\u0020to\u0020the\u0020cart.', 7827 type: 'error' 7828 }); 7829 } finally { 7830 setTimeout(() => { 7831 loader.remove(); 7832 button && button.classList.remove('is-loading'); 7833 if (button) { 7834 button.disabled = false; 7835 } 7836 }, delay); 7837 } 7838 }); 7839 }); 7840 } 7841 7842 function setMessage(message) { 7843 typeof window.dispatchMessages !== 'undefined' && 7844 window.dispatchMessages([message], 5000); 7845 } 7846 7847 window.setAjaxCart(); 7848})(); 7849</script>
vendor: 1 bytes, line 7849
7849
7850<script type="text/json" id="default-section-data"> 7851 {"messages":[],"customer":[],"compare-products":[],"last-ordered-items":[],"cart":[],"directory-data":{"AD":{"name":"Andorra"},"AE":{"name":"United Arab Emirates"},"AF":{"name":"Afghanistan"},"AG":{"name":"Antigua & Barbuda"},"AI":{"name":"Anguilla"},"AL":{"name":"Albania","regions":{"1051":{"code":"AL-01","name":"Berat"},"1054":{"code":"AL-09","name":"Dib\u00ebr"},"1057":{"code":"AL-02","name":"Durr\u00ebs"},"1060":{"code":"AL-03","name":"Elbasan"},"1063":{"code":"AL-04","name":"Fier"},"1066":{"code":"AL-05","name":"Gjirokast\u00ebr"},"1069":{"code":"AL-06","name":"Kor\u00e7\u00eb"},"1072":{"code":"AL-07","name":"Kuk\u00ebs"},"1075":{"code":"AL-08","name":"Lezh\u00eb"},"1078":{"code":"AL-10","name":"Shkod\u00ebr"},"1081":{"code":"AL-11","name":"Tiran\u00eb"},"1084":{"code":"AL-12","name":"Vlor\u00eb"}}},"AM":{"name":"Armenia"},"AN":{"name":null},"AO":{"name":"Angola"},"AQ":{"name":"Antarctica"},"AR":{"name":"Argentina","regions":{"1090":{"code":"AR-B","name":"Buenos Aires"},"1093":{"code":"AR-K","name":"Catamarca"},"1096":{"code":"AR-H","name":"Chaco"},"1099":{"code":"AR-U","name":"Chubut"},"1087":{"code":"AR-C","name":"Ciudad Aut\u00f3noma de Buenos Aires"},"1102":{"code":"AR-X","name":"C\u00f3rdoba"},"1105":{"code":"AR-W","name":"Corrientes"},"1108":{"code":"AR-E","name":"Entre R\u00edos"},"1111":{"code":"AR-P","name":"Formosa"},"1114":{"code":"AR-Y","name":"Jujuy"},"1117":{"code":"AR-L","name":"La Pampa"},"1120":{"code":"AR-F","name":"La Rioja"},"1123":{"code":"AR-M","name":"Mendoza"},"1126":{"code":"AR-N","name":"Misiones"},"1129":{"code":"AR-Q","name":"Neuqu\u00e9n"},"1132":{"code":"AR-R","name":"R\u00edo Negro"},"1135":{"code":"AR-A","name":"Salta"},"1138":{"code":"AR-J","name":"San Juan"},"1141":{"code":"AR-D","name":"San Luis"},"1144":{"code":"AR-Z","name":"Santa Cruz"},"1147":{"code":"AR-S","name":"Santa Fe"},"1150":{"code":"AR-G","name":"Santiago del Estero"},"1153":{"code":"AR-V","name":"Tierra del Fuego"},"1156":{"code":"AR-T","name":"Tucum\u00e1n"}}},"AS":{"name":"American Samoa"},"AT":{"name":"Austria","regions":{"102":{"code":"BL","name":"Burgenland"},"99":{"code":"KN","name":"K\u00e4rnten"},"96":{"code":"NO","name":"Nieder\u00f6sterreich"},"97":{"code":"OO","name":"Ober\u00f6sterreich"},"98":{"code":"SB","name":"Salzburg"},"100":{"code":"ST","name":"Steiermark"},"101":{"code":"TI","name":"Tirol"},"103":{"code":"VB","name":"Vorarlberg"},"95":{"code":"WI","name":"Wien"}}},"AU":{"name":"Australia","regions":{"645":{"code":"ACT","name":"Australian Capital Territory"},"648":{"code":"NSW","name":"New South Wales"},"666":{"code":"NT","name":"Northern Territory"},"654":{"code":"QLD","name":"Queensland"},"657":{"code":"SA","name":"South Australia"},"660":{"code":"TAS","name":"Tasmania"},"651":{"code":"VIC","name":"Victoria"},"663":{"code":"WA","name":"Western Australia"}}},"AW":{"name":"Aruba"},"AX":{"name":"\u00c5land Islands"},"AZ":{"name":"Azerbaijan"},"BA":{"name":"Bosnia & Herzegovina"},"BB":{"name":"Barbados"},"BD":{"name":"Bangladesh"},"BE":{"name":"Belgium","regions":{"771":{"code":"VAN","name":"Antwerpen"},"774":{"code":"WBR","name":"Brabant wallon"},"777":{"code":"BRU","name":"Brussels-Capital Region"},"780":{"code":"WHT","name":"Hainaut"},"786":{"code":"WLG","name":"Li\u00e8ge"},"783":{"code":"VLI","name":"Limburg"},"789":{"code":"WLX","name":"Luxembourg"},"792":{"code":"WNA","name":"Namur"},"795":{"code":"VOV","name":"Oost-Vlaanderen"},"798":{"code":"VBR","name":"Vlaams-Brabant"},"801":{"code":"VWV","name":"West-Vlaanderen"}}},"BF":{"name":"Burkina Faso"},"BG":{"name":"Bulgaria","regions":{"1207":{"code":"BG-01","name":"Blagoevgrad"},"1210":{"code":"BG-02","name":"Burgas"},"1228":{"code":"BG-08","name":"Dobrich"},"1225":{"code":"BG-07","name":"Gabrovo"},"1282":{"code":"BG-26","name":"Haskovo"},"1231":{"code":"BG-09","name":"Kardzhali"},"1234":{"code":"BG-10","name":"Kyustendil"},"1237":{"code":"BG-11","name":"Lovech"},"1240":{"code":"BG-12","name":"Montana"},"1243":{"code":"BG-13","name":"Pazardzhik"},"1246":{"code":"BG-14","name":"Pernik"},"1249":{"code":"BG-15","name":"Pleven"},"1252":{"code":"BG-16","name":"Plovdiv"},"1255":{"code":"BG-17","name":"Razgrad"},"1258":{"code":"BG-18","name":"Ruse"},"1285":{"code":"BG-27","name":"Shumen"},"1261":{"code":"BG-19","name":"Silistra"},"1264":{"code":"BG-20","name":"Sliven"},"1267":{"code":"BG-21","name":"Smolyan"},"1270":{"code":"BG-22","name":"Sofia City"},"1273":{"code":"BG-23","name":"Sofia Province"},"1276":{"code":"BG-24","name":"Stara Zagora"},"1279":{"code":"BG-25","name":"Targovishte"},"1213":{"code":"BG-03","name":"Varna"},"1216":{"code":"BG-04","name":"Veliko Tarnovo"},"1219":{"code":"BG-05","name":"Vidin"},"1222":{"code":"BG-06","name":"Vratsa"},"1288":{"code":"BG-28","name":"Yambol"}}},"BH":{"name":"Bahrain"},"BI":{"name":"Burundi"},"BJ":{"name":"Benin"},"BL":{"name":"St. Barth\u00e9lemy"},"BM":{"name":"Bermuda"},"BN":{"name":"Brunei"}
7851,"BO":{"name":"Bolivia","regions":{"1183":{"code":"BO-H","name":"Chuquisaca"},"1180":{"code":"BO-C","name":"Cochabamba"},"1186":{"code":"BO-B","name":"El Beni"},"1189":{"code":"BO-L","name":"La Paz"},"1192":{"code":"BO-O","name":"Oruro"},"1195":{"code":"BO-N","name":"Pando"},"1198":{"code":"BO-P","name":"Potos\u00ed"},"1201":{"code":"BO-S","name":"Santa Cruz"},"1204":{"code":"BO-T","name":"Tarija"}}},"BQ":{"name":"Caribbean Netherlands"},"BR":{"name":"Brazil","regions":{"485":{"code":"AC","name":"Acre"},"486":{"code":"AL","name":"Alagoas"},"487":{"code":"AP","name":"Amap\u00e1"},"488":{"code":"AM","name":"Amazonas"},"489":{"code":"BA","name":"Bahia"},"490":{"code":"CE","name":"Cear\u00e1"},"511":{"code":"DF","name":"Distrito Federal"},"491":{"code":"ES","name":"Esp\u00edrito Santo"},"492":{"code":"GO","name":"Goi\u00e1s"},"493":{"code":"MA","name":"Maranh\u00e3o"},"494":{"code":"MT","name":"Mato Grosso"},"495":{"code":"MS","name":"Mato Grosso do Sul"},"496":{"code":"MG","name":"Minas Gerais"},"497":{"code":"PA","name":"Par\u00e1"},"498":{"code":"PB","name":"Para\u00edba"},"499":{"code":"PR","name":"Paran\u00e1"},"500":{"code":"PE","name":"Pernambuco"},"501":{"code":"PI","name":"Piau\u00ed"},"502":{"code":"RJ","name":"Rio de Janeiro"},"503":{"code":"RN","name":"Rio Grande do Norte"},"504":{"code":"RS","name":"Rio Grande do Sul"},"505":{"code":"RO","name":"Rond\u00f4nia"},"506":{"code":"RR","name":"Roraima"},"507":{"code":"SC","name":"Santa Catarina"},"508":{"code":"SP","name":"S\u00e3o Paulo"},"509":{"code":"SE","name":"Sergipe"},"510":{"code":"TO","name":"Tocantins"}}},"BS":{"name":"Bahamas"},"BT":{"name":"Bhutan"},"BV":{"name":"Bouvet Island"},"BW":{"name":"Botswana"},"BY":{"name":"Belarus","regions":{"1159":{"code":"BY-BR","name":"Bresckaja voblas\u0107"},"1162":{"code":"BY-HO","name":"Homie\u013askaja voblas\u0107"},"1165":{"code":"BY-HM","name":"Horad Minsk"},"1168":{"code":"BY-HR","name":"Hrodzienskaja voblas\u0107"},"1171":{"code":"BY-MA","name":"Mahilio\u016dskaja voblas\u0107"},"1174":{"code":"BY-MI","name":"Minskaja voblas\u0107"},"1177":{"code":"BY-VI","name":"Viciebskaja voblas\u0107"}}},"BZ":{"name":"Belize"},"CA":{"name":"Canada","regions":{"66":{"code":"AB","name":"Alberta"},"67":{"code":"BC","name":"British Columbia"},"68":{"code":"MB","name":"Manitoba"},"70":{"code":"NB","name":"New Brunswick"},"69":{"code":"NL","name":"Newfoundland and Labrador"},"72":{"code":"NT","name":"Northwest Territories"},"71":{"code":"NS","name":"Nova Scotia"},"73":{"code":"NU","name":"Nunavut"},"74":{"code":"ON","name":"Ontario"},"75":{"code":"PE","name":"Prince Edward Island"},"76":{"code":"QC","name":"Quebec"},"77":{"code":"SK","name":"Saskatchewan"},"78":{"code":"YT","name":"Yukon Territory"}}},"CC":{"name":"Cocos (Keeling) Islands"},"CD":{"name":"Congo - Kinshasa"},"CF":{"name":"Central African Republic"},"CG":{"name":"Congo - Brazzaville"},"CH":{"name":"Switzerland","regions":{"104":{"code":"AG","name":"Aargau"},"106":{"code":"AR","name":"Appenzell Ausserrhoden"},"105":{"code":"AI","name":"Appenzell Innerrhoden"},"108":{"code":"BL","name":"Basel-Landschaft"},"109":{"code":"BS","name":"Basel-Stadt"},"107":{"code":"BE","name":"Bern"},"110":{"code":"FR","name":"Friburg"},"111":{"code":"GE","name":"Geneva"},"112":{"code":"GL","name":"Glarus"},"113":{"code":"GR","name":"Graub\u00fcnden"},"114":{"code":"JU","name":"Jura"},"115":{"code":"LU","name":"Lucerne"},"116":{"code":"NE","name":"Neuch\u00e2tel"},"117":{"code":"NW","name":"Nidwalden"},"118":{"code":"OW","name":"Obwalden"},"120":{"code":"SH","name":"Schaffhausen"},"122":{"code":"SZ","name":"Schwyz"},"121":{"code":"SO","name":"Solothurn"},"119":{"code":"SG","name":"St. Gallen"},"123":{"code":"TG","name":"Thurgau"},"124":{"code":"TI","name":"Ticino"},"125":{"code":"UR","name":"Uri"},"126":{"code":"VD","name":"Vaud"},"127":{"code":"VS","name":"Wallis"},"128":{"code":"ZG","name":"Zug"},"129":{"code":"ZH","name":"Z\u00fcrich"}}},"CI":{"name":"C\u00f4te d\u2019Ivoire"},"CK":{"name":"Cook Islands"},"CL":{"name":"Chile","regions":{"1291":{"code":"CL-AI","name":"Ais\u00e9n del General Carlos Iba\u00f1ez del Campo"},"1294":{"code":"CL-AN","name":"Antofagasta"},"1297":{"code":"CL-AP","name":"Arica y Parinacota"},"1303":{"code":"CL-AT","name":"Atacama"},"1306":{"code":"CL-BI","name":"Biob\u00edo"},"1309":{"code":"CL-CO","name":"Coquimbo"},"1300":{"code":"CL-AR","name":"La Araucan\u00eda"},"1312":{"code":"CL-LI","name":"Libertador General Bernardo O'Higgins"}
7851,"1315":{"code":"CL-LL","name":"Los Lagos"},"1318":{"code":"CL-LR","name":"Los R\u00edos"},"1321":{"code":"CL-MA","name":"Magallanes"},"1324":{"code":"CL-ML","name":"Maule"},"1327":{"code":"CL-NB","name":"\u00d1uble"},"1330":{"code":"CL-RM","name":"Regi\u00f3n Metropolitana de Santiago"},"1333":{"code":"CL-TA","name":"Tarapac\u00e1"},"1336":{"code":"CL-VS","name":"Valpara\u00edso"}}},"CM":{"name":"Cameroon"},"CN":{"name":"China","regions":{"804":{"code":"CN-AH","name":"Anhui Sheng"},"807":{"code":"CN-BJ","name":"Beijing Shi"},"810":{"code":"CN-CQ","name":"Chongqing Shi"},"813":{"code":"CN-FJ","name":"Fujian Sheng"},"816":{"code":"CN-GS","name":"Gansu Sheng"},"819":{"code":"CN-GD","name":"Guangdong Sheng"},"822":{"code":"CN-GX","name":"Guangxi Zhuangzu Zizhiqu"},"825":{"code":"CN-GZ","name":"Guizhou Sheng"},"828":{"code":"CN-HI","name":"Hainan Sheng"},"831":{"code":"CN-HE","name":"Hebei Sheng"},"834":{"code":"CN-HL","name":"Heilongjiang Sheng"},"837":{"code":"CN-HA","name":"Henan Sheng"},"840":{"code":"CN-HK","name":"Hong Kong SAR"},"843":{"code":"CN-HB","name":"Hubei Sheng"},"846":{"code":"CN-HN","name":"Hunan Sheng"},"849":{"code":"CN-JS","name":"Jiangsu Sheng"},"852":{"code":"CN-JX","name":"Jiangxi Sheng"},"855":{"code":"CN-JL","name":"Jilin Sheng"},"858":{"code":"CN-LN","name":"Liaoning Sheng"},"861":{"code":"CN-MO","name":"Macao SAR"},"864":{"code":"CN-NM","name":"Nei Mongol Zizhiqu"},"867":{"code":"CN-NX","name":"Ningxia Huizi Zizhiqu"},"870":{"code":"CN-QH","name":"Qinghai Sheng"},"873":{"code":"CN-SN","name":"Shaanxi Sheng"},"876":{"code":"CN-SD","name":"Shandong Sheng"},"879":{"code":"CN-SH","name":"Shanghai Shi"},"882":{"code":"CN-SX","name":"Shanxi Sheng"},"885":{"code":"CN-SC","name":"Sichuan Sheng"},"888":{"code":"CN-TW","name":"Taiwan Sheng"},"891":{"code":"CN-TJ","name":"Tianjin Shi"},"894":{"code":"CN-XJ","name":"Xinjiang Uygur Zizhiqu"},"897":{"code":"CN-XZ","name":"Xizang Zizhiqu"},"900":{"code":"CN-YN","name":"Yunnan Sheng"},"903":{"code":"CN-ZJ","name":"Zhejiang Sheng"}}},"CO":{"name":"Colombia","regions":{"909":{"code":"CO-AMA","name":"Amazonas"},"912":{"code":"CO-ANT","name":"Antioquia"},"915":{"code":"CO-ARA","name":"Arauca"},"918":{"code":"CO-ATL","name":"Atl\u00e1ntico"},"921":{"code":"CO-BOL","name":"Bol\u00edvar"},"924":{"code":"CO-BOY","name":"Boyac\u00e1"},"927":{"code":"CO-CAL","name":"Caldas"},"930":{"code":"CO-CAQ","name":"Caquet\u00e1"},"933":{"code":"CO-CAS","name":"Casanare"},"936":{"code":"CO-CAU","name":"Cauca"},"939":{"code":"CO-CES","name":"Cesar"},"942":{"code":"CO-CHO","name":"Choc\u00f3"},"945":{"code":"CO-COR","name":"C\u00f3rdoba"},"948":{"code":"CO-CUN","name":"Cundinamarca"},"951":{"code":"CO-GUA","name":"Guain\u00eda"},"954":{"code":"CO-GUV","name":"Guaviare"},"957":{"code":"CO-HUL","name":"Huila"},"960":{"code":"CO-LAG","name":"La Guajira"},"963":{"code":"CO-MAG","name":"Magdalena"},"966":{"code":"CO-MET","name":"Meta"},"969":{"code":"CO-NAR","name":"Nari\u00f1o"},"972":{"code":"CO-NSA","name":"Norte de Santander"},"975":{"code":"CO-PUT","name":"Putumayo"},"978":{"code":"CO-QUI","name":"Quind\u00edo"},"981":{"code":"CO-RIS","name":"Risaralda"},"984":{"code":"CO-SAP","name":"San Andr\u00e9s y Providencia"},"987":{"code":"CO-SAN","name":"Santander"},"990":{"code":"CO-SUC","name":"Sucre"},"993":{"code":"CO-TOL","name":"Tolima"},"996":{"code":"CO-VAC","name":"Valle del Cauca"},"999":{"code":"CO-VAU","name":"Vaup\u00e9s"},"1002":{"code":"CO-VID","name":"Vichada"}}},"CR":{"name":"Costa Rica"},"CU":{"name":"Cuba"},"CV":{"name":"Cape Verde"},"CW":{"name":"Cura\u00e7ao"},"CX":{"name":"Christmas Island"},"CY":{"name":"Cyprus"},"CZ":{"name":"Czechia"},"DE":{"name":"Germany","regions":{"80":{"code":"BAW","name":"Baden-W\u00fcrttemberg"},"81":{"code":"BAY","name":"Bayern"},"82":{"code":"BER","name":"Berlin"},"83":{"code":"BRG","name":"Brandenburg"},"84":{"code":"BRE","name":"Bremen"},"85":{"code":"HAM","name":"Hamburg"},"86":{"code":"HES","name":"Hessen"},"87":{"code":"MEC","name":"Mecklenburg-Vorpommern"},"79":{"code":"NDS","name":"Niedersachsen"},"88":{"code":"NRW","name":"Nordrhein-Westfalen"},"89":{"code":"RHE","name":"Rheinland-Pfalz"},"90":{"code":"SAR","name":"Saarland"},"91":{"code":"SAS","name":"Sachsen"},"92":{"code":"SAC","name":"Sachsen-Anhalt"},"93":{"code":"SCN","name":"Schleswig-Holstein"},"94":{"code":"THE","name":"Th\u00fcringen"}}},"DJ":{"name":"Djibouti"},"DK":{"name":"Denmark","regions":{"1339":{"code":"DK-84","name":"Hovedstaden"},"1342":{"code":"DK-82","name":"Midtjylland"},"1345":{"code":"DK-81","name":"Nordjylland"},"1348":{"code":"DK-85","name":"Sj\u00e6lland"},"1351":{"code":"DK-83","name":"Syddanmark"}}},"DM":{"name":"Dominica"}
7851,"DO":{"name":"Dominican Republic"},"DZ":{"name":"Algeria"},"EC":{"name":"Ecuador","regions":{"1354":{"code":"EC-A","name":"Azuay"},"1357":{"code":"EC-B","name":"Bol\u00edvar"},"1360":{"code":"EC-F","name":"Ca\u00f1ar"},"1363":{"code":"EC-C","name":"Carchi"},"1366":{"code":"EC-H","name":"Chimborazo"},"1369":{"code":"EC-X","name":"Cotopaxi"},"1372":{"code":"EC-O","name":"El Oro"},"1375":{"code":"EC-E","name":"Esmeraldas"},"1378":{"code":"EC-W","name":"Gal\u00e1pagos"},"1381":{"code":"EC-G","name":"Guayas"},"1384":{"code":"EC-I","name":"Imbabura"},"1387":{"code":"EC-L","name":"Loja"},"1390":{"code":"EC-R","name":"Los R\u00edos"},"1393":{"code":"EC-M","name":"Manab\u00ed"},"1396":{"code":"EC-S","name":"Morona Santiago"},"1399":{"code":"EC-N","name":"Napo"},"1402":{"code":"EC-D","name":"Orellana"},"1405":{"code":"EC-Y","name":"Pastaza"},"1408":{"code":"EC-P","name":"Pichincha"},"1411":{"code":"EC-SE","name":"Santa Elena"},"1414":{"code":"EC-SD","name":"Santo Domingo de los Ts\u00e1chilas"},"1417":{"code":"EC-U","name":"Sucumb\u00edos"},"1420":{"code":"EC-T","name":"Tungurahua"},"1423":{"code":"EC-Z","name":"Zamora Chinchipe"}}},"EE":{"name":"Estonia","regions":{"340":{"code":"EE-37","name":"Harjumaa"},"341":{"code":"EE-39","name":"Hiiumaa"},"342":{"code":"EE-44","name":"Ida-Virumaa"},"344":{"code":"EE-51","name":"J\u00e4rvamaa"},"343":{"code":"EE-49","name":"J\u00f5gevamaa"},"346":{"code":"EE-59","name":"L\u00e4\u00e4ne-Virumaa"},"345":{"code":"EE-57","name":"L\u00e4\u00e4nemaa"},"348":{"code":"EE-67","name":"P\u00e4rnumaa"},"347":{"code":"EE-65","name":"P\u00f5lvamaa"},"349":{"code":"EE-70","name":"Raplamaa"},"350":{"code":"EE-74","name":"Saaremaa"},"351":{"code":"EE-78","name":"Tartumaa"},"352":{"code":"EE-82","name":"Valgamaa"},"353":{"code":"EE-84","name":"Viljandimaa"},"354":{"code":"EE-86","name":"V\u00f5rumaa"}}},"EG":{"name":"Egypt"},"EH":{"name":"Western Sahara"},"ER":{"name":"Eritrea"},"ES":{"name":"Spain","regions":{"130":{"code":"A Coru\u0441a","name":"A Coru\u00f1a"},"131":{"code":"Alava","name":"Alava"},"132":{"code":"Albacete","name":"Albacete"},"133":{"code":"Alicante","name":"Alicante"},"134":{"code":"Almeria","name":"Almeria"},"135":{"code":"Asturias","name":"Asturias"},"136":{"code":"Avila","name":"Avila"},"137":{"code":"Badajoz","name":"Badajoz"},"138":{"code":"Baleares","name":"Baleares"},"139":{"code":"Barcelona","name":"Barcelona"},"140":{"code":"Burgos","name":"Burgos"},"141":{"code":"Caceres","name":"Caceres"},"142":{"code":"Cadiz","name":"Cadiz"},"143":{"code":"Cantabria","name":"Cantabria"},"144":{"code":"Castellon","name":"Castellon"},"145":{"code":"Ceuta","name":"Ceuta"},"146":{"code":"Ciudad Real","name":"Ciudad Real"},"147":{"code":"Cordoba","name":"Cordoba"},"148":{"code":"Cuenca","name":"Cuenca"},"149":{"code":"Girona","name":"Girona"},"150":{"code":"Granada","name":"Granada"},"151":{"code":"Guadalajara","name":"Guadalajara"},"152":{"code":"Guipuzcoa","name":"Guipuzcoa"},"153":{"code":"Huelva","name":"Huelva"},"154":{"code":"Huesca","name":"Huesca"},"155":{"code":"Jaen","name":"Jaen"},"156":{"code":"La Rioja","name":"La Rioja"},"157":{"code":"Las Palmas","name":"Las Palmas"},"158":{"code":"Leon","name":"Leon"},"159":{"code":"Lleida","name":"Lleida"},"160":{"code":"Lugo","name":"Lugo"},"161":{"code":"Madrid","name":"Madrid"},"162":{"code":"Malaga","name":"Malaga"},"163":{"code":"Melilla","name":"Melilla"},"164":{"code":"Murcia","name":"Murcia"},"165":{"code":"Navarra","name":"Navarra"},"166":{"code":"Ourense","name":"Ourense"},"167":{"code":"Palencia","name":"Palencia"},"168":{"code":"Pontevedra","name":"Pontevedra"},"169":{"code":"Salamanca","name":"Salamanca"},"170":{"code":"Santa Cruz de Tenerife","name":"Santa Cruz de Tenerife"},"171":{"code":"Segovia","name":"Segovia"},"172":{"code":"Sevilla","name":"Sevilla"},"173":{"code":"Soria","name":"Soria"},"174":{"code":"Tarragona","name":"Tarragona"},"175":{"code":"Teruel","name":"Teruel"},"176":{"code":"Toledo","name":"Toledo"},"177":{"code":"Valencia","name":"Valencia"},"178":{"code":"Valladolid","name":"Valladolid"},"179":{"code":"Vizcaya","name":"Vizcaya"},"180":{"code":"Zamora","name":"Zamora"},"181":{"code":"Zaragoza","name":"Zaragoza"}}},"ET":{"name":"Ethiopia"},"FI":{"name":"Finland","regions":{"339":{"code":"Ahvenanmaa","name":"Ahvenanmaa"},"333":{"code":"Etel\u00e4-Karjala","name":"Etel\u00e4-Karjala"},"326":{"code":"Etel\u00e4-Pohjanmaa","name":"Etel\u00e4-Pohjanmaa"},"325":{"code":"Etel\u00e4-Savo","name":"Etel\u00e4-Savo"},"337":{"code":"It\u00e4-Uusimaa","name":"It\u00e4-Uusimaa"},"322":{"code":"Kainuu","name":"Kainuu"},"335":{"code":"Kanta-H\u00e4me","name":"Kanta-H\u00e4me"},"330":{"code":"Keski-Pohjanmaa","name":"Keski-Pohjanmaa"},"331":{"code":"Keski-Suomi","name":"Keski-Suomi"},"338":{"code":"Kymenlaakso","name":"Kymenlaakso"},"320":{"code":"Lappi","name":"Lappi"},"334":{"code":"P\u00e4ij\u00e4t-H\u00e4me","name":"P\u00e4ij\u00e4t-H\u00e4me"},"328":{"code":"Pirkanmaa","name":"Pirkanmaa"},"327":{"code":"Pohjanmaa","name":"Pohjanmaa"},"323":{"code":"Pohjois-Karjala","name":"Pohjois-Karjala"},"321":{"code":"Pohjois-Pohjanmaa","name":"Pohjois-Pohjanmaa"},"324":{"code":"Pohjois-Savo","name":"Pohjois-Savo"},"329":{"code":"Satakunta","name":"Satakunta"},"336":{"code":"Uusimaa","name":"Uusimaa"},"332":{"code":"Varsinais-Suomi","name":"Varsinais-Suomi"}}},"FJ":{"name":"Fiji"},"FK":{"name":"Falkland Islands"},"FM":{"name":"Micronesia"},"FO":{"name":"Faroe Islands"},"FR":{"name":"France","regions":{"182":{"code":"1","name":"Ain"},"183":{"code":"2","name":"Aisne"},"184":{"code":"3","name":"Allier"}
7851,"185":{"code":"4","name":"Alpes-de-Haute-Provence"},"187":{"code":"6","name":"Alpes-Maritimes"},"188":{"code":"7","name":"Ard\u00e8che"},"189":{"code":"8","name":"Ardennes"},"190":{"code":"9","name":"Ari\u00e8ge"},"191":{"code":"10","name":"Aube"},"192":{"code":"11","name":"Aude"},"193":{"code":"12","name":"Aveyron"},"249":{"code":"67","name":"Bas-Rhin"},"194":{"code":"13","name":"Bouches-du-Rh\u00f4ne"},"195":{"code":"14","name":"Calvados"},"196":{"code":"15","name":"Cantal"},"197":{"code":"16","name":"Charente"},"198":{"code":"17","name":"Charente-Maritime"},"199":{"code":"18","name":"Cher"},"200":{"code":"19","name":"Corr\u00e8ze"},"201":{"code":"2A","name":"Corse-du-Sud"},"203":{"code":"21","name":"C\u00f4te-d'Or"},"204":{"code":"22","name":"C\u00f4tes-d'Armor"},"205":{"code":"23","name":"Creuse"},"261":{"code":"79","name":"Deux-S\u00e8vres"},"206":{"code":"24","name":"Dordogne"},"207":{"code":"25","name":"Doubs"},"208":{"code":"26","name":"Dr\u00f4me"},"273":{"code":"91","name":"Essonne"},"209":{"code":"27","name":"Eure"},"210":{"code":"28","name":"Eure-et-Loir"},"211":{"code":"29","name":"Finist\u00e8re"},"212":{"code":"30","name":"Gard"},"214":{"code":"32","name":"Gers"},"215":{"code":"33","name":"Gironde"},"250":{"code":"68","name":"Haut-Rhin"},"202":{"code":"2B","name":"Haute-Corse"},"213":{"code":"31","name":"Haute-Garonne"},"225":{"code":"43","name":"Haute-Loire"},"234":{"code":"52","name":"Haute-Marne"},"252":{"code":"70","name":"Haute-Sa\u00f4ne"},"256":{"code":"74","name":"Haute-Savoie"},"269":{"code":"87","name":"Haute-Vienne"},"186":{"code":"5","name":"Hautes-Alpes"},"247":{"code":"65","name":"Hautes-Pyr\u00e9n\u00e9es"},"274":{"code":"92","name":"Hauts-de-Seine"},"216":{"code":"34","name":"H\u00e9rault"},"217":{"code":"35","name":"Ille-et-Vilaine"},"218":{"code":"36","name":"Indre"},"219":{"code":"37","name":"Indre-et-Loire"},"220":{"code":"38","name":"Is\u00e8re"},"221":{"code":"39","name":"Jura"},"222":{"code":"40","name":"Landes"},"223":{"code":"41","name":"Loir-et-Cher"},"224":{"code":"42","name":"Loire"},"226":{"code":"44","name":"Loire-Atlantique"},"227":{"code":"45","name":"Loiret"},"228":{"code":"46","name":"Lot"},"229":{"code":"47","name":"Lot-et-Garonne"},"230":{"code":"48","name":"Loz\u00e8re"},"231":{"code":"49","name":"Maine-et-Loire"},"232":{"code":"50","name":"Manche"},"233":{"code":"51","name":"Marne"},"235":{"code":"53","name":"Mayenne"},"236":{"code":"54","name":"Meurthe-et-Moselle"},"237":{"code":"55","name":"Meuse"},"238":{"code":"56","name":"Morbihan"},"239":{"code":"57","name":"Moselle"},"240":{"code":"58","name":"Ni\u00e8vre"},"241":{"code":"59","name":"Nord"},"242":{"code":"60","name":"Oise"},"243":{"code":"61","name":"Orne"},"257":{"code":"75","name":"Paris"},"244":{"code":"62","name":"Pas-de-Calais"},"245":{"code":"63","name":"Puy-de-D\u00f4me"},"246":{"code":"64","name":"Pyr\u00e9n\u00e9es-Atlantiques"},"248":{"code":"66","name":"Pyr\u00e9n\u00e9es-Orientales"},"251":{"code":"69","name":"Rh\u00f4ne"},"253":{"code":"71","name":"Sa\u00f4ne-et-Loire"},"254":{"code":"72","name":"Sarthe"},"255":{"code":"73","name":"Savoie"},"259":{"code":"77","name":"Seine-et-Marne"},"258":{"code":"76","name":"Seine-Maritime"},"275":{"code":"93","name":"Seine-Saint-Denis"},"262":{"code":"80","name":"Somme"},"263":{"code":"81","name":"Tarn"},"264":{"code":"82","name":"Tarn-et-Garonne"},"272":{"code":"90","name":"Territoire-de-Belfort"},"277":{"code":"95","name":"Val-d'Oise"},"276":{"code":"94","name":"Val-de-Marne"},"265":{"code":"83","name":"Var"},"266":{"code":"84","name":"Vaucluse"},"267":{"code":"85","name":"Vend\u00e9e"},"268":{"code":"86","name":"Vienne"},"270":{"code":"88","name":"Vosges"},"271":{"code":"89","name":"Yonne"},"260":{"code":"78","name":"Yvelines"}}},"GA":{"name":"Gabon"},"GB":{"name":"United Kingdom"},"GD":{"name":"Grenada"},"GE":{"name":"Georgia"},"GF":{"name":"French Guiana"},"GG":{"name":"Guernsey"},"GH":{"name":"Ghana"},"GI":{"name":"Gibraltar"},"GL":{"name":"Greenland"},"GM":{"name":"Gambia"},"GN":{"name":"Guinea"},"GP":{"name":"Guadeloupe"},"GQ":{"name":"Equatorial Guinea"},"GR":{"name":"Greece","regions":{"1465":{"code":"GR-69","name":"\u00c1gion \u00d3ros"},"1426":{"code":"GR-A","name":"Anatolik\u00ed Makedon\u00eda kai Thr\u00e1ki"},"1429":{"code":"GR-I","name":"Attik\u00ed"},"1432":{"code":"GR-G","name":"Dytik\u00ed Ell\u00e1da"},"1435":{"code":"GR-C","name":"Dytik\u00ed Makedon\u00eda"},"1438":{"code":"GR-F","name":"Ion\u00eda N\u00edsia"},"1441":{"code":"GR-D","name":"\u00cdpeiros"},"1444":{"code":"GR-B","name":"Kentrik\u00ed Makedon\u00eda"},"1447":{"code":"GR-M","name":"Kr\u00edti"},"1450":{"code":"GR-L","name":"N\u00f3tio Aiga\u00edo"},"1453":{"code":"GR-J","name":"Pelop\u00f3nnisos"},"1456":{"code":"GR-H","name":"Stere\u00e1 Ell\u00e1da"}
7851,"1459":{"code":"GR-E","name":"Thessal\u00eda"},"1462":{"code":"GR-K","name":"V\u00f3reio Aiga\u00edo"}}},"GS":{"name":"South Georgia & South Sandwich Islands"},"GT":{"name":"Guatemala"},"GU":{"name":"Guam"},"GW":{"name":"Guinea-Bissau"},"GY":{"name":"Guyana","regions":{"1468":{"code":"GY-BA","name":"Barima-Waini"},"1471":{"code":"GY-CU","name":"Cuyuni-Mazaruni"},"1474":{"code":"GY-DE","name":"Demerara-Mahaica"},"1477":{"code":"GY-EB","name":"East Berbice-Corentyne"},"1480":{"code":"GY-ES","name":"Essequibo Islands-West Demerara"},"1483":{"code":"GY-MA","name":"Mahaica-Berbice"},"1486":{"code":"GY-PM","name":"Pomeroon-Supenaam"},"1489":{"code":"GY-PT","name":"Potaro-Siparuni"},"1492":{"code":"GY-UD","name":"Upper Demerara-Berbice"},"1495":{"code":"GY-UT","name":"Upper Takutu-Upper Essequibo"}}},"HK":{"name":"Hong Kong SAR China"},"HM":{"name":"Heard & McDonald Islands"},"HN":{"name":"Honduras"},"HR":{"name":"Croatia","regions":{"518":{"code":"HR-07","name":"Bjelovarsko-bilogorska \u017eupanija"},"523":{"code":"HR-12","name":"Brodsko-posavska \u017eupanija"},"530":{"code":"HR-19","name":"Dubrova\u010dko-neretvanska \u017eupanija"},"532":{"code":"HR-21","name":"Grad Zagreb"},"529":{"code":"HR-18","name":"Istarska \u017eupanija"},"515":{"code":"HR-04","name":"Karlova\u010dka \u017eupanija"},"517":{"code":"HR-06","name":"Koprivni\u010dko-kri\u017eeva\u010dka \u017eupanija"},"513":{"code":"HR-02","name":"Krapinsko-zagorska \u017eupanija"},"520":{"code":"HR-09","name":"Li\u010dko-senjska \u017eupanija"},"531":{"code":"HR-20","name":"Me\u0111imurska \u017eupanija"},"525":{"code":"HR-14","name":"Osje\u010dko-baranjska \u017eupanija"},"522":{"code":"HR-11","name":"Po\u017ee\u0161ko-slavonska \u017eupanija"},"519":{"code":"HR-08","name":"Primorsko-goranska \u017eupanija"},"526":{"code":"HR-15","name":"\u0160ibensko-kninska \u017eupanija"},"514":{"code":"HR-03","name":"Sisa\u010dko-moslava\u010dka \u017eupanija"},"528":{"code":"HR-17","name":"Splitsko-dalmatinska \u017eupanija"},"516":{"code":"HR-05","name":"Vara\u017edinska \u017eupanija"},"521":{"code":"HR-10","name":"Viroviti\u010dko-podravska \u017eupanija"},"527":{"code":"HR-16","name":"Vukovarsko-srijemska \u017eupanija"},"524":{"code":"HR-13","name":"Zadarska \u017eupanija"},"512":{"code":"HR-01","name":"Zagreba\u010dka \u017eupanija"}}},"HT":{"name":"Haiti"},"HU":{"name":"Hungary"},"ID":{"name":"Indonesia"},"IE":{"name":"Ireland"},"IL":{"name":"Israel"},"IM":{"name":"Isle of Man"},"IN":{"name":"India","regions":{"537":{"code":"AN","name":"Andaman and Nicobar Islands"},"540":{"code":"AP","name":"Andhra Pradesh"},"543":{"code":"AR","name":"Arunachal Pradesh"},"546":{"code":"AS","name":"Assam"},"549":{"code":"BR","name":"Bihar"},"552":{"code":"CH","name":"Chandigarh"},"555":{"code":"CT","name":"Chhattisgarh"},"558":{"code":"DN","name":"Dadra and Nagar Haveli"},"561":{"code":"DD","name":"Daman and Diu"},"564":{"code":"DL","name":"Delhi"},"567":{"code":"GA","name":"Goa"},"570":{"code":"GJ","name":"Gujarat"},"573":{"code":"HR","name":"Haryana"},"576":{"code":"HP","name":"Himachal Pradesh"},"579":{"code":"JK","name":"Jammu and Kashmir"},"582":{"code":"JH","name":"Jharkhand"},"585":{"code":"KA","name":"Karnataka"},"588":{"code":"KL","name":"Kerala"},"591":{"code":"LD","name":"Lakshadweep"},"594":{"code":"MP","name":"Madhya Pradesh"},"597":{"code":"MH","name":"Maharashtra"},"600":{"code":"MN","name":"Manipur"},"603":{"code":"ML","name":"Meghalaya"},"606":{"code":"MZ","name":"Mizoram"},"609":{"code":"NL","name":"Nagaland"},"612":{"code":"OR","name":"Odisha"},"615":{"code":"PY","name":"Puducherry"},"618":{"code":"PB","name":"Punjab"},"621":{"code":"RJ","name":"Rajasthan"},"624":{"code":"SK","name":"Sikkim"},"627":{"code":"TN","name":"Tamil Nadu"},"630":{"code":"TG","name":"Telangana"},"633":{"code":"TR","name":"Tripura"},"636":{"code":"UP","name":"Uttar Pradesh"},"639":{"code":"UT","name":"Uttarakhand"},"642":{"code":"WB","name":"West Bengal"}}},"IO":{"name":"British Indian Ocean Territory"},"IQ":{"name":"Iraq"},"IR":{"name":"Iran"},"IS":{"name":"Iceland","regions":{"1516":{"code":"IS-07","name":"Austurland"},"1498":{"code":"IS-01","name":"H\u00f6fu\u00f0borgarsv\u00e6\u00f0i"},"1513":{"code":"IS-06","name":"Nor\u00f0urland eystra"},"1510":{"code":"IS-05","name":"Nor\u00f0urland vestra"},"1519":{"code":"IS-08","name":"Su\u00f0urland"},"1501":{"code":"IS-02","name":"Su\u00f0urnes"},"1507":{"code":"IS-04","name":"Vestfir\u00f0ir"},"1504":{"code":"IS-03","name":"Vesturland"}}},"IT":{"name":"Italy","regions":{"1522":{"code":"AG","name":"Agrigento"},"1525":{"code":"AL","name":"Alessandria"},"1528":{"code":"AN","name":"Ancona"},"1531":{"code":"AO","name":"Aosta"},"1537":{"code":"AR","name":"Arezzo"},"1540":{"code":"AP","name":"Ascoli-Piceno"},"1543":{"code":"AT","name":"Asti"},"1546":{"code":"AV","name":"Avellino"},"1549":{"code":"BA","name":"Bari"},"1552":{"code":"BT","name":"Barletta-Andria-Trani"},"1555":{"code":"BL","name":"Belluno"},"1558":{"code":"BN","name":"Benevento"},"1561":{"code":"BG","name":"Bergamo"},"1564":{"code":"BI","name":"Biella"},"1567":{"code":"BO","name":"Bologna"},"1570":{"code":"BZ","name":"Bolzano"},"1573":{"code":"BS","name":"Brescia"},"1576":{"code":"BR","name":"Brindisi"}
7851,"1579":{"code":"CA","name":"Cagliari"},"1582":{"code":"CL","name":"Caltanissetta"},"1585":{"code":"CB","name":"Campobasso"},"1588":{"code":"CI","name":"Carbonia Iglesias"},"1591":{"code":"CE","name":"Caserta"},"1594":{"code":"CT","name":"Catania"},"1597":{"code":"CZ","name":"Catanzaro"},"1600":{"code":"CH","name":"Chieti"},"1603":{"code":"CO","name":"Como"},"1606":{"code":"CS","name":"Cosenza"},"1609":{"code":"CR","name":"Cremona"},"1612":{"code":"KR","name":"Crotone"},"1615":{"code":"CN","name":"Cuneo"},"1618":{"code":"EN","name":"Enna"},"1621":{"code":"FM","name":"Fermo"},"1624":{"code":"FE","name":"Ferrara"},"1627":{"code":"FI","name":"Firenze"},"1630":{"code":"FG","name":"Foggia"},"1633":{"code":"FC","name":"Forli-Cesena"},"1636":{"code":"FR","name":"Frosinone"},"1639":{"code":"GE","name":"Genova"},"1642":{"code":"GO","name":"Gorizia"},"1645":{"code":"GR","name":"Grosseto"},"1648":{"code":"IM","name":"Imperia"},"1651":{"code":"IS","name":"Isernia"},"1534":{"code":"AQ","name":"L'Aquila"},"1654":{"code":"SP","name":"La-Spezia"},"1657":{"code":"LT","name":"Latina"},"1660":{"code":"LE","name":"Lecce"},"1663":{"code":"LC","name":"Lecco"},"1666":{"code":"LI","name":"Livorno"},"1669":{"code":"LO","name":"Lodi"},"1672":{"code":"LU","name":"Lucca"},"1675":{"code":"MC","name":"Macerata"},"1678":{"code":"MN","name":"Mantova"},"1681":{"code":"MS","name":"Massa-Carrara"},"1684":{"code":"MT","name":"Matera"},"1687":{"code":"VS","name":"Medio Campidano"},"1690":{"code":"ME","name":"Messina"},"1693":{"code":"MI","name":"Milano"},"1696":{"code":"MO","name":"Modena"},"1699":{"code":"MB","name":"Monza-Brianza"},"1702":{"code":"NA","name":"Napoli"},"1705":{"code":"NO","name":"Novara"},"1708":{"code":"NU","name":"Nuoro"},"1711":{"code":"OG","name":"Ogliastra"},"1714":{"code":"OT","name":"Olbia Tempio"},"1717":{"code":"OR","name":"Oristano"},"1720":{"code":"PD","name":"Padova"},"1723":{"code":"PA","name":"Palermo"},"1726":{"code":"PR","name":"Parma"},"1729":{"code":"PV","name":"Pavia"},"1732":{"code":"PG","name":"Perugia"},"1735":{"code":"PU","name":"Pesaro-Urbino"},"1738":{"code":"PE","name":"Pescara"},"1741":{"code":"PC","name":"Piacenza"},"1744":{"code":"PI","name":"Pisa"},"1747":{"code":"PT","name":"Pistoia"},"1750":{"code":"PN","name":"Pordenone"},"1753":{"code":"PZ","name":"Potenza"},"1756":{"code":"PO","name":"Prato"},"1759":{"code":"RG","name":"Ragusa"},"1762":{"code":"RA","name":"Ravenna"},"1765":{"code":"RC","name":"Reggio-Calabria"},"1768":{"code":"RE","name":"Reggio-Emilia"},"1771":{"code":"RI","name":"Rieti"},"1774":{"code":"RN","name":"Rimini"},"1777":{"code":"RM","name":"Roma"},"1780":{"code":"RO","name":"Rovigo"},"1783":{"code":"SA","name":"Salerno"},"1786":{"code":"SS","name":"Sassari"},"1789":{"code":"SV","name":"Savona"},"1792":{"code":"SI","name":"Siena"},"1795":{"code":"SR","name":"Siracusa"},"1798":{"code":"SO","name":"Sondrio"},"1801":{"code":"TA","name":"Taranto"},"1804":{"code":"TE","name":"Teramo"},"1807":{"code":"TR","name":"Terni"},"1810":{"code":"TO","name":"Torino"},"1813":{"code":"TP","name":"Trapani"},"1816":{"code":"TN","name":"Trento"},"1819":{"code":"TV","name":"Treviso"},"1822":{"code":"TS","name":"Trieste"},"1825":{"code":"UD","name":"Udine"},"1828":{"code":"VA","name":"Varese"},"1831":{"code":"VE","name":"Venezia"},"1834":{"code":"VB","name":"Verbania"},"1837":{"code":"VC","name":"Vercelli"},"1840":{"code":"VR","name":"Verona"},"1843":{"code":"VV","name":"Vibo-Valentia"},"1846":{"code":"VI","name":"Vicenza"},"1849":{"code":"VT","name":"Viterbo"}}},"JE":{"name":"Jersey"},"JM":{"name":"Jamaica"},"JO":{"name":"Jordan"},"JP":{"name":"Japan"},"KE":{"name":"Kenya"},"KG":{"name":"Kyrgyzstan"},"KH":{"name":"Cambodia"},"KI":{"name":"Kiribati"},"KM":{"name":"Comoros"},"KN":{"name":"St. Kitts & Nevis"},"KP":{"name":"North Korea"},"KR":{"name":"South Korea"},"KW":{"name":"Kuwait"},"KY":{"name":"Cayman Islands"},"KZ":{"name":"Kazakhstan"},"LA":{"name":"Laos"},"LB":{"name":"Lebanon"},"LC":{"name":"St. Lucia"},"LI":{"name":"Liechtenstein"},"LK":{"name":"Sri Lanka"},"LR":{"name":"Liberia"},"LS":{"name":"Lesotho"},"LT":{"name":"Lithuania","regions":{"475":{"code":"LT-AL","name":"Alytaus Apskritis"}
7851,"476":{"code":"LT-KU","name":"Kauno Apskritis"},"477":{"code":"LT-KL","name":"Klaip\u0117dos Apskritis"},"478":{"code":"LT-MR","name":"Marijampol\u0117s Apskritis"},"479":{"code":"LT-PN","name":"Panev\u0117\u017eio Apskritis"},"480":{"code":"LT-SA","name":"\u0160iauli\u0173 Apskritis"},"481":{"code":"LT-TA","name":"Taurag\u0117s Apskritis"},"482":{"code":"LT-TE","name":"Tel\u0161i\u0173 Apskritis"},"483":{"code":"LT-UT","name":"Utenos Apskritis"},"484":{"code":"LT-VL","name":"Vilniaus Apskritis"}}},"LU":{"name":"Luxembourg"},"LV":{"name":"Latvia","regions":{"471":{"code":"\u0100da\u017eu novads","name":"\u0100da\u017eu novads"},"366":{"code":"Aglonas novads","name":"Aglonas novads"},"367":{"code":"LV-AI","name":"Aizkraukles novads"},"368":{"code":"Aizputes novads","name":"Aizputes novads"},"369":{"code":"Akn\u012bstes novads","name":"Akn\u012bstes novads"},"370":{"code":"Alojas novads","name":"Alojas novads"},"371":{"code":"Alsungas novads","name":"Alsungas novads"},"372":{"code":"LV-AL","name":"Al\u016bksnes novads"},"373":{"code":"Amatas novads","name":"Amatas novads"},"374":{"code":"Apes novads","name":"Apes novads"},"375":{"code":"Auces novads","name":"Auces novads"},"376":{"code":"Bab\u012btes novads","name":"Bab\u012btes novads"},"377":{"code":"Baldones novads","name":"Baldones novads"},"378":{"code":"Baltinavas novads","name":"Baltinavas novads"},"379":{"code":"LV-BL","name":"Balvu novads"},"380":{"code":"LV-BU","name":"Bauskas novads"},"381":{"code":"Bever\u012bnas novads","name":"Bever\u012bnas novads"},"382":{"code":"Broc\u0113nu novads","name":"Broc\u0113nu novads"},"383":{"code":"Burtnieku novads","name":"Burtnieku novads"},"384":{"code":"Carnikavas novads","name":"Carnikavas novads"},"387":{"code":"LV-CE","name":"C\u0113su novads"},"385":{"code":"Cesvaines novads","name":"Cesvaines novads"},"386":{"code":"Ciblas novads","name":"Ciblas novads"},"388":{"code":"Dagdas novads","name":"Dagdas novads"},"355":{"code":"LV-DGV","name":"Daugavpils"},"389":{"code":"LV-DA","name":"Daugavpils novads"},"390":{"code":"LV-DO","name":"Dobeles novads"},"391":{"code":"Dundagas novads","name":"Dundagas novads"},"392":{"code":"Durbes novads","name":"Durbes novads"},"393":{"code":"Engures novads","name":"Engures novads"},"472":{"code":"\u0112rg\u013cu novads","name":"\u0112rg\u013cu novads"},"394":{"code":"Garkalnes novads","name":"Garkalnes novads"},"395":{"code":"Grobi\u0146as novads","name":"Grobi\u0146as novads"},"396":{"code":"LV-GU","name":"Gulbenes novads"},"397":{"code":"Iecavas novads","name":"Iecavas novads"},"398":{"code":"Ik\u0161\u0137iles novads","name":"Ik\u0161\u0137iles novads"},"399":{"code":"Il\u016bkstes novads","name":"Il\u016bkstes novads"},"400":{"code":"In\u010dukalna novads","name":"In\u010dukalna novads"},"401":{"code":"Jaunjelgavas novads","name":"Jaunjelgavas novads"},"402":{"code":"Jaunpiebalgas novads","name":"Jaunpiebalgas novads"},"403":{"code":"Jaunpils novads","name":"Jaunpils novads"},"357":{"code":"J\u0113kabpils","name":"J\u0113kabpils"},"405":{"code":"LV-JK","name":"J\u0113kabpils novads"},"356":{"code":"LV-JEL","name":"Jelgava"},"404":{"code":"LV-JL","name":"Jelgavas novads"},"358":{"code":"LV-JUR","name":"J\u016brmala"},"406":{"code":"Kandavas novads","name":"Kandavas novads"},"412":{"code":"K\u0101rsavas novads","name":"K\u0101rsavas novads"},"473":{"code":"\u0136eguma novads","name":"\u0136eguma novads"},"474":{"code":"\u0136ekavas novads","name":"\u0136ekavas novads"},"407":{"code":"Kokneses novads","name":"Kokneses novads"},"410":{"code":"LV-KR","name":"Kr\u0101slavas novads"},"408":{"code":"Krimuldas novads","name":"Krimuldas novads"},"409":{"code":"Krustpils novads","name":"Krustpils novads"},"411":{"code":"LV-KU","name":"Kuld\u012bgas novads"},"413":{"code":"Lielv\u0101rdes novads","name":"Lielv\u0101rdes novads"},"359":{"code":"LV-LPX","name":"Liep\u0101ja"},"360":{"code":"LV-LE","name":"Liep\u0101jas novads"},"417":{"code":"L\u012bgatnes novads","name":"L\u012bgatnes novads"},"414":{"code":"LV-LM","name":"Limba\u017eu novads"},"418":{"code":"L\u012bv\u0101nu novads","name":"L\u012bv\u0101nu novads"},"415":{"code":"Lub\u0101nas novads","name":"Lub\u0101nas novads"},"416":{"code":"LV-LU","name":"Ludzas novads"},"419":{"code":"LV-MA","name":"Madonas novads"},"421":{"code":"M\u0101lpils novads","name":"M\u0101lpils novads"},"422":{"code":"M\u0101rupes novads","name":"M\u0101rupes novads"},"420":{"code":"Mazsalacas novads","name":"Mazsalacas novads"},"423":{"code":"Nauk\u0161\u0113nu novads","name":"Nauk\u0161\u0113nu novads"},"424":{"code":"Neretas novads","name":"Neretas novads"},"425":{"code":"N\u012bcas novads","name":"N\u012bcas novads"},"426":{"code":"LV-OG","name":"Ogres novads"},"427":{"code":"Olaines novads","name":"Olaines novads"},"428":{"code":"Ozolnieku novads","name":"Ozolnieku novads"},"432":{"code":"P\u0101rgaujas novads","name":"P\u0101rgaujas novads"},"433":{"code":"P\u0101vilostas novads","name":"P\u0101vilostas novads"},"434":{"code":"P\u013cavi\u0146u novads","name":"P\u013cavi\u0146u novads"},"429":{"code":"LV-PR","name":"Prei\u013cu novads"},"430":{"code":"Priekules novads","name":"Priekules novads"},"431":{"code":"Prieku\u013cu novads","name":"Prieku\u013cu novads"},"435":{"code":"Raunas novads","name":"Raunas novads"},"361":{"code":"LV-REZ","name":"R\u0113zekne"},"442":{"code":"LV-RE","name":"R\u0113zeknes novads"},"436":{"code":"Riebi\u0146u novads","name":"Riebi\u0146u novads"},"362":{"code":"LV-RIX","name":"R\u012bga"},"363":{"code":"LV-RI","name":"R\u012bgas novads"},"437":{"code":"Rojas novads","name":"Rojas novads"},"438":{"code":"Ropa\u017eu novads","name":"Ropa\u017eu novads"},"439":{"code":"Rucavas novads","name":"Rucavas novads"},"440":{"code":"Rug\u0101ju novads","name":"Rug\u0101ju novads"},"443":{"code":"R\u016bjienas novads","name":"R\u016bjienas novads"},"441":{"code":"Rund\u0101les novads","name":"Rund\u0101les novads"},"444":{"code":"Salacgr\u012bvas novads","name":"Salacgr\u012bvas novads"},"445":{"code":"Salas novads","name":"Salas novads"},"446":{"code":"Salaspils novads","name":"Salaspils novads"},"447":{"code":"LV-SA","name":"Saldus novads"},"448":{"code":"Saulkrastu novads","name":"Saulkrastu novads"},"455":{"code":"S\u0113jas novads","name":"S\u0113jas novads"},"449":{"code":"Siguldas novads","name":"Siguldas novads"}
7851,"451":{"code":"Skr\u012bveru novads","name":"Skr\u012bveru novads"},"450":{"code":"Skrundas novads","name":"Skrundas novads"},"452":{"code":"Smiltenes novads","name":"Smiltenes novads"},"453":{"code":"Stopi\u0146u novads","name":"Stopi\u0146u novads"},"454":{"code":"Stren\u010du novads","name":"Stren\u010du novads"},"456":{"code":"LV-TA","name":"Talsu novads"},"458":{"code":"T\u0113rvetes novads","name":"T\u0113rvetes novads"},"457":{"code":"LV-TU","name":"Tukuma novads"},"459":{"code":"Vai\u0146odes novads","name":"Vai\u0146odes novads"},"460":{"code":"LV-VK","name":"Valkas novads"},"364":{"code":"Valmiera","name":"Valmiera"},"461":{"code":"LV-VM","name":"Valmieras novads"},"462":{"code":"Varak\u013c\u0101nu novads","name":"Varak\u013c\u0101nu novads"},"469":{"code":"V\u0101rkavas novads","name":"V\u0101rkavas novads"},"463":{"code":"Vecpiebalgas novads","name":"Vecpiebalgas novads"},"464":{"code":"Vecumnieku novads","name":"Vecumnieku novads"},"365":{"code":"LV-VEN","name":"Ventspils"},"465":{"code":"LV-VE","name":"Ventspils novads"},"466":{"code":"Vies\u012btes novads","name":"Vies\u012btes novads"},"467":{"code":"Vi\u013cakas novads","name":"Vi\u013cakas novads"},"468":{"code":"Vi\u013c\u0101nu novads","name":"Vi\u013c\u0101nu novads"},"470":{"code":"Zilupes novads","name":"Zilupes novads"}}},"LY":{"name":"Libya"},"MA":{"name":"Morocco"},"MC":{"name":"Monaco"},"MD":{"name":"Moldova"},"ME":{"name":"Montenegro"},"MF":{"name":"St. Martin"},"MG":{"name":"Madagascar"},"MH":{"name":"Marshall Islands"},"MK":{"name":"North Macedonia"},"ML":{"name":"Mali"},"MM":{"name":"Myanmar (Burma)"},"MN":{"name":"Mongolia"},"MO":{"name":"Macao SAR China"},"MP":{"name":"Northern Mariana Islands"},"MQ":{"name":"Martinique"},"MR":{"name":"Mauritania"},"MS":{"name":"Montserrat"},"MT":{"name":"Malta"},"MU":{"name":"Mauritius"},"MV":{"name":"Maldives"},"MW":{"name":"Malawi"},"MX":{"name":"Mexico","regions":{"672":{"code":"AGU","name":"Aguascalientes"},"675":{"code":"BCN","name":"Baja California"},"678":{"code":"BCS","name":"Baja California Sur"},"681":{"code":"CAM","name":"Campeche"},"684":{"code":"CHP","name":"Chiapas"},"687":{"code":"CHH","name":"Chihuahua"},"690":{"code":"CMX","name":"Ciudad de M\u00e9xico"},"693":{"code":"COA","name":"Coahuila"},"696":{"code":"COL","name":"Colima"},"699":{"code":"DUR","name":"Durango"},"702":{"code":"MEX","name":"Estado de M\u00e9xico"},"705":{"code":"GUA","name":"Guanajuato"},"708":{"code":"GRO","name":"Guerrero"},"711":{"code":"HID","name":"Hidalgo"},"714":{"code":"JAL","name":"Jalisco"},"717":{"code":"MIC","name":"Michoac\u00e1n"},"720":{"code":"MOR","name":"Morelos"},"723":{"code":"NAY","name":"Nayarit"},"726":{"code":"NLE","name":"Nuevo Le\u00f3n"},"729":{"code":"OAX","name":"Oaxaca"},"732":{"code":"PUE","name":"Puebla"},"735":{"code":"QUE","name":"Quer\u00e9taro"},"738":{"code":"ROO","name":"Quintana Roo"},"741":{"code":"SLP","name":"San Luis Potos\u00ed"},"744":{"code":"SIN","name":"Sinaloa"},"747":{"code":"SON","name":"Sonora"},"750":{"code":"TAB","name":"Tabasco"},"753":{"code":"TAM","name":"Tamaulipas"},"756":{"code":"TLA","name":"Tlaxcala"},"759":{"code":"VER","name":"Veracruz"},"762":{"code":"YUC","name":"Yucat\u00e1n"},"765":{"code":"ZAC","name":"Zacatecas"}}},"MY":{"name":"Malaysia"},"MZ":{"name":"Mozambique"},"NA":{"name":"Namibia"},"NC":{"name":"New Caledonia"},"NE":{"name":"Niger"},"NF":{"name":"Norfolk Island"},"NG":{"name":"Nigeria"},"NI":{"name":"Nicaragua"},"NL":{"name":"Netherlands"},"NO":{"name":"Norway"},"NP":{"name":"Nepal"},"NR":{"name":"Nauru"},"NU":{"name":"Niue"},"NZ":{"name":"New Zealand"},"OM":{"name":"Oman"},"PA":{"name":"Panama"},"PE":{"name":"Peru","regions":{"1909":{"code":"PE-AMA","name":"Amazonas"},"1912":{"code":"PE-ANC","name":"Ancash"},"1915":{"code":"PE-APU","name":"Apur\u00edmac"},"1918":{"code":"PE-ARE","name":"Arequipa"},"1921":{"code":"PE-AYA","name":"Ayacucho"},"1924":{"code":"PE-CAJ","name":"Cajamarca"},"1927":{"code":"PE-CUS","name":"Cusco"},"1930":{"code":"PE-CAL","name":"El Callao"},"1933":{"code":"PE-HUV","name":"Huancavelica"},"1936":{"code":"PE-HUC","name":"Hu\u00e1nuco"},"1939":{"code":"PE-ICA","name":"Ica"},"1942":{"code":"PE-JUN","name":"Jun\u00edn"},"1945":{"code":"PE-LAL","name":"La Libertad"},"1948":{"code":"PE-LAM","name":"Lambayeque"},"1951":{"code":"PE-LIM","name":"Lima"},"1954":{"code":"PE-LOR","name":"Loreto"},"1957":{"code":"PE-MDD","name":"Madre de Dios"},"1960":{"code":"PE-MOQ","name":"Moquegua"}
7851,"1906":{"code":"PE-LMA","name":"Municipalidad Metropolitana de Lima"},"1963":{"code":"PE-PAS","name":"Pasco"},"1966":{"code":"PE-PIU","name":"Piura"},"1969":{"code":"PE-PUN","name":"Puno"},"1972":{"code":"PE-SAM","name":"San Mart\u00edn"},"1975":{"code":"PE-TAC","name":"Tacna"},"1978":{"code":"PE-TUM","name":"Tumbes"},"1981":{"code":"PE-UCA","name":"Ucayali"}}},"PF":{"name":"French Polynesia"},"PG":{"name":"Papua New Guinea"},"PH":{"name":"Philippines"},"PK":{"name":"Pakistan"},"PL":{"name":"Poland","regions":{"1005":{"code":"PL-02","name":"dolno\u015bl\u0105skie"},"1008":{"code":"PL-04","name":"kujawsko-pomorskie"},"1011":{"code":"PL-06","name":"lubelskie"},"1014":{"code":"PL-08","name":"lubuskie"},"1023":{"code":"PL-14","name":"mazowieckie"},"1020":{"code":"PL-12","name":"ma\u0142opolskie"},"1026":{"code":"PL-16","name":"opolskie"},"1029":{"code":"PL-18","name":"podkarpackie"},"1032":{"code":"PL-20","name":"podlaskie"},"1035":{"code":"PL-22","name":"pomorskie"},"1038":{"code":"PL-24","name":"\u015bl\u0105skie"},"1041":{"code":"PL-26","name":"\u015bwi\u0119tokrzyskie"},"1044":{"code":"PL-28","name":"warmi\u0144sko-mazurskie"},"1047":{"code":"PL-30","name":"wielkopolskie"},"1050":{"code":"PL-32","name":"zachodniopomorskie"},"1017":{"code":"PL-10","name":"\u0142\u00f3dzkie"}}},"PM":{"name":"St. Pierre & Miquelon"},"PN":{"name":"Pitcairn Islands"},"PS":{"name":"Palestinian Territories"},"PT":{"name":"Portugal","regions":{"1984":{"code":"PT-01","name":"Aveiro"},"1987":{"code":"PT-02","name":"Beja"},"1990":{"code":"PT-03","name":"Braga"},"1993":{"code":"PT-04","name":"Bragan\u00e7a"},"1996":{"code":"PT-05","name":"Castelo Branco"},"1999":{"code":"PT-06","name":"Coimbra"},"2002":{"code":"PT-07","name":"\u00c9vora"},"2005":{"code":"PT-08","name":"Faro"},"2008":{"code":"PT-09","name":"Guarda"},"2011":{"code":"PT-10","name":"Leiria"},"2014":{"code":"PT-11","name":"Lisboa"},"2017":{"code":"PT-12","name":"Portalegre"},"2020":{"code":"PT-13","name":"Porto"},"2041":{"code":"PT-30","name":"Regi\u00e3o Aut\u00f3noma da Madeira"},"2038":{"code":"PT-20","name":"Regi\u00e3o Aut\u00f3noma dos A\u00e7ores"},"2023":{"code":"PT-14","name":"Santar\u00e9m"},"2026":{"code":"PT-15","name":"Set\u00fabal"},"2029":{"code":"PT-16","name":"Viana do Castelo"},"2032":{"code":"PT-17","name":"Vila Real"},"2035":{"code":"PT-18","name":"Viseu"}}},"PW":{"name":"Palau"},"PY":{"name":"Paraguay","regions":{"1855":{"code":"PY-16","name":"Alto Paraguay"},"1858":{"code":"PY-10","name":"Alto Paran\u00e1"},"1861":{"code":"PY-13","name":"Amambay"},"1852":{"code":"PY-ASU","name":"Asunci\u00f3n"},"1864":{"code":"PY-19","name":"Boquer\u00f3n"},"1867":{"code":"PY-5","name":"Caaguaz\u00fa"},"1870":{"code":"PY-6","name":"Caazap\u00e1"},"1873":{"code":"PY-14","name":"Canindey\u00fa"},"1876":{"code":"PY-11","name":"Central"},"1879":{"code":"PY-1","name":"Concepci\u00f3n"},"1882":{"code":"PY-3","name":"Cordillera"},"1885":{"code":"PY-4","name":"Guair\u00e1"},"1888":{"code":"PY-7","name":"Itap\u00faa"},"1891":{"code":"PY-8","name":"Misiones"},"1894":{"code":"PY-12","name":"\u00d1eembuc\u00fa"},"1897":{"code":"PY-9","name":"Paraguar\u00ed"},"1900":{"code":"PY-15","name":"Presidente Hayes"},"1903":{"code":"PY-2","name":"San Pedro"}}},"QA":{"name":"Qatar"},"RE":{"name":"R\u00e9union"},"RO":{"name":"Romania","regions":{"278":{"code":"AB","name":"Alba"},"279":{"code":"AR","name":"Arad"},"280":{"code":"AG","name":"Arge\u015f"},"281":{"code":"BC","name":"Bac\u0103u"},"282":{"code":"BH","name":"Bihor"},"283":{"code":"BN","name":"Bistri\u0163a-N\u0103s\u0103ud"},"284":{"code":"BT","name":"Boto\u015fani"},"286":{"code":"BR","name":"Br\u0103ila"},"285":{"code":"BV","name":"Bra\u015fov"},"287":{"code":"B","name":"Bucure\u015fti"},"288":{"code":"BZ","name":"Buz\u0103u"},"290":{"code":"CL","name":"C\u0103l\u0103ra\u015fi"},"289":{"code":"CS","name":"Cara\u015f-Severin"},"291":{"code":"CJ","name":"Cluj"},"292":{"code":"CT","name":"Constan\u0163a"},"293":{"code":"CV","name":"Covasna"},"294":{"code":"DB","name":"D\u00e2mbovi\u0163a"},"295":{"code":"DJ","name":"Dolj"},"296":{"code":"GL","name":"Gala\u0163i"},"297":{"code":"GR","name":"Giurgiu"},"298":{"code":"GJ","name":"Gorj"},"299":{"code":"HR","name":"Harghita"},"300":{"code":"HD","name":"Hunedoara"},"301":{"code":"IL","name":"Ialomi\u0163a"},"302":{"code":"IS","name":"Ia\u015fi"},"303":{"code":"IF","name":"Ilfov"},"304":{"code":"MM","name":"Maramure\u015f"},"305":{"code":"MH","name":"Mehedin\u0163i"},"306":{"code":"MS","name":"Mure\u015f"},"307":{"code":"NT","name":"Neam\u0163"},"308":{"code":"OT","name":"Olt"},"309":{"code":"PH","name":"Prahova"},"311":{"code":"SJ","name":"S\u0103laj"},"310":{"code":"SM","name":"Satu-Mare"},"312":{"code":"SB","name":"Sibiu"},"313":{"code":"SV","name":"Suceava"},"314":{"code":"TR","name":"Teleorman"},"315":{"code":"TM","name":"Timi\u015f"},"316":{"code":"TL","name":"Tulcea"},"318":{"code":"VL","name":"V\u00e2lcea"},"317":{"code":"VS","name":"Vaslui"},"319":{"code":"VN","name":"Vrancea"}}},"RS":{"name":"Serbia"},"RU":{"name":"Russia"},"RW":{"name":"Rwanda"},"SA":{"name":"Saudi Arabia"},"SB":{"name":"Solomon Islands"},"SC":{"name":"Seychelles"},"SD":{"name":"Sudan"},"SE":{"name":"Sweden","regions":{"2074":{"code":"SE-K","name":"Blekinge l\u00e4n"}
7851,"2077":{"code":"SE-W","name":"Dalarnas l\u00e4n"},"2083":{"code":"SE-X","name":"G\u00e4vleborgs l\u00e4n"},"2080":{"code":"SE-I","name":"Gotlands l\u00e4n"},"2086":{"code":"SE-N","name":"Hallands l\u00e4n"},"2089":{"code":"SE-Z","name":"J\u00e4mtlands l\u00e4n"},"2092":{"code":"SE-F","name":"J\u00f6nk\u00f6pings l\u00e4n"},"2095":{"code":"SE-H","name":"Kalmar l\u00e4n"},"2098":{"code":"SE-G","name":"Kronobergs l\u00e4n"},"2101":{"code":"SE-BD","name":"Norrbottens l\u00e4n"},"2131":{"code":"SE-T","name":"\u00d6rebro l\u00e4n"},"2134":{"code":"SE-E","name":"\u00d6sterg\u00f6tlands l\u00e4n"},"2104":{"code":"SE-M","name":"Sk\u00e5ne l\u00e4n"},"2110":{"code":"SE-D","name":"S\u00f6dermanlands l\u00e4n"},"2107":{"code":"SE-AB","name":"Stockholms l\u00e4n"},"2113":{"code":"SE-C","name":"Uppsala l\u00e4n"},"2116":{"code":"SE-S","name":"V\u00e4rmlands l\u00e4n"},"2119":{"code":"SE-AC","name":"V\u00e4sterbottens l\u00e4n"},"2122":{"code":"SE-Y","name":"V\u00e4sternorrlands l\u00e4n"},"2125":{"code":"SE-U","name":"V\u00e4stmanlands l\u00e4n"},"2128":{"code":"SE-O","name":"V\u00e4stra G\u00f6talands l\u00e4n"}}},"SG":{"name":"Singapore"},"SH":{"name":"St. Helena"},"SI":{"name":"Slovenia"},"SJ":{"name":"Svalbard & Jan Mayen"},"SK":{"name":"Slovakia"},"SL":{"name":"Sierra Leone"},"SM":{"name":"San Marino"},"SN":{"name":"Senegal"},"SO":{"name":"Somalia"},"SR":{"name":"Suriname","regions":{"2044":{"code":"SR-BR","name":"Brokopondo"},"2047":{"code":"SR-CM","name":"Commewijne"},"2050":{"code":"SR-CR","name":"Coronie"},"2053":{"code":"SR-MA","name":"Marowijne"},"2056":{"code":"SR-NI","name":"Nickerie"},"2059":{"code":"SR-PR","name":"Para"},"2062":{"code":"SR-PM","name":"Paramaribo"},"2065":{"code":"SR-SA","name":"Saramacca"},"2068":{"code":"SR-SI","name":"Sipaliwini"},"2071":{"code":"SR-WA","name":"Wanica"}}},"ST":{"name":"S\u00e3o Tom\u00e9 & Pr\u00edncipe"},"SV":{"name":"El Salvador"},"SX":{"name":"Sint Maarten"},"SY":{"name":"Syria"},"SZ":{"name":"Eswatini"},"TC":{"name":"Turks & Caicos Islands"},"TD":{"name":"Chad"},"TF":{"name":"French Southern Territories"},"TG":{"name":"Togo"},"TH":{"name":"Thailand"},"TJ":{"name":"Tajikistan"},"TK":{"name":"Tokelau"},"TL":{"name":"Timor-Leste"},"TM":{"name":"Turkmenistan"},"TN":{"name":"Tunisia"},"TO":{"name":"Tonga"},"TR":{"name":"T\u00fcrkiye"},"TT":{"name":"Trinidad & Tobago"},"TV":{"name":"Tuvalu"},"TW":{"name":"Taiwan, Province of China"},"TZ":{"name":"Tanzania"},"UA":{"name":"Ukraine"},"UG":{"name":"Uganda"},"UM":{"name":"U.S. Outlying Islands"},"US":{"name":"United States","regions":{"1":{"code":"AL","name":"Alabama"},"2":{"code":"AK","name":"Alaska"},"3":{"code":"AS","name":"American Samoa"},"4":{"code":"AZ","name":"Arizona"},"5":{"code":"AR","name":"Arkansas"},"6":{"code":"AE","name":"Armed Forces Africa"},"7":{"code":"AA","name":"Armed Forces Americas"},"8":{"code":"AE","name":"Armed Forces Canada"},"9":{"code":"AE","name":"Armed Forces Europe"},"10":{"code":"AE","name":"Armed Forces Middle East"},"11":{"code":"AP","name":"Armed Forces Pacific"},"12":{"code":"CA","name":"California"},"13":{"code":"CO","name":"Colorado"},"14":{"code":"CT","name":"Connecticut"},"15":{"code":"DE","name":"Delaware"},"16":{"code":"DC","name":"District of Columbia"},"17":{"code":"FM","name":"Federated States Of Micronesia"},"18":{"code":"FL","name":"Florida"},"19":{"code":"GA","name":"Georgia"},"20":{"code":"GU","name":"Guam"},"21":{"code":"HI","name":"Hawaii"},"22":{"code":"ID","name":"Idaho"},"23":{"code":"IL","name":"Illinois"},"24":{"code":"IN","name":"Indiana"},"25":{"code":"IA","name":"Iowa"},"26":{"code":"KS","name":"Kansas"},"27":{"code":"KY","name":"Kentucky"},"28":{"code":"LA","name":"Louisiana"},"29":{"code":"ME","name":"Maine"},"30":{"code":"MH","name":"Marshall Islands"},"31":{"code":"MD","name":"Maryland"},"32":{"code":"MA","name":"Massachusetts"},"33":{"code":"MI","name":"Michigan"},"34":{"code":"MN","name":"Minnesota"},"35":{"code":"MS","name":"Mississippi"},"36":{"code":"MO","name":"Missouri"},"37":{"code":"MT","name":"Montana"},"38":{"code":"NE","name":"Nebraska"},"39":{"code":"NV","name":"Nevada"},"40":{"code":"NH","name":"New Hampshire"},"41":{"code":"NJ","name":"New Jersey"},"42":{"code":"NM","name":"New Mexico"},"43":{"code":"NY","name":"New York"},"44":{"code":"NC","name":"North Carolina"},"45":{"code":"ND","name":"North Dakota"},"46":{"code":"MP","name":"Northern Mariana Islands"},"47":{"code":"OH","name":"Ohio"},"48":{"code":"OK","name":"Oklahoma"},"49":{"code":"OR","name":"Oregon"},"50":{"code":"PW","name":"Palau"},"51":{"code":"PA","name":"Pennsylvania"},"52":{"code":"PR","name":"Puerto Rico"},"53":{"code":"RI","name":"Rhode Island"},"54":{"code":"SC","name":"South Carolina"},"55":{"code":"SD","name":"South Dakota"},"56":{"code":"TN","name":"Tennessee"},"57":{"code":"TX","name":"Texas"}
7851,"58":{"code":"UT","name":"Utah"},"59":{"code":"VT","name":"Vermont"},"60":{"code":"VI","name":"Virgin Islands"},"61":{"code":"VA","name":"Virginia"},"62":{"code":"WA","name":"Washington"},"63":{"code":"WV","name":"West Virginia"},"64":{"code":"WI","name":"Wisconsin"},"65":{"code":"WY","name":"Wyoming"}}},"UY":{"name":"Uruguay","regions":{"2137":{"code":"UY-AR","name":"Artigas"},"2140":{"code":"UY-CA","name":"Canelones"},"2143":{"code":"UY-CL","name":"Cerro Largo"},"2146":{"code":"UY-CO","name":"Colonia"},"2149":{"code":"UY-DU","name":"Durazno"},"2152":{"code":"UY-FS","name":"Flores"},"2155":{"code":"UY-FD","name":"Florida"},"2158":{"code":"UY-LA","name":"Lavalleja"},"2161":{"code":"UY-MA","name":"Maldonado"},"2164":{"code":"UY-MO","name":"Montevideo"},"2167":{"code":"UY-PA","name":"Paysandu"},"2170":{"code":"UY-RN","name":"R\u00edo Negro"},"2173":{"code":"UY-RV","name":"Rivera"},"2176":{"code":"UY-RO","name":"Rocha"},"2179":{"code":"UY-SA","name":"Salto"},"2182":{"code":"UY-SJ","name":"San Jos\u00e9"},"2185":{"code":"UY-SO","name":"Soriano"},"2188":{"code":"UY-TA","name":"Tacuaremb\u00f3"},"2191":{"code":"UY-TT","name":"Treinta y Tres"}}},"UZ":{"name":"Uzbekistan"},"VA":{"name":"Vatican City"},"VC":{"name":"St. Vincent & Grenadines"},"VE":{"name":"Venezuela","regions":{"2200":{"code":"VE-Z","name":"Amazonas"},"2203":{"code":"VE-B","name":"Anzo\u00e1tegui"},"2206":{"code":"VE-C","name":"Apure"},"2209":{"code":"VE-D","name":"Aragua"},"2212":{"code":"VE-E","name":"Barinas"},"2215":{"code":"VE-F","name":"Bol\u00edvar"},"2218":{"code":"VE-G","name":"Carabobo"},"2221":{"code":"VE-H","name":"Cojedes"},"2224":{"code":"VE-Y","name":"Delta Amacuro"},"2194":{"code":"VE-W","name":"Dependencias Federales"},"2197":{"code":"VE-A","name":"Distrito Capital"},"2227":{"code":"VE-I","name":"Falc\u00f3n"},"2230":{"code":"VE-J","name":"Gu\u00e1rico"},"2233":{"code":"VE-K","name":"Lara"},"2236":{"code":"VE-L","name":"M\u00e9rida"},"2239":{"code":"VE-M","name":"Miranda"},"2242":{"code":"VE-N","name":"Monagas"},"2245":{"code":"VE-O","name":"Nueva Esparta"},"2248":{"code":"VE-P","name":"Portuguesa"},"2251":{"code":"VE-R","name":"Sucre"},"2254":{"code":"VE-S","name":"T\u00e1chira"},"2257":{"code":"VE-T","name":"Trujillo"},"2260":{"code":"VE-X","name":"Vargas"},"2263":{"code":"VE-U","name":"Yaracuy"},"2266":{"code":"VE-V","name":"Zulia"}}},"VG":{"name":"British Virgin Islands"},"VI":{"name":"U.S. Virgin Islands"},"VN":{"name":"Vietnam"},"VU":{"name":"Vanuatu"},"WF":{"name":"Wallis & Futuna"},"WS":{"name":"Samoa"},"XK":{"name":"Kosovo"},"YE":{"name":"Yemen"},"YT":{"name":"Mayotte"},"ZA":{"name":"South Africa"},"ZM":{"name":"Zambia"},"ZW":{"name":"Zimbabwe"},"data_id":1790321995},"captcha":[],"wishlist":{"items":[]},"instant-purchase":[],"loggedAsCustomer":[],"multiplewishlist":[],"persistent":[],"review":[],"faq":[],"ammessages":[],"signifyd-fingerprint":[],"hyva_checkout":[],"hyva_enterprise":[],"wp_confirmation_popup":[],"recently_viewed_product":[],"recently_compared_product":[],"product_data_storage":[],"paypal-billing-agreement":[]}</script>
7851 7852
7853<script> 7854 document.addEventListener('DOMContentLoaded', () => { 7855 const mobileAsideSelector = '#amblog-mobile-aside-wrapper'; 7856 7857 if (window._amswipedEvents) { 7858 return; 7859 } 7860 7861 if (!document.querySelector(mobileAsideSelector)) { 7862 return; 7863 } 7864 7865 // load swiped events 7866 const script = document.createElement('script'); 7867 script.src = 'https://www.riccar.com/static/version1789042133/frontend/Snowdog/Riccar/en_US/Amasty_BlogHyva/js/swiped-events.min.js'; 7868 script.defer = true; 7869 document.body.appendChild(script); 7870 7871 window._amswipedEvents = true; 7872 }); 7873</script>
7873 7874</div>
7874<script type="text/javascript">window.NREUM||(NREUM={});NREUM.info={"beacon":"bam.nr-data.net","licenseKey":"8185b07d0f","applicationID":"154432994","transactionName":"YQFVbEcHXUdQB0UPDVhLdltBD1xaHgVcBA5ZAxhRWwJWTB4UXhUW","queueTime":0,"applicationTime":419,"atts":"TUZWGg8dTkk=","errorBeacon":"bam.nr-data.net","agent":""}</script>
7874</body> 7875</html>
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.