<!doctype html>
<html lang="fr">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# product: http://ogp.me/ns/product#">
<meta charset="utf-8"/>
<meta name="title" content="Bombe lacrymogène gel poivre Umarex P2P PDG-60"/>
<meta name="description" content="Bombe lacrymogène gel poivre Umarex P2P PDG-60"/>
<meta name="keywords" content="Bombe lacrymogène gel poivre Umarex P2P PDG-60, Bombe lacrymogène gaz, Bombe lacrymogène gel OC, Bombe lacrymogène de défense, Bombe lacrymogène Umarex, Bombe lacrymogène de défense Umarex, bombe lacrymogène, arme auto-défense, Bombe lacrymogène auto-défense, bombe au poivre, lacrymogène, lacrymogènes"/>
<meta name="robots" content="INDEX,FOLLOW"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Bombe lacrymogène gel poivre Umarex P2P PDG-60</title>
<link rel="stylesheet" type="text/css" media="all" href="https://www.arprotech.com/static/_cache/merged/orig_8e7eafcda8dc619a5edbdecfcc790711.min.css" />
<link rel="icon" type="image/png" href="https://www.arprotech.com/static/frontend/Arprotech/default/fr_FR/Magento_Theme/favicon-light.png" />
<link rel="canonical" href="https://www.arprotech.com/bombe-lacrymogene-gel-poivre-umarex-p2p-pdg-60.html" />
<meta name="p:domain_verify" content="ixCXvJBrl4jMJhru0Y7tjSnlHCc8gRzr"/>
<!--KozIhQll4WxQIsE49cYMI5hQTE2CunVk--><!--KozIhQll4WxQIsE49cYMI5hQTE2CunVk--><!--yR7uTKyLx7Scku0rZxlYKoUbfhbLH7CU-->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-SJB964EYW2"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-SJB964EYW2');
</script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.arprotech.com/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '4']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
<style>
#description p { margin-bottom:1rem;}
#description ul {
padding-inline-start: 40px;
list-style-type: disc;
margin-block-end: 16px;
margin-block-start: 16px;
}
</style> <script>
var BASE_URL = 'https://www.arprotech.com/';
var THEME_PATH = 'https://www.arprotech.com/static/frontend/Arprotech/default/fr_FR';
var COOKIE_CONFIG = {
"expires": null,
"path": "\u002F",
"domain": ".www.arprotech.com",
"secure": true,
"lifetime": "43200",
"cookie_restriction_enabled": true };
var CURRENT_STORE_CODE = 'default';
var CURRENT_WEBSITE_ID = '1';
window.hyva = window.hyva || {}
window.cookie_consent_groups = window.cookie_consent_groups || {}
window.cookie_consent_groups['necessary'] = true;
window.cookie_consent_config = window.cookie_consent_config || {};
window.cookie_consent_config['necessary'] = [].concat(
window.cookie_consent_config['necessary'] || [],
[
'user_allowed_save_cookie',
'form_key',
'mage-messages',
'private_content_version',
'mage-cache-sessid',
'last_visited_store',
'section_data_ids'
]
);
</script>
<script>
'use strict';
(function( hyva, undefined ) {
function lifetimeToExpires(options, defaults) {
const lifetime = options.lifetime || defaults.lifetime;
if (lifetime) {
const date = new Date;
date.setTime(date.getTime() + lifetime * 1000);
return date;
}
return null;
}
function generateRandomString() {
const allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
length = 16;
let formKey = '',
charactersLength = allowedCharacters.length;
for (let i = 0; i < length; i++) {
formKey += allowedCharacters[Math.round(Math.random() * (charactersLength - 1))]
}
return formKey;
}
const sessionCookieMarker = {noLifetime: true}
const cookieTempStorage = {};
const internalCookie = {
get(name) {
const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
return v ? v[2] : null;
},
set(name, value, days, skipSetDomain) {
let expires,
path,
domain,
secure,
samesite;
const defaultCookieConfig = {
expires: null,
path: '/',
domain: null,
secure: false,
lifetime: null,
samesite: 'lax'
};
const cookieConfig = window.COOKIE_CONFIG || {};
expires = days && days !== sessionCookieMarker
? lifetimeToExpires({lifetime: 24 * 60 * 60 * days, expires: null}, defaultCookieConfig)
: lifetimeToExpires(window.COOKIE_CONFIG, defaultCookieConfig) || defaultCookieConfig.expires;
path = cookieConfig.path || defaultCookieConfig.path;
domain = !skipSetDomain && (cookieConfig.domain || defaultCookieConfig.domain);
secure = cookieConfig.secure || defaultCookieConfig.secure;
samesite = cookieConfig.samesite || defaultCookieConfig.samesite;
document.cookie = name + "=" + encodeURIComponent(value) +
(expires && days !== sessionCookieMarker ? '; expires=' + expires.toGMTString() : '') +
(path ? '; path=' + path : '') +
(domain ? '; domain=' + domain : '') +
(secure ? '; secure' : '') +
(samesite ? '; samesite=' + samesite : 'lax');
},
isWebsiteAllowedToSaveCookie() {
const allowedCookies = this.get('user_allowed_save_cookie');
if (allowedCookies) {
const allowedWebsites = JSON.parse(unescape(allowedCookies));
return allowedWebsites[CURRENT_WEBSITE_ID] === 1;
}
return false;
},
getGroupByCookieName(name) {
const cookieConsentConfig = window.cookie_consent_config || {};
let group = null;
for (let prop in cookieConsentConfig) {
if (!cookieConsentConfig.hasOwnProperty(prop)) continue;
if (cookieConsentConfig[prop].includes(name)) {
group = prop;
break;
}
}
return group;
},
isCookieAllowed(name) {
const cookieGroup = this.getGroupByCookieName(name);
return cookieGroup
? window.cookie_consent_groups[cookieGroup]
: this.isWebsiteAllowedToSaveCookie();
},
saveTempStorageCookies() {
for (const [name, data] of Object.entries(cookieTempStorage)) {
if (this.isCookieAllowed(name)) {
this.set(name, data['value'], data['days'], data['skipSetDomain']);
delete cookieTempStorage[name];
}
}
}
};
hyva.getCookie = (name) => {
const cookieConfig = window.COOKIE_CONFIG || {};
if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) {
return cookieTempStorage[name] ? cookieTempStorage[name]['value'] : null;
}
return internalCookie.get(name);
}
hyva.setCookie = (name, value, days, skipSetDomain) => {
const cookieConfig = window.COOKIE_CONFIG || {};
if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) {
cookieTempStorage[name] = {value, days, skipSetDomain};
return;
}
return internalCookie.set(name, value, days, skipSetDomain);
}
hyva.setSessionCookie = (name, value, skipSetDomain) => {
return hyva.setCookie(name, value, sessionCookieMarker, skipSetDomain)
}
hyva.getBrowserStorage = () => {
const browserStorage = window.localStorage || window.sessionStorage;
if (!browserStorage) {
console.warn('Browser Storage is unavailable');
return false;
}
try {
browserStorage.setItem('storage_test', '1');
browserStorage.removeItem('storage_test');
} catch (error) {
console.warn('Browser Storage is not accessible', error);
return false;
}
return browserStorage;
}
hyva.postForm = (postParams) => {
const form = document.createElement("form");
let data = postParams.data;
if (! postParams.skipUenc && ! data.uenc) {
data.uenc = btoa(window.location.href);
}
form.method = "POST";
form.action = postParams.action;
Object.keys(postParams.data).map(key => {
const field = document.createElement("input");
field.type = 'hidden'
field.value = postParams.data[key];
field.name = key;
form.appendChild(field);
});
const form_key = document.createElement("input");
form_key.type = 'hidden';
form_key.value = hyva.getFormKey();
form_key.name="form_key";
form.appendChild(form_key);
document.body.appendChild(form);
form.submit();
}
hyva.getFormKey = function () {
let formKey = hyva.getCookie('form_key');
if (!formKey) {
formKey = generateRandomString();
hyva.setCookie('form_key', formKey);
}
return formKey;
}
hyva.formatPrice = (value, showSign, options = {}) => {
const groupSeparator = options.groupSeparator;
const decimalSeparator = options.decimalSeparator
delete options.groupSeparator;
delete options.decimalSeparator;
const formatter = new Intl.NumberFormat(
'fr\u002DFR',
Object.assign({
style: 'currency',
currency: 'EUR',
signDisplay: showSign ? 'always' : 'auto'
}, options)
);
return (typeof Intl.NumberFormat.prototype.formatToParts === 'function') ?
formatter.formatToParts(value).map(({type, value}) => {
switch (type) {
case 'currency':
return '\u20AC' || value;
case 'minusSign':
return '- ';
case 'plusSign':
return '+ ';
case 'group':
return groupSeparator !== undefined ? groupSeparator : value;
case 'decimal':
return decimalSeparator !== undefined ? decimalSeparator : value;
default :
return value;
}
}).reduce((string, part) => string + part) :
formatter.format(value);
}
const formatStr = function (str, nStart) {
const args = Array.from(arguments).slice(2);
return str.replace(/(%+)([0-9]+)/g, (m, p, n) => {
const idx = parseInt(n) - nStart;
if (args[idx] === null || args[idx] === void 0) {
return m;
}
return p.length % 2
? p.slice(0, -1).replace('%%', '%') + args[idx]
: p.replace('%%', '%') + n;
})
}
hyva.str = function (string) {
const args = Array.from(arguments);
args.splice(1, 0, 1);
return formatStr.apply(undefined, args);
}
hyva.strf = function () {
const args = Array.from(arguments);
args.splice(1, 0, 0);
return formatStr.apply(undefined, args);
}
/**
* Take a html string as `content` parameter and
* extract an element from the DOM to replace in
* the current page under the same selector,
* defined by `targetSelector`
*/
hyva.replaceDomElement = (targetSelector, content) => {
// Parse the content and extract the DOM node using the `targetSelector`
const parser = new DOMParser();
const doc = parser.parseFromString(content, 'text/html');
const contentNode = doc.querySelector(targetSelector);
// Bail if content or target can't be found
if (!contentNode || !document.querySelector(targetSelector)) {
return;
}
hyva.activateScripts(contentNode);
// Replace the old DOM node with the new content
document.querySelector(targetSelector).replaceWith(contentNode);
// Reload customerSectionData and display cookie-messages if present
window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
hyva.initMessages();
}
hyva.removeScripts = (contentNode) => {
const scripts = contentNode.getElementsByTagName('script');
for (let i = 0; i < scripts.length; i++) {
scripts[i].parentNode.removeChild(scripts[i]);
}
const templates = contentNode.getElementsByTagName('template');
for (let i = 0; i < templates.length; i++) {
const container = document.createElement('div');
container.innerHTML = templates[i].innerHTML;
hyva.removeScripts(container);
templates[i].innerHTML = container.innerHTML;
}
}
hyva.activateScripts = (contentNode) => {
// Create new array from HTMLCollection to avoid mutation of collection while manipulating the DOM.
const scripts = Array.from(contentNode.getElementsByTagName('script'));
// Iterate over all script tags to duplicate+inject each into the head
for (const original of scripts) {
const script = document.createElement('script');
original.type && (script.type = original.type);
script.innerHTML = original.innerHTML;
// Remove the original (non-executing) script from the contentNode
original.parentNode.removeChild(original)
// Add script to head
document.head.appendChild(script);
}
return contentNode;
}
const replace = {['+']: '-', ['/']: '_', ['=']: ','};
hyva.getUenc = () => btoa(window.location.href).replace(/[+/=]/g, match => replace[match]);
let currentTrap;
const focusableElements = (rootElement) => {
const selector = 'button, [href], input, select, textarea, details, [tabindex]:not([tabindex="-1"]';
return Array.from(rootElement.querySelectorAll(selector))
.filter(el => {
return el.style.display !== 'none'
&& !el.disabled
&& el.tabIndex !== -1
&& (el.offsetWidth || el.offsetHeight || el.getClientRects().length)
})
}
const focusTrap = (e) => {
const isTabPressed = e.key === 'Tab' || e.keyCode === 9;
if (!isTabPressed) return;
const focusable = focusableElements(currentTrap)
const firstFocusableElement = focusable[0]
const lastFocusableElement = focusable[focusable.length - 1]
e.shiftKey
? document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), e.preventDefault())
: document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), e.preventDefault())
};
hyva.releaseFocus = (rootElement) => {
if (currentTrap && (!rootElement || rootElement === currentTrap)) {
currentTrap.removeEventListener('keydown', focusTrap)
currentTrap = null
}
}
hyva.trapFocus = (rootElement) => {
if (!rootElement) return;
hyva.releaseFocus()
currentTrap = rootElement
rootElement.addEventListener('keydown', focusTrap)
const firstElement = focusableElements(rootElement)[0]
firstElement && firstElement.focus()
}
hyva.safeParseNumber = (rawValue) => {
const number = rawValue ? parseFloat(rawValue) : null;
return Array.isArray(number) || isNaN(number) ? rawValue : number;
}
const toCamelCase = s => s.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
hyva.createBooleanObject = (name, value = false, additionalMethods = {}) => {
const camelCase = toCamelCase(name);
const key = '__hyva_bool_' + name
return new Proxy(Object.assign(
additionalMethods,
{
[key]: !!value,
[name]() {return !!this[key]},
['!' + name]() {return !this[key]}, // @deprecated This does not work with non-CSP Alpine
['not' + camelCase]() {return !this[key]},
['toggle' + camelCase]() {this[key] = !this[key]},
[`set${camelCase}True`]() {this[key] = true},
[`set${camelCase}False`]() {this[key] = false},
}
), {
set(target, prop, value) {
return prop === name
? (target[key] = !!value)
: Reflect.set(...arguments);
}
})
}
hyva.alpineInitialized = (fn) => window.addEventListener('alpine:initialized', fn, {once: true})
window.addEventListener('alpine:init', () => Alpine.data('{}', () => ({})), {once: true});
window.addEventListener('user-allowed-save-cookie', () => internalCookie.saveTempStorageCookies())
}( window.hyva = window.hyva || {} ));
</script>
<script>
if (!window.IntersectionObserver) {
window.IntersectionObserver = function (callback) {
this.observe = el => el && callback(this.takeRecords());
this.takeRecords = () => [{isIntersecting: true, intersectionRatio: 1}];
this.disconnect = () => {};
this.unobserve = () => {};
}
}
</script>
<meta property="og:type" content="product"/>
<meta property="og:title" content="Bombe lacrymogène gel poivre Umarex P2P PDG-60"/>
<meta property="og:description" content="Bombe lacrymogène gel poivre Umarex P2P PDG-60"/>
<meta property="og:url" content="https://www.arprotech.com/bombe-lacrymogene-gel-poivre-umarex-p2p-pdg-60.html"/>
<meta property="og:image" content="https://www.arprotech.com/media/catalog/product/cache/5466586929ff96f138659d9a3defd4cf/2/_/2_2065.jpg"/>
<meta property="og:site_name" content="ARprotech"/>
<meta property="product:price:amount" content="7.95"/>
<meta property="product:price:currency" content="EUR"/>
<script>
(function () {
let amSwiperProcessed = false;
window.addEventListener('load-amswiper', () => {
if (amSwiperProcessed) {
window?.Swiper && window.dispatchEvent(new CustomEvent('amswiper-loaded', {}));
return;
}
const script = document.createElement('script');
script.src = 'https://www.arprotech.com/static/frontend/Arprotech/default/fr_FR/Amasty_LibSwiperJs/js/vendor/swiper/swiper.min.js';
script.async = true;
document.body.appendChild(script);
amSwiperProcessed = true;
script.onload = () => {
window.dispatchEvent(new CustomEvent('amswiper-loaded', {}));
}
const stylesHref = 'https://www.arprotech.com/static/frontend/Arprotech/default/fr_FR/Amasty_LibSwiperJs/vendor/swiper/swiper.min.css';
if (document.querySelector(`link[href="${stylesHref}"]`)) {
return;
}
const styles = document.createElement('link');
styles.rel = 'stylesheet';
styles.type = 'text/css';
styles.href = stylesHref;
document.head.appendChild(styles);
});
}());
</script>
<script>
window.addEventListener('init-external-scripts', () => {
if (window._amPurifyLoaded) {
return;
}
// Load Purify script asynchronously
const script = document.createElement('script');
script.src = 'https://www.arprotech.com/static/frontend/Arprotech/default/fr_FR/Amasty_XsearchHyvaCompatibility/js/purify.min.js';
script.async = true;
document.body.appendChild(script);
window._amPurifyLoaded = true;
script.onload = () => {
// Dispatch custom event when Swiper is loaded
window.dispatchEvent(new CustomEvent('amPurifyLoaded', {}));
}
}, { once: true, passive: true });
</script>
</head>
<body id="html-body" class="catalog-product-view product-bombe-lacrymogene-gel-poivre-umarex-p2p-pdg-60 categorypath-arme-de-defense-aerosol category-bombe-lacrymogene page-layout-1column">
<input name="form_key" type="hidden" value="eTB4IhRhBQzWlDue" />
<noscript>
<section class="message global noscript border-b-2 border-blue-500 bg-blue-50 shadow-none m-0 px-0 rounded-none font-normal">
<div class="container text-center">
<p>
<strong>Javascript est désactivé dans votre navigateur.</strong>
<span>
Pour une expérience optimale sur notre site, veuillez autoriser Javascript sur votre navigateur. </span>
</p>
</div>
</section>
</noscript>
<script>
document.body.addEventListener('touchstart', () => {}, {passive: true})
</script>
<script>
function initCookieBanner() {
const isUserAllowedSaveCookieName = 'user_allowed_save_cookie'
const currentWebsiteId = 1;
const isAllowedSaveCookie = () => {
const allowedCookies = hyva.getCookie(isUserAllowedSaveCookieName)
const allowedCookieWebsites = allowedCookies
? JSON.parse(unescape(allowedCookies))
: []
return allowedCookieWebsites[currentWebsiteId] !== undefined
? !!allowedCookieWebsites[currentWebsiteId]
: false
}
return {
showCookieBanner: false,
cookieName: isUserAllowedSaveCookieName,
cookieValue: '{"1":1}',
cookieLifetime: '31536000',
noCookiesUrl: 'https\u003A\u002F\u002Fwww.arprotech.com\u002Fcookie\u002Findex\u002FnoCookies\u002F',
checkAcceptCookies() {
this.showCookieBanner = !isAllowedSaveCookie()
},
setAcceptCookies() {
const cookieExpires = this.cookieLifetime / 60 / 60 / 24
hyva.setCookie(this.cookieName, this.cookieValue, cookieExpires)
if (!hyva.getCookie(this.cookieName)) {
window.location.href = this.noCookiesUrl
} else {
window.dispatchEvent(new CustomEvent('user-allowed-save-cookie'))
}
}
}
}
</script>
<section
id="notice-cookie-block"
aria-label="Nous utilisons des cookies pour améliorer votre expérience utilisateur."
x-data="initCookieBanner();"
x-defer="intersect"
@private-content-loaded.window="checkAcceptCookies()"
>
<template x-if="showCookieBanner">
<div
role="dialog"
aria-modal="true"
class="z-30 fixed bottom-0 w-full bg-yellow-200 p-3"
>
<div class="container flex flex-col gap-4 lg:flex-row lg:items-center">
<p class="font-bold text-gray-800 flex items-center justify-center gap-2 lg:flex-1 lg:justify-start">
<span>
Nous utilisons des cookies pour améliorer votre expérience utilisateur. </span>
<a
href="https://www.arprotech.com/privacy-policy-cookie-restriction-mode/"
aria-label="Read our policy"
class="inline-block text-gray-500 hover:text-gray-800"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="2" stroke="currentColor" class="stroke-current" width="24" height="24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</a>
</p>
<button
type="button"
id="btn-cookie-allow"
class="btn btn-primary"
@click="setAcceptCookies(); showCookieBanner = false"
>
Autoriser </button>
</div>
</div>
</template>
</section>
<div class="widget block block-static-block">
</div>
<div class="page messages"><script>
window.defaultSuccessMessageTimeout = 4000;
function initMessages() {
"use strict";
return {
messages: window.mageMessages || [],
isEmpty() {
return this.messages.reduce(
function (isEmpty, message) {
return isEmpty && message === undefined
}, true
)
},
removeMessage(messageIndex) {
const message = this.messages[messageIndex];
message.show = false;
setTimeout(() => {
this.messages[messageIndex] = undefined;
}, 500);
},
addMessages(messages, hideAfter) {
messages.map((message) => {
message.show = false;
this.messages = this.messages.concat(message);
if (hideAfter === undefined && message.type === 'success' && window.defaultSuccessMessageTimeout) {
hideAfter = window.defaultSuccessMessageTimeout;
}
if (hideAfter) {
this.setHideTimeOut(this.messages.length -1, hideAfter);
}
});
},
setHideTimeOut(messageIndex, hideAfter) {
setTimeout((messageIndex) => {
this.removeMessage(messageIndex);
}, hideAfter, messageIndex);
},
eventListeners: {
['@messages-loaded.window'](event) {
this.addMessages(event.detail.messages, event.detail.hideAfter)
},
['@private-content-loaded.window'](event) {
const data = event.detail.data;
if (
data.messages &&
data.messages.messages &&
data.messages.messages.length
) {
this.addMessages(data.messages.messages);
}
},
['@clear-messages.window']() {
this.messages = [];
}
}
}
}
</script>
<section id="messages"
x-data="initMessages()"
x-bind="eventListeners"
aria-live="assertive"
role="alert"
>
<template x-if="!isEmpty()">
<div class="w-full">
<div class="messages">
<template x-for="(message, index) in messages" :key="index">
<template x-if="message">
<div
x-init="$nextTick(() => { message.show = true })"
x-show="message.show"
class="message"
:class="message.type"
:ui-id="'message-' + message.type"
x-transition:enter="enter"
x-transition:enter-start="enter-start"
x-transition:enter-end="enter-end"
x-transition:leave="leave"
x-transition:leave-start="leave-start"
x-transition:leave-end="leave-end"
>
<span x-html="message.text"></span>
<button
type="button"
class=""
aria-label="Close message"
@click.prevent="removeMessage(index)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
</div>
</template>
</template>
</div>
</div>
</template>
</section>
</div><div class="page-wrapper"><header class="page-header amsearch-full-width"><div class="container">
<div class="am-hyva-top-links-container pt-2 pb-2 flex flex-row items-end justify-end"
role="navigation"
aria-label="Top Navigation Links"
>
<div class="pl-3">
</div>
</div>
</div>
<a class="action skip sr-only focus:not-sr-only focus:absolute focus:z-40 focus:bg-white contentarea"
href="#contentarea">
<span>
Aller au contenu </span>
</a>
<script>
function initHeader() {
return {
searchOpen: false,
cart: {},
isCartOpen: false,
isSearchOpen: false,
isMobile: true,
init() {
this.$watch('isMobile', () => this.updateSearchBasedOnDevice())
this.checkIsSearchMobile()
this.checkHeaderSize()
this.$refs.searchContainerDesktop.classList.remove('hidden')
},
checkHeaderSize() {
const pageHeader = document.querySelector('.page-header amsearch-full-width')
if (!pageHeader) return
document.documentElement.style.setProperty('--page-header amsearch-full-width-height', `${pageHeader.offsetHeight}px`)
},
getData(data) {
if (data.cart) {
this.cart = data.cart
}
},
isCartEmpty() {
return !this.cart.summary_count
},
checkIsSearchMobile() {
const mobileElement = this.$refs.searchContainerMobile
this.isMobile = mobileElement
? getComputedStyle(mobileElement).display !== 'none'
: window.matchMedia('(max-width: 1023px)').matches // Fallback to `md` breakpoint
},
updateSearchBasedOnDevice() {
// const target = this.isMobile ? this.$refs.searchContainerMobile : this.$refs.searchContainerDesktop
// target.appendChild(this.$refs.searchForm)
},
onSearchBackdropClickHelper(event, target) {
if (this.isSearchOpen) return true
const rect = this.$refs.searchForm.getBoundingClientRect()
const isInDialog =
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width
return isInDialog
},
toggleSearch() {
this.isSearchOpen = !this.isSearchOpen
},
toggleCart(event) {
if (event.detail && event.detail.isOpen !== undefined) {
this.isCartOpen = event.detail.isOpen
if (!this.isCartOpen && this.$refs && this.$refs.cartButton) {
this.$refs.cartButton.focus()
}
} else {
this.isCartOpen = true
}
},
updateScrollbarWidth() {
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth
document.body.style.setProperty('--scrollbar-width', `${scrollbarWidth}px`)
},
eventListeners: {
// ['@click'](event) {
// if (this.onSearchBackdropClickHelper(event)) return
// this.toggleSearch()
// },
['@private-content-loaded.window'](event) {
this.getData(event.detail.data)
this.updateScrollbarWidth()
},
['@resize.window.debounce']() {
this.checkIsSearchMobile()
this.updateScrollbarWidth()
},
['@visibilitychange.window.debounce']() {
this.checkIsSearchMobile()
}
}
}
}
function initCompareHeader() {
return {
compareProducts: null,
itemCount: 0,
receiveCompareData(data) {
if (data['compare-products']) {
this.compareProducts = data['compare-products']
this.itemCount = this.compareProducts.count
}
}
}
}
</script>
<div
id="header"
class=""
x-data="initHeader()"
x-bind="eventListeners"
@resize.window.debounce="checkHeaderSize"
>
<div class="container py-7 flex gap-4 items-center">
<a
id="main-logo"
class="inline-block align-middle"
href="https://www.arprotech.com/"
title="Go to Home page"
>
<!-- <img-->
<!-- src="--><!--"-->
<!-- alt="--><!--"-->
<!-- width="--><!--"-->
<!-- height="--><!--"-->
<!-- loading="eager"-->
<!-- fetchpriority="high"-->
<!-- >-->
<svg xmlns="http://www.w3.org/2000/svg" class="hidden md:block" width="283" height="52" fill="none"
viewbox="0 0 283 52">
<title>Armurerie en ligne Arprotech</title>
<path fill="#0F309A"
d="m103.73 31.191-3.425-4.991H92.44v4.991h-4.862V14.175h17.243c.735 0 1.416.13 2.053.4a5.41 5.41 0 0 1 1.664 1.059c.475.442.853.94 1.123 1.512.271.562.411 1.145.411 1.729v2.517a4.04 4.04 0 0 1-.313 1.513 5.848 5.848 0 0 1-.843 1.437c-.346.432-.756.81-1.221 1.112a3.961 3.961 0 0 1-1.404.595l-.184.032 3.565 5.121h-5.931l-.011-.01ZM92.44 21.35h11.322c.465 0 .821-.108 1.059-.324.249-.216.378-.497.378-.843v-.065c0-.291-.129-.55-.378-.767-.248-.216-.605-.324-1.059-.324H92.44v2.323Zm20.041 9.841V14.175h17.243c.735 0 1.416.14 2.042.41a5.32 5.32 0 0 1 1.664 1.124 5.31 5.31 0 0 1 1.124 1.664c.27.627.41 1.318.41 2.042v3.047c0 .713-.14 1.404-.41 2.03a5.235 5.235 0 0 1-2.788 2.8c-.626.27-1.318.41-2.042.41h-12.381v3.478h-4.862v.011Zm4.862-8.34h10.588c.756 0 1.286-.12 1.642-.357.368-.248.54-.756.54-1.49v-.066c0-.702-.172-1.21-.529-1.49-.346-.27-.897-.411-1.664-.411h-10.588v3.824l.011-.01Zm36.183 8.34L150.09 26.2h-7.865v4.991h-4.862V14.175h17.243c.735 0 1.416.13 2.053.4a5.387 5.387 0 0 1 1.664 1.059c.475.442.853.94 1.124 1.512.27.562.41 1.145.41 1.729v2.517a4.04 4.04 0 0 1-.313 1.513 6.18 6.18 0 0 1-.843 1.437c-.346.432-.756.81-1.221 1.112a3.961 3.961 0 0 1-1.404.595l-.184.032 3.565 5.121h-5.931v-.01Zm-11.29-9.842h11.322c.465 0 .821-.108 1.07-.324a1.07 1.07 0 0 0 .378-.843v-.065c0-.291-.13-.55-.378-.767-.249-.216-.605-.324-1.07-.324h-11.322v2.323Zm24.773 9.842a5.214 5.214 0 0 1-3.695-1.534 5.324 5.324 0 0 1-1.123-1.664 5.132 5.132 0 0 1-.411-2.03v-6.57c0-.713.141-1.393.411-2.02a5.204 5.204 0 0 1 1.123-1.664 5.336 5.336 0 0 1 1.664-1.123 5.17 5.17 0 0 1 2.031-.411h12.036c.713 0 1.394.14 2.02.41a5.19 5.19 0 0 1 1.664 1.124 5.31 5.31 0 0 1 1.124 1.664c.27.627.41 1.307.41 2.02v6.57a5.19 5.19 0 0 1-1.534 3.695 5.315 5.315 0 0 1-1.664 1.123c-.626.27-1.307.41-2.02.41h-12.036Zm1.826-12.165c-.605 0-1.123.216-1.556.637a2.12 2.12 0 0 0-.637 1.556v2.928c0 .605.216 1.124.637 1.556.422.421.94.637 1.556.637h8.395c.605 0 1.124-.216 1.556-.637a2.12 2.12 0 0 0 .637-1.556V21.22c0-.605-.216-1.123-.637-1.556a2.12 2.12 0 0 0-1.556-.637h-8.395ZM195.1 31.191V19.037h-8.903v-4.862h22.775v4.862h-9.01V31.19H195.1Zm16.293 0V14.175h21.456v4.862h-16.605v2.55h14.671v2.193h-14.671v2.55h16.605v4.861h-21.456Zm28.868 0c-.713 0-1.405-.14-2.031-.41a5.25 5.25 0 0 1-1.675-1.124 5.25 5.25 0 0 1-1.123-1.674 5.153 5.153 0 0 1-.411-2.032v-6.525c0-.735.14-1.426.411-2.042a5.25 5.25 0 0 1 4.829-3.198h12.544c.81 0 1.555.173 2.225.53.67.345 1.253.81 1.729 1.371.475.562.853 1.2 1.123 1.913.26.702.4 1.415.4 2.117v.357h-4.862c-.032-.324-.194-.638-.475-.919-.324-.324-.81-.497-1.469-.497h-9.4c-.605 0-1.124.216-1.556.638a2.12 2.12 0 0 0-.637 1.556v2.928c0 .605.216 1.123.637 1.555.422.422.94.638 1.556.638h9.4c.27 0 .529-.054.767-.152.237-.097.443-.226.605-.378.162-.15.302-.335.41-.53a1.3 1.3 0 0 0 .152-.464h4.861v.357a6.13 6.13 0 0 1-.399 2.182 6.471 6.471 0 0 1-1.124 1.945 5.478 5.478 0 0 1-1.718 1.383 4.764 4.764 0 0 1-2.225.53h-12.544v-.055Zm37.134 0v-6.017h-11.852v6.017h-4.862V14.175h4.862v6.137h11.852v-6.137h4.861V31.19h-4.861Zm-197.38 0v-3.543h-11.15L67.32 31.19h-5.218l7.4-17.016h15.32V31.19h-4.829.022Zm-9.065-8.34h9.065v-3.825h-7.4l-1.665 3.825Z"
class="name"/>
<path fill="#0F309A"
d="m33.768 32.872-4.776-8.665h-3.749v8.665H21.43v-8.665h-6.235l.325-3.814h5.91v-6.58h-8.536l-1.167 19.06H8L9.405 10h15.828v10.393h5.92l6.98 12.48h-4.365Zm2.88-8.272-2.032-3.813v-4.549a2.043 2.043 0 0 0-2.03-2.03h-4.344v-3.815h4.343a5.849 5.849 0 0 1 5.845 5.845v8.363h-1.782Z"
class="ar"/>
<path fill="#0F309A" d="M25.292 7.358V3.814h9.724V0h-23.25v3.814h9.723v3.544h3.814-.01Z" class="t accent"/>
<path fill="#0F309A"
d="m23.39 52 23.392-15.093V0h-8.72v3.814h4.906v31.008L25.292 46.23v-9.919h-3.814v9.919L3.814 34.82V3.814h4.905V0H0v36.907L23.39 52Z"
class="shield accent"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="md:hidden" width="46" height="52" fill="none"
viewbox="0 0 46 52">
<path fill="#0F309A"
d="m32.94 32.872-4.775-8.665h-3.749v8.665h-3.814v-8.665h-6.234l.325-3.814h5.91v-6.58h-8.536L10.9 32.874H7.173L8.577 10h15.828v10.393h5.921l6.98 12.48H32.94Zm2.88-8.272-2.03-3.813V16.24a2.043 2.043 0 0 0-2.032-2.032h-4.343v-3.813h4.343a5.849 5.849 0 0 1 5.845 5.845v8.36H35.82Z"
class="ar"/>
<path fill="#0F309A" d="M24.465 7.358V3.814h9.724V0h-23.25v3.814h9.723v3.544h3.814-.01Z" class="t"/>
<path fill="#0F309A"
d="m22.564 52 23.39-15.093V0h-8.718v3.814h4.905v31.008L24.465 46.23v-9.919h-3.814v9.919L2.987 34.82V3.814h4.905V0h-8.72v36.907L22.565 52Z"
class="shield"/>
</svg>
</a>
<div
x-ref="searchContainerDesktop"
x-show="isSearchOpen"
class="hidden min-h-a11y px-6 flex-1 ease-bumpy"
:class="{ 'active': isSearchOpen, }"
x-transition:enter="duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end=""
x-transition:leave="duration-200"
x-transition:leave-start=""
x-transition:leave-end="opacity-0"
>
<div
x-ref="searchForm"
class=""
@click.outside="isSearchOpen = false"
>
<script>
'use strict';
function amXsearchProductsComponent() {
const postFormRequest = (postUrl, id) => {
const req = fetch(BASE_URL + postUrl, {
"headers": {
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
},
"body": "form_key=" + hyva.getFormKey() + "&product=" + id + "&uenc=" + hyva.getUenc(),
"method": "POST",
"mode": "cors",
"credentials": "include"
});
req.finally(() => this.isLoading = false);
return req;
}
return {
mutationAddToCartQuery: "mutation addProductsToCart($cartId: String!, $cartItems: [CartItemInput!]!) {addProductsToCart(\n cartId: $cartId,\n cartItems: $cartItems\n ) {\n cart {\n items {\n product {\n name\n }\n }\n total_quantity\n }\n user_errors {\n code\n message\n }\n }}",
mutationAddToWishlistQuery: "mutation addProductsToWishlist($wishlistId: ID!, $wishlistItems: [WishlistItemInput!]!) {addProductsToWishlist(\n wishlistId: $wishlistId,\n wishlistItems: $wishlistItems\n ) {\n wishlist {\n items {\n id\n product {\n name\n }\n }\n items_count\n }\n user_errors {\n code\n message\n }\n }}",
mutationAddToCompareListQuery: "mutation addProductsToCompareList($uid: ID!, $products: [ID!]!) {addProductsToCompareList(input: {\n uid: $uid,\n products: $products\n }) {\n items {\n product {\n name\n }\n }\n item_count\n }}",
sliderInitialization(event) {
this[event.detail.key] = event.detail.value;
},
getResultProductsCount() {
const suggestions = this.sections.products;
const totalCount = suggestions?.total_count ?? 0;
const itemsCount = suggestions?.items?.length ?? 0;
return totalCount > 0 ? totalCount - itemsCount : 0;
},
processProductName(value) {
if (value.items) {
value.items = value.items.map(item => {
item.name = this.addHighlight(item, 'name');
item.sku = this.addHighlight(item, 'sku');
item.name = this.truncateWithDots(item.name, this.productNameMaxLength, true);
return item;
});
}
return value;
},
addHighlight(product, key = 'name') {
const name = product[key];
const { latestQuery } = this;
const queries = latestQuery.toLowerCase().split(" ");
let highlightedName = name;
for (const query of queries) {
const safeQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const regex = new RegExp(`(?!<[^>]*)(${safeQuery})(?![^<]*>)`, "gi");
highlightedName = highlightedName.replace(regex, match => `<span class="amsearch-highlight">${match}</span>`);
}
return highlightedName;
},
truncateWithDots(str, maxLength, returnOriginal = false) {
if (maxLength === '' || maxLength < 1) {
return returnOriginal ? str : "";
}
let output = [];
let tagBuffer = [];
let count = 0;
let inTag = false;
for (const char of str) {
if (char === "<") {
inTag = true;
}
if (inTag) {
tagBuffer.push(char);
} else {
count++;
}
if (char === ">") {
inTag = false;
output.push(tagBuffer.join(""));
tagBuffer = [];
} else if (!inTag) {
output.push(char);
}
if (count >= maxLength) {
break;
}
}
if (count >= maxLength) {
output.push("...");
}
// Close any unclosed tags
while (tagBuffer.length > 0) {
const closingTagPos = str.indexOf(">", str.indexOf(tagBuffer.join("")) + tagBuffer.length);
if (closingTagPos !== -1) {
output.push(str.slice(str.indexOf(tagBuffer.join("")) + tagBuffer.length, closingTagPos + 1));
tagBuffer = [];
} else {
break;
}
}
return output.join("");
},
getProductUrl(product) {
return window.BASE_URL + product.url_key + (product.url_suffix || '');
},
getProductImageUrl(product) {
const imageUrl = product.small_image.url;
console.log(product)
let mediaURL = this.config.customMediaUrl || imageUrl;
if (mediaURL.includes('/media') && imageUrl.startsWith('media/')) {
mediaURL = mediaURL.replace('/media', '');
}
return (imageUrl.includes('://') ? '' : mediaURL) + imageUrl;
},
/**
* @param Product {id: string}
*/
addToWishlist({id}) {
postFormRequest('wishlist/index/add/', id).then(response => {
if (response.redirected) {
window.location.href = response.url;
} else if (response.ok) {
return response.json();
} else {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "warning",
text: "Could not add item to wishlist."
}], 5000
);
}
}).then(response => {
if (!response) { return }
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: response.success ? "success" : "error",
text: response.success
? "Produit a été ajouté à votre liste d'achats." : response.error_message
}], 5000
);
window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
}).catch(function (error) {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "error",
text: error
}], 5000
);
});
},
/**
* @param Product {id: string}
*/
addToCompare({id}) {
postFormRequest('catalog/product_compare/add', id)
.then(response => {
if (response.redirected) {
window.location.href = response.url;
}
this.isLoading = false;
}).catch(error => {
this.isLoading = false;
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "error",
text: error
}], 5000
);
});
},
/**
*
* @param product
*/
getRating(product) {
const { rating_summary } = product;
product.ratingData = {
ratingSteps: 5,
starsFilled: Math.floor(+rating_summary / 100 * 5),
starFragment: rating_summary / 100 * 5 % 1,
starsEmpty: Math.floor(5 - (+rating_summary / 100 * 5)),
yellowHex: '#f6e05e',
greyHex: '#cbd5e0'
};
return product;
},
/**
* Compatibility function for Amasty_AjaxCart module
*
* @param id
* @param $event
*/
addToCart({id}, $event) {
this.isLoading = true;
const action = 'https://www.arprotech.com/checkout/cart/add/';
const data = { product: id, qty: 1 };
hyva.postForm({ action, data });
}
}
}
</script>
<script>
'use strict';
(()=> {
const browserCache = {
set(key, value) {
const now = new Date();
const item = {
value: value,
expiry: now.getTime() + 5 * 60 * 1000, // 5 minutes from now
};
localStorage.setItem(key, JSON.stringify(item));
},
get(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) {
return null;
}
const item = JSON.parse(itemStr);
const now = new Date();
if (now.getTime() > item.expiry) {
localStorage.removeItem(key);
return null;
}
return item.value;
}
};
window._amXSearchConfigFetcher = null;
window.amXsearchAutocompleteComponent = () => {
const INITIAL_QUERY_CACHE_KEY = 'x.InitialQuery';
const CONFIG_QUERY_CACHE_KEY = 'x.ConfigQuery';
const PREV_QUERY_CACHE_KEY = 'x.PrevQuery';
// TODO: Possible it will needs to change after the configurations are added to Admin
const HEADER_TYPE = 'c';
const cache = {};
const dataSections = {
products: false,
category: false,
page: false,
faq: false,
landingPage: false,
browsingHistory: false,
popularSearches: false,
bestsellers: false,
recentSearches: false,
recentlyViewed: false,
brand: false,
blog: false
};
return {
isLoading: false,
searchInitialized: false,
latestQuery: '',
productNameMaxLength: 50,
resultPageUrl: 'https://www.arprotech.com/catalogsearch/result/?q=',
minSearchLength: 3,
maxSearchLength: 128,
isDefaultSearchInput: false,
isFullWidthSearch: true,
searchPopupWidth: 450,
showOverlay: false,
config: {},
slider: {
bestsellers: false,
recentlyViewed: false
},
isHorizontalView: true,
noResultsFound: false,
errorMessage: null,
// sections
sections: Object.create(dataSections),
searchQuery: '',
isHyvaUiHeader() {
return HEADER_TYPE.length && HEADER_TYPE !== 'default';
},
checkHyvaUiHeaderVariant(needle) {
return this.isHyvaUiHeader() && needle === HEADER_TYPE;
},
dynamicLayout($el) {
const matchMedia = window.matchMedia('(max-width: 768px)');
const isHorizontalViewPopupWidth = this.searchPopupWidth < 700 && !this.isDefaultSearchInput && !this.isFullWidthSearch;
// Fix cms preview
this.normalizeBaseUrl()
this.isHorizontalView = !matchMedia.matches ? isHorizontalViewPopupWidth : true;
matchMedia.addEventListener('change', event => {
this.isHorizontalView = !matchMedia.matches ? isHorizontalViewPopupWidth : true;
})
if (!window._amXSearchConfigFetcher) {
window._amXSearchConfigFetcher = new Promise(async resolve => {
const cachedData = browserCache.get(CONFIG_QUERY_CACHE_KEY);
if (cachedData) {
return resolve(cachedData);
}
const query = `query {config: storeConfig {
isProductReviewsBlockEnabled: amasty_xsearch_product_reviews
isProductAddToCartBlockEnabled: amasty_xsearch_product_add_to_cart
isRedirectToSingleProductEnabled: amasty_xsearch_product_redirect_single_product
isFullScreenMode: amasty_xsearch_general_full_screen
isGridView: amasty_xsearch_product_popup_display
isShowSku: amasty_xsearch_product_show_sku
shortDescriptionLength: amasty_xsearch_product_desc_length
customMediaUrl: secure_base_media_url
amasty_xsearch_products_title: amasty_xsearch_product_title
amasty_xsearch_popularSearches_title: amasty_xsearch_popular_searches_title
amasty_xsearch_browsingHistory_title: amasty_xsearch_browsing_history_title
amasty_xsearch_recentSearches_title: amasty_xsearch_recent_searches_title
amasty_xsearch_recentlyViewed_title: amasty_xsearch_recently_viewed_title
amasty_xsearch_landingPage_title: amasty_xsearch_landing_page_title
amasty_xsearch_bestsellers_position
amasty_xsearch_faq_title
amasty_xsearch_brand_title
amasty_xsearch_blog_title
amasty_xsearch_category_title
amasty_xsearch_bestsellers_title
amasty_xsearch_page_title
amasty_xsearch_popularSearches_first_click: amasty_xsearch_popular_searches_first_click
amasty_xsearch_browsingHistory_first_click: amasty_xsearch_browsing_history_first_click
amasty_xsearch_recentSearches_first_click: amasty_xsearch_recent_searches_first_click
amasty_xsearch_layout_enabled
amasty_xsearch_layout_border
amasty_xsearch_layout_hover
amasty_xsearch_layout_highlight
amasty_xsearch_layout_background
amasty_xsearch_layout_text
amasty_xsearch_layout_hover_text
amasty_xsearch_layout_search_button
amasty_xsearch_layout_search_button_text
}}`;
const response = await this.fetch(query, {}, CONFIG_QUERY_CACHE_KEY, false);
if (response.errors && response.errors.length > 0) {
console.error(response.errors);
}
browserCache.set(CONFIG_QUERY_CACHE_KEY, response);
resolve(response);
});
}
_amXSearchConfigFetcher.then(response => {
if (!response?.data?.config) {
return;
}
this.config = response.data.config;
this.processCustomLayoutStyles($el);
});
if (typeof this.searchOpen !== "undefined") {
this.$watch('searchOpen', val => {
if (!val) {
return;
}
requestAnimationFrame(() => {
const searchInput = document.querySelector('#search');
searchInput && searchInput.focus();
});
});
}
if (typeof this.showOverlay !== "undefined") {
this.$watch('showOverlay', val => {
if (!val) {
return;
}
this.applyHyvaUiHeaderConfig()
});
}
this.applyHeaderTypeToContainers();
},
isSidebarSectionsDisabled() {
if (!this.isHorizontalView) {
return !Object.entries(this.sections).some(([key, value]) =>
key !== 'products' && key !== 'bestsellers' && key !== 'recentlyViewed' && value.total_count > 0
);
}
},
showSideBar() {
const recentlyViewed = this.sections?.recentlyViewed;
return this.latestQuery.length >= 3
|| (recentlyViewed && recentlyViewed?.items?.length);
},
showOnFirstClick(blockName) {
const sectionsToCheck = [
'popularSearches',
'browsingHistory',
'recentSearches'
];
if (!sectionsToCheck.includes(blockName)) {
return false;
}
return this.latestQuery.length < this.minSearchLength
&& this.config[`amasty_xsearch_${blockName}_first_click`]
&& this.sections[blockName]?.items?.length;
},
processCustomLayoutStyles() {
const conf = key => this.config[`amasty_xsearch_layout_${key}`];
if (!conf("enabled")) {
return "";
}
const styles = [
"border",
"hover",
"highlight",
"background",
"text",
"hover_text",
'search_button',
'search_button_text'
];
const cachedConf = styles.reduce((acc, key) => {
acc[key] = conf(key);
return acc;
}, {});
const getDarken = (color, amount) => {
const hex = parseInt(color.slice(1), 16);
const r = Math.min(255, Math.max(0, ((hex >> 16) & 0xff) + amount));
const g = Math.min(255, Math.max(0, ((hex >> 8) & 0xff) + amount));
const b = Math.min(255, Math.max(0, (hex & 0xff) + amount));
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, "0")}`;
};
const prefix = "--amsearch-color-";
styles.forEach((key) => {
const color = cachedConf[key];
document.body.style.setProperty(prefix + key, `#${color}`);
document.body.style.setProperty(`${prefix + key}-focus`, getDarken(`#${color}`, -12));
document.body.style.setProperty(`${prefix + key}-hover`, getDarken(`#${color}`, -16));
});
},
canShowSection(sectionData) {
return sectionData && sectionData.items && sectionData.items.length > 0;
},
initialSectionLoad() {
const req = this.fetch(`query xSearchQuery {
recentlyViewed: xsearchRecentlyViewed {
items {
small_image {
label
url
}
id
is_salable
short_description {
html
}
name
options_container
rating_summary
reviews_count
sku
url_key
url_suffix
url_rewrites {
url
}
price_range {
minimum_price {
regular_price {
value
currency
}
final_price {
value
currency
}
}
maximum_price {
regular_price {
value
currency
}
final_price {
value
currency
}
}
}
}
}
}`, {}, INITIAL_QUERY_CACHE_KEY);
req.then(response => {
if (response.errors && response.errors.length > 0) {
console.error(response.errors);
}
this.searchInitialized = true;
this.processResponse(response);
});
},
encodeHtml(html) {
const txt = document.createElement('textarea');
txt.textContent = html;
return txt.innerHTML;
},
sanitize(value) {
if (typeof DOMPurify === 'function') {
return DOMPurify.sanitize(value)
} else {
return this.encodeHtml(value)
}
},
doSearch() {
const { searchInput } = this.$refs;
const { latestQuery, minSearchLength } = this;
const inputText = this.sanitize(searchInput.value);
this.searchQuery = inputText;
if (inputText !== latestQuery && cache[PREV_QUERY_CACHE_KEY]) {
delete cache[PREV_QUERY_CACHE_KEY];
}
this.latestQuery = this.sanitize(searchInput.value);
if (inputText.length < minSearchLength) {
this.initialSectionLoad();
return;
}
this.noResultsFound = null;
this.errorMessage = null;
const query = `query xSearchQuery($inputText: String!) {products: xsearchProducts(search: $inputText) {
code
items {
__typename
small_image {
label
url
}
id
is_salable
short_description {
html
}
name
rating_summary
reviews_count
sku
url_key
url_suffix
url_path
canonical_url
url_rewrites {
url
}
price_range {
minimum_price {
regular_price {
value
currency
}
final_price {
value
currency
}
}
maximum_price {
regular_price {
value
currency
}
final_price {
value
currency
}
}
}
}
total_count
}
terms: xsearchRelatedTerms(search: $inputText) {
items {
count
name
}
}
}`;
const req = this.fetch(query, { inputText }, PREV_QUERY_CACHE_KEY);
req.then(response => {
if (response.errors && response.errors.length > 0) {
this.errorMessage = response.errors[0].message;
console.error(this.errorMessage);
response.data.popularSearches = null;
}
this.searchInitialized = true;
this.processResponse(response);
});
},
fetch(query, variables = {}, cacheKey = null, useLoading = true) {
if (cacheKey && cache[cacheKey]) {
return Promise.resolve(cache[cacheKey]);
}
if (useLoading) {
this.isLoading = true;
}
const req = fetch(`${BASE_URL}graphql`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Store': 'default'
},
credentials: 'include',
body: JSON.stringify({query, variables}),
});
return req.then(response => {
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const body = response.json();
if (cacheKey) {
cache[cacheKey] = body;
}
return body;
})
.catch(reason => {
console.error(reason);
})
.finally(() => {
this.isLoading = false;
});
},
checkSearchInput() {
if (this.$refs.searchInput.value === '') {
this.clear();
}
},
redirect() {
this.isLoading = true;
const { searchInput } = this.$refs;
const inputText = this.sanitize(searchInput.value);
const products = this.sections.products;
if (products && products.items.length === 1 && this.config.isRedirectToSingleProductEnabled) {
location.href = this.getProductUrl(products.items[0]);
return;
}
const url = 'https://www.arprotech.com/catalogsearch/result/?q=';
location.href = url + encodeURI(inputText);
},
focusElement(element) {
if (element && element.nodeName === "DIV") {
element.focus();
return true;
}
return false;
},
processResponse(response) {
this.updateSections(response.data);
},
clear() {
const initialQueryCache = cache[INITIAL_QUERY_CACHE_KEY];
if (!initialQueryCache) {
return;
}
initialQueryCache.then(result => {
this.updateSections(result.data ?? {});
});
},
clearSearchQuery() {
this.searchQuery = '';
this.$refs.searchInput.value = '';
this.$refs.searchInput.focus();
},
closeSearch() {
if (this.searchOpen) {
this.searchOpen = false;
}
this.$nextTick(() => {
this.showOverlay = false;
this.searchInitialized = false;
})
if (this.checkHyvaUiHeaderVariant('c')) {
this.$refs.searchContainerDesktop.classList.remove(HEADER_TYPE + '-header-type');
}
},
processItemsWithRating(value) {
if (value?.items) {
value.items = value.items.map(this.getRating);
}
return value;
},
processSection(key, value) {
if (!value) return value;
let processedValue = { ...value };
switch (key) {
case 'recentlyViewed':
case 'bestsellers':
processedValue = this.processItemsWithRating(processedValue);
processedValue.items = (processedValue.items || []).map(item => ({
...item,
isSliderItem: true,
}));
break;
case 'products':
processedValue = this.processItemsWithRating(processedValue);
processedValue = this.processProductName(processedValue);
break;
default:
break;
}
processedValue.title = this.config[`amasty_xsearch_${key}_title`] || 'Default Title';
return processedValue;
},
updateSections(rows) {
if (!this.showOverlay) this.showOverlay = true;
this.isLoading = false;
this.noResultsFound = !rows.products?.total_count && this.latestQuery.length >= this.minSearchLength;
if (!this.noResultsFound) this.errorMessage = null;
Object.keys(rows).forEach(key => {
const data = rows[key];
this.sections[key] = data?.items?.length ? this.processSection(key, data) : { items: [], total_count: 0 };
});
if (this.latestQuery.length >= this.minSearchLength) return;
Object.keys(this.slider).forEach(key => {
const items = rows[key]?.items;
if (items?.length && !this.slider[key]) {
this.slider[key] = this.amXsearchCarouselComponent(key, items.length);
}
});
window.dispatchEvent(new CustomEvent('amxsearch-updated-sections'));
},
getBlockOrder() {
const enabled = [];
const order = (this.config.amasty_xsearch_bestsellers_position === '1')
? ['bestsellers', 'recentlyViewed']
: ['recentlyViewed', 'bestsellers'];
return order.filter(item => enabled.includes(item));
}
}
}
})();
</script>
<script>
'use strict';
/**
* Carousel component for xsearch
*
* @param key
* @param itemCount
* @returns Object
*/
function amXsearchCarouselComponent(key, itemCount) {
return {
itemCount,
pageSize: 4,
active: 0,
slider: null,
pageFillers: 0,
sliderEl: false,
smallWindowItemWidth: false,
init($refs) {
const sliderEl = $refs[`${key}Container`];
if (!sliderEl || itemCount === 0) {
return this;
}
if (sliderEl) {
if (!this.isDefaultSearchInput && !this.isFullWidthSearch) {
if (this.searchPopupWidth <= 900) {
this.smallWindowItemWidth = sliderEl.clientWidth / 3;
}
if (this.searchPopupWidth <= 700) {
this.smallWindowItemWidth = sliderEl.clientWidth / 2;
}
if (this.searchPopupWidth <= 500) {
this.smallWindowItemWidth = sliderEl.clientWidth - 30;
}
}
}
this.sliderEl = sliderEl;
this.recalculate();
},
getSlider() {
return this.sliderEl.querySelector('.carousel-slides');
},
calcPageSize() {
const slider = this.getSlider();
if (!slider) {
return this;
}
const slides = slider.querySelectorAll('.carousel-slide');
if (this.smallWindowItemWidth) {
slides.forEach(slide => {
slide.style.width = `${this.smallWindowItemWidth}px`;
});
}
const firstSlide = slides[0];
this.itemCount = slides.length;
this.pageSize = Math.round(slider.clientWidth / firstSlide.clientWidth);
this.pageFillers = this.pageSize * Math.ceil(this.itemCount / this.pageSize) - this.itemCount;
},
calcActive() {
const slider = this.getSlider();
if (!slider) {
return this;
}
const sliderItems = Math.round(this.itemCount) + Math.round(this.pageFillers);
const calculatedActiveSlide = Math.round(
Math.round(slider.scrollLeft) / (Math.round(slider.scrollWidth) / sliderItems)
);
this.active = Math.round(calculatedActiveSlide / Math.round(this.pageSize)) * Math.round(this.pageSize);
},
prev() {
this.scrollTo(this.active - this.pageSize);
},
next() {
this.scrollTo(this.active + this.pageSize);
},
scrollTo(index) {
const slider = this.getSlider();
if (!slider) {
return this;
}
const slideWidth = slider.scrollWidth / (this.itemCount + this.pageFillers);
slider.scrollLeft = Math.floor(slideWidth) * index;
this.calcActive();
},
isActive(index) {
return index === this.active;
},
recalculate() {
this.calcPageSize();
setTimeout(() => this.calcActive(), 100);
},
onResize() {
this.calcPageSize();
setTimeout(() => this.calcActive(), 100);
}
};
}
</script>
<script>
'use strict';
function amXsearchAutocompleteHyvaUIHeaderCompat() {
const HEADER_TYPE = 'c';
return {
applyHyvaUiHeaderConfig() {
const searchContent = document.getElementById('search-content');
if (this.isFullWidthSearch) {
if (!this.isHorizontalView) {
if (this.checkHyvaUiHeaderVariant('b')) {
searchContent.style = 'max-width:none';
searchContent.parentNode.style = 'padding-right:0; padding-left:0;';
}
if (this.checkHyvaUiHeaderVariant('c')) {
this.$refs.searchContainerDesktop.classList.add(HEADER_TYPE + '-header-type');
this.$refs.searchForm.style = 'padding-right:0; padding-left:0;';
}
}
if (this.checkHyvaUiHeaderVariant('a')) {
searchContent.style = 'max-width: none';
}
}
},
applyHeaderTypeToContainers() {
const searchHeader = document.getElementById('header');
const columnMain = document.querySelector('.column.main');
const searchContent = document.getElementById('search-content');
const headerTypeClass = HEADER_TYPE + '-header-type';
if (searchHeader) {
searchHeader.classList.add(headerTypeClass);
}
if (columnMain) {
columnMain.classList.add(headerTypeClass);
}
if (this.checkHyvaUiHeaderVariant('a')) {
searchContent.className = 'container';
}
},
normalizeBaseUrl() {
let url = new URL(BASE_URL);
BASE_URL = url.origin + url.pathname
}
}
}
</script>
<div :class="{ 'container': !config.isFullScreenMode, 'relative mx-auto text-black z-20 p-0': true, 'max-w-none px-0': isHyvaUiHeader() && isFullWidthSearch, 'px-0': isHyvaUiHeader() && isHorizontalView }"
x-data="Object.assign( {amXsearchCarouselComponent}, amXsearchProductsComponent(), amXsearchAutocompleteComponent(), amXsearchAutocompleteHyvaUIHeaderCompat(), )"
x-init="dynamicLayout($el)">
<div class="flex flex-row justify-center items-center w-full h-full fixed select-none z-50"
style="left: 50%;top: 50%;transform: translateX(-50%) translateY(-50%);background: rgba(255,255,255,0.9);"
x-show="isLoading"
x-cloak
x-transition:enter="ease-out duration-200"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0">
<svg xmlns="http://www.w3.org/2000/svg"
width="54"
height="54"
viewbox="0 0 60 55" xml:space="preserve">
<rect x="20" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="30" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.2s" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="40" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.4s" dur="0.6s" repeatcount="indefinite"/>
</rect>
</svg>
<div class="ml-3 text-style-6">
En cours de chargement... </div>
</div>
<div x-show="showOverlay"
class="fixed inset-0 bg-black bg-opacity-50 z-20 w-full h-full top-0 left-0 right-0 bottom-0"
@click.prevent="closeSearch()"
@keydown.window.escape="closeSearch()"></div>
<div class="form mini-search z-20 relative"
:class="{ 'right-0': !isHyvaUiHeader(), 'md:flex md:justify-center': checkHyvaUiHeaderVariant('c') && !isDefaultSearchInput && !isFullWidthSearch }"
>
<form id="search_mini_form" @submit.prevent="redirect()"
action="https://www.arprotech.com/catalogsearch/result/?q="
:class="{ 'w-full absolute right-0': checkHyvaUiHeaderVariant('a') && !isDefaultSearchInput && !isFullWidthSearch, 'justify-end': !checkHyvaUiHeaderVariant('c') }"
class="flex" method="GET">
<label class="hidden" for="search" data-role="mini-search-label">
<span>Rechercher</span>
</label>
<div class="w-full flex align-center justify-center"
:style="`max-width: ${!isDefaultSearchInput && !isFullWidthSearch ? searchPopupWidth + 'px' : '100%'}`">
<input id="search"
x-ref="searchInput"
maxlength="128"
form="search_mini_form"
type="search"
name="q"
value=""
autocomplete="off"
placeholder="Rechercher dans tout le magasin..."
class="p-2 leading-normal transition appearance-none relative z-20 focus:outline-none flex-am-search-sidebar"
:class="{ 'rounded-tl': isHyvaUiHeader(), 'rounded-tr': !'1' && isHyvaUiHeader() }"
:style="`width: ${checkHyvaUiHeaderVariant('c') && !isDefaultSearchInput && !isFullWidthSearch ? searchPopupWidth + 'px' : '100%'}`"
@focus="doSearch()"
@search="checkSearchInput()"
@input.debounce.500="doSearch()"
@keydown.arrow-down.prevent="focusElement($el.querySelector('[tabindex]'))"/>
<button type="submit" title="Rechercher"
class="am-custom-search-button h-full action search w-auto btn btn-primary justify-center button--search"
x-bind:disabled="isLoading || latestQuery.length < minSearchLength"
:class="{ 'opacity-50': isLoading || latestQuery.length < minSearchLength, 'am-custom-search-button': false, '': isHyvaUiHeader() }"
aria-label="Search">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="21" fill="none"
viewbox="0 0 20 21">
<circle cx="7.5" cy="7.5" r="6.5" stroke="currentColor" stroke-width="2"></circle>
<path fill="currentColor"
d="m12.5 11.086 6.47 6.47v2.829L11.087 12.5l1.414-1.414Z"></path>
</svg>
</button>
</div>
</form>
<template x-if="searchInitialized">
<div
class="w-full -right-position -bottom-position top-15 bg-white shadow-lg has-[.item.cart]:border-t border-black/20 max-h-screen-75 overflow-auto text-sm amsearch-container"
:class="{ '': isHyvaUiHeader(), 'right-0': !checkHyvaUiHeaderVariant('c'), 'top-12': checkHyvaUiHeaderVariant('c') && !isHorizontalView, 'top-14': checkHyvaUiHeaderVariant('a') && isHorizontalView }"
tabindex="-1"
x-cloak
:style="`${!isDefaultSearchInput && !isFullWidthSearch ? 'max-width:' + searchPopupWidth + 'px' : ''}; ${!isHorizontalView && checkHyvaUiHeaderVariant('a') ? 'top: 44px; margin-top: 1px;' : ''}`"
x-show="!isLoading && showOverlay">
<div
class="flex w-full content-start flex-wrap box-border relative"
:class="{ 'flex-col': isHorizontalView, 'flex-col md:flex-row': !isHorizontalView, }">
<div class="w-full am-search-sidebar"
:class="{ 'border-black/20': showSideBar() && getResultProductsCount() > 0, 'hidden': latestQuery.length < minSearchLength && ( !showOnFirstClick('recentSearches') && !showOnFirstClick('popularSearches') && !showOnFirstClick('browsingHistory') ) || isSidebarSectionsDisabled(), 'am-search-horizontal-view': isHorizontalView, }">
<template
x-if=" sections?.blog?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('blog'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.blog.title"></h3>
<div>
<template x-for="(item, index) in sections.blog.items" :key="index">
<div>
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="window.BASE_URL + item.url">
<span x-html="item.title" class="font-semibold"></span>
</a>
<span class="text-black block mt-1 px-4 block"
x-html="item.description"></span>
</div>
</template>
</div>
</div>
</div>
</template>
<template
x-if=" sections?.faq?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('faq'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.faq.title"></h3>
<template x-for="(item, index) in sections.faq.items" :key="index">
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="window.BASE_URL + item.url"
x-html="item.name">
</a>
</template>
</div>
</div>
</template>
<template
x-if=" sections?.brand?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('brand'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.brand.title"></h3>
<template x-for="(item, index) in sections.brand.items" :key="index">
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="`${BASE_URL + item.url}`"
x-html="item.name">
</a>
</template>
</div>
</div>
</template>
<template
x-if=" sections?.landingPage?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('landingPage'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.landingPage.title"></h3>
<template x-for="(item, index) in sections.landingPage.items" :key="index">
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="window.BASE_URL + item.url"
x-html="item.title">
</a>
</template>
</div>
</div>
</template>
<template
x-if="isHorizontalView && !noResultsFound && sections?.products?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('products'))"
x-cloak>
<div class="w-full">
<div class="relative flex flex-wrap w-full">
<template x-for="(product, index) in (sections.products.items || [])" :key="index">
<div
class="item cart flex items-center gap-5 round-none shadow-none flex-row p-5 list-view list-view border-b border-black/20 w-full">
<a :href="getProductUrl(product)"
class="product-item-photo shrink-0"
tabindex="-1"
>
<img class="photo image product-image-photo"
style="object-fit: contain"
:src="getProductImageUrl(product)"
:alt="product.small_image.label"
width="200"
/>
</a>
<div class="flex flex-col grow">
<div class="items-center justify-center"
:class="{'md:text-left': config.isGridView, 'text-center': !config.isGridView}"
>
<a class="product-item-link action link"
:href="getProductUrl(product)"
>
<span x-html="product.name" class="amsearch-product-name text-lg"></span>
</a>
</div>
<div class="price-container flex flex-col justify-center">
<div class="final-price">
<template
x-if="product.price_range.minimum_price.final_price.value < product.price_range.maximum_price.final_price.value">
<span class="price-label">
à partir de </span>
</template>
<span class="price-wrapper text-style-3">
<span class="price"
x-html="hyva.formatPrice(product.price_range.minimum_price.final_price.value)"></span>
</span>
<template
x-if="product.price_range.minimum_price.regular_price.value !== product.price_range.minimum_price.final_price.value">
<div class="old-price text-grey-900">
<span class="price-container">
<span class="price-label">Ancien prix: </span>
<span class="price-wrapper"
x-html="hyva.formatPrice(product.price_range.minimum_price.regular_price.value)"></span>
</span>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<template
x-if=" sections?.popularSearches?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('popularSearches'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.popularSearches.title"></h3>
<template x-for="(searchItem, index) in sections.popularSearches.items" :key="index">
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="resultPageUrl + searchItem.name.toLowerCase().replace(/<[^>]*>?/gm, '')"
x-html="searchItem.name">
</a>
</template>
</div>
</div>
</template>
<template
x-if=" sections?.page?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('page'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.page.title"></h3>
<template x-for="(item, index) in sections.page.items" :key="index">
<div>
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="`${BASE_URL + item.url}`">
<span x-html="item.title" class="font-semibold"></span>
</a>
<span class="text-black block mt-1 px-4 block"
x-html="item.description"></span>
</div>
</template>
</div>
</div>
</template>
<template
x-if=" sections?.category?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('category'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.category.title"></h3>
<template x-for="(item, index) in sections.category.items" :key="index">
<div>
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="window.BASE_URL + item.url">
<span x-html="item.name" class="font-semibold"></span>
</a>
<span class="text-black block mt-1 px-4 block"
x-html="item.description"
x-show="item.description"></span>
</div>
</template>
</div>
</div>
</template>
<template
x-if=" sections?.recentSearches?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('recentSearches'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4" x-text="sections.recentSearches.title"></h3>
<div class="flex direction-row flex-wrap mx-4">
<template x-for="(searchItem, index) in sections.recentSearches.items" :key="index">
<a class="bg-gray-100 hover:bg-gray-200 py-1 px-4 rounded-lg mr-2 mb-2"
:href="resultPageUrl + searchItem.name.toLowerCase().replace(/<[^>]*>?/gm, '')"
x-html="searchItem.name">
</a>
</template>
</div>
</div>
</div>
</template>
<template
x-if=" sections?.browsingHistory?.items?.length">
<div
x-show="(latestQuery.length >= minSearchLength || showOnFirstClick('browsingHistory'))"
x-cloak>
<div class="w-full mb-6 am-search-item-list">
<h3 class="text-lg font-bold mb-2 px-4"
x-text="sections.browsingHistory.title"></h3>
<template x-for="(searchItem, index) in sections.browsingHistory.items" :key="index">
<a class="w-full block hover:bg-gray-100 py-2 px-4"
:href="resultPageUrl + searchItem.name.toLowerCase().replace(/<[^>]*>?/gm, '')"
x-html="searchItem.name">
</a>
</template>
</div>
</div>
</template>
</div>
<div class="relative"
:class="{ 'am-search-content': latestQuery.length >= minSearchLength || ( showOnFirstClick('recentSearches') || showOnFirstClick('popularSearches') || showOnFirstClick('browsingHistory') ), 'w-full': latestQuery.length < minSearchLength && ( !showOnFirstClick('recentSearches') && !showOnFirstClick('popularSearches') && !showOnFirstClick('browsingHistory') ), 'am-search-horizontal-view': isHorizontalView, 'p-2 pt-6': slider.recentlyViewed || slider.bestsellers, 'am-search-sidebar-disabled': isSidebarSectionsDisabled(), }">
<div class="flex flex-nowrap flex-col" x-show="latestQuery.length < minSearchLength" x-cloak>
</div>
<template x-if="!noResultsFound && !isHorizontalView && latestQuery.length >= minSearchLength">
<div class="w-full">
<div class="relative flex flex-wrap w-full">
<template x-for="(product, index) in (sections.products.items || [])" :key="index">
<div
class="item cart flex items-center gap-5 round-none shadow-none flex-row p-5 list-view list-view border-b border-black/20 w-full">
<a :href="getProductUrl(product)"
class="product-item-photo shrink-0"
tabindex="-1"
>
<img class="photo image product-image-photo"
style="object-fit: contain"
:src="getProductImageUrl(product)"
:alt="product.small_image.label"
width="200"
/>
</a>
<div class="flex flex-col grow">
<div class="items-center justify-center"
:class="{'md:text-left': config.isGridView, 'text-center': !config.isGridView}"
>
<a class="product-item-link action link"
:href="getProductUrl(product)"
>
<span x-html="product.name" class="amsearch-product-name text-lg"></span>
</a>
</div>
<div class="price-container flex flex-col justify-center">
<div class="final-price">
<template
x-if="product.price_range.minimum_price.final_price.value < product.price_range.maximum_price.final_price.value">
<span class="price-label">
à partir de </span>
</template>
<span class="price-wrapper text-style-3">
<span class="price"
x-html="hyva.formatPrice(product.price_range.minimum_price.final_price.value)"></span>
</span>
<template
x-if="product.price_range.minimum_price.regular_price.value !== product.price_range.minimum_price.final_price.value">
<div class="old-price text-grey-900">
<span class="price-container">
<span class="price-label">Ancien prix: </span>
<span class="price-wrapper"
x-html="hyva.formatPrice(product.price_range.minimum_price.regular_price.value)"></span>
</span>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</template>
<div class="p-4 box-border border-t border-black/20 w-full h-full flex"
x-show="noResultsFound && !errorMessage" x-cloak>
<div class="flex justify-center content-center flex-row items-center flex-wrap align-center w-full h-full max-h-[90vh] text-center text-xl word-break"
x-html="'😔 Aucun résultat pour la recherche <strong>"%s"</strong>'.replace('%s', latestQuery)">
</div>
</div>
<div class="p-4 box-border border-t border-black/20 w-full h-full flex"
x-show="noResultsFound && errorMessage" x-cloak>
<div
class="text-center flex align-center w-full text-xl justify-center content-center flex-row items-center flex-wrap h-full max-h-[90vh] word-break"
x-html="errorMessage">
</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
<div class="ml-auto flex gap-5 sm:gap-7 items-center">
<div class="hidden lg:flex gap-5 items-center mx-6">
<a
class="inline-block secondary-menu-item"
href="/contact/"
aria-label="Nous contacter"
>
Contact
</a>
<a
class="inline-block secondary-menu-item"
href="/foire-aux-questions"
aria-label="Questions/Réponses"
>
FAQ
</a>
</div>
<span
@click=" isSearchOpen = !isSearchOpen; $nextTick(() => { const input = $refs.searchForm.querySelector('input[x-ref=searchInput]'); input?.focus(); }) "
class="inline-block secondary-menu-item"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="21" fill="none" viewbox="0 0 20 21">
<circle cx="7.5" cy="7.5" r="6.5" stroke="currentColor" stroke-width="2"/>
<path fill="currentColor" d="m12.5 11.086 6.47 6.47v2.829L11.087 12.5l1.414-1.414Z"/>
</svg>
</span>
<div
class="relative inline-block"
x-data="{ open: false }"
@keyup.escape="open = false"
@click.outside="open = false"
>
<button
type="button"
id="customer-menu"
class="block secondary-menu-item"
@click="open = !open"
:aria-expanded="open ? 'true' : 'false'"
aria-label="Mon compte"
aria-haspopup="true"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewbox="0 0 20 20">
<path stroke="currentColor" stroke-miterlimit="10" stroke-width="2"
d="M16.75 19H3.25L1 16.75V3.25L3.25 1h13.5L19 3.25v13.5L16.75 19Z"/>
<path stroke="currentColor" stroke-width="2" d="M16 19c-1.551-2.515-2.613-3.656-5-5"/>
<circle cx="10" cy="10" r="4" stroke="currentColor" stroke-width="2"/>
<path stroke="currentColor" stroke-width="2" d="M3.5 19c1.551-2.515 2.612-3.656 5-5"/>
</svg>
</button>
<nav
class="absolute right-0 z-20 w-40 py-2 mt-2 -mr-4 px-1 overflow-auto origin-top-right rounded-sm shadow-lg sm:w-48 lg:mt-3 text-black bg-container-lighter"
x-cloak
x-show="open"
x-transition
aria-labelledby="customer-menu"
>
<a id="customer.header.sign.in.link"
class="block px-4 py-2 lg:px-5 lg:py-2 hover:bg-gray-100"
onclick="hyva.setCookie && hyva.setCookie( 'login_redirect', window.location.href, 1 )"
href="https://www.arprotech.com/customer/account/index/"
title="Se connecter"
>
Se connecter</a>
<a id="customer.header.register.link"
class="block px-4 py-2 lg:px-5 lg:py-2 hover:bg-gray-100"
href="https://www.arprotech.com/customer/account/create/"
title="Créer un compte"
>
Créer un compte </a>
</nav>
</div>
<button
id="menu-cart-icon"
class="relative inline-block secondary-menu-item"
x-ref="cartButton"
:aria-disabled="isCartEmpty()"
:aria-label="` Toggle minicart, ${isCartEmpty() ? 'Cart is empty' : cart.summary_count > 1 ? hyva.str('%1 articles', cart.summary_count) : hyva.str('%1 item', cart.summary_count) }`"
@click.prevent.stop="() => { $dispatch('toggle-cart', { isOpen: true }) }"
@toggle-cart.window="toggleCart($event)"
:aria-expanded="isCartOpen"
aria-haspopup="dialog"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewbox="0 0 20 20">
<path stroke="currentColor" stroke-miterlimit="10" stroke-width="2"
d="M16.75 19H3.25L1 16.75V8h18v8.75L16.75 19ZM6 8V5a4 4 0 0 1 8 0v3"/>
</svg>
<span
x-text="cart.summary_count"
x-show="!isCartEmpty()"
x-cloak
class="absolute -top-1.5 -right-1.5 min-w-4 h-4 inline-flex items-center pl-[5px] pr-[2px] rounded-full bg-green text-green-800 text-xs font-bold leading-none text-center uppercase tabular-nums"
aria-hidden="true"
></span>
</button>
<nav
id="mobile-menu"
class="navigation xl:hidden"
aria-label="Site navigation"
x-data="initMenuMobile_69d82f8bea006()"
@load.window="setActiveMenu($root)"
@keydown.window.escape="closeMenu()"
>
<div
class="controls">
<button
type="button"
class="flex items-center gap-3"
aria-label="Open menu"
:aria-expanded="open"
x-ref="mobileMenuTrigger"
@click="openMenu()"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewbox="0 0 20 20">
<path d="M1 5.071h16l2-2H3l-2 2Zm0 12h16l2-2H3l-2 2Zm0-6h16l2-2H3l-2 2Z"/>
</svg>
<span class="text-label">Menu</span>
</button>
<div class="back-cut-out --outline --left --interact"></div>
</div>
<div
x-ref="mobileMenuNavLinks"
class="panel"
:class="{ 'flex': open, 'invisible': !open }"
:aria-hidden="open ? 'false' : 'true'"
role="dialog"
aria-modal="true"
>
<div class="panel-wrapper">
<div
class="panel-body"
x-show="open"
x-transition:enter="enter"
x-transition:enter-start="enter-start"
x-transition:enter-end="enter-end"
x-transition:leave="leave"
x-transition:leave-start="leave-start"
x-transition:leave-end="leave-end"
role="region"
:tabindex="open ? 0 : -1"
aria-label="Menu"
tabindex="0"
>
<div class="panel-content">
<div class="panel-title">Menu</div>
<div class="panel-reset-padding px-0 relative mt-10 flex overflow-hidden min-h-full">
<ul
class="flex flex-col w-full shrink-0"
aria-label="Site navigation links"
x-show="!mobilePanelActiveId"
x-transition:enter="transition-all ease-bumpy duration-500"
x-transition:enter-start="-translate-x-full"
x-transition:enter-end="translate-x-0"
x-transition:leave="transition-all ease-bumpy duration-500"
x-transition:leave-start="translate-x-0"
x-transition:leave-end="-translate-x-full"
>
<li
data-child-id="category-node-1568-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('category-node-1568')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/accessoires"
title="Accessoires"
>
Accessoires </a>
<button
class="flex items-center justify-center w-8 h-8 cursor-pointer"
aria-label="Open Accessoires subcategories"
aria-haspopup="true"
:aria-expanded="mobilePanelActiveId === 'category-node-1568'"
>
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="16"
fill="currentColor" viewbox="0 0 11 16">
<path d="m2.235.179 8.5 8.5-1.5 1.328-7-7V.18Z"/>
<path d="M10.735 8.65 3.65 15.734H.821L7.907 8.65h2.828Z"/>
</svg>
</button>
</div>
</li>
<li
data-child-id="category-node-1573-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('category-node-1573')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/arme-de-loisir"
title="Airgun"
>
Airgun </a>
<button
class="flex items-center justify-center w-8 h-8 cursor-pointer"
aria-label="Open Airgun subcategories"
aria-haspopup="true"
:aria-expanded="mobilePanelActiveId === 'category-node-1573'"
>
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="16"
fill="currentColor" viewbox="0 0 11 16">
<path d="m2.235.179 8.5 8.5-1.5 1.328-7-7V.18Z"/>
<path d="M10.735 8.65 3.65 15.734H.821L7.907 8.65h2.828Z"/>
</svg>
</button>
</div>
</li>
<li
data-child-id="category-node-1577-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('category-node-1577')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/arme-airsoft"
title="Airsoft"
>
Airsoft </a>
<button
class="flex items-center justify-center w-8 h-8 cursor-pointer"
aria-label="Open Airsoft subcategories"
aria-haspopup="true"
:aria-expanded="mobilePanelActiveId === 'category-node-1577'"
>
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="16"
fill="currentColor" viewbox="0 0 11 16">
<path d="m2.235.179 8.5 8.5-1.5 1.328-7-7V.18Z"/>
<path d="M10.735 8.65 3.65 15.734H.821L7.907 8.65h2.828Z"/>
</svg>
</button>
</div>
</li>
<li
data-child-id="category-node-1587-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('category-node-1587')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/arme-de-defense"
title="Défense"
>
Défense </a>
<button
class="flex items-center justify-center w-8 h-8 cursor-pointer"
aria-label="Open Défense subcategories"
aria-haspopup="true"
:aria-expanded="mobilePanelActiveId === 'category-node-1587'"
>
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="16"
fill="currentColor" viewbox="0 0 11 16">
<path d="m2.235.179 8.5 8.5-1.5 1.328-7-7V.18Z"/>
<path d="M10.735 8.65 3.65 15.734H.821L7.907 8.65h2.828Z"/>
</svg>
</button>
</div>
</li>
<li
data-child-id="category-node-1690-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('category-node-1690')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/arme-de-tir"
title="Tir"
>
Tir </a>
<button
class="flex items-center justify-center w-8 h-8 cursor-pointer"
aria-label="Open Tir subcategories"
aria-haspopup="true"
:aria-expanded="mobilePanelActiveId === 'category-node-1690'"
>
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="16"
fill="currentColor" viewbox="0 0 11 16">
<path d="m2.235.179 8.5 8.5-1.5 1.328-7-7V.18Z"/>
<path d="M10.735 8.65 3.65 15.734H.821L7.907 8.65h2.828Z"/>
</svg>
</button>
</div>
</li>
<li
data-child-id="category-node-1567-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('category-node-1567')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/optique"
title="Optique"
>
Optique </a>
<button
class="flex items-center justify-center w-8 h-8 cursor-pointer"
aria-label="Open Optique subcategories"
aria-haspopup="true"
:aria-expanded="mobilePanelActiveId === 'category-node-1567'"
>
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="16"
fill="currentColor" viewbox="0 0 11 16">
<path d="m2.235.179 8.5 8.5-1.5 1.328-7-7V.18Z"/>
<path d="M10.735 8.65 3.65 15.734H.821L7.907 8.65h2.828Z"/>
</svg>
</button>
</div>
</li>
<li
data-child-id="category-node-1697-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('category-node-1697')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/destockage"
title="Destockage"
>
Destockage </a>
</div>
</li>
<li
data-child-id="mg-blog-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('mg-blog')"
>
<a
class="flex items-center level-0"
@click.stop
href="https://www.arprotech.com/blog.html"
title="Blog"
>
Blog </a>
<button
class="flex items-center justify-center w-8 h-8 cursor-pointer"
aria-label="Open Blog subcategories"
aria-haspopup="true"
:aria-expanded="mobilePanelActiveId === 'mg-blog'"
>
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="16"
fill="currentColor" viewbox="0 0 11 16">
<path d="m2.235.179 8.5 8.5-1.5 1.328-7-7V.18Z"/>
<path d="M10.735 8.65 3.65 15.734H.821L7.907 8.65h2.828Z"/>
</svg>
</button>
</div>
</li>
<li
data-child-id="stand-main"
class="level-0 last:border-b border-black/25"
>
<div
class="panel-padding border-t border-black/25 flex items-center justify-between min-h-14 py-2 transition-transform duration-150 ease-in-out transform"
@click="openSubcategory('stand')"
>
<a
class="flex items-center level-0"
@click.stop
href="/stand-de-tir-arprotech-villeveyrac"
title="Stand de tir"
>
Stand de tir </a>
</div>
</li>
</ul>
<div
data-child-id="category-node-1568"
class="w-full shrink-0"
x-show="mobilePanelActiveId === 'category-node-1568'"
x-transition:enter="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:enter-start="left-full"
x-transition:enter-end="left-0"
x-transition:leave="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:leave-start="left-0"
x-transition:leave-end="left-full"
>
<ul
class=""
aria-label="Subcategories"
>
<li>
<button
type="button"
class="bg-black/5 flex items-center panel-padding py-4 border-b cursor-pointer border-black/25 w-full border-t"
@click="backToMainCategories('category-node-1568-main')"
aria-label="Back to main categories"
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16"
fill="currentColor" viewbox="0 0 10 16">
<path d="M8.5 15.735 0 7.235l1.5-1.328 7 7v2.828Z"/>
<path d="M0 7.265 7.086.179h2.828L2.828 7.265H0Z"/>
</svg>
<span class="ml-3">
Accessoires </span>
</button>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires"
title="Accessoires"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10">
Tout voir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/armes-blanches"
title="Armes blanches"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Armes blanches </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/armoires-fortes"
title="Armoires et coffres forts"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Armoires et coffres forts </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/cadeaux"
title="Cadeaux"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Cadeaux </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/divers"
title="Divers"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Divers </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/entretien"
title="Entretien"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Entretien </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/holsters"
title="Holsters"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Holsters </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/lampes"
title="Lampes"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Lampes </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/lance-pierre"
title="Lance pierre"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Lance pierre </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/mallettes-sacoches"
title="Mallettes, sacoches"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Mallettes, sacoches </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/militaire"
title="Militaire"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Militaire </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/outils"
title="Outils"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Outils </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/protections"
title="Protections"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Protections </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/sacs-a-dos"
title="Sacs à dos"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Sacs à dos </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/accessoires/sapeur-pompier"
title="Sapeur-pompier"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Sapeur-pompier </span>
</a>
</li>
</ul>
</div>
<div
data-child-id="category-node-1573"
class="w-full shrink-0"
x-show="mobilePanelActiveId === 'category-node-1573'"
x-transition:enter="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:enter-start="left-full"
x-transition:enter-end="left-0"
x-transition:leave="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:leave-start="left-0"
x-transition:leave-end="left-full"
>
<ul
class=""
aria-label="Subcategories"
>
<li>
<button
type="button"
class="bg-black/5 flex items-center panel-padding py-4 border-b cursor-pointer border-black/25 w-full border-t"
@click="backToMainCategories('category-node-1573-main')"
aria-label="Back to main categories"
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16"
fill="currentColor" viewbox="0 0 10 16">
<path d="M8.5 15.735 0 7.235l1.5-1.328 7 7v2.828Z"/>
<path d="M0 7.265 7.086.179h2.828L2.828 7.265H0Z"/>
</svg>
<span class="ml-3">
Airgun </span>
</button>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir"
title="Airgun"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10">
Tout voir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/accessoire"
title="Accessoires airgun"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Accessoires airgun </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/carabine-air-comprime"
title="Carabines à air comprimé"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Carabines à air comprimé </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/carabine-co2-loisir"
title="Carabines CO2 Loisir"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Carabines CO2 Loisir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/carabine-pcp"
title="Carabines PCP"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Carabines PCP </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/cibles"
title="Cibles"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Cibles </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/pieces-detachees"
title="Pièces détachées airgun"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Pièces détachées airgun </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/pistolet-air-loisir"
title="Pistolets à air comprimé"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Pistolets à air comprimé </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/pistolet-co2-loisir"
title="Pistolets à plomb CO2 loisir"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Pistolets à plomb CO2 loisir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/pistolet-pcp"
title="Pistolets PCP"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Pistolets PCP </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-loisir/plomb-et-bille"
title="Plombs et billes"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Plombs et billes </span>
</a>
</li>
</ul>
</div>
<div
data-child-id="category-node-1577"
class="w-full shrink-0"
x-show="mobilePanelActiveId === 'category-node-1577'"
x-transition:enter="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:enter-start="left-full"
x-transition:enter-end="left-0"
x-transition:leave="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:leave-start="left-0"
x-transition:leave-end="left-full"
>
<ul
class=""
aria-label="Subcategories"
>
<li>
<button
type="button"
class="bg-black/5 flex items-center panel-padding py-4 border-b cursor-pointer border-black/25 w-full border-t"
@click="backToMainCategories('category-node-1577-main')"
aria-label="Back to main categories"
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16"
fill="currentColor" viewbox="0 0 10 16">
<path d="M8.5 15.735 0 7.235l1.5-1.328 7 7v2.828Z"/>
<path d="M0 7.265 7.086.179h2.828L2.828 7.265H0Z"/>
</svg>
<span class="ml-3">
Airsoft </span>
</button>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft"
title="Airsoft"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10">
Tout voir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-co2"
title="6 mm Airsoft Co2"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
6 mm Airsoft Co2 </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-aeg"
title="6 mm Airsoft AEG"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
6 mm Airsoft AEG </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-gaz"
title="6 mm Airsoft gaz"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
6 mm Airsoft gaz </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-ressort"
title="6 mm Airsoft ressort"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
6 mm Airsoft ressort </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/accessoires"
title="Accessoires airsoft"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Accessoires airsoft </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/bille-6mm"
title="Billes 6mm"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Billes 6mm </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/gaz-co2"
title="Gaz/CO2"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Gaz/CO2 </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-airsoft/pieces-detachees-airsoft"
title="Pièces détachées airsoft"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Pièces détachées airsoft </span>
</a>
</li>
</ul>
</div>
<div
data-child-id="category-node-1587"
class="w-full shrink-0"
x-show="mobilePanelActiveId === 'category-node-1587'"
x-transition:enter="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:enter-start="left-full"
x-transition:enter-end="left-0"
x-transition:leave="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:leave-start="left-0"
x-transition:leave-end="left-full"
>
<ul
class=""
aria-label="Subcategories"
>
<li>
<button
type="button"
class="bg-black/5 flex items-center panel-padding py-4 border-b cursor-pointer border-black/25 w-full border-t"
@click="backToMainCategories('category-node-1587-main')"
aria-label="Back to main categories"
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16"
fill="currentColor" viewbox="0 0 10 16">
<path d="M8.5 15.735 0 7.235l1.5-1.328 7 7v2.828Z"/>
<path d="M0 7.265 7.086.179h2.828L2.828 7.265H0Z"/>
</svg>
<span class="ml-3">
Défense </span>
</button>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense"
title="Défense"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10">
Tout voir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/6mm-blanc"
title="6mm Blanc"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
6mm Blanc </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/9mm-gaz-et-blanc"
title="9mm Gaz et Blanc"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
9mm Gaz et Blanc </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/accessoire"
title="Accessoires défense"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Accessoires défense </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/arme-a-balle-caoutchouc"
title="Armes à balle caoutchouc"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Armes à balle caoutchouc </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/aerosol"
title="Bombes lacrymogènes"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Bombes lacrymogènes </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/electrochoc"
title="Electrochocs"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Electrochocs </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/matraque-telescopique"
title="Matraque telescopique"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Matraque telescopique </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-defense/pieces-detachees-defense"
title="Pièces détachées défense"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Pièces détachées défense </span>
</a>
</li>
</ul>
</div>
<div
data-child-id="category-node-1690"
class="w-full shrink-0"
x-show="mobilePanelActiveId === 'category-node-1690'"
x-transition:enter="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:enter-start="left-full"
x-transition:enter-end="left-0"
x-transition:leave="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:leave-start="left-0"
x-transition:leave-end="left-full"
>
<ul
class=""
aria-label="Subcategories"
>
<li>
<button
type="button"
class="bg-black/5 flex items-center panel-padding py-4 border-b cursor-pointer border-black/25 w-full border-t"
@click="backToMainCategories('category-node-1690-main')"
aria-label="Back to main categories"
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16"
fill="currentColor" viewbox="0 0 10 16">
<path d="M8.5 15.735 0 7.235l1.5-1.328 7 7v2.828Z"/>
<path d="M0 7.265 7.086.179h2.828L2.828 7.265H0Z"/>
</svg>
<span class="ml-3">
Tir </span>
</button>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir"
title="Tir"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10">
Tout voir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir/armes-occasion"
title="Armes occasion"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Armes occasion </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir/accessoires"
title="Accessoires"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Accessoires </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir/carabines"
title="Carabines"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Carabines </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir/cartouches"
title="Cartouches"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Cartouches </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir/pistolet"
title="Pistolets"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Pistolets </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir/poudre"
title="Poudre"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Poudre </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/arme-de-tir/revolvers"
title="Revolvers"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Revolvers </span>
</a>
</li>
</ul>
</div>
<div
data-child-id="category-node-1567"
class="w-full shrink-0"
x-show="mobilePanelActiveId === 'category-node-1567'"
x-transition:enter="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:enter-start="left-full"
x-transition:enter-end="left-0"
x-transition:leave="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:leave-start="left-0"
x-transition:leave-end="left-full"
>
<ul
class=""
aria-label="Subcategories"
>
<li>
<button
type="button"
class="bg-black/5 flex items-center panel-padding py-4 border-b cursor-pointer border-black/25 w-full border-t"
@click="backToMainCategories('category-node-1567-main')"
aria-label="Back to main categories"
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16"
fill="currentColor" viewbox="0 0 10 16">
<path d="M8.5 15.735 0 7.235l1.5-1.328 7 7v2.828Z"/>
<path d="M0 7.265 7.086.179h2.828L2.828 7.265H0Z"/>
</svg>
<span class="ml-3">
Optique </span>
</button>
</li>
<li>
<a
href="https://www.arprotech.com/optique"
title="Optique"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10">
Tout voir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/optique/accessoire"
title="Accessoires"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Accessoires </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/optique/jumelle"
title="Jumelles"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Jumelles </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/optique/lunette-de-tir"
title="Lunettes de tir"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Lunettes de tir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/optique/point-rouge-red-dot"
title="Points rouges/Red dot"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Points rouges/Red dot </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/optique/telemetre-laser"
title="Télémètres laser"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Télémètres laser </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/optique/telescope"
title="Téléscopes"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Téléscopes </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/optique/visee-laser"
title="Visées laser"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Visées laser </span>
</a>
</li>
</ul>
</div>
<div
data-child-id="mg-blog"
class="w-full shrink-0"
x-show="mobilePanelActiveId === 'mg-blog'"
x-transition:enter="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:enter-start="left-full"
x-transition:enter-end="left-0"
x-transition:leave="absolute transition-all ease-bumpy duration-500 min-h-full w-full"
x-transition:leave-start="left-0"
x-transition:leave-end="left-full"
>
<ul
class=""
aria-label="Subcategories"
>
<li>
<button
type="button"
class="bg-black/5 flex items-center panel-padding py-4 border-b cursor-pointer border-black/25 w-full border-t"
@click="backToMainCategories('mg-blog-main')"
aria-label="Back to main categories"
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16"
fill="currentColor" viewbox="0 0 10 16">
<path d="M8.5 15.735 0 7.235l1.5-1.328 7 7v2.828Z"/>
<path d="M0 7.265 7.086.179h2.828L2.828 7.265H0Z"/>
</svg>
<span class="ml-3">
Blog </span>
</button>
</li>
<li>
<a
href="https://www.arprotech.com/blog.html"
title="Blog"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10">
Tout voir </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/blog/category/arme.html"
title="Arme"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Arme </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/blog/category/optique.html"
title="Optique"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Optique </span>
</a>
</li>
<li>
<a
href="https://www.arprotech.com/blog/category/armurerie.html"
title="Armurerie"
class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container"
>
<span class="ml-10 text-base text-gray-700">
Armurerie </span>
</a>
</li>
</ul>
</div>
</div>
<div
class="flex flex-col gap-5 mt-5"
:class="{ '-translate-x-full' : mobilePanelActiveId, 'translate-x-0' : !mobilePanelActiveId }"
>
<a
href="/contact/"
aria-label="Nous contacter"
>
Contact
</a>
<a
href="/foire-aux-questions"
aria-label="Questions/Réponses"
>
FAQ
</a>
</div>
</div>
<button @click="closeMenu()" class="panel-close"
aria-label="Close" title="Close" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
</div>
</div>
<div
class="backdrop cursor-default"
x-show="open"
x-transition:enter="ease-in-out duration-500"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in-out duration-500"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
role="button"
@click="closeMenu()"
aria-label="Close menu">
</div>
</div>
</nav>
<script>
'use strict'
const initMenuMobile_69d82f8bea006 = () => {
return {
mobilePanelActiveId: null,
open: false,
init() {
this.$refs.mobileMenuNavLinks.classList.add('ready')
},
setActiveMenu(menuNode) {
Array.from(menuNode.querySelectorAll('a')).filter(link => {
return link.href === window.location.href.split('?')[0]
}).map(item => {
item.classList.add('underline')
item.closest('li.level-0') &&
item.closest('li.level-0').querySelector('a.level-0').classList.add('underline')
})
},
openMenu() {
this.open = true
this.$nextTick(() => hyva.trapFocus(this.$refs['mobileMenuNavLinks']))
// Prevent from body scrolling while mobile menu opened
document.body.style.overflow = 'hidden'
},
closeMenu() {
document.body.style.overflow = ''
if (this.open) {
this.$nextTick(() => this.$refs['mobileMenuTrigger'].focus() || hyva.releaseFocus())
}
this.open = false
this.mobilePanelActiveId = null
},
openSubcategory(index) {
const menuNodeRef = document.querySelector('[data-child-id=' + index + ']')
this.mobilePanelActiveId = this.mobilePanelActiveId === index ? 0 : index
this.$nextTick(() => {
menuNodeRef.closest('.panel-content').scrollTo({top: 0})
console.log(menuNodeRef)
hyva.trapFocus(menuNodeRef)
})
},
backToMainCategories(index) {
const menuNodeRef = document.querySelector('[data-child-id=' + index + ']')
this.mobilePanelActiveId = 0
this.$nextTick(() => {
hyva.trapFocus(this.$refs['mobileMenuNavLinks'])
menuNodeRef.querySelector('a').focus()
})
}
}
}
</script>
</div>
</div>
<div id="header-wrapper">
<div class="relative hidden lg:block">
<div
x-data="initMenuDesktop_69d82f8bec9a5()"
id="desktop-menu"
class="z-20 order-2 sm:order-1 lg:order-2 navigation hidden xl:flex"
>
<!-- desktop -->
<div
x-ref="nav-desktop"
@load.window="setActiveMenu($root)"
class="hidden w-full lg:block">
<nav
class="relative"
aria-label="Main menu"
>
<ul class="flex justify-start xl:justify-between flex-wrap gap-5 2xl:gap-10 2xl:justify-start">
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'category-node-1568'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/accessoires"
title="Accessoires"
@focus="hoverPanelActiveId = 0"
>
Accessoires </a>
<button
type="button"
data-sr-button-id="category-node-1568"
:aria-expanded="hoverPanelActiveId === 'category-node-1568' ? 'true' : 'false'"
@click="openMenuOnClick('category-node-1568')"
class="rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" fill="none"
viewbox="0 0 16 10">
<path fill="currentColor" d="m0 1.414 8.5 8.5 1.328-1.5-7-7H0Z"/>
<path fill="currentColor" d="m8.47 9.914 7.086-7.086V0L8.47 7.086v2.828Z"/>
</svg>
<span class="sr-only">
Show submenu for Accessoires category </span>
</button>
</span>
<ul
class="sub-menu"
:class="{ 'inactive' : hoverPanelActiveId !== 'category-node-1568', 'active' : hoverPanelActiveId === 'category-node-1568' }"
>
<li>
<a href="https://www.arprotech.com/accessoires/armes-blanches"
title="Armes blanches"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Armes blanches </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/armoires-fortes"
title="Armoires et coffres forts"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Armoires et coffres forts </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/cadeaux"
title="Cadeaux"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Cadeaux </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/divers"
title="Divers"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Divers </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/entretien"
title="Entretien"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Entretien </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/holsters"
title="Holsters"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Holsters </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/lampes"
title="Lampes"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Lampes </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/lance-pierre"
title="Lance pierre"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Lance pierre </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/mallettes-sacoches"
title="Mallettes, sacoches"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Mallettes, sacoches </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/militaire"
title="Militaire"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Militaire </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/outils"
title="Outils"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Outils </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/protections"
title="Protections"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Protections </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/sacs-a-dos"
title="Sacs à dos"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Sacs à dos </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/accessoires/sapeur-pompier"
title="Sapeur-pompier"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1568]').focus())"
>
<span class="text-base">
Sapeur-pompier </span>
</a>
</li>
</ul>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'category-node-1573'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/arme-de-loisir"
title="Airgun"
@focus="hoverPanelActiveId = 0"
>
Airgun </a>
<button
type="button"
data-sr-button-id="category-node-1573"
:aria-expanded="hoverPanelActiveId === 'category-node-1573' ? 'true' : 'false'"
@click="openMenuOnClick('category-node-1573')"
class="rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" fill="none"
viewbox="0 0 16 10">
<path fill="currentColor" d="m0 1.414 8.5 8.5 1.328-1.5-7-7H0Z"/>
<path fill="currentColor" d="m8.47 9.914 7.086-7.086V0L8.47 7.086v2.828Z"/>
</svg>
<span class="sr-only">
Show submenu for Airgun category </span>
</button>
</span>
<ul
class="sub-menu"
:class="{ 'inactive' : hoverPanelActiveId !== 'category-node-1573', 'active' : hoverPanelActiveId === 'category-node-1573' }"
>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/accessoire"
title="Accessoires airgun"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Accessoires airgun </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/carabine-air-comprime"
title="Carabines à air comprimé"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Carabines à air comprimé </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/carabine-co2-loisir"
title="Carabines CO2 Loisir"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Carabines CO2 Loisir </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/carabine-pcp"
title="Carabines PCP"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Carabines PCP </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/cibles"
title="Cibles"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Cibles </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/pieces-detachees"
title="Pièces détachées airgun"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Pièces détachées airgun </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/pistolet-air-loisir"
title="Pistolets à air comprimé"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Pistolets à air comprimé </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/pistolet-co2-loisir"
title="Pistolets à plomb CO2 loisir"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Pistolets à plomb CO2 loisir </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/pistolet-pcp"
title="Pistolets PCP"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Pistolets PCP </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-loisir/plomb-et-bille"
title="Plombs et billes"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1573]').focus())"
>
<span class="text-base">
Plombs et billes </span>
</a>
</li>
</ul>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'category-node-1577'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/arme-airsoft"
title="Airsoft"
@focus="hoverPanelActiveId = 0"
>
Airsoft </a>
<button
type="button"
data-sr-button-id="category-node-1577"
:aria-expanded="hoverPanelActiveId === 'category-node-1577' ? 'true' : 'false'"
@click="openMenuOnClick('category-node-1577')"
class="rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" fill="none"
viewbox="0 0 16 10">
<path fill="currentColor" d="m0 1.414 8.5 8.5 1.328-1.5-7-7H0Z"/>
<path fill="currentColor" d="m8.47 9.914 7.086-7.086V0L8.47 7.086v2.828Z"/>
</svg>
<span class="sr-only">
Show submenu for Airsoft category </span>
</button>
</span>
<ul
class="sub-menu"
:class="{ 'inactive' : hoverPanelActiveId !== 'category-node-1577', 'active' : hoverPanelActiveId === 'category-node-1577' }"
>
<li>
<a href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-co2"
title="6 mm Airsoft Co2"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
6 mm Airsoft Co2 </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-aeg"
title="6 mm Airsoft AEG"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
6 mm Airsoft AEG </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-gaz"
title="6 mm Airsoft gaz"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
6 mm Airsoft gaz </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-airsoft/6-mm-airsoft-ressort"
title="6 mm Airsoft ressort"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
6 mm Airsoft ressort </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-airsoft/accessoires"
title="Accessoires airsoft"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
Accessoires airsoft </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-airsoft/bille-6mm"
title="Billes 6mm"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
Billes 6mm </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-airsoft/gaz-co2"
title="Gaz/CO2"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
Gaz/CO2 </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-airsoft/pieces-detachees-airsoft"
title="Pièces détachées airsoft"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1577]').focus())"
>
<span class="text-base">
Pièces détachées airsoft </span>
</a>
</li>
</ul>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'category-node-1587'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/arme-de-defense"
title="Défense"
@focus="hoverPanelActiveId = 0"
>
Défense </a>
<button
type="button"
data-sr-button-id="category-node-1587"
:aria-expanded="hoverPanelActiveId === 'category-node-1587' ? 'true' : 'false'"
@click="openMenuOnClick('category-node-1587')"
class="rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" fill="none"
viewbox="0 0 16 10">
<path fill="currentColor" d="m0 1.414 8.5 8.5 1.328-1.5-7-7H0Z"/>
<path fill="currentColor" d="m8.47 9.914 7.086-7.086V0L8.47 7.086v2.828Z"/>
</svg>
<span class="sr-only">
Show submenu for Défense category </span>
</button>
</span>
<ul
class="sub-menu"
:class="{ 'inactive' : hoverPanelActiveId !== 'category-node-1587', 'active' : hoverPanelActiveId === 'category-node-1587' }"
>
<li>
<a href="https://www.arprotech.com/arme-de-defense/6mm-blanc"
title="6mm Blanc"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
6mm Blanc </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-defense/9mm-gaz-et-blanc"
title="9mm Gaz et Blanc"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
9mm Gaz et Blanc </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-defense/accessoire"
title="Accessoires défense"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
Accessoires défense </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-defense/arme-a-balle-caoutchouc"
title="Armes à balle caoutchouc"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
Armes à balle caoutchouc </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-defense/aerosol"
title="Bombes lacrymogènes"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
Bombes lacrymogènes </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-defense/electrochoc"
title="Electrochocs"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
Electrochocs </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-defense/matraque-telescopique"
title="Matraque telescopique"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
Matraque telescopique </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-defense/pieces-detachees-defense"
title="Pièces détachées défense"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1587]').focus())"
>
<span class="text-base">
Pièces détachées défense </span>
</a>
</li>
</ul>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'category-node-1690'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/arme-de-tir"
title="Tir"
@focus="hoverPanelActiveId = 0"
>
Tir </a>
<button
type="button"
data-sr-button-id="category-node-1690"
:aria-expanded="hoverPanelActiveId === 'category-node-1690' ? 'true' : 'false'"
@click="openMenuOnClick('category-node-1690')"
class="rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" fill="none"
viewbox="0 0 16 10">
<path fill="currentColor" d="m0 1.414 8.5 8.5 1.328-1.5-7-7H0Z"/>
<path fill="currentColor" d="m8.47 9.914 7.086-7.086V0L8.47 7.086v2.828Z"/>
</svg>
<span class="sr-only">
Show submenu for Tir category </span>
</button>
</span>
<ul
class="sub-menu"
:class="{ 'inactive' : hoverPanelActiveId !== 'category-node-1690', 'active' : hoverPanelActiveId === 'category-node-1690' }"
>
<li>
<a href="https://www.arprotech.com/arme-de-tir/armes-occasion"
title="Armes occasion"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1690]').focus())"
>
<span class="text-base">
Armes occasion </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-tir/accessoires"
title="Accessoires"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1690]').focus())"
>
<span class="text-base">
Accessoires </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-tir/carabines"
title="Carabines"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1690]').focus())"
>
<span class="text-base">
Carabines </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-tir/cartouches"
title="Cartouches"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1690]').focus())"
>
<span class="text-base">
Cartouches </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-tir/pistolet"
title="Pistolets"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1690]').focus())"
>
<span class="text-base">
Pistolets </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-tir/poudre"
title="Poudre"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1690]').focus())"
>
<span class="text-base">
Poudre </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/arme-de-tir/revolvers"
title="Revolvers"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1690]').focus())"
>
<span class="text-base">
Revolvers </span>
</a>
</li>
</ul>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'category-node-1567'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/optique"
title="Optique"
@focus="hoverPanelActiveId = 0"
>
Optique </a>
<button
type="button"
data-sr-button-id="category-node-1567"
:aria-expanded="hoverPanelActiveId === 'category-node-1567' ? 'true' : 'false'"
@click="openMenuOnClick('category-node-1567')"
class="rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" fill="none"
viewbox="0 0 16 10">
<path fill="currentColor" d="m0 1.414 8.5 8.5 1.328-1.5-7-7H0Z"/>
<path fill="currentColor" d="m8.47 9.914 7.086-7.086V0L8.47 7.086v2.828Z"/>
</svg>
<span class="sr-only">
Show submenu for Optique category </span>
</button>
</span>
<ul
class="sub-menu"
:class="{ 'inactive' : hoverPanelActiveId !== 'category-node-1567', 'active' : hoverPanelActiveId === 'category-node-1567' }"
>
<li>
<a href="https://www.arprotech.com/optique/accessoire"
title="Accessoires"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1567]').focus())"
>
<span class="text-base">
Accessoires </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/optique/jumelle"
title="Jumelles"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1567]').focus())"
>
<span class="text-base">
Jumelles </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/optique/lunette-de-tir"
title="Lunettes de tir"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1567]').focus())"
>
<span class="text-base">
Lunettes de tir </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/optique/point-rouge-red-dot"
title="Points rouges/Red dot"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1567]').focus())"
>
<span class="text-base">
Points rouges/Red dot </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/optique/telemetre-laser"
title="Télémètres laser"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1567]').focus())"
>
<span class="text-base">
Télémètres laser </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/optique/telescope"
title="Téléscopes"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1567]').focus())"
>
<span class="text-base">
Téléscopes </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/optique/visee-laser"
title="Visées laser"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=category\u002Dnode\u002D1567]').focus())"
>
<span class="text-base">
Visées laser </span>
</a>
</li>
</ul>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'category-node-1697'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/destockage"
title="Destockage"
@focus="hoverPanelActiveId = 0"
>
Destockage </a>
</span>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'mg-blog'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="https://www.arprotech.com/blog.html"
title="Blog"
@focus="hoverPanelActiveId = 0"
>
Blog </a>
<button
type="button"
data-sr-button-id="mg-blog"
:aria-expanded="hoverPanelActiveId === 'mg-blog' ? 'true' : 'false'"
@click="openMenuOnClick('mg-blog')"
class="rounded"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" fill="none"
viewbox="0 0 16 10">
<path fill="currentColor" d="m0 1.414 8.5 8.5 1.328-1.5-7-7H0Z"/>
<path fill="currentColor" d="m8.47 9.914 7.086-7.086V0L8.47 7.086v2.828Z"/>
</svg>
<span class="sr-only">
Show submenu for Blog category </span>
</button>
</span>
<ul
class="sub-menu"
:class="{ 'inactive' : hoverPanelActiveId !== 'mg-blog', 'active' : hoverPanelActiveId === 'mg-blog' }"
>
<li>
<a href="https://www.arprotech.com/blog/category/arme.html"
title="Arme"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=mg\u002Dblog]').focus())"
>
<span class="text-base">
Arme </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/blog/category/optique.html"
title="Optique"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=mg\u002Dblog]').focus())"
>
<span class="text-base">
Optique </span>
</a>
</li>
<li>
<a href="https://www.arprotech.com/blog/category/armurerie.html"
title="Armurerie"
class="text-black transition-colors hover:text-secondary block w-full px-3 py-1 my-1 whitespace-nowrap first:mt-0 aria-[current=page]:font-bold"
@keyup.escape="$nextTick(() => document.querySelector('[data-sr-button-id=mg\u002Dblog]').focus())"
>
<span class="text-base">
Armurerie </span>
</a>
</li>
</ul>
</li>
<li class="relative level-0"
@mouseenter="hoverPanelActiveId = 'stand'"
@mouseleave="hoverPanelActiveId = 0"
@keyup.escape="hoverPanelActiveId = 0"
>
<span class="flex items-center text-md gap-1.5">
<a class="menu-item level-0"
href="/stand-de-tir-arprotech-villeveyrac"
title="Stand de tir"
@focus="hoverPanelActiveId = 0"
>
Stand de tir </a>
</span>
</li>
</ul>
</nav>
</div>
<div class="back-cut-out --outline"></div>
</div>
<script>
'use strict'
const initMenuDesktop_69d82f8bec9a5 = () => {
return {
hoverPanelActiveId: null,
setActiveMenu(menuNode) {
Array.from(menuNode.querySelectorAll('a')).filter(link => {
return link.href === window.location.href.split('?')[0]
}).map(item => {
item.setAttribute('aria-current', 'page')
item.closest('li.level-0').setAttribute('data-active', 'true')
})
},
openMenuOnClick(menuNode) {
if (menuNode === this.hoverPanelActiveId) {
this.hoverPanelActiveId = 0
} else {
this.hoverPanelActiveId = menuNode
}
}
}
}
</script>
<div id="desktop-menu-brand-link"
@mouseenter="hoverPanelActiveId = 'am-brand'"
@mouseleave="hoverPanelActiveId = null"
class="relative level-0 flex items-center text-md">
<a href="https://www.arprotech.com/marques/"
class="level-0 menu-item"
x-cloak
>
Marques
</a>
</div>
<span id="mobile-menu-brand-link"
class="flex items-center transition-transform duration-150 ease-in-out transform hidden">
<a class="flex items-center w-full px-8 py-4 border-b cursor-pointer bg-container-lighter border-container level-0"
href="https://www.arprotech.com/marques/"
title="Marques">
Marques </a>
</span>
<script>
(() => {
'use strict'
const isFirst = ``
function mobileMenuTargetFallback() {
return (
document.querySelector('div[x-ref="mobileMenuNavLinks"] > ul')
)
}
function desktopMenuTargetFallback() {
const mainElement = document.querySelector('div[x-ref="nav-desktop"] > nav > ul')
return mainElement || document.querySelector('div[x-ref="nav-desktop"] > nav')
}
function moveElement(element, target, itemTagName = 'li') {
const childElementTagName = target?.children[0]?.tagName.toLowerCase() || 'div'
const wrapper = document.createElement(childElementTagName)
wrapper.classList.add('relative', 'level-0')
wrapper.appendChild(element)
if(target) {
isFirst ? target.prepend(wrapper) : target.append(wrapper)
}
element.classList.remove('hidden')
}
function adjustMobileMenuPosition() {
const element = document.querySelector('#mobile-menu-brand-link')
if (!element) {
return
}
const target = mobileMenuTargetFallback()
moveElement(element, target)
}
function adjustTopMenuPosition() {
const element = document.querySelector('#desktop-menu-brand-link')
if (!element) {
return
}
moveElement(element, desktopMenuTargetFallback())
}
document.addEventListener('DOMContentLoaded', () => {
adjustTopMenuPosition()
adjustMobileMenuPosition()
})
})()
</script>
</div>
<div x-ref="searchContainerMobile" class="container hidden"></div>
</div>
<script>
function initCartDrawer() {
return {
open: false,
isLoading: false,
cart: {},
maxItemsToDisplay: 10,
itemsCount: 0,
showSku: true,
init() {
this.$refs.cartDialogContent.classList.add('ready')
},
getData(data) {
if (data.cart) {
this.cart = data.cart
this.itemsCount = data.cart.items && data.cart.items.length || 0
this.setCartItems()
}
this.isLoading = false
},
cartItems: [],
getItemCountTitle() {
return hyva.strf('\u00250\u0020of\u0020\u00251\u0020products\u0020in\u0020cart\u0020displayed', this.maxItemsToDisplay, this.itemsCount)
},
setCartItems() {
this.cartItems = this.cart.items && this.cart.items.sort((a, b) => b.item_id - a.item_id) || []
if (this.maxItemsToDisplay > 0) {
this.cartItems = this.cartItems.slice(0, parseInt(this.maxItemsToDisplay, 10))
}
},
updateItemQty(form) {
this.isLoading = true
hyvaAjaxFormMinicart({
form,
redirect: false
}, () => {
this.isLoading = false
})
},
deleteItemFromCart(itemId) {
this.isLoading = true
const formKey = hyva.getFormKey()
hyvaAjaxFormMinicart({
url: BASE_URL + 'checkout/sidebar/removeItem/',
body: 'form_key=' + formKey + '&item_id=' + itemId,
message: 'Vous\u0020avez\u0020supprim\u00E9\u0020l\u0027\u00E9l\u00E9ment.'
}, () => {
this.isLoading = false
})
},
scrollLock(use = true) {
document.body.style.overflow = use ? 'hidden' : ''
},
toggleCartDrawer(event) {
if (event.detail && event.detail.isOpen) {
this.open = event.detail.isOpen
} else {
this.open = !this.open
}
// if (this.open) {
// this.$root.showModal()
// } else {
// this.$root.close()
// }
// this.scrollLock(this.open)
},
openCartDrawer() {
// this.$root.showModal()
this.open = true
// this.scrollLock(true)
},
closeCartDrawer() {
// this.$root.close()
this.open = false
// this.scrollLock(false)
},
getSectionDataExtraActions() {
if (!this.cart.extra_actions) {
return ''
}
const contentNode = document.createElement('div')
contentNode.innerHTML = this.cart.extra_actions
hyva.activateScripts(contentNode)
return contentNode.innerHTML
},
onDialogBackdropClickHelper(event, target) {
const rect = target.getBoundingClientRect()
const isInDialog =
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width
return isInDialog
},
setItemMessage(itemId, message) {
const items = this.cartItems
items.forEach((item) => {
if (item.item_id === itemId) {
item.message = message
}
})
},
cartListeners: {
['@private-content-loaded.window'](event) {
this.getData(event.detail.data)
},
['@click'](event) {
if (this.onDialogBackdropClickHelper(event, this.$root)) return
this.closeCartDrawer()
},
['@toggle-cart.window'](event) {
this.toggleCartDrawer(event)
},
['@keydown.window.escape']() {
this.closeCartDrawer()
},
['@minicart-error-message.window'](event) {
if (!event.detail) return
const {itemId, message} = event.detail
this.setItemMessage(itemId, message)
}
}
}
}
async function hyvaAjaxFormMinicart(
{
form = null,
url = '',
body = '',
redirect = 'default',
message = ''
} = {},
callback = () => {
}
) {
const formData = body ? body : (form ? new FormData(form) : '')
const postUrl = url ? url : (form ? form.action : '')
if (!formData || !postUrl) {
console.warn('You must provide the form or formData and postUrl!')
return
}
const formUenc = hyva.getUenc()
const itemId = body ? new URLSearchParams(body).get('item_id') : formData.get('item_id')
let bodyUrl = new URLSearchParams(formData)
bodyUrl.append('uenc', formUenc)
try {
const response = await fetch(postUrl, {
method: 'POST',
body: bodyUrl.toString(),
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest'
}
})
if (!response.ok) {
return form.submit()
}
if (redirect === 'default' && response.redirected) {
return window.location.href = response.url
} else if (redirect !== 'default' && redirect !== false) {
return window.location.href = redirect
}
const responseBody = await response.json()
if (!responseBody.success) {
throw responseBody.error_message
}
window.dispatchEvent(new CustomEvent('reload-customer-section-data'))
} catch (error) {
window.dispatchEvent(new CustomEvent('minicart-error-message', {detail: {itemId, message: error}}))
} finally {
callback()
}
}
</script>
<div
id="cart-drawer"
aria-labelledby="cart-drawer-title"
class="panel panel--large"
:class="{ 'invisible': !open }"
:aria-hidden="open ? 'false' : 'true'"
x-ref="cartDialogContent"
x-data="initCartDrawer()"
x-bind="cartListeners"
x-cloak
>
<div class="panel-wrapper">
<div
class="panel-body"
x-show="open"
x-transition:enter="enter"
x-transition:enter-start="enter-start"
x-transition:enter-end="enter-end"
x-transition:leave="leave"
x-transition:leave-start="leave-start"
x-transition:leave-end="leave-end"
role="region"
:tabindex="open ? 0 : -1"
aria-label="Site navigatielinks"
tabindex="0"
>
<div x-ref="mobileMenuContainer" class="panel-content overflow-hidden flex flex-col">
<div class="panel-title flex items-center gap-3">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewbox="0 0 20 20">
<path stroke="currentColor" stroke-miterlimit="10" stroke-width="2"
d="M16.75 19H3.25L1 16.75V8h18v8.75L16.75 19ZM6 8V5a4 4 0 0 1 8 0v3"/>
</svg>
<span>Mon panier</span>
<span
class="items-total text-xs"
x-show="maxItemsToDisplay && maxItemsToDisplay < itemsCount"
x-text="getItemCountTitle()"
></span>
</div>
<template x-if="!itemsCount">
<div class="grow grid place-items-center">
<div class="text-center">
<p>Votre panier est vide</p>
</div>
</div>
</template>
<template x-if="itemsCount">
<ul class="grow flex flex-col overflow-y-auto overflow-x-hidden overscroll-y-contain panel-reset-padding border-t border-black">
<template x-for="item in cartItems">
<li class="minicart-item panel-reset-padding flex gap-4 md:gap-5 items-start py-7 border-t border-black first-of-type:border-t-0">
<a
class="block shrink-0 cut-outline max-w-[25%]"
style="--cut-size: 16px"
:href="item.product_url"
:title="hyva.str('Product\u0020\u0022\u00251\u0022', item.product_name)"
>
<img
:src="item.product_image.src"
:width="item.product_image.width"
:height="item.product_image.height"
class="cut-image"
loading="lazy"
:alt="hyva.str('Product\u0020\u0022\u00251\u0022', item.product_name)"
>
</a>
<div class="grow space-y-3">
<div class="flex gap-5 justify-between">
<p class="">
<strong x-html="item.product_name"></strong>
</p>
<span class="[&_.price]:text-style-5" x-html="item.product_price"></span>
</div>
<template x-if="item.options && item.options.length || showSku">
<dl class="table text-sm">
<template x-if="showSku">
<div class="table-row">
<dt class="table-cell text-label min-w-[theme(spacing.16)] pr-2 pb-2">
SKU </dt>
<dd class="table-cell pb-2"
x-html="item.product_sku"></dd>
</div>
</template>
<template x-for="option in item.options">
<div class="table-row">
<dt
class="table-cell text-label min-w-[theme(spacing.16)] pr-2 pb-2"
x-text="option.label"
></dt>
<dd class="table-cell pb-2" x-html="option.value"></dd>
</div>
</template>
</dl>
</template>
<div
class="flex items-end gap-5 !mt-0 justify-between">
<form
action="https://www.arprotech.com/checkout/sidebar/updateItemQty/"
x-data="{ initQty: item.qty, itemQty: item.qty, prevQty: item.qty, updateQty() { const submitEvent = new Event('submit', { cancelable: true }); this.$root.dispatchEvent(submitEvent); }, setQtyDefaults() { this.initQty = item.qty; this.itemQty = item.qty; this.prevQty = item.qty; } }"
@submit.prevent="updateItemQty($event.target);"
x-init="$watch('item.qty', () => setQtyDefaults());"
method="post"
class="form form-cart form-qty flex gap-[-1px] flex-auto"
>
<input name="form_key" type="hidden" value="eTB4IhRhBQzWlDue" /> <input type="hidden" name="item_id" :value="item.item_id">
<button
type="button"
@click="itemQty <= 0 ? itemQty = 0 : itemQty--"
@click.debounce.1000ms="updateQty($event);"
class="button button--outline button--icon large !font-semibold"
>
-
</button>
<label class="mb-0 -ml-[1px] -mr-[1px]">
<span class="sr-only">Qte </span>
<input
type="number"
class="qty border-black shadow-none [-moz-appearance:textfield] form-input w-16 text-center [&::-webkit-inner-spin-button]:hidden"
required
min="0"
step="any"
x-model.number="itemQty"
:id="`minicart-${item.item_id}-qty`"
name="item_qty"
@change.debounce.1000ms="updateQty($event)"
>
</label>
<button
type="button"
@click="itemQty++"
@click.debounce.1000ms="updateQty($event);"
class="button button--outline button--icon large !font-semibold"
>
+
</button>
</form>
<div class="inline-flex flex-wrap items-center gap-5 flex-1">
<a
:href="item.configure_url"
x-show="item.product_type !== 'grouped'"
class="underline transition-all text-sm hover:text-secondary disabled:opacity-50"
:aria-label="hyva.str( 'Edit\u0020product\u0020\u0022\u00251\u0022', item.product_name )"
>
Modifier </a>
<button
type="button"
class="button button--outline button--icon small"
@click="deleteItemFromCart(item.item_id)"
:aria-label="hyva.str( 'Remove\u0020product\u0020\u0022\u00251\u0022\u0020from\u0020cart', item.product_name )"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"
fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
</div>
<template x-if="item.message">
<div class="message error px-5 py-3" x-text="item.message"></div>
</template>
</div>
</div>
</li>
</template>
</ul>
</template>
<template x-if="itemsCount">
<div class="panel-reset-padding border-t border-black pt-8">
<dl class="flex gap-2 justify-between items-start">
<dt class="text-label">Sous-total</dt>
<dd class="text-style-3" x-html="cart.subtotal"></dd>
</dl>
<div class="flex flex-col gap-y-4 mt-5">
<a
@click.prevent.stop="closeCartDrawer; $dispatch( 'toggle-authentication', { url: 'https://www.arprotech.com/checkout/' } );"
href="https://www.arprotech.com/checkout/"
class="button button--primary large"
>
Commander </a>
<a
href="https://www.arprotech.com/checkout/cart/"
class="flex justify-center py-3 px-6 text-base shadow-none transition bg-white text-black border border-black hover:bg-black/5 focus:ring-black-200"
>
Afficher et modifier le panier </a>
<div x-html="getSectionDataExtraActions()"></div>
</div>
</div>
</template>
<template x-if="!itemsCount">
<div class="flex flex-col">
<button
type="button"
@click="closeCartDrawer"
class="flex justify-center py-3 px-6 text-base shadow-none transition bg-white text-black border border-black hover:bg-black/5 focus:ring-black-200 disabled:opacity-30"
>Continuez vos achats</button>
</div>
</template>
<div class="flex flex-row justify-center items-center w-full h-full fixed select-none z-50"
style="left: 50%;top: 50%;transform: translateX(-50%) translateY(-50%);background: rgba(255,255,255,0.9);"
x-show="isLoading"
x-cloak
x-transition:enter="ease-out duration-200"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0">
<svg xmlns="http://www.w3.org/2000/svg"
width="54"
height="54"
viewbox="0 0 60 55" xml:space="preserve">
<rect x="20" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="30" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.2s" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="40" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.4s" dur="0.6s" repeatcount="indefinite"/>
</rect>
</svg>
<div class="ml-3 text-style-6">
En cours de chargement... </div>
</div>
</div>
<button @click="closeCartDrawer()" class="panel-close"
aria-label="Close filters" title="Close filters" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
</div>
</div>
<div
class="backdrop cursor-default"
x-show="open"
x-transition:enter="ease-in-out duration-500"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in-out duration-500"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
role="button"
@click="closeCartDrawer()"
aria-label="Close filters">
</div>
</div>
<script>
function initAuthentication() {
return {
open: false,
forceAuthentication: false,
checkoutUrl: 'https://www.arprotech.com/checkout/index/',
errors: 0,
hasCaptchaToken: 0,
displayErrorMessage: false,
errorMessages: [],
init() {
this.$root.classList.add('ready')
},
setErrorMessages: function setErrorMessages(messages) {
this.errorMessages = [messages]
this.displayErrorMessage = this.errorMessages.length
},
submitForm: function () {
// Do not rename $form, the variable is expected to be declared in the recaptcha output
const $form = document.querySelector('#login-form')
if (this.errors === 0) {
this.dispatchLoginRequest($form)
}
},
onPrivateContentLoaded: function (data) {
const isLoggedIn = data.customer && data.customer.firstname
if (data.cart && !isLoggedIn) {
this.forceAuthentication = !data.cart.isGuestCheckoutAllowed
}
},
redirectIfAuthenticated: function (event) {
if (event.detail && event.detail.url) {
this.checkoutUrl = event.detail.url
}
if (!this.forceAuthentication) {
window.location.href = this.checkoutUrl
}
},
dispatchLoginRequest: function (form) {
this.isLoading = true
const username = this.$refs['customer-email'].value
const password = this.$refs['customer-password'].value
const formKey = hyva.getFormKey()
const bodyFields = {
'username': username,
'password': password,
'formKey': formKey
}
const fieldName = 'g\u002Drecaptcha\u002Dresponse'
const recaptchaField = fieldName && form[fieldName]
if (recaptchaField) {
bodyFields[fieldName] = recaptchaField.value
}
fetch('https://www.arprotech.com/customer/ajax/login/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
body: JSON.stringify(bodyFields)
}
).then(response => {
return response.json()
}
).then(data => {
this.isLoading = false
if (data.errors) {
dispatchMessages([{
type: 'error',
text: data.message
}], 5000)
this.errors = 1
this.hasCaptchaToken = 0
} else {
window.location.href = this.checkoutUrl
}
})
}
}
}
</script>
<section id="authentication-popup"
x-data="initAuthentication()"
@private-content-loaded.window="onPrivateContentLoaded($event.detail.data)"
@toggle-authentication.window="open = forceAuthentication; redirectIfAuthenticated(event)"
@keydown.window.escape="open = false"
class="panel"
:class="{ 'invisible': !open }"
:aria-hidden="open ? 'false' : 'true'"
role="dialog"
aria-modal="true"
aria-hidden="false"
>
<div class="panel-wrapper">
<div class="panel-body"
x-show="open"
x-cloak=""
x-transition:enter="enter"
x-transition:enter-start="enter-start"
x-transition:enter-end="enter-end"
x-transition:leave="leave"
x-transition:leave-start="leave-start"
x-transition:leave-end="leave-end"
>
<button @click="open = false" class="panel-close"
aria-label="Close" title="Close filters" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
<div class="panel-content">
<div class="block-customer-login">
<h3 class="panel-title mb-5">Commandez en utilisant votre compte</h3>
<form class="form form-login"
method="post"
@submit.prevent="submitForm();"
id="login-form"
>
<div class="fieldset login">
<div class="field email required">
<label class="label" for="form-login-username" form="login-form">
<span>Adresse mail</span>
</label>
<div class="control">
<input name="username"
id="form-login-username"
x-ref="customer-email"
@change="errors = 0"
type="email"
required
autocomplete="off"
class="form-input input-text"
>
</div>
</div>
<div class="field password required">
<label for="form-login-password" class="label" form="login-form">
<span>Mot de passe</span>
</label>
<div class="control">
<input name="password"
id="form-login-password"
type="password"
class="form-input input-text"
required
x-ref="customer-password"
autocomplete="off"
@change="errors = 0"
>
</div>
</div>
<input name="context" type="hidden" value="checkout"/>
<div class="flex flex-col gap-5 items-center">
<a href="https://www.arprotech.com/customer/account/forgotpassword/"
class="text-sm hover:text-secondary transition-colors"
>
Mot de passe oublié ? </a>
<button
type="submit" class="inline-flex button button--primary w-full disabled:opacity-75"
>
Se connecter </button>
</div>
</div>
</form>
</div>
<div class="mx-4">
</div>
<div class="block-new-customer mt-10">
<h4 class="panel-title mb-5">Commander en tant que nouveau client</h4>
<div class="block-content">
<p class="mb-1">
Créer un compte a de nombreux avantages : </p>
<ul class="list-disc pl-5">
<li> Voir la commande et suivre l'expédition</li>
<li> Suivre l'historique des commandes</li>
<li> Commander plus rapidement</li>
</ul>
<a href="https://www.arprotech.com/customer/account/create/"
class="button w-full mt-5">
Créer un compte </a>
</div>
</div>
</div>
</div>
</div>
<div
class="backdrop"
aria-hidden="true"
x-cloak
x-show="open"
x-transition:enter="ease-in-out duration-500"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in-out duration-500"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@click="open = false"
></div>
</section>
</div>
<nav class="breadcrumbs" aria-label="Breadcrumb">
<div class="container px-0">
<ol class="items list-reset py-3 overflow-x-auto px-gutter whitespace-nowrap overflow-touch flex font-semibold text-xs uppercase tracking-wide">
<li class="item flex home">
<a href="https://www.arprotech.com/"
class="no-underline hover:text-secondary transition-colors"
title="Aller à la page d'accueil"
>Accueil</a>
</li>
<li class="item flex product">
<span aria-hidden="true" class="separator px-1">/</span>
<span
class="opacity-50"
aria-current="page"
>Bombe lacrymogène gel poivre Umarex P2P PDG-60 38ml</span>
</li>
</ol>
</div>
</nav>
</header><main id="maincontent" class="page-main"><div id="contentarea" tabindex="-1"></div>
<div class="columns"><div class="column main"><div class="product-info-main"><section class="product-detail">
<div class="flex lg:flex-row flex-col items-center">
<div
class="grid grid-rows-auto grid-cols-1 md:gap-x-5 md:grid-cols-[42%_minmax(0,_1fr)] md:grid-rows-[min-content_minmax(0,_1fr)] lg:gap-x-10 lg:grid-cols-2 w-full">
<div class="product-title product-detail-col">
<div class="page-title-wrapper">
<h1 class="page-title title-font"
>
<span class="base" data-ui-id="page-title-wrapper" >Bombe lacrymogène gel poivre Umarex P2P PDG-60 38ml</span> </h1>
</div>
</div>
<div id="gallery"
x-data="initGallery()"
x-bind="eventListeners"
class="w-full md:h-auto md:row-start-1 md:row-span-2 md:col-start-1"
:class="{'is-open': fullscreen}"
>
<div
class="gallery-wrapper"
:class="{'w-full h-full fixed top-0 left-0 bg-white z-50 flex': fullscreen}"
:role="fullscreen ? 'dialog' : false"
:aria-modal="fullscreen"
:aria-label="fullscreen ? 'Gallery\u0020modal\u0020fullscreen' : false"
>
<div class="gallery-viewer relative self-center w-full"
@touchstart.passive="handleTouchStart"
@touchmove.passive="handleTouchMove"
x-transition:enter="ease-out duration-500"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
>
<div class="gallery-viewer-item" aria-live="polite" aria-atomic="true">
<img
alt="Bombe lacrymogène gel poivre Umarex P2P PDG-60"
title="Bombe lacrymogène gel poivre Umarex P2P PDG-60"
class="object-contain object-center w-full h-auto max-h-screen-75"
:class="'invisible'"
src="https://www.arprotech.com/media/catalog/product/cache/3a8002a40b181f22fc5625c057de1cff/2/_/2_2065.jpg"
width="700"
height="700"
itemprop="image"
/>
<template x-for="(image, index) in images" :key="index">
<img
:alt="image.caption || 'Bombe\u0020lacrymog\u00E8ne\u0020gel\u0020poivre\u0020Umarex\u0020P2P\u0020PDG\u002D60\u002038ml'"
:title="image.caption || 'Bombe\u0020lacrymog\u00E8ne\u0020gel\u0020poivre\u0020Umarex\u0020P2P\u0020PDG\u002D60\u002038ml'"
class="absolute inset-0 object-contain object-center w-full m-auto max-h-screen-75"
width="700"
height="700"
:loading="active !== index ? 'lazy' : 'eager'"
:src="fullscreen ? image.full : image.img"
x-transition.opacity.duration.500ms
x-show="active === index"
/>
</template>
<button
type="button"
class="absolute inset-0 w-full outline-offset-2"
aria-label="Click to view image in fullscreen"
x-ref="galleryFullscreenBtn"
x-show="!fullscreen && images[active].type !== 'video'"
x-cloak
@click="openFullscreen()"
@keydown.enter="openFullscreen()"
></button>
<button
type="button"
class="group absolute inset-0 outline-offset-2 grid place-items-center"
aria-label="Play video"
x-show="images[active].type === 'video' && !activeVideoType"
x-cloak
@click="activateVideo()"
@keydown.enter="activateVideo()"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="stroke-white/75 fill-black/20 transition ease-in group-hover:scale-110 md:w-24 md:h-24" width="44" height="44" aria-hidden="true">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd"/>
</svg>
</button>
<div class="absolute inset-0 hidden w-full h-full bg-white nonmobile"
:class="{ 'hidden': activeVideoType !== 'youtube' }"
x-transition.opacity.duration.500ms
x-show="images[active].type === 'video' && activeVideoType === 'youtube'"
>
<div id="youtube-player" class="w-full h-full"></div>
</div>
<div class="absolute inset-0 hidden w-full h-full bg-white"
:class="{ 'hidden': activeVideoType !== 'vimeo' }"
x-transition.opacity.duration.500ms
x-show="images[active].type === 'video' && activeVideoType === 'vimeo'"
>
<div id="vimeo-player" class="w-full h-full"></div>
</div>
</div>
</div>
<div @resize.window.debounce="calcPageSize(); $nextTick(() => calcActive())">
<div
id="thumbs"
class="flex items-center gap-4"
:class="{ 'fixed justify-center bottom-0 left-0 right-0 m-gutter': fullscreen }"
x-show="images.length > 1"
x-cloak
>
<button
type="button"
aria-label="Précédent"
tabindex="-1"
class="p-2.5 flex items-center justify-center self-stretch text-black outline-none focus:outline-none flex-none"
:class="{ 'opacity-25 pointer-events-none' : isSliderStart, 'hidden' : !isSlider }"
aria-hidden="true"
@click="scrollPrevious"
><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">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7"/>
<title>chevron-left</title></svg>
</button>
<div class="js_thumbs_slides thumbs-wrapper relative flex flex-nowrap w-full overflow-auto js_slides snap"
x-ref="jsThumbSlides"
@scroll.debounce="calcPageSize(); calcActive(); calcScrollStartEnd()"
>
<template x-for="(image, index) in images" :key="index">
<div class="js_thumbs_slide flex shrink-0 mr-3 last:mr-0">
<button
type="button"
@click.prevent="setActive(index);"
class="relative block transition-colors border hover:border-black/50 focus:border-black p-1"
:class="{ 'border-black': active === index, 'border-black/20 ': active !== index }"
>
<span class="sr-only">
View larger image </span>
<img
:src="image.thumb"
:alt="hyva.str('%1 thumbnail', image.caption) || 'Bombe\u0020lacrymog\u00E8ne\u0020gel\u0020poivre\u0020Umarex\u0020P2P\u0020PDG\u002D60\u002038ml\u0020thumbnail'"
:title="hyva.str('%1 thumbnail', image.caption) || 'Bombe\u0020lacrymog\u00E8ne\u0020gel\u0020poivre\u0020Umarex\u0020P2P\u0020PDG\u002D60\u002038ml\u0020thumbnail'"
width="82"
height="82"
class="object-contain aspect-square"
/>
<span
class="absolute inset-0 grid place-items-center"
x-show="image.type === 'video'"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="2" stroke="currentColor" class="stroke-white/75 fill-black/20" width="44" height="44" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"/>
</svg>
</span>
</button>
</div>
</template>
</div>
<button
type="button"
x-show="images.length > 1"
x-cloak
aria-label="Suivant"
tabindex="-1"
class="p-2.5 flex items-center justify-center self-stretch text-black outline-none focus:outline-none flex-none"
:class="{ 'opacity-25 pointer-events-none' : isSliderEnd, 'hidden' : !isSlider }"
aria-hidden="true"
@click="scrollNext"
><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">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/>
<title>chevron-right</title></svg>
</button>
</div>
</div>
<div class="absolute top-0 right-0 pt-4 pr-4">
<button @click="closeFullScreen()"
type="button"
class="button button--primary button--icon gallery-close large"
aria-label="Close fullscreen"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
</div>
</div>
</div>
<script>
function initGallery () {
let touchXDown, touchYDown;
return {
"active": 0,
"videoData": {},
"activeVideoType": false,
"autoplayVideo": false,
"loopVideo": false,
"relatedVideos": false,
"vimeoPlayer": null,
"fullscreen": false,
"isSlider": false,
"initialImages": [{"thumb":"https:\/\/www.arprotech.com\/media\/catalog\/product\/cache\/a39c5478b3f662005fcb61a29e7c6ca5\/2\/_\/2_2065.jpg","img":"https:\/\/www.arprotech.com\/media\/catalog\/product\/cache\/3a8002a40b181f22fc5625c057de1cff\/2\/_\/2_2065.jpg","full":"https:\/\/www.arprotech.com\/media\/catalog\/product\/cache\/9378c97105d93a8cd10d61b7730cef91\/2\/_\/2_2065.jpg","caption":"Bombe lacrymog\u00e8ne gel poivre Umarex P2P PDG-60","position":"1","isMain":true,"type":"image","videoUrl":null}],
"images": [{"thumb":"https:\/\/www.arprotech.com\/media\/catalog\/product\/cache\/a39c5478b3f662005fcb61a29e7c6ca5\/2\/_\/2_2065.jpg","img":"https:\/\/www.arprotech.com\/media\/catalog\/product\/cache\/3a8002a40b181f22fc5625c057de1cff\/2\/_\/2_2065.jpg","full":"https:\/\/www.arprotech.com\/media\/catalog\/product\/cache\/9378c97105d93a8cd10d61b7730cef91\/2\/_\/2_2065.jpg","caption":"Bombe lacrymog\u00e8ne gel poivre Umarex P2P PDG-60","position":"1","isMain":true,"type":"image","videoUrl":null}],
"appendOnReceiveImages": true,
"activeSlide": 0,
"isSliderStart": true,
"isSliderEnd": false,
"itemCount": 0,
"pageSize": 4,
"pageFillers": 0,
"focusTrapListener": null,
init() {
this.initActive();
this.$nextTick(() => {
this.calcPageSize();
this.calcScrollStartEnd();
});
this.$watch('fullscreen', open => {
this.$nextTick(() => {
this.scrollLock(open);
window.requestAnimationFrame(() => {
this.calcPageSize()
});
});
})
},
receiveImages(images) {
if (this.appendOnReceiveImages) {
const initialUrls = this.initialImages.map(image => image.full);
const newImages = images.filter(image => ! initialUrls.includes(image.full));
this.images = [].concat(this.initialImages, newImages);
this.setActive(newImages.length ? this.initialImages.length : 0);
} else {
this.images = images;
this.setActive(0);
}
this.$nextTick(() => {
this.scrollTo(this.active);
});
this.itemCount = this.images.length;
},
resetGallery() {
this.images = this.initialImages;
this.itemCount = this.images.length;
this.initActive();
this.$nextTick(() => {
this.scrollTo(this.active);
});
},
initActive() {
let active = this.images.findIndex(function(image) {
return image.isMain === true
});
if (active === -1) {
active = 0;
}
this.setActive(active);
},
setActive(index) {
this.active = index;
this.activeVideoType = false;
if (window.youtubePlayer) {
window.youtubePlayer.stopVideo();
}
if (this.vimeoPlayer) {
this.vimeoPlayer.contentWindow.postMessage(JSON.stringify({"method": "pause"}), "*");
}
if (this.images[index].type === 'video' && this.autoplayVideo) {
this.activateVideo();
}
},
activateVideo() {
const videoData = this.getVideoData();
if (!videoData) { return }
this.activeVideoType = videoData.type;
if (videoData.type === "youtube") {
if (!window.youtubePlayer) {
this.initYoutubeAPI(videoData);
} else {
window.youtubePlayer.loadVideoById(videoData.id);
}
} else if (videoData.type === "vimeo") {
this.initVimeoVideo(videoData);
}
},
getVideoData() {
const videoUrl = this.images[this.active] && this.images[this.active].videoUrl;
if (!videoUrl) { return }
let id,
type,
youtubeRegex,
vimeoRegex,
useYoutubeNoCookie = false;
if (videoUrl.match(/youtube\.com|youtu\.be|youtube-nocookie.com/)) {
id = videoUrl.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, '');
type = 'youtube';
youtubeRegex = /^.*(?:(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/;
id = videoUrl.match(youtubeRegex)[1];
if (videoUrl.match(/youtube-nocookie.com/)) {
useYoutubeNoCookie = true;
}
} else if (videoUrl.match(/vimeo\.com/)) {
type = 'vimeo';
vimeoRegex = new RegExp(['https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)',
'?|groups\\/([^\\/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)'
].join(''));
id = videoUrl.match(vimeoRegex)[3];
}
return id ? {
id: id, type: type, useYoutubeNoCookie: useYoutubeNoCookie
} : false;
},
initYoutubeAPI(videoData) {
if (document.getElementById('loadYoutubeAPI')) {
return;
}
const params = {
"autoplay": true
};
const loadYoutubeAPI = document.createElement('script');
loadYoutubeAPI.src = 'https://www.youtube.com/iframe_api';
loadYoutubeAPI.id = 'loadYoutubeAPI';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(loadYoutubeAPI, firstScriptTag);
const host = (videoData.useYoutubeNoCookie) ?
'https://www.youtube-nocookie.com' :
'https://www.youtube.com';
if (!this.relatedVideos) {
params.rel = 0;
}
const fireYoutubeAPI = document.createElement('script');
fireYoutubeAPI.innerHTML = `function onYouTubeIframeAPIReady() {
window.youtubePlayer = new YT.Player('youtube-player', {
host: '${host}',
videoId: '${videoData.id}',
playerVars: ${JSON.stringify(params)},
});
}`;
firstScriptTag.parentNode.insertBefore(fireYoutubeAPI, firstScriptTag);
},
initVimeoVideo(videoData) {
let additionalParams = '&autoplay=1';
let src = '';
const timestamp = new Date().getTime();
const vimeoContainer = document.getElementById("vimeo-player");
const videoId = videoData.id;
if (!vimeoContainer || !videoId) return;
if (this.loopVideo) {
additionalParams += '&loop=1';
}
src = 'https://player.vimeo.com/video/' +
videoId + '?api=1&player_id=vimeo' +
videoId +
timestamp +
additionalParams;
vimeoContainer.innerHTML =
`<iframe id="${'vimeo' + videoId + timestamp}"
src="${src}"
width="640" height="360"
webkitallowfullscreen
mozallowfullscreen
allowfullscreen
referrerPolicy="origin"
allow="autoplay"
class="object-center w-full h-full object-fit"
></iframe>`;
this.vimeoPlayer = vimeoContainer.childNodes[0];
},
getSlider() {
return this.$refs.jsThumbSlides;
},
calcPageSize() {
const slider = this.getSlider();
if (slider) {
const slideEl = slider.querySelector('.js_thumbs_slide'),
marginRight = parseInt(window.getComputedStyle(slideEl).marginRight);
this.itemCount = slider.querySelectorAll('.js_thumbs_slide').length;
this.pageSize = Math.round(slider.clientWidth / (slideEl.clientWidth + marginRight));
this.pageFillers = (
this.pageSize * Math.ceil(this.itemCount / this.pageSize)
) - this.itemCount;
this.isSlider = ((slider.clientWidth - (this.itemCount * (slideEl.clientWidth + marginRight))) < 0);
}
},
calcScrollStartEnd() {
const slider = this.getSlider();
if (slider) {
this.isSliderStart = slider.scrollLeft === 0;
this.isSliderEnd = Math.ceil(slider.scrollLeft + slider.offsetWidth) >= slider.scrollWidth;
}
},
calcActive() {
const slider = this.getSlider();
if (slider) {
const sliderItems = this.itemCount + this.pageFillers;
const calculatedActiveSlide = slider.scrollLeft / (slider.scrollWidth / sliderItems);
this.activeSlide = Math.round(calculatedActiveSlide / this.pageSize) * this.pageSize;
}
},
scrollPrevious() {
this.scrollTo(this.activeSlide - this.pageSize);
},
scrollNext() {
this.scrollTo(this.activeSlide + this.pageSize);
},
scrollTo(idx) {
const slider = this.getSlider();
if (slider) {
const slideWidth = slider.scrollWidth / (this.itemCount + this.pageFillers);
slider.scrollLeft = Math.floor(slideWidth) * idx;
this.activeSlide = idx;
}
},
setActiveAndScrollTo(index) {
this.setActive(index)
if (this.isSlider) {
this.scrollTo(index);
}
},
eventListeners: {
['@keydown.window.escape']() {
if (!this.fullscreen) return;
this.closeFullScreen()
},
['@update-gallery.window'](event) {
this.receiveImages(event.detail);
},
['@reset-gallery.window'](event) {
this.resetGallery();
},
['@keyup.arrow-right.window']() {
if (!this.fullscreen) return;
this.nextItem();
},
['@keyup.arrow-left.window']() {
if (!this.fullscreen) return;
this.previousItem();
},
},
scrollLock(use = true) {
document.body.style.overflow = use ? "hidden" : "";
},
openFullscreen() {
this.fullscreen = true;
hyva.trapFocus(this.$root);
},
closeFullScreen(setFocusTo = this.$refs.galleryFullscreenBtn) {
this.fullscreen = false;
hyva.releaseFocus(this.$root);
this.$nextTick(() => {
this.calcPageSize();
setFocusTo && setFocusTo.focus()
});
},
handleTouchStart(event) {
if (this.images.length <= 1) {
return;
}
const firstTouch = event.touches[0];
touchXDown = firstTouch.clientX;
touchYDown = firstTouch.clientY;
},
handleTouchMove(event) {
if (this.images.length <= 1 || !touchXDown || !touchYDown) {
return;
}
const xDiff = touchXDown - event.touches[0].clientX;
const yDiff = touchYDown - event.touches[0].clientY;
if (Math.abs(xDiff) > Math.abs(yDiff)) {
const newIndex = xDiff > 0 ? this.getNextIndex() : this.getPreviousIndex();
this.setActiveAndScrollTo(newIndex)
}
touchXDown = touchYDown = null;
},
getPreviousIndex() {
return this.active > 0 ? this.active - 1 : this.itemCount - 1;
},
getNextIndex() {
return this.active + 1 === this.itemCount ? 0 : this.active + 1;
},
previousItem() {
if (this.active === 0) return;
this.setActiveAndScrollTo(this.active - 1);
},
nextItem() {
if ((this.active + 1) === this.itemCount) return;
this.setActiveAndScrollTo(this.active + 1);
},
}
}
</script>
<div class="product-info product-detail-col">
<dl id="product-attributes">
<div class="flex gap-1 attribute-sku">
<dt class="product-detail-label text-label">
Référence :
</dt>
<dd class="product-detail-value text-label">
2.2065-IWA26 </dd>
</div>
<div class="flex gap-1 attribute-catgorie-arme">
<dt class="product-detail-label text-label">
Catégorie d'arme :
</dt>
<dd class="product-detail-value text-label">
D libre +18 ans </dd>
</div>
</dl>
<div class="flex flex-col gap-2">
<div role="group" aria-label="Price">
<script>
function initPrice30525() {
const regularPriceInclTaxKey = 'oldPrice',
regularPriceExclTaxKey = 'baseOldPrice',
finalPriceInclTaxKey = 'finalPrice',
finalPriceExclTaxKey = 'basePrice'
function calculateCustomOptionPrices(activeCustomOptions, customOptionPrices) {
return activeCustomOptions.reduce((priceAccumulator, activeCustomOptionId) => {
const customOptionPrice = customOptionPrices[activeCustomOptionId]
if (customOptionPrice) {
return Number.parseFloat(priceAccumulator) + Number.parseFloat(customOptionPrice)
}
return priceAccumulator
}, 0)
}
return {
regularPriceKey: regularPriceInclTaxKey,
finalPriceKey: finalPriceInclTaxKey,
activeProductsPriceData: false,
initialFinalPrice: 7.95,
calculatedFinalPrice: false,
calculatedFinalPriceWithCustomOptions: false,
initialTierPrices: [],
showRegularPriceLabel: false,
customOptionPrices: [],
activeCustomOptions: [],
qty: 1,
updateCustomOptionActive(data) {
let activeCustomOptions = this.activeCustomOptions
const customOptionId = data.customOptionId
if (data.active) {
if (!activeCustomOptions.includes(customOptionId)) {
activeCustomOptions.push(data.customOptionId)
}
} else {
if (customOptionId && activeCustomOptions.includes(customOptionId)) {
let index = activeCustomOptions.indexOf(customOptionId)
activeCustomOptions.splice(index, 1)
}
}
this.calculateFinalPriceWithCustomOptions()
},
updateCustomOptionPrices(prices, basePrices) {
if (prices) {
this.customOptionPrices = prices
}
this.calculateFinalPriceWithCustomOptions()
},
calculateFinalPrice() {
const getOptionTierPrice = (tierPrice, withTax) => {
return tierPrice[withTax ? 'price' : 'basePrice']
}
const findApplicableTierPrice = (initialPrice, withTax) => {
if (this.activeProductsPriceData && this.activeProductsPriceData.tierPrices) {
return this.activeProductsPriceData.tierPrices.reduce((acc, tierPrice) => {
const tierPriceCandidate = getOptionTierPrice(tierPrice, withTax)
if (this.qty >= tierPrice.qty && tierPriceCandidate < acc) {
return tierPriceCandidate
}
return acc
}, this.activeProductsPriceData[withTax ? finalPriceInclTaxKey : finalPriceExclTaxKey].amount)
} else {
const key = withTax ? 'price_incl_tax' : 'price_excl_tax'
return Object.values(this.initialTierPrices).reduce((acc, tierPrice) => {
if (this.qty >= tierPrice.price_qty && tierPrice[key] < acc) {
return tierPrice[key]
}
return acc
}, initialPrice)
}
}
this.calculatedFinalPrice = findApplicableTierPrice(this.initialFinalPrice, true)
window.dispatchEvent(new CustomEvent('update-product-final-price', {detail: this.calculatedFinalPrice}))
},
calculatePriceLabelVisibility() {
this.showRegularPriceLabel =
(this.calculatedFinalPrice === this.activeProductsPriceData[this.regularPriceKey].amount) &&
this.activeProductsPriceData.isMinimalPrice
},
calculateFinalPriceWithCustomOptions() {
const finalPrice = this.calculatedFinalPrice || this.initialFinalPrice
this.calculatedFinalPriceWithCustomOptions = finalPrice + this.getCustomOptionPrice()
},
getCustomOptionPrice() {
return calculateCustomOptionPrices(this.activeCustomOptions, this.customOptionPrices)
},
getFormattedFinalPrice() {
return hyva.formatPrice(
this.calculatedFinalPriceWithCustomOptions ||
this.calculatedFinalPrice ||
this.initialFinalPrice
)
},
isPriceHidden() {
const finalPrice = this.calculatedFinalPriceWithCustomOptions ||
this.calculatedFinalPrice ||
this.initialFinalPrice
return true && finalPrice === 0
},
eventListeners: {
['@update-prices-30525.window'](event) {
this.activeProductsPriceData = event.detail
this.calculateFinalPrice()
this.calculateFinalPriceWithCustomOptions()
this.calculatePriceLabelVisibility()
},
['@update-qty-30525.window'](event) {
this.qty = event.detail
this.calculateFinalPrice()
this.calculateFinalPriceWithCustomOptions()
},
['@update-custom-option-active.window'](event) {
this.updateCustomOptionActive(event.detail)
},
['@update-custom-option-prices.window'](event) {
this.updateCustomOptionPrices(event.detail)
},
}
}
}
</script>
<div x-data="initPrice30525()"
x-bind="eventListeners"
class="price-box price-final_price"
>
<div x-show="!activeProductsPriceData && !isPriceHidden()">
<div class="price-container">
<div class="final-price inline-block relative" itemprop="offers" itemscope="" itemtype="http://schema.org/Offer">
<span id="product-price-30525"
class="price-wrapper text-style-1">
<span class="price" x-html="getFormattedFinalPrice()">
<span class="price">7,95 €</span> </span>
</span>
<meta itemprop="price" content="7.95">
<meta itemprop="priceCurrency"
content="EUR">
</div>
</div>
</div>
<template x-if="activeProductsPriceData && activeProductsPriceData.oldPrice && activeProductsPriceData[finalPriceKey].amount < activeProductsPriceData[regularPriceKey].amount ">
<div class="old-price flex mr-2">
<span id="product-price-30525"
class="price-wrapper text-style-1">
<span class="price"
x-html="hyva.formatPrice(activeProductsPriceData[regularPriceKey].amount + getCustomOptionPrice())"></span>
</span>
</div>
</template>
<template x-if="activeProductsPriceData">
<div class="final-price inline-block relative">
<span id="product-price-30525"
class="price-wrapper text-style-1">
<span class="price" x-html="getFormattedFinalPrice()"></span>
</span>
</div>
</template>
</div>
</div>
<div
x-data="initRating3052569d838a5b6880()"
x-defer="intersect"
@keyup.enter="scrollToRatings()"
@click="scrollToRatings()"
class="rating-summary full flex gap-2"
:class="{'cursor-pointer' : reviewsSection}"
title=" Soyez le premier à commenter ce produit"
:tabindex="reviewsSection ? '0' : '-1'"
:aria-label="reviewsSection ? 'Bombe\u0020lacrymog\u00E8ne\u0020gel\u0020poivre\u0020Umarex\u0020P2P\u0020PDG\u002D60\u002038ml\u0020rating.\u00200\u0020out\u0020of\u00205\u0020stars.\u0020Click\u0020to\u0020go\u0020to\u0020reviews.' : 'Bombe\u0020lacrymog\u00E8ne\u0020gel\u0020poivre\u0020Umarex\u0020P2P\u0020PDG\u002D60\u002038ml\u0020rating.\u00200\u0020out\u0020of\u00205\u0020stars' "
:role="reviewsSection ? 'button' : 'img'"
>
<div class="flex items-center gap-0.5">
<svg
xmlns="http://www.w3.org/2000/svg"
class="fill-current text-black/25"
width="14"
height="13"
viewbox="0 0 14 13"
fill="currentColor"
aria-hidden="true"
>
<path
d="M6.52772 0.358694C6.68337 -0.0890865 7.31663 -0.0890864 7.47228 0.358694L8.76668 4.0825C8.83534 4.28004 9.01969 4.41397 9.22877 4.41823L13.1703 4.49856C13.6443 4.50822 13.84 5.11049 13.4622 5.39689L10.3206 7.77865C10.154 7.905 10.0836 8.12171 10.1441 8.32188L11.2857 12.0953C11.423 12.5491 10.9107 12.9213 10.5216 12.6505L7.28559 10.3987C7.11393 10.2793 6.88607 10.2793 6.71441 10.3987L3.47842 12.6505C3.0893 12.9213 2.57698 12.5491 2.71425 12.0953L3.85587 8.32188C3.91643 8.12171 3.84601 7.905 3.67936 7.77865L0.537799 5.39689C0.160033 5.11049 0.355723 4.50822 0.829685 4.49856L4.77123 4.41823C4.98031 4.41397 5.16466 4.28004 5.23332 4.0825L6.52772 0.358694Z"/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
class="fill-current text-black/25"
width="14"
height="13"
viewbox="0 0 14 13"
fill="currentColor"
aria-hidden="true"
>
<path
d="M6.52772 0.358694C6.68337 -0.0890865 7.31663 -0.0890864 7.47228 0.358694L8.76668 4.0825C8.83534 4.28004 9.01969 4.41397 9.22877 4.41823L13.1703 4.49856C13.6443 4.50822 13.84 5.11049 13.4622 5.39689L10.3206 7.77865C10.154 7.905 10.0836 8.12171 10.1441 8.32188L11.2857 12.0953C11.423 12.5491 10.9107 12.9213 10.5216 12.6505L7.28559 10.3987C7.11393 10.2793 6.88607 10.2793 6.71441 10.3987L3.47842 12.6505C3.0893 12.9213 2.57698 12.5491 2.71425 12.0953L3.85587 8.32188C3.91643 8.12171 3.84601 7.905 3.67936 7.77865L0.537799 5.39689C0.160033 5.11049 0.355723 4.50822 0.829685 4.49856L4.77123 4.41823C4.98031 4.41397 5.16466 4.28004 5.23332 4.0825L6.52772 0.358694Z"/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
class="fill-current text-black/25"
width="14"
height="13"
viewbox="0 0 14 13"
fill="currentColor"
aria-hidden="true"
>
<path
d="M6.52772 0.358694C6.68337 -0.0890865 7.31663 -0.0890864 7.47228 0.358694L8.76668 4.0825C8.83534 4.28004 9.01969 4.41397 9.22877 4.41823L13.1703 4.49856C13.6443 4.50822 13.84 5.11049 13.4622 5.39689L10.3206 7.77865C10.154 7.905 10.0836 8.12171 10.1441 8.32188L11.2857 12.0953C11.423 12.5491 10.9107 12.9213 10.5216 12.6505L7.28559 10.3987C7.11393 10.2793 6.88607 10.2793 6.71441 10.3987L3.47842 12.6505C3.0893 12.9213 2.57698 12.5491 2.71425 12.0953L3.85587 8.32188C3.91643 8.12171 3.84601 7.905 3.67936 7.77865L0.537799 5.39689C0.160033 5.11049 0.355723 4.50822 0.829685 4.49856L4.77123 4.41823C4.98031 4.41397 5.16466 4.28004 5.23332 4.0825L6.52772 0.358694Z"/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
class="fill-current text-black/25"
width="14"
height="13"
viewbox="0 0 14 13"
fill="currentColor"
aria-hidden="true"
>
<path
d="M6.52772 0.358694C6.68337 -0.0890865 7.31663 -0.0890864 7.47228 0.358694L8.76668 4.0825C8.83534 4.28004 9.01969 4.41397 9.22877 4.41823L13.1703 4.49856C13.6443 4.50822 13.84 5.11049 13.4622 5.39689L10.3206 7.77865C10.154 7.905 10.0836 8.12171 10.1441 8.32188L11.2857 12.0953C11.423 12.5491 10.9107 12.9213 10.5216 12.6505L7.28559 10.3987C7.11393 10.2793 6.88607 10.2793 6.71441 10.3987L3.47842 12.6505C3.0893 12.9213 2.57698 12.5491 2.71425 12.0953L3.85587 8.32188C3.91643 8.12171 3.84601 7.905 3.67936 7.77865L0.537799 5.39689C0.160033 5.11049 0.355723 4.50822 0.829685 4.49856L4.77123 4.41823C4.98031 4.41397 5.16466 4.28004 5.23332 4.0825L6.52772 0.358694Z"/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
class="fill-current text-black/25"
width="14"
height="13"
viewbox="0 0 14 13"
fill="currentColor"
aria-hidden="true"
>
<path
d="M6.52772 0.358694C6.68337 -0.0890865 7.31663 -0.0890864 7.47228 0.358694L8.76668 4.0825C8.83534 4.28004 9.01969 4.41397 9.22877 4.41823L13.1703 4.49856C13.6443 4.50822 13.84 5.11049 13.4622 5.39689L10.3206 7.77865C10.154 7.905 10.0836 8.12171 10.1441 8.32188L11.2857 12.0953C11.423 12.5491 10.9107 12.9213 10.5216 12.6505L7.28559 10.3987C7.11393 10.2793 6.88607 10.2793 6.71441 10.3987L3.47842 12.6505C3.0893 12.9213 2.57698 12.5491 2.71425 12.0953L3.85587 8.32188C3.91643 8.12171 3.84601 7.905 3.67936 7.77865L0.537799 5.39689C0.160033 5.11049 0.355723 4.50822 0.829685 4.49856L4.77123 4.41823C4.98031 4.41397 5.16466 4.28004 5.23332 4.0825L6.52772 0.358694Z"/>
</svg>
</div>
<p class="text-sm leading-none">0 commentaire</p>
</div>
<script>
'use strict'
function initRating3052569d838a5b6880() {
return {
reviewsSection: document.getElementById('tab-product-review-wrapper'),
scrollToRatings() {
let scrollTimeout = null
if (!this.reviewsSection) {
return
}
addEventListener('scroll', () => {
clearTimeout(scrollTimeout)
scrollTimeout = setTimeout(() => {
if (this.reviewsSection) {
this.reviewsSection.focus()
}
}, 50)
}, {once: true})
document.querySelector('[aria-controls="tab-product-review-wrapper"]').click()
// this.reviewsSection.scrollIntoView({
// behavior: 'smooth',
// block: 'start'
// })
}
}
}
</script>
</div>
<div
class="flex flex-col product-cart-info"
>
<div class="flex flex-col sm:flex-row justify-end gap-5 z-[1] relative">
</div>
<div class="product-status-wrapper">
<div class="product-status">
<div class="amnotif-container w-full"><div class="amxnotif-block-wrapper w-full flex flex-col gap-1">
<p class="flex items-center align-middle gap-x-2 unavailable stock"
title="Disponibilité">
<span class="w-3 h-3 bg-red rounded-full flex-shrink-0"></span>
<span class="text-label"> Nous contacter</span>
</p>
</div>
<div class="amxnotif-block-wrapper w-full mt-2">
<div class="amxnotif-block"
x-data="amXnotifSubscribeComponent_30525()"
>
<div class="flex flex-row justify-center items-center w-full h-full fixed select-none z-50"
style="left: 50%;top: 50%;transform: translateX(-50%) translateY(-50%);background: rgba(255,255,255,0.9);"
x-show="isLoading"
x-cloak
x-transition:enter="ease-out duration-200"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0">
<svg xmlns="http://www.w3.org/2000/svg"
width="54"
height="54"
viewbox="0 0 60 55" xml:space="preserve">
<rect x="20" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="30" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.2s" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="40" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml"
attributename="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.4s" dur="0.6s" repeatcount="indefinite"/>
</rect>
</svg>
<div class="ml-3 text-style-6">
En cours de chargement... </div>
</div>
<div :id="'form-validate-stock' + ('' ? groupedIndex : productIdentifier)"
class="amxnotif-form-stock"
x-show="groupedIndex && '' ? true : !isInStock ">
<input name="form_key" type="hidden" value="eTB4IhRhBQzWlDue" />
<label :for="'amxnotif-guest-email-' +('' ? groupedIndex : productIdentifier)" class="text-sm mb-2 block">
Enregistrez-vous pour recevoir une alerte de disponibilité </label>
<div class="notification-container flex gap-4"
:id="'notification-container-' + ('' ? groupedIndex : productIdentifier)">
<div class="input-fields fieldset flex-1">
<input type="email"
name="guest_email"
:id="'amxnotif-guest-email-' + ('' ? groupedIndex : productIdentifier)"
class="form-input amxnotif-guest-email w-full"
x-model="emailInput"
x-ref="emailElement"
placeholder="Mettez votre email"
/>
<input type="hidden" name="product_id"
:value="('' ? groupedIndex : productIdentifier)"/>
<input type="hidden" name="type" value="email"/>
<input type="hidden"
name="uenc"
value="aHR0cHM6Ly93d3cuYXJwcm90ZWNoLmNvbS9ib21iZS1sYWNyeW1vZ2VuZS1nZWwtcG9pdnJlLXVtYXJleC1wMnAtcGRnLTYwLmh0bWw~"/>
</div>
<div class="amxnotif_guest_action">
<button type="button"
class="button button--primary large"
@click.prevent="fetchSubscribe('stock', ('' ? groupedIndex : productIdentifier))"
>
<span>Valider</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</div>
</div>
<script>
function initWishlist_69d838a5b7437() {
return {
addToWishlist(productId) {
const postParams = {
action: BASE_URL + "wishlist/index/add/",
data: {
product: productId,
uenc: hyva.getUenc()
}
}
postParams.data['form_key'] = hyva.getFormKey();
postParams.data['qty'] = document.getElementById(`qty[${productId}]`)
? document.getElementById(`qty[${productId}]`).value || 1
: 1;
let postData = Object.keys(postParams.data).map(key => {
return `${key}=${postParams.data[key]}`;
}).join('&');
// take the all the input fields that configure this product
// includes custom, configurable, grouped and bundled options
Array.from(document.querySelectorAll(
'[name^=options], [name^=super_attribute], [name^=bundle_option], [name^=super_group], [name^=links]')
).map(input => {
if (input.type === "select-multiple") {
Array.from(input.selectedOptions).forEach(option => {
postData += `&${input.name}=${option.value}`
})
} else {
// skip "checkable inputs" that are not checked
if(!(['radio', 'checkbox', 'select'].includes(input.type) && !input.checked)) {
postData += `&${input.name}=${input.value}`
}
}
});
fetch(postParams.action, {
"headers": {
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
},
"body": postData,
"method": "POST",
"mode": "cors",
"credentials": "include"
}).then((response) => {
if (response.redirected) {
window.location.href = response.url;
} else if (response.ok) {
return response.json();
} else {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "warning",
text: "Could not add item to wishlist."
}], 5000
);
}
}).then((response) => {
if (!response) {
return;
}
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: (response.success) ? "success" : "error",
text: (response.success)
? "Produit a été ajouté à votre liste d'achats."
: response.error_message
}], 5000
);
const reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data");
window.dispatchEvent(reloadCustomerDataEvent);
}).catch((error) => {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "error",
text: error
}], 5000
);
});
}
}
}
</script>
<button x-data="initWishlist_69d838a5b7437()"
x-defer="intersect"
@click.prevent="addToWishlist(30525)"
title="Ajouter à la liste de souhait"
aria-label="Ajouter à la liste de souhait"
id="add-to-wishlist"
class="rounded-full w-10 h-10 bg-gray-200 p-0 border-0 inline-flex items-center justify-center text-gray-500 hover:text-red-600 ml-4"
data-addto="wishlist"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="20" height="20" aria-hidden="true">
<path fill-rule="evenodd" d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z" clip-rule="evenodd"/>
</svg>
</button>
<div class="amshopby-option-link flex flex-col sm:flex-row items-start" x-data="initBrandNavigation()">
<a href="https://www.arprotech.com/umarex"
title="Umarex"
aria-labelledby="amshopby-option-id-69d838a5b833c-30525"
>
<span
id="amshopby-option-id-69d838a5b833c-30525"
role="button"
aria-label="Umarex"
>
<img title="Umarex"
class="brand-image"
alt="Umarex"
src="https://www.arprotech.com/media/images/cache/amasty/shopby/option_images/slider/resized/200x100/umarexred.jpg"/>
</span>
</a>
<div class="link-short-description text-sm">
Umarex est devenu en 50 ans le plus grand fabricant au monde de répliques d'armes.Après avoir acheté leurs licences, il fabrique les répliques de certains calibres des marques Mauser, Walther, HK, Beretta, Colt, Smith & Wesson, Magnum Research, Ruger, Hammerli et Röhm. <span class="inline cursor-pointer underline"
@click="openFilters()"
x-ref="brandTrigger"
type="button"
aria-controls="brand-content"
aria-haspopup="menu"
:aria-expanded="open"
:hidden="open"
>
Lire la description complète </span>
</div>
<div
x-ref="brandContent"
id="brand-content"
class="panel"
:class="{ 'invisible': !open }"
:aria-hidden="open ? 'false' : 'true'"
role="dialog"
aria-modal="true"
aria-hidden="false"
>
<div class="panel-wrapper">
<div
class="panel-body"
x-show="open"
x-transition:enter="enter"
x-transition:enter-start="enter-start"
x-transition:enter-end="enter-end"
x-transition:leave="leave"
x-transition:leave-start="leave-start"
x-transition:leave-end="leave-end"
role="region"
:tabindex="open ? 0 : -1"
aria-label="Site navigatielinks"
tabindex="0">
<div x-ref="mobileMenuContainer"
class="panel-content">
<div
class="panel-title">
<p>Description de la marque UMAREX</p>
<img title="Umarex"
class="brand-image"
alt="Umarex"
src="https://www.arprotech.com/media/images/cache/amasty/shopby/option_images/slider/resized/200x100/umarexred.jpg"/>
</div>
<p><strong>Umarex</strong> a été créé en 1949 sous sa première dénomination "Mayer & Riem Kg". En 1977, la société achète la fabrique d'armes Reck et en 1981 elle devient définitivement "<strong>Umarex</strong> Sportwafen GmbH & Co".</p>
<p>"<em>Cela a commencé avec des répliques</em>" : Le courage de s'engager sur de nouvelles voies a été démontré par les fondateurs d'<strong>Umarex</strong>. Lorsque la législation a été adoptée pour restreindre la vente d'armes létales, <strong>Umarex</strong> a acquis des licences pour construire et vendre librement des répliques. Cela lui a ouvert la voie de l'avenir.<br /><em>Ouvrir la voie vers de nouveaux horizons (</em>Franz Kafka), voici son principe directeur.</p>
<p><strong>Umarex</strong> a grandi pour devenir le plus grand fabricant au monde de répliques d'armes et forme le noyau du groupe d'entreprises en expansion nommé Groupe PW depuis 2010, composé de C. Walther, Umarex USA, Umarex Austria, Umarex et PW Tobacco.<br />Depuis 1983, <strong>Umarex</strong> a acquis les licences de <strong>Mauser</strong> (1983), <strong>Browning</strong> (1984), <strong>Carl Walther</strong> et <strong>HK</strong> (1990), <strong>Beretta</strong>, <strong>Colt</strong> et <strong>Smith & Wesson</strong> (1996), <strong>Magnum Research</strong> (2003), <strong>Ruger</strong> (2007), pour fabriquer les répliques de certains calibres.<br />De plus, <strong>Umarex</strong> a acheté en 2006 l'entreprise suisse <strong>Hammerli</strong> et en 2010 la division "Armes à feu" de <strong>Röhm</strong> GmbH.
<br />Retrouvez le site internet de la marque et leurs produits <a title="Marque Umarex" href="https://www.umarex.de" target="_blank" rel="noopener">en cliquant ici</a></p> </div>
<button @click="closeFilters()" class="panel-close"
aria-label="Close" title="Close" type="button">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
</div>
</div>
<div
class="backdrop cursor-default"
x-show="open"
x-transition:enter="ease-in-out duration-500"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in-out duration-500"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
role="button"
@click="closeFilters()"
aria-label="Close filters">
</div>
</div>
</div>
<script>
function initBrandNavigation() {
return {
open: false,
init() {
this.$refs.brandContent.classList.add('ready')
},
openFilters() {
this.open = true
this.$nextTick(() => setTimeout(() => hyva.trapFocus(this.$refs['brandContent']), 500))
},
closeFilters() {
if (this.open) {
this.$nextTick(() => this.$refs['brandTrigger'].focus() || hyva.releaseFocus())
}
this.open = false
}
}
}
</script>
</div>
</div>
</div>
</section>
<section>
<div class="product-options-bottom container flex flex-col md:flex-row flex-no-wrap gap-4">
</div>
</section>
<div x-data="initProductSections" class="product-sections">
<nav
class="hidden lg:flex snap overflow-x-auto overscroll-x-contain"
aria-label="Navigate to Product Section"
x-show="items.length"
>
<template x-for="tab in items">
<button
type="button"
class="tab"
:aria-expanded="sectionItemIsOpen(tab.id)"
:aria-controls="tab.id"
@click="openSectionItem(tab.id)"
x-text="tab.getAttribute('data-name')"
></button>
</template>
</nav>
<div
x-ref="accordion"
style="min-height: 500px"
>
<details
id="tab-description"
data-name="Description"
x-data="{ id: $el.id }"
class="tab-content"
:open="sectionItemIsOpen(id)"
>
<summary
@click.prevent="openSectionItem(id, true)"
class="tab-content-title"
>
<span>Description</span>
<span class="transition-transform group-open:rotate-180">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 6.414 8.5 8.5 1.328-1.5-7-7H2Z"/>
<path d="m10.47 14.914 7.086-7.086V5l-7.086 7.086v2.828Z"/>
</svg>
</span>
</summary>
<div x-show="sectionItemIsOpen(id)" x-collapse>
<div class="pb-3">
<div class="prose prose-slate max-w-full prose-h2:text-xl prose-h3:text-lg prose-h4:text-base prose-headings:first:mt-0">
<style>#html-body [data-pb-style=V17RB1W]{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="V17RB1W"><div data-content-type="text" data-appearance="default" data-element="main"><p><a class="am-crosslink" href="https://www.arprotech.com/arme-de-defense/aerosol" title="https://www.arprotech.com/arme-de-defense/aerosol" target="_self">Bombe lacrymogène</a> gel poivre <a class="am-crosslink" href="https://www.arprotech.com/umarex" title="umarex" target="_self">Umarex</a> P2P PDG-60 <br>Nouveauté Umarex 2026 </p>
<p>Le P2P PDG-60 est un gel de défense au poivre en format classique, contenant 10% d'OC. <br>Sa formule en gel collant ne s'enlève pas facilement et renforce l'effet du produit actif. <br>Buse balistique pour une visée précise. <br>Il est équipé d'un levier de sécurité, pour un transport en toute sécurité. <br>Distance d'efficacité : 4,5 mètres <br>Contenance (en ml) : 38 <br>Fabricant : Umarex <br>Hauteur (mm) : 117 <br>Marque : Umarex <br>Poids (g) : 67</p></div></div></div></div>
</div>
</div>
</details>
<details
id="tab-product-attributes"
data-name="Plus d'infos"
x-data="{ id: $el.id }"
class="tab-content"
:open="sectionItemIsOpen(id)"
>
<summary
@click.prevent="openSectionItem(id, true)"
class="tab-content-title"
>
<span>Plus d'infos</span>
<span class="transition-transform group-open:rotate-180">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 6.414 8.5 8.5 1.328-1.5-7-7H2Z"/>
<path d="m10.47 14.914 7.086-7.086V5l-7.086 7.086v2.828Z"/>
</svg>
</span>
</summary>
<div x-show="sectionItemIsOpen(id)" x-collapse>
<div class="pb-3">
<div class="table-wrapper overflow-x-auto" id="product-attributes">
<table class="additional-attributes table-fixed w-full">
<tr class="border-b border-black/20 last:border-b-0 odd:bg-black/5 block lg:table-row">
<th
class="col label product-attribute-label text-start font-semibold break-words hyphens-auto block lg:table-cell pt-3 lg:py-2 px-3"
scope="row"
>Catégorie arme</th>
<td
class="col data product-attribute-value text-start break-words hyphens-auto block lg:table-cell pb-3 lg:py-2 px-3"
data-th="Catégorie arme"
>D libre +18 ans</td>
</tr>
<tr class="border-b border-black/20 last:border-b-0 odd:bg-black/5 block lg:table-row">
<th
class="col label product-attribute-label text-start font-semibold break-words hyphens-auto block lg:table-cell pt-3 lg:py-2 px-3"
scope="row"
>Contenance (en ml)</th>
<td
class="col data product-attribute-value text-start break-words hyphens-auto block lg:table-cell pb-3 lg:py-2 px-3"
data-th="Contenance (en ml)"
>38</td>
</tr>
<tr class="border-b border-black/20 last:border-b-0 odd:bg-black/5 block lg:table-row">
<th
class="col label product-attribute-label text-start font-semibold break-words hyphens-auto block lg:table-cell pt-3 lg:py-2 px-3"
scope="row"
>Fabricant</th>
<td
class="col data product-attribute-value text-start break-words hyphens-auto block lg:table-cell pb-3 lg:py-2 px-3"
data-th="Fabricant"
><a class="am-crosslink" href="https://www.arprotech.com/umarex" title="umarex" target="_self">Umarex</a></td>
</tr>
<tr class="border-b border-black/20 last:border-b-0 odd:bg-black/5 block lg:table-row">
<th
class="col label product-attribute-label text-start font-semibold break-words hyphens-auto block lg:table-cell pt-3 lg:py-2 px-3"
scope="row"
>Hauteur (mm)</th>
<td
class="col data product-attribute-value text-start break-words hyphens-auto block lg:table-cell pb-3 lg:py-2 px-3"
data-th="Hauteur (mm)"
>117</td>
</tr>
<tr class="border-b border-black/20 last:border-b-0 odd:bg-black/5 block lg:table-row">
<th
class="col label product-attribute-label text-start font-semibold break-words hyphens-auto block lg:table-cell pt-3 lg:py-2 px-3"
scope="row"
>Marque</th>
<td
class="col data product-attribute-value text-start break-words hyphens-auto block lg:table-cell pb-3 lg:py-2 px-3"
data-th="Marque"
><a class="am-crosslink" href="https://www.arprotech.com/umarex" title="umarex" target="_self">Umarex</a></td>
</tr>
<tr class="border-b border-black/20 last:border-b-0 odd:bg-black/5 block lg:table-row">
<th
class="col label product-attribute-label text-start font-semibold break-words hyphens-auto block lg:table-cell pt-3 lg:py-2 px-3"
scope="row"
>Poids (g)</th>
<td
class="col data product-attribute-value text-start break-words hyphens-auto block lg:table-cell pb-3 lg:py-2 px-3"
data-th="Poids (g)"
>67,00 </td>
</tr>
</table>
</div>
</div>
</div>
</details>
<details
id="tab-moins-cher-tab"
data-name="Moins cher ?"
x-data="{ id: $el.id }"
class="tab-content"
:open="sectionItemIsOpen(id)"
>
<summary
@click.prevent="openSectionItem(id, true)"
class="tab-content-title"
>
<span>Moins cher ?</span>
<span class="transition-transform group-open:rotate-180">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 6.414 8.5 8.5 1.328-1.5-7-7H2Z"/>
<path d="m10.47 14.914 7.086-7.086V5l-7.086 7.086v2.828Z"/>
</svg>
</span>
</summary>
<div x-show="sectionItemIsOpen(id)" x-collapse>
<div class="pb-3">
<div class="grid grid-cols-1 gap-8 md:grid-cols-2">
<div class="moinscher-form">
<div class="text-xl my-3">
Vous avez trouvé notre produit moins cher ailleurs ?
</div>
<p>
Toujours soucieux de vous apporter des services à la hauteur de vos attentes, ARprotech met à votre disposition
ce localisateur de prix.<br>
Vous avez trouvé un article moins cher sur Internet (revendeur France uniquement hors promotion, soldes, article
en rupture de stock, etc...), nous vous invitons à nous faire connaître le fruit de vos recherches. Il vous
suffit de remplir le formulaire ci-dessous..
</p>
<form
id="moinscher-form"
method="post"
@submit.prevent="submitForm()"
action=""
x-data="initMoinsCherForm()"
x-defer="intersect"
>
<fieldset >
<div>
<div class="mt-3">
<label for="clientEmail" >
<span>Votre email </span>
</label>
<div>
<input class="form-input block w-full"
required
placeholder="Votre email*" type="email"
name="email" id="clientEmail">
</div>
</div>
<div class="mt-3">
<label for="concurrentPrix" >
<span>Prix Concurrent </span>
</label>
<div>
<input class="form-input block w-full"
required
type="text"
name="concurrentPrix" id="concurrentPrix">
</div>
</div>
<div class="mt-3">
<label for="concurrentUrl" >
<span>URL exacte produit concurrent </span>
</label>
<div>
<input class="form-input block w-full"
required
type="url"
placeholder="https://"
name="concurrentUrl" id="concurrentUrl">
</div>
</div>
<div class="mt-3">
<label for="clientMessage" >
<span>Votre message </span>
</label>
<div>
<textarea class="form-textarea block w-full"
required
type="text"
rows="5"
name="clientMessage" id="clientMessage">
</textarea>
</div>
</div>
</div>
</fieldset>
<div class="my-3">
<div>
<button x-show="!displaySuccessMessage" type="submit"
class="btn btn-primary">
<span>
Envoyer </span>
</button>
<div class="flex flex-row justify-start items-center w-full"
x-show="isLoading"
x-cloak>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 60 55" xml:space="preserve" class="text-primary" width="57" height="57" role="img">
<rect x="20" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml" attributename="transform" type="translate" values="0 0; 0 20; 0 0" begin="0" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="30" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml" attributename="transform" type="translate" values="0 0; 0 20; 0 0" begin="0.2s" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="40" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml" attributename="transform" type="translate" values="0 0; 0 20; 0 0" begin="0.4s" dur="0.6s" repeatcount="indefinite"/>
</rect>
<title>loader</title></svg>
<div class="ml-4 text-primary">
Chargement... </div>
</div>
<p x-show="displaySuccessMessage"
x-cloak
class="text-green-800 flex items-center mt-2">
<span class="flex items-center w-8 h-8 mr-1">
<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">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</span>
Merci ! Votre message a bien été envoyé </p>
<template x-if="displayErrorMessage">
<p class="text-red flex items-center mt-2">
<span class="flex items-center w-8 h-8 mr-1">
<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">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</span>
<template x-for="errorMessage in errorMessages">
<span x-html="errorMessage"></span>
</template>
</p>
</template>
</div>
</div>
</form>
</div>
</div>
<script>
function initMoinsCherForm() {
return {
isLoading: false,
displaySuccessMessage: false,
displayErrorMessage: false,
errorMessages: [],
errors: 0,
clientEmail: null,
concurrentPrix: null,
concurrentUrl: null,
clientMessage: null,
setErrorMessages: function (messages) {
this.errorMessages = [messages]
this.displayErrorMessage = this.errorMessages.length
},
submitForm: function () {
// Do not remove $form. The variable is used in the recaptcha child template.
const $form = document.querySelector('#moinscher-form');
this.validate();
if (this.errors === 0) {
this.placeMoinsCher();
}
},
validate: function () {
this.clientEmail = document.getElementById('clientEmail').value;
this.concurrentPrix = document.getElementById('concurrentPrix').value;
this.concurrentUrl = document.getElementById('concurrentUrl').value;
this.clientMessage = document.getElementById('clientMessage').value;
if (!(this.clientEmail &&
this.concurrentPrix &&
this.concurrentUrl &&
this.clientMessage
)) {
this.setErrorMessages(
['Il\u0020y\u0020a\u0020eu\u0020une\u0020erreur\u0020lors\u0020de\u0020l\u0027envoi\u0020de\u0020votre\u0020message.']
);
this.displayErrorMessage = true;
this.errors = 1;
}
},
placeMoinsCher: function () {
this.isLoading = true;
this.displayErrorMessage = false;
const variables = {
clientEmail: this.clientEmail,
concurrentPrix: this.concurrentPrix,
concurrentUrl: this.concurrentUrl,
clientMessage: this.clientMessage,
produitNom: "Bombe\u0020lacrymog\u00E8ne\u0020gel\u0020poivre\u0020Umarex\u0020P2P\u0020PDG\u002D60\u002038ml",
produitCode: "2.2065-IWA26",
arprotechUrl: "https://www.arprotech.com/bombe-lacrymogene-gel-poivre-umarex-p2p-pdg-60.html",
arprotechPrix: "7.95",
arprotechId: "30525"
};
fetch(`https://www.arprotech.com/aw-moinscher/index/send`+ '?form_key=' + hyva.getFormKey(), {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Store': 'default'
},
credentials: 'include',
body: JSON.stringify(variables)
})
.then(response => response.json())
.then(data => {
this.isLoading = false;
if (data.errors) {
this.setErrorMessages(['Il\u0020y\u0020a\u0020eu\u0020une\u0020erreur\u0020lors\u0020de\u0020l\u0027envoi\u0020de\u0020votre\u0020message.']);
this.displayErrorMessage = true;
} else {
this.displaySuccessMessage = true;
}
}
);
}
}
}
</script>
</div>
</div>
</details>
<details
id="tab-product-review-wrapper"
data-name="Commentaires"
x-data="{ id: $el.id }"
class="tab-content"
:open="sectionItemIsOpen(id)"
>
<summary
@click.prevent="openSectionItem(id, true)"
class="tab-content-title"
>
<span>Commentaires</span>
<span class="transition-transform group-open:rotate-180">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 6.414 8.5 8.5 1.328-1.5-7-7H2Z"/>
<path d="m10.47 14.914 7.086-7.086V5l-7.086 7.086v2.828Z"/>
</svg>
</span>
</summary>
<div x-show="sectionItemIsOpen(id)" x-collapse>
<div class="pb-3">
<div class="grid grid-cols-1 gap-8 md:grid-cols-2">
<div id="review-form" tabindex="-1">
<div>
<div class="text-xl my-3">
Rédigez votre propre commentaire </div>
<form class="review-form"
id="review_form"
@submit.prevent="submitForm()"
action=""
x-data="initReviewForm()"
x-defer="intersect"
>
<div class="control">
<input type="hidden"
value=""
name="g-recaptcha-response"
/>
</div>
<fieldset>
<legend class="text-xs">
<span>
Vous commentez : </span>
<span class="font-semibold">
Bombe lacrymogène gel poivre Umarex P2P PDG-60 38ml </span>
</legend>
<fieldset name="rating-group">
<div class="flex flex-col mt-4 mb-3">
<div class="text-md hidden">
Votre notation:
</div>
<div class="mt-4">
<div id="product-review-table">
<div class="table-row">
<label
class="table-cell pr-6 align-middle text-left"
id="Note générale_rating_label"
>
<span>
Votre notation:
</span>
</label>
<div
class="flex flex-row grow-0 focus-within:ring-4 ring-primary ring-opacity-50"
x-data="{ clickedRatingId: 0 }"
>
<div
class="relative"
@click="clickedRatingId = 1 || 0"
>
<label
class="rating-1 m-0 cursor-pointer text-gray-400"
for="Note générale_1"
id="Note générale_1_label"
>
<span :class="1 <= clickedRatingId ? 'text-yellow-400' : 'text-gray-400'"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="32" height="32" aria-hidden="true">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
</svg>
</span>
<input
class="absolute opacity-0 bottom-0 left-0 cursor-pointer"
type="radio"
required name="ratings[1]"
id="Note générale_1"
value="1"
aria-label="1 star"
>
</label>
</div>
<div
class="relative"
@click="clickedRatingId = 2 || 0"
>
<label
class="rating-2 m-0 cursor-pointer text-gray-400"
for="Note générale_2"
id="Note générale_2_label"
>
<span :class="2 <= clickedRatingId ? 'text-yellow-400' : 'text-gray-400'"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="32" height="32" aria-hidden="true">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
</svg>
</span>
<input
class="absolute opacity-0 bottom-0 left-0 cursor-pointer"
type="radio"
name="ratings[1]"
id="Note générale_2"
value="2"
aria-label="2 étoiles"
>
</label>
</div>
<div
class="relative"
@click="clickedRatingId = 3 || 0"
>
<label
class="rating-3 m-0 cursor-pointer text-gray-400"
for="Note générale_3"
id="Note générale_3_label"
>
<span :class="3 <= clickedRatingId ? 'text-yellow-400' : 'text-gray-400'"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="32" height="32" aria-hidden="true">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
</svg>
</span>
<input
class="absolute opacity-0 bottom-0 left-0 cursor-pointer"
type="radio"
name="ratings[1]"
id="Note générale_3"
value="3"
aria-label="3 étoiles"
>
</label>
</div>
<div
class="relative"
@click="clickedRatingId = 4 || 0"
>
<label
class="rating-4 m-0 cursor-pointer text-gray-400"
for="Note générale_4"
id="Note générale_4_label"
>
<span :class="4 <= clickedRatingId ? 'text-yellow-400' : 'text-gray-400'"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="32" height="32" aria-hidden="true">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
</svg>
</span>
<input
class="absolute opacity-0 bottom-0 left-0 cursor-pointer"
type="radio"
name="ratings[1]"
id="Note générale_4"
value="4"
aria-label="4 étoiles"
>
</label>
</div>
<div
class="relative"
@click="clickedRatingId = 5 || 0"
>
<label
class="rating-5 m-0 cursor-pointer text-gray-400"
for="Note générale_5"
id="Note générale_5_label"
>
<span :class="5 <= clickedRatingId ? 'text-yellow-400' : 'text-gray-400'"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="32" height="32" aria-hidden="true">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
</svg>
</span>
<input
class="absolute opacity-0 bottom-0 left-0 cursor-pointer"
type="radio"
name="ratings[1]"
id="Note générale_5"
value="5"
aria-label="5 étoiles"
>
</label>
</div>
</div>
</div>
</div>
<input type="hidden" name="validate_rating" value="">
</div>
</div>
</fieldset>
<div>
<div>
<label for="nickname_field" class="sr-only">
<span>Pseudo</span>
</label>
<div>
<input class="form-input mt-3 block w-full"
required
placeholder="Pseudo*" type="text"
name="nickname" id="nickname_field">
</div>
</div>
<div>
<label for="summary_field" class="sr-only">
<span>Résumé</span>
</label>
<div>
<input class="form-input mt-3 block w-full"
required
placeholder="Résumé*" type="text"
name="title"
id="summary_field">
</div>
</div>
<div>
<label for="review_field" class="sr-only">
<span>Commentaire</span>
</label>
<div>
<textarea class="form-input mt-3 block w-full"
required
placeholder="Commentaire*" name="detail"
id="review_field" cols="5"
rows="3"></textarea>
</div>
</div>
</div>
</fieldset>
<div class="my-3">
<div>
<button x-show="!displaySuccessMessage" type="submit"
class="btn btn-primary">
<span>
Poster le commentaire </span>
</button>
<div class="flex flex-row justify-start items-center w-full"
x-show="isLoading"
x-cloak>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 60 55" xml:space="preserve" class="text-primary" width="57" height="57" role="img">
<rect x="20" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml" attributename="transform" type="translate" values="0 0; 0 20; 0 0" begin="0" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="30" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml" attributename="transform" type="translate" values="0 0; 0 20; 0 0" begin="0.2s" dur="0.6s" repeatcount="indefinite"/>
</rect>
<rect x="40" y="15" width="4" height="10" fill="currentColor">
<animatetransform attributetype="xml" attributename="transform" type="translate" values="0 0; 0 20; 0 0" begin="0.4s" dur="0.6s" repeatcount="indefinite"/>
</rect>
<title>loader</title></svg>
<div class="ml-4 text-primary">
En cours de chargement... </div>
</div>
<p x-show="displaySuccessMessage"
x-cloak
class="text-green flex items-center">
<span class="inline-block w-8 h-8 mr-3">
<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">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</span>
Votre évaluation est enrégistrée avec succès. Merci. </p>
<template x-if="displayErrorMessage">
<p class="text-red flex items-center">
<span class="inline-block w-8 h-8 mr-3">
<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">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</span>
<template x-for="errorMessage in errorMessages">
<span x-html="errorMessage"></span>
</template>
</p>
</template>
</div>
<p class="my-4 text-sm text-gray-900">
This form is protected by reCAPTCHA - the <a class="underline" href="https://policies.google.com/privacy" target="_blank" rel="noopener">Google Privacy Policy</a> and <a class="underline" href="https://policies.google.com/terms" target="_blank" rel="noopener">Terms of Service</a> apply.</p>
</div>
</form>
<script>
function initReviewForm() {
return {
isLoading: false,
displayNickname: false,
displaySuccessMessage: false,
displayErrorMessage: false,
errorMessages: [],
errors: 0,
hasCaptchaToken: 0,
nickname: null,
summary: null,
ratings: [],
review: null,
setErrorMessages: function (messages) {
this.errorMessages = [messages]
this.displayErrorMessage = this.errorMessages.length
},
submitForm: function () {
// Do not remove $form. The variable is used in the recaptcha child template.
const $form = document.querySelector('#review_form');
this.validate();
if (!this.hasCaptchaToken) {
this.errors = 1;
const executeGreCaptcha = () => {
grecaptcha.ready(() => {
grecaptcha.execute(
'6LeUktkZAAAAAKAyW_ydkVjPVjvJ4N48E7p2pBoh',
{action: 'submit'}
).then((token) => {
const tokenElement = $form['g\u002Drecaptcha\u002Dresponse'];
if (tokenElement && token && token.length > 0) {
$form['g\u002Drecaptcha\u002Dresponse'].value = token;
this.errors = 0;
this.hasCaptchaToken = 1;
(this.submitForm || $form.submit).call(this);
} else {
this.errors = 1;
const error = tokenElement
? 'ReCaptcha\u0020validation\u0020failed,\u0020please\u0020try\u0020again'
: 'ReCaptcha\u0020token\u0020element\u0020is\u0020missing.\u0020Please\u0020refresh\u0020the\u0020page\u0020and\u0020trying\u0020again.';
if (this.setErrorMessages) {
this.setErrorMessages([error])
this.displayErrorMessage = true;
} else {
window.dispatchMessages && window.dispatchMessages([{type: "error", text: error}], 5000);
}
}
}).catch(exception => {
console.error(exception || `An unknown error occurred during ReCaptcha validation. Are the tokens and the domain correctly set up in the Google console?`)
});
})
}
if (window.grecaptcha) {
executeGreCaptcha();
} else {
const recaptchaUrl = "https://www.google.com/recaptcha/api.js?render=6LeUktkZAAAAAKAyW_ydkVjPVjvJ4N48E7p2pBoh";
const script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', recaptchaUrl);
document.head.appendChild(script);
script.addEventListener("load", executeGreCaptcha, false);
}
}
if (this.errors === 0) {
this.placeReview();
}
},
validate: function () {
this.nickname = document.getElementById('nickname_field').value;
this.summary = document.getElementById('summary_field').value;
this.review = document.getElementById('review_field').value;
let ratingValue;
try {
ratingValue =
document
.querySelector('input[name="ratings[1]"]:checked')
.value;
this.ratings[1] = btoa(ratingValue);
} catch (e) {
console.log(e);
}
if (!(this.nickname &&
this.summary &&
this.review &&
Object.keys(this.ratings).length === 1 )) {
this.setErrorMessages(
['Please\u0020verify\u0020you\u0027ve\u0020entered\u0020all\u0020required\u0020information']
);
this.displayErrorMessage = true;
this.errors = 1;
this.hasCaptchaToken = 0;
}
},
placeReview: function () {
this.isLoading = true;
this.displayErrorMessage = false;
const query = `
mutation createProductReviewMutation(
$sku: String!,
$nick: String!,
$summary: String!,
$review: String!,
$ratings: [ProductReviewRatingInput]!
) {
createProductReview(
input: {
sku: $sku,
nickname: $nick,
summary: $summary,
text: $review,
ratings: $ratings
}
) {
review {
nickname
}
}
}
`;
const variables = {
sku: '2.2065\u002DIWA26',
nick: this.nickname,
summary: this.summary,
review: this.review,
ratings: Object.keys(this.ratings).map(key => {
return {id: btoa(key), value_id: this.ratings[key]}
})
};
const form = document.querySelector('#review_form');
const fieldName = 'g\u002Drecaptcha\u002Dresponse';
const recaptchaHeader = fieldName && form && form.elements[fieldName]
? {'X-ReCaptcha': form.elements[fieldName].value}
: {};
fetch(`${BASE_URL}graphql`, {
method: 'POST',
headers: Object.assign({
'Content-Type': 'application/json;charset=utf-8',
'Store': 'default'
}, recaptchaHeader),
credentials: 'include',
body: JSON.stringify({query: query, variables: variables})
})
.then(response => response.json())
.then(data => {
this.isLoading = false;
if (data.errors) {
this.setErrorMessages(['Submitting\u0020your\u0020review\u0020failed,\u0020please\u0020try\u0020again.']);
this.displayErrorMessage = true;
} else {
this.displaySuccessMessage = true;
}
}
);
}
}
}
</script>
</div>
</div>
</div>
</div>
</div>
</details>
</div>
<script>
function initProductSections() {
return {
items: [],
currentOpen: 'tab-description',
init() {
this.$refs.accordion.style.minHeight = null
this.items = [...this.$refs.accordion.children]
if (location.hash && document.querySelector(location.hash)) {
if (location.hash === '#customer-review-list') {
location.hash = '#tab-product-review-wrapper'
}
this.currentOpen = location.hash.replace('#', '')
}
},
openSectionItem(id, toggle = false) {
if (this.currentOpen === id && toggle) {
this.currentOpen = null
return
}
this.currentOpen = id
// localStorage.setItem('tap_open', id)
location.hash = id
this.$nextTick(() => {
document.getElementById(this.currentOpen).scrollIntoView({
behavior: 'smooth'
})
})
},
sectionItemIsOpen(id) {
return this.currentOpen === id
}
}
}
</script>
<noscript>
<style>details[data-name] summary {
display: flex
}</style>
</noscript>
</div>
<section class="mt-10 flex flex-col gap-10">
</section>
<div class="product-social-links">
<div class="product-addto-links">
</div>
</div></div></div></div></main><footer class="page-footer"><div class="footer content">
<div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><div class="aw-reassurances">
<div class="wrapper">
<div class="item">
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="68" fill="none" viewbox="0 0 68 68">
<path fill="currentColor"
d="M12.585 11 7 16.56v28.78h2.69l6.07-7.48.06-.08c.37-.562.995-.9 1.67-.9h20.925L44 31.32V11H12.585ZM42 30.495l-4.415 4.394H17.49c-1.335 0-2.57.657-3.315 1.757L9 43.022V17.385l4.415-4.394H42v17.504Zm19 23.058h-1.935l-.015-.02-1.555 1.254 2.025 2.499H61v-3.733Zm-14.61-8.212h-5v1.99h5v-1.99Zm-6.82 0h-5v1.99h5v-1.99Zm10.94 0h-2.305v1.99h2.305a1.99 1.99 0 0 1 1.565.752l1.565-1.239a3.988 3.988 0 0 0-3.13-1.503Zm4.257 2.906-1.556 1.25 3.143 3.872 1.556-1.251-3.143-3.871ZM28.76 43.699l-1.41 1.403 2.235 2.23h3.165v-1.99h-2.335l-1.655-1.643Z"/>
<path fill="currentColor"
d="M26 40.946v-2.324h-2v3.15l2.24 2.225 1.41-1.403L26 40.946Zm33-13.109v1.886h2v-2.712l-2.46-2.444-1.41 1.404L59 27.837Zm2 3.833h-2v5.35h2v-5.35Zm0 14.587h-2v5.35h2v-5.35Zm0-7.297h-2v5.35h2v-5.35ZM49.73 21.452H46v1.99h3.73v-1.99Zm6.02 3.145 1.41-1.403-1.745-1.742h-3.73v1.99h2.9l1.165 1.155Z"/>
</svg>
<div class="content">
<div class="title">
SERVICE CLIENT
</div>
<div class="desc">
Du Lundi au Vendredi : 8h30-17h30, par téléphone, non surtaxé, <a href="https://www.arprotech.com/contact/" target="_blank" rel="noopener">ou par email en cliquant ici.</a>
</div>
</div>
</div>
<div class="item">
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="68" fill="none" viewbox="0 0 68 68">
<path fill="currentColor"
d="M59.2 18.95H33.85l-2.6 2.6v5.8l.65-.75 1.35-1.45v-2.8l1.4-1.4h7.6v26.5h-7.6l-1.4-1.4V43.7l-1.35-1.2-.65-.55v4.95l2.6 2.6H59.2l2.6-2.6V21.55l-2.6-2.6Zm-14.9 28.5v-26.5h4.5v26.5h-4.5Zm15.5-1.4-1.4 1.4h-7.6v-26.5h7.6l1.4 1.4v23.7Z"/>
<path fill="currentColor"
d="M20.35 35.2h15.2l-4 4.35 1.5 1.3 6.15-6.7-6.2-5.7-1.35 1.5 3.55 3.25H20.35v2ZM8.8 32.45h-2v4.5h2v-4.5Zm0-3.85 1.3-1.25-1.4-1.45-1.9 1.9v2.65h2V28.6Zm2-2.4h4.5v-2h-4.9l-.3.3.7.7v1Z"/>
<path fill="currentColor"
d="M24.8 30.95h2V27.8l-2.6-2.6-1.4 1.4 2 2v2.35Zm-3-6.75h-4.5v2h4.5v-2Zm1 18h-4.5v2h4.9l.3-.3-.7-.7v-1Zm2-2.4-1.3 1.25 1.45 1.45 1.85-1.9v-3.15h-2v2.35Zm-8.5 2.4h-4.5v2h4.5v-2Zm-7.5-3.25h-2v1.65l2.6 2.6 1.4-1.4-2-2v-.85Z"/>
</svg>
<div class="content">
<div class="title">
RETRAIT COLIS POSSIBLE
</div>
<div class="desc">
Nous préparons la commande en quelques minutes, vous pouvez faire le retrait de votre
marchandise sur place, en nos locaux.
</div>
</div>
</div>
<div class="item">
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="68" fill="none" viewbox="0 0 68 68">
<path fill="currentColor"
d="M7.475 35.4h18.7v-2h-16.7l-2 2Zm6-6h12.7v-2h-10.7l-2 2Zm5.5-5.5h7.2v-2h-5.2l-2 2Zm40.15-5h-25.85l-2.6 2.6v25.85l2.6 2.6h25.85l2.6-2.6V21.5l-2.6-2.6Zm-25 29-1.4-1.4V22.3l1.4-1.4h7.6v27h-7.6Zm9.6 0v-27h4.5v27h-4.5Zm16-1.4-1.4 1.4h-8.1v-27h8.1l1.4 1.4v24.2Zm-41.95-.15v.05h8.4v-2h-6.5l-1.9 1.95Zm-5.1-4.95h13.5v-2h-11.5l-2 2Z"/>
</svg>
<div class="content">
<div class="title">
EXPEDITION RAPIDE
</div>
<div class="desc">
Nous expédions généralement sous 24H les produits en stock, dans toute
l'Europe.
</div>
</div>
</div>
<div class="item">
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="68" fill="none" viewbox="0 0 68 68">
<path fill="currentColor"
d="M14.935 12.225c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1Zm38 0c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1Zm-38 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm38 0c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1Zm-38 12.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm38 0c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1Zm-7.25-14.75h-4v-3.9l-2.6-2.6h-3.95v-4h-2v4h-3.9l-2.6 2.6v3.9h-4.05v2h4.05v3.9l2.6 2.6h3.9v4h2v-4h3.95l2.6-2.6v-3.9h4v-2Zm-12.5 6.5h-3.05l-1.4-1.4v-3.1h4.5v4.5h-.05Zm0-6.5h-4.5v-3.1l1.4-1.4h3.05v4.5h.05Zm6.5 5.1-1.4 1.4h-3.1v-4.5h4.5v3.1Zm0-5.1h-4.5v-4.5h3.1l1.4 1.4v3.1Zm-33.4 34.5 1.35 1.5 18-16.5-1.35-1.5-18 16.5Zm37.35-16.5-1.35 1.5 18 16.5 1.35-1.5-18-16.5Z"/>
</svg>
<div class="content">
<div class="title">
STAND DE TIR
</div>
<div class="desc">
Stand de tir 25 mètres, jusqu’à 1500 Joules, 3 postes, chronographe, rapport d’essais
et informatique à disposition, réservé aux membres du club.
</div>
</div>
</div>
</div>
</div></div><div class="">
<div class="container mx-auto">
<div class="footer-grid">
<div
x-data="{ open: false, isMobile: false, checkIsMobileResolution() { this.isMobile = getComputedStyle(this.$refs.toggleIcon).display !== 'none' } }"
x-id="['collapse-id']"
x-init="checkIsMobileResolution()"
@resize.window.debounce="checkIsMobileResolution()"
@visibilitychange.window.debounce="checkIsMobileResolution()"
class="footer-col"
>
<div
:id="$id('collapse-id')"
:role="isMobile && 'button'"
:tabindex="isMobile && '0'"
class="footer-col-title"
@click="isMobile && (open = !open)"
@keyup.enter="isMobile && (open = !open)"
@keyup.space="isMobile && (open = !open)"
:aria-expanded="isMobile ? open : null"
:aria-controls="isMobile ? $id('collapse-id') : null"
>
<p class="title">Boutique</p>
<span
class="transition-transform group-aria-expanded:rotate-180 lg:hidden"
x-ref="toggleIcon"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="20" height="20" aria-hidden="true">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
</span>
</div>
<div
class="hidden lg:block"
:class="{ 'hidden': isMobile && !open }"
:aria-labelledby="isMobile ? $id('collapse-id') : null"
:aria-hidden="isMobile && (open ? 'false' : 'true')"
>
<div class="pt-0.5 pb-5">
<style>.cmsb233-block {
display: block
}
.cmsb233-py-1\.5 {
padding-top: 0.375rem;
padding-bottom: 0.375rem
}
.cmsb233-hover\:underline:hover {
text-decoration-line: underline
}</style>
<div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><ul>
<li><a class="cmsb233-block cmsb233-py-1.5 cmsb233-hover:underline" href="https://www.arprotech.com/a-propos-de-la-societe/" title="A propos">A propos de Arprotech</a></li>
<li><a class="cmsb233-block cmsb233-py-1.5 cmsb233-hover:underline" href="https://www.arprotech.com/confidentialite/" title="Confidentialité">Confidentialité</a></li>
<li><a class="cmsb233-block cmsb233-py-1.5 cmsb233-hover:underline" href="https://www.arprotech.com/cgv/" title="CGV">Conditions générales de ventes</a></li>
<li><a class="cmsb233-block cmsb233-py-1.5 cmsb233-hover:underline" href="https://www.arprotech.com/sitemaps/arprotech-sitemap.xml" title="Sitemap">Sitemap</a></li>
<li><a class="cmsb233-block cmsb233-py-1.5 cmsb233-hover:underline" href="https://www.h-rechargement.fr" title="Matériel de rechargement, ogives et cartouches Hornady">Rechargement, ogives et cartouches Hornady</a></li>
</ul>
</div> </div>
</div>
</div>
<div
x-data="{ open: false, isMobile: false, checkIsMobileResolution() { this.isMobile = getComputedStyle(this.$refs.toggleIcon).display !== 'none' } }"
x-id="['collapse-id']"
x-init="checkIsMobileResolution()"
@resize.window.debounce="checkIsMobileResolution()"
@visibilitychange.window.debounce="checkIsMobileResolution()"
class="footer-col"
>
<div
:id="$id('collapse-id')"
:role="isMobile && 'button'"
:tabindex="isMobile && '0'"
class="footer-col-title"
@click="isMobile && (open = !open)"
@keyup.enter="isMobile && (open = !open)"
@keyup.space="isMobile && (open = !open)"
:aria-expanded="isMobile ? open : null"
:aria-controls="isMobile ? $id('collapse-id') : null"
>
<p class="title">Société</p>
<span
class="transition-transform group-aria-expanded:rotate-180 lg:hidden"
x-ref="toggleIcon"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="20" height="20" aria-hidden="true">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
</span>
</div>
<div
class="hidden lg:block"
:class="{ 'hidden': isMobile && !open }"
:aria-labelledby="isMobile ? $id('collapse-id') : null"
:aria-hidden="isMobile && (open ? 'false' : 'true')"
>
<div class="pt-0.5 pb-5">
<div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><ul >
<li>
<p><a href="https://www.google.com/maps/place/Armurerie+ARprotech/@43.498609,3.5926024,17.87z/data=!4m12!1m6!3m5!1s0x12b14b7da5b7331d:0x2c7c47623a63760e!2sArmurerie+ARprotech!8m2!3d43.49905!4d3.59283!3m4!1s0x12b14b7da5b7331d:0x2c7c47623a63760e!8m2!3d43.49905!4d3.59283" target="_blank">ARprotech.com <br />Z.A.E de Malpasset 37 Rue Sautaroch<br />34560 Villeveyrac - FRANCE</a></p>
</li>
<li>
<p><strong>Tél. : </strong> <span>+33 (0)9.67.59.68.03</span></p>
</li>
<li>
<p><strong>E-mail : </strong> <a href="https://www.arprotech.com/contact/">cliquez ici</a></p>
</li>
<li>
<p><strong>Horaires : </strong> du Lundi au Vendredi 8h30 - 17h30</p>
</li>
</ul>
</div> </div>
</div>
</div>
<div
x-data="{ open: false, isMobile: false, checkIsMobileResolution() { this.isMobile = getComputedStyle(this.$refs.toggleIcon).display !== 'none' } }"
x-id="['collapse-id']"
x-init="checkIsMobileResolution()"
@resize.window.debounce="checkIsMobileResolution()"
@visibilitychange.window.debounce="checkIsMobileResolution()"
class="footer-col"
>
<div
:id="$id('collapse-id')"
:role="isMobile && 'button'"
:tabindex="isMobile && '0'"
class="footer-col-title"
@click="isMobile && (open = !open)"
@keyup.enter="isMobile && (open = !open)"
@keyup.space="isMobile && (open = !open)"
:aria-expanded="isMobile ? open : null"
:aria-controls="isMobile ? $id('collapse-id') : null"
>
<p class="title">Service client</p>
<span
class="transition-transform group-aria-expanded:rotate-180 lg:hidden"
x-ref="toggleIcon"
>
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" width="20" height="20" aria-hidden="true">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
</span>
</div>
<div
class="hidden lg:block"
:class="{ 'hidden': isMobile && !open }"
:aria-labelledby="isMobile ? $id('collapse-id') : null"
:aria-hidden="isMobile && (open ? 'false' : 'true')"
>
<div class="pt-0.5 pb-5">
<div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true"><ul>
<li><a href="https://www.arprotech.com/customer/account/index/">Mon compte</a></li>
<li><a href="https://www.arprotech.com/sales/order/history/">Mes commandes</a></li>
<li><a href="https://www.arprotech.com/rma/account/history/">Le service après vente</a></li>
<li><a href="https://www.arprotech.com/contact/">Nous contacter</a></li>
</ul></div> </div>
</div>
</div>
<div data-content-type="html" data-appearance="default" data-element="main" data-decoded="true">
<div class="aw-subscribe">
<div class="flex flex-col text-center gap-3">
<p class="text-style-3">Restez connecté</p>
<p>Offres, services et conseils pour vous démarquer !</p>
</div>
<form class="form subscribe w-full sm:max-w-xl lg:w-full" action="https://www.arprotech.com/newsletter/subscriber/new/" method="post" x-data="initNewsletterForm()" @submit.prevent="submitForm()" id="newsletter-validate-detail" aria-label="S'abonner à la newsletter">
<div class="flex flex-col sm:flex-row gap-4">
<label class="grow m-0">
<span class="sr-only">Adresse mail</span>
<input type="email" id="newsletter-subscribe" name="email" class="form-input form-input--dark w-full" required placeholder="Saisissez votre email">
<input name="form_key" type="hidden" value="eTB4IhRhBQzWlDue"> </label>
<button class="button button--primary large">
Valider </button>
</div>
<template x-if="displayErrorMessage">
<p class="flex items-center text-red mt-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewbox="0 0 24 24" stroke-width="2" stroke="currentColor" class="inline-block mr-3" width="24" height="24" role="img">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
<title>exclamation-circle</title></svg>
<template x-for="errorMessage in errorMessages">
<span x-html="errorMessage"></span>
</template>
</p>
</template>
<div class="w-full">
</div>
</form>
<div class="flex gap-5 justify-center items-center">
<a href="https://www.facebook.com/ARprotech/" target="_blank" rel="noopener noreferrer" class="">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" fill="none" viewbox="0 0 24 25">
<path fill="currentColor" d="M24 12.5c0-6.627-5.373-12-12-12S0 5.873 0 12.5c0 5.99 4.388 10.954 10.125 11.854V15.97H7.078V12.5h3.047V9.856c0-3.007 1.792-4.668 4.533-4.668 1.312 0 2.686.234 2.686.234v2.953H15.83c-1.491 0-1.956.925-1.956 1.875v2.25h3.328l-.532 3.469h-2.796v8.385C19.612 23.454 24 18.49 24 12.5Z"></path>
<title>Suivez nous sur Facebook</title>
</svg>
</a>
<a href="https://twitter.com/ARprotech" target="_blank" rel="noopener noreferrer" class="">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" fill="currentColor" viewbox="0 0 24 25">
<path d="M18.326 2.404H21.7l-7.37 8.423L23 22.29h-6.789l-5.317-6.952L4.81 22.29H1.434l7.883-9.01L1 2.404h6.961l4.806 6.354 5.56-6.354ZM17.142 20.27h1.87L6.945 4.317H4.94L17.142 20.27Z"></path>
<title>Suivez nous sur X</title>
</svg>
</a>
<a href="https://www.instagram.com/arprotech/" target="_blank" rel="noopener noreferrer" class="">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" fill="currentColor" viewbox="0 0 24 25">
<path d="M12 2.66c3.206 0 3.586.015 4.847.071 1.172.052 1.805.249 2.226.413a3.71 3.71 0 0 1 1.379.895c.421.422.68.82.895 1.378.164.422.36 1.06.412 2.227.057 1.265.07 1.645.07 4.847 0 3.206-.013 3.586-.07 4.846-.051 1.172-.248 1.805-.412 2.227a3.714 3.714 0 0 1-.895 1.378 3.69 3.69 0 0 1-1.379.895c-.421.165-1.059.361-2.226.413-1.266.056-1.645.07-4.847.07-3.206 0-3.586-.014-4.847-.07-1.172-.052-1.805-.248-2.226-.413a3.71 3.71 0 0 1-1.379-.895 3.691 3.691 0 0 1-.895-1.378c-.164-.422-.36-1.06-.412-2.227-.057-1.265-.07-1.645-.07-4.846 0-3.207.013-3.586.07-4.847.051-1.172.248-1.805.412-2.227.216-.558.478-.96.895-1.378.422-.422.82-.68 1.379-.895.421-.164 1.059-.361 2.226-.413 1.261-.056 1.64-.07 4.847-.07ZM12 .5C8.742.5 8.334.514 7.055.57c-1.275.057-2.152.263-2.911.558a5.857 5.857 0 0 0-2.128 1.388A5.88 5.88 0 0 0 .628 4.639C.333 5.403.127 6.275.07 7.55.014 8.834 0 9.242 0 12.5s.014 3.666.07 4.945c.057 1.275.263 2.152.558 2.911.31.792.717 1.463 1.388 2.128a5.866 5.866 0 0 0 2.123 1.383c.764.296 1.636.502 2.911.558 1.28.056 1.688.07 4.945.07 3.258 0 3.666-.014 4.946-.07 1.275-.056 2.151-.262 2.91-.558a5.866 5.866 0 0 0 2.124-1.383 5.866 5.866 0 0 0 1.383-2.123c.295-.764.501-1.636.558-2.911.056-1.28.07-1.688.07-4.945 0-3.258-.014-3.666-.07-4.946-.057-1.275-.263-2.151-.558-2.91a5.62 5.62 0 0 0-1.374-2.133 5.866 5.866 0 0 0-2.123-1.383C19.097.838 18.225.63 16.95.575 15.666.515 15.258.5 12 .5Z"></path>
<path d="M12 6.336A6.166 6.166 0 0 0 5.836 12.5 6.166 6.166 0 0 0 12 18.664a6.166 6.166 0 0 0 6.164-6.164A6.166 6.166 0 0 0 12 6.336Zm0 10.162a3.999 3.999 0 1 1 .001-7.998A3.999 3.999 0 0 1 12 16.498Zm7.847-10.406a1.44 1.44 0 1 1-2.879 0 1.44 1.44 0 0 1 2.879 0Z"></path>
<title>Suivez nous sur Instagram</title>
</svg>
</a>
</div>
<script>
function initNewsletterForm() {
return {
errors: 0,
hasCaptchaToken: 0,
displayErrorMessage: false,
errorMessages: [],
setErrorMessages(messages) {
this.errorMessages = [messages]
this.displayErrorMessage = this.errorMessages.length
},
submitForm() {
// Do not rename $form, the variable is expected to be declared in the recaptcha output
const $form = document.querySelector('#newsletter-validate-detail')
if (this.errors === 0) {
$form.submit()
}
}
}
}
</script>
<div class="back-cut-out --outline --left"></div>
</div>
</div> </div>
</div>
<div class="footer end">
<div class="container mx-auto flex flex-col sm:items-center sm:justify-between sm:flex-row py-5">
<small>
<span>© 2020 Arprotech. Tous droits réservés.</span>
</small>
<div class="flex items-center gap-2">
<a href="https://alsace-web.fr" class="opacity-50 hover:opacity-100 transition-opacity"
title="Développement - ARProTech / Alsace-Web" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewbox="0 0 16 16">
<path fill="#F06D70" fill-rule="evenodd"
d="M8.01 16a8 8 0 0 0 7.548-10.657l-3.954 6.855-.301-.523-1.366-2.368-.211-.367-1.878 3.258-1.693-2.934h-4.8l-.86 1.488A8.003 8.003 0 0 0 8.01 16ZM.238 9.903a7.97 7.97 0 0 1-.017-.068L3.755 3.71l4.092 7.095L9.32 8.253l-.45-.783a1.976 1.976 0 0 1-.008-.011l-.003-.006a2.956 2.956 0 0 1-.137-.255c-.066-.138-.167-.373-.167-.588 0-.645.526-1.171 1.17-1.171.639 0 1.178.523 1.149 1.18-.004.213-.103.443-.168.579a3.34 3.34 0 0 1-.137.255l-.01.017v.001l-.438.763.42.727 1.063 1.845 3.618-6.272A8 8 0 0 0 .238 9.903Zm5.516-1.335-2-3.466-1.999 3.466h3.999Zm4.21-1.459.001-.002a1.106 1.106 0 0 0 .033-.057c.022-.039.052-.093.08-.154a.92.92 0 0 0 .1-.287V6.59a.445.445 0 0 0-.452-.458.479.479 0 0 0-.476.476c0 .04.032.146.1.287a2.617 2.617 0 0 0 .106.2l.005.007.002.004.002.002.003.005.246.43.246-.43.004-.005Z"
clip-rule="evenodd"/>
</svg>
</a>
/
<a href="https://cerbere.fr" class="opacity-50 hover:opacity-100 transition-opacity" target="_blank"
title="Studio de Création - ARProTech / Cerbère">
<svg xmlns="http://www.w3.org/2000/svg" width="38" height="14" fill="none" viewbox="0 0 38 14">
<path fill="#fff"
d="M.01 14h4.24V6.071H2.82v6.477H1.46V1.447h1.36v3.22h1.43V0H.01v14Zm9.866-4.67h-1.43v3.217h-1.36V7.925h2.79V0H5.635v14h4.241V9.331Zm-2.79-7.878h1.36v5.043h-1.36V1.452Zm5.626 4.621h1.36V14h1.43V6.098l-.455-.455-.975-.976h-1.36V1.452h1.36v3.215h1.43V0H11.26v14h1.452V6.073ZM28.134 14h1.451V6.073h1.36V14h1.43V6.098l-.454-.455-.976-.976h-1.36V1.452h1.36v3.215h1.43V0h-4.241v14ZM38 7.925V0h-4.242v14H38V9.332h-1.43v3.216h-1.36V7.925H38Zm-2.79-6.472h1.36v5.042h-1.36V1.452v.001ZM22.509 4.15V14h4.241V9.332h-1.43v3.216h-1.36V7.925h2.79V2.857l-4.241-.415V4.15Zm1.451.023 1.36.137v2.185h-1.36V4.172v.001ZM22.509.982l4.241.424V0h-4.241v.982Zm-1.384.431L19.719.005h-2.835V14h4.241V1.413Zm-1.43 11.135h-1.36V6.073h1.36v6.475Zm0-7.881h-1.36V1.459h1.36v3.208Z"/>
</svg>
</a>
</div>
</div>
</div>
</div>
<script>
'use strict';
function amBrandsPopup() {
let cached = false;
const displayError = (error) => {
console.error(error);
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "error",
text: "Une\u0020erreur\u0020s\u0027est\u0020produite.\u0020Merci\u0020d\u0027essayer\u0020ult\u00E9rieurement."
}], 10000
);
};
let letters = [
"A","B","C","D",
"E","F","G","H","I","J","K","L","M",
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z","#"
];
return {
hoverPanelActiveId: null,
selectedLetter: null,
items: [],
letters: [],
showCount: null,
showFilter: null,
showImages: true,
showSearch: null,
loading: false,
label: 'Marques',
isPopupEnabled: false,
isTopMenuItemEnabled: false,
cache: false,
isMobile: false,
initErrorMessages(errors) {
const messages = [];
for (let error in Object.keys(errors)) {
messages.push({type: 'error', text: errors[error].message});
}
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(messages, 10000);
},
chooseLetter(letter) {
this.selectedLetter = this.selectedLetter === letter ? null : letter;
},
getQuery() {
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 } }" },
/**
* Retrieve media url for given path
*
* @param path
* @returns {string}
*/
getMediaUrl(path) {
const baseUrl = BASE_URL.replace('index.php/', '');
if (path.includes('://')) {
return path;
}
let productImageUrl = `${baseUrl}${path}`;
const regexDuplicateDomain = new RegExp(`^(https?:\/\/[^/]+).*\\1`);
productImageUrl = productImageUrl.replace(regexDuplicateDomain, '$1');
return productImageUrl.includes('/product/placeholder/')
? productImageUrl.replace(/\/media(?=\/static)/, '')
: productImageUrl;
},
checkIsMobileResolution() {
this.isMobile = window.matchMedia('(max-width: 1023px)').matches;
},
getBrandUrl(url){
return BASE_URL + url;
},
init() {
this.checkIsMobileResolution();
this.$watch('hoverPanelActiveId', (value) => {
if (value === 'am-brand') {
this.sendRequest();
}
});
},
/**
* Get brands by letter
*
* @param result
* @returns {{imageWidth: *, isTopMenuItemEnabled: *, showCount: *, displayAll: *, showFilter: *, showImages: *, isPopupEnabled: *, label: *, imageHeight: *, filterDisplayAll: *, brandsPage: *}}
*/
settingsMapper(result) {
const config = result.data.storeConfig?.amshopby_brand_general_brands_popup_config;
return {
showImages: config.show_images,
showCount: config.show_count,
showFilter: config.show_filter,
imageWidth: config.image_width,
imageHeight: config.image_height,
filterDisplayAll: config.filter_display_all,
displayAll: config.display_zero,
isPopupEnabled: result.data.storeConfig?.amshopby_brand_general_brands_brands_popup,
label: result.data.storeConfig?.amshopby_brand_general_menu_item_label,
isTopMenuItemEnabled: result.data.storeConfig?.amshopby_brand_general_topmenu_enabled,
brandsPage: result.data.storeConfig?.amshopby_brand_general_brands_page,
}
},
/**
* Send request to graphql
*
* @returns {Promise<any>}
*/
async sendRequest() {
if (this.isMobile) {
return false;
}
this.loading = true;
try {
if (cached) {
this.loading = false;
return false;
}
const response = await fetch('https://www.arprotech.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Store': 'default'
},
credentials: 'include',
body: JSON.stringify({query: this.getQuery(), variables: {}})
});
const result = await response.json();
if (result?.errors) {
this.initErrorMessages(result.errors);
return;
}
const data = result.data?.ambrandlist;
const mapper = this.settingsMapper(result);
// Update component settings
Object.keys(mapper).forEach(config => {
this[config] = mapper[config];
});
if (!this.filterDisplayAll) {
letters = data.all_letters.split(',');
}
const items = data.items.map(brand => {
brand.image = brand.img
? this.getMediaUrl(brand.img) : (brand.image ? this.getMediaUrl(brand.image) : null);
return brand;
});
this.letters = letters.map(letter => ({
letter,
brands: this.getLetterItems(items, letter),
}));
this.items = this.letters.filter(row => row.brands?.length > 0);
cached = true;
} catch (error) {
displayError(error);
} finally {
this.loading = false;
}
},
/**
* Get brands by letter
*
* @param items
* @param letter
* @returns {*}
*/
getLetterItems(items, letter) {
return items.filter(row => row.letter === letter);
},
convertHtml(text) {
let textField = document.createElement("textarea");
textField.innerHTML = text;
return textField.value;
}
}
}
</script>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
var cookies = (document.cookie || "").split(";")
.reduce(function (obj, cookie) {
var parsedCookie = (cookie || "").split("=");
var name = decodeURIComponent((parsedCookie[0] || "").trim());
var value = decodeURIComponent((parsedCookie[1] || "").trim());
obj[name] = value;
return obj;
}, {});
var customerIsLoggedIn = false;
if(!customerIsLoggedIn && !cookies["ki_cus"]) {
return;
}
var url = window.location.href;
var productId = '30525';
var categoryId = '0';
var storeId = '1';
var formKey = cookies["form_key"] || "";
var baseUrl = window.BASE_URL || "/";
fetch(baseUrl + "kilibam2/record/visit", {
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
url: url,
productId: productId,
categoryId: categoryId,
storeId: storeId,
form_key: formKey
})
}).then(function (response) {
return response.text();
}).catch(function (error) {
console.error("Kiliba - Unable to collect visit", error);
});
});
</script>
</footer><script>
function initConfigurableOptions(productId, optionConfig) {
function findPathParam(key) {
const baseUrl = (BASE_URL.substring(0, 2) === '//' ? 'http:' : '') + BASE_URL;
const baseUrlParts = (new URL(baseUrl)).pathname.replace(/\/$/, '').split('/');
const pathParts = window.location.pathname.split('/').slice(baseUrlParts.length + 3);
for (let i = 0; i < pathParts.length; i += 2) {
if (pathParts[i] === key && pathParts.length > i) {
return pathParts[i + 1];
}
}
}
return {
optionConfig,
productId,
itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'),
allowedAttributeOptions: [],
selectedValues: [],
init() {
this.findAllowedAttributeOptions();
this.$nextTick(() => {
if (typeof this.optionConfig.defaultValues === 'object') {
for (const [attributeId, value] of Object.entries(this.optionConfig.defaultValues)) {
this.changeOption(attributeId, value + '');
}
}
this.preselectQuerystringItems();
this.preselectLocationHashItems();
});
},
productIndex: 0,
productIndexForPrice: 0,
optionIsActive(attributeId, optionId) {
return !!this.getAllowedAttributeOptions(attributeId).find(
option => option.id === optionId
)
},
optionIsEnabled(attributeId, optionId) {
for (const productId in this.optionConfig.index) {
if (this.optionConfig.index[productId][attributeId] === optionId) {
return true;
}
}
return false;
},
findSimpleIndex() {
this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues);
this.productIndexForPrice = this.findCheapestProductForPartialSelection(this.selectedValues);
},
calculateSimpleIndexForPartialSelection(selectedValues) {
if (selectedValues.length === 0) return 0;
return this.findProductIdsForPartialSelection(selectedValues)[0];
},
calculateSimpleIndexForFullSelection(selectedValues) {
if (! this.isFullSelection(selectedValues)) return false;
const productIndexes = this.optionConfig.index;
return Object.keys(productIndexes).find(productIndex => {
const productCandidateOptions = productIndexes[productIndex];
for (const productOption in productCandidateOptions) {
if (
!selectedValues[productOption] ||
selectedValues[productOption] !== productCandidateOptions[productOption]
) {
return false;
}
}
return productIndex;
});
},
findAllowedAttributeOptions() {
this.allowedAttributeOptions = this.calculateAllowedAttributeOptions(this.selectedValues);
},
calculateAllowedAttributeOptions(selectedValues) {
const allAttributes = this.optionConfig.attributes;
const allAttributesSorted = Object.values(allAttributes).sort((a,b) => {
return a.position - b.position
});
const newAllowedAttributeOptions = [];
allAttributesSorted.forEach(attribute => {
const selectionWithoutAttr = Object.assign({}, this.removeAttrFromSelection(selectedValues, attribute.id));
const availableIndexes = this.calculateAvailableProductIndexes(selectionWithoutAttr);
newAllowedAttributeOptions[attribute.id] = allAttributes[attribute.id].options.filter(option => {
return !!option.products.find(product => {
return availableIndexes.includes(product);
})
});
});
return newAllowedAttributeOptions;
},
calculateAvailableProductIndexes(selectedOptions) {
if (Object.keys(selectedOptions).length === 0) {
if (Object.values(this.optionConfig.salable || {}).length) {
return [].concat.apply([], [].concat.apply([], Object.values(this.optionConfig.salable).map(Object.values))).filter((x, i, a) => a.indexOf(x) === i)
}
return Object.keys(this.optionConfig.index);
}
const selectedIds = Object.keys(selectedOptions);
if (Object.values(this.optionConfig.salable || {}).length) {
const selectedOptionIndexes = selectedIds.map(attrId => {
const optionValue = selectedOptions[attrId];
return this.optionConfig.salable[attrId] && this.optionConfig.salable[attrId][optionValue] || []
})
return selectedOptionIndexes.reduce((acc, optionIndexes) => {
return acc.filter(index => optionIndexes.includes(index));
});
} else {
const productIndexes = this.optionConfig.index;
return Object.keys(productIndexes).filter(index => {
for (const attrId of selectedIds) {
if (productIndexes[index][attrId] !== `${selectedOptions[attrId]}`) return false
}
return true
});
}
},
findAttributeByOptionId(optionId) {
for (const attributeId in this.optionConfig.attributes) {
const attributeOptions = this.optionConfig.attributes[attributeId].options || [];
if (attributeOptions.find(option => option.id === optionId)) {
return attributeId;
}
}
},
getAllowedAttributeOptions(attributeId) {
return this.allowedAttributeOptions[attributeId] || []
},
getAllAttributeOptions(attributeId) {
return (
this.optionConfig.attributes[attributeId] &&
this.optionConfig.attributes[attributeId].options
) || []
},
getProductIdsForOption(option) {
const attributeId = this.findAttributeByOptionId(option.id);
const allOptions = this.optionConfig.attributes[attributeId];
const opt = (allOptions && allOptions.options || []).find(o => o.id === option.id);
return opt && opt.products
? opt.products
: [];
},
findProductIdsForPartialSelection(optionSelection) {
const candidateProducts = Object.values(optionSelection).reduce((candidates, optionId) => {
const newCandidates = this.getProductIdsForOption({id: optionId});
return candidates === null
? newCandidates
: candidates.filter(productId => newCandidates.includes(productId));
}, null);
return candidateProducts || [];
},
findCheapestProductForPartialSelection(optionSelection) {
const candidateProducts = this.findProductIdsForPartialSelection(optionSelection);
return candidateProducts.reduce((cheapest, simpleIdx) => {
// in the first iteration we start with simpleIdx as the currently cheapest product
if (! this.optionConfig.optionPrices[cheapest]) return simpleIdx;
const knownCheapestPrice = this.optionConfig.optionPrices[cheapest].finalPrice.amount;
return knownCheapestPrice > this.optionConfig.optionPrices[simpleIdx].finalPrice.amount
? simpleIdx
: cheapest;
}, 0)
},
findProductIdToUseForOptionPrice(option) {
// try to find a product for a complete selection
const attributeId = this.findAttributeByOptionId(option.id);
const optionSelection = Object.assign({}, this.selectedValues, {[attributeId]: option.id});
const matchingSimpleIndex = this.calculateSimpleIndexForFullSelection(optionSelection);
// if there is no complete selection, use the cheapest product for the option
return matchingSimpleIndex || this.findCheapestProductForPartialSelection(optionSelection);
},
getAttributeOptionLabel(option) {
const optionProduct = this.findProductIdToUseForOptionPrice(option);
if ((! optionProduct) || (optionProduct === this.productIndexForPrice)) {
return option.label;
}
const currentPrice = this.getOptionPriceAdjustmentBasePrice();
if (this.optionConfig.optionPrices[optionProduct]) {
const optionPrice = this.optionConfig.optionPrices[optionProduct].finalPrice.amount;
if (optionPrice !== currentPrice){
return option.label + ' ' + hyva.formatPrice(optionPrice - currentPrice, true);
}
}
return option.label;
},
getOptionPriceAdjustmentBasePrice() {
if (this.optionConfig.optionPrices[this.productIndexForPrice]) {
return this.optionConfig.optionPrices[this.productIndexForPrice].finalPrice.amount
}
return this.optionConfig.prices.finalPrice.amount; // default price if no option selection
},
clearOptionIfActive(optionId, value) {
if (this.selectedValues[optionId] === value) {
this.blurLabel()
this.changeOption(optionId, '')
}
},
removeAttrFromSelection(selectedValues, attributeId) {
attributeId = parseInt(attributeId);
return selectedValues.reduce((newSelection, val, attr) => {
if (attr !== attributeId) {
newSelection[attr] = val;
}
return newSelection;
}, []);
},
changeOption(attributeId, value) {
if (value === '') {
this.selectedValues = this.removeAttrFromSelection(this.selectedValues, attributeId)
} else if (value && this.getAllowedAttributeOptions(attributeId).find(option => option.id === value)) {
this.selectedValues[attributeId] = value;
}
this.findSimpleIndex();
this.findAllowedAttributeOptions();
this.updatePrices();
this.updateGallery();
const candidates = this.findProductIdsForPartialSelection(this.selectedValues);
window.dispatchEvent(
new CustomEvent(
'configurable-selection-changed',
{
detail: {
productId: this.productId,
optionId: attributeId,
value: value,
productIndex: this.productIndex,
selectedValues: this.selectedValues,
candidates: candidates,
skuCandidates: Object.values(candidates).map(id => this.optionConfig.sku?.[id] ?? null).filter(Boolean),
}
}
)
);
},
calculateIsMinimalPrice() {
return ! this.isFullSelection(this.selectedValues);
},
isFullSelection(selectedValues) {
return Object.values(selectedValues).length === Object.keys(this.optionConfig.attributes).length;
},
updatePrices() {
const value = this.optionConfig.optionPrices[this.productIndexForPrice] || this.optionConfig.prices;
window.dispatchEvent(
new CustomEvent(
"update-prices-" + this.productId,
{
detail: Object.assign(
value,
{ isMinimalPrice: this.calculateIsMinimalPrice() }
)
}
)
);
},
updateGallery () {
if (this.productIndex) {
const images = this.optionConfig.images[this.productIndex];
images && window.dispatchEvent(new CustomEvent(
"update-gallery",
{ detail: this.sortImagesByPosition(images) }
));
} else {
window.dispatchEvent(new Event("reset-gallery"));
}
},
sortImagesByPosition(images) {
return images.sort((x, y) => {
return x.position === y.position ? 0 : (parseInt(x.position) > parseInt(y.position) ? 1 : -1)
});
},
onGetCartData(data) {
if (this.productId === '30525') {
this.preselectCartItems(data);
}
},
preselectCartItems(data) {
// pre-select options based on cart data for current (quote) itemId
const cart = data && data.cart;
if (cart && cart.items) {
const cartItem = cart.items.find((item) => {
return (
item.item_id === this.itemId
&& item.product_id === this.productId
)
});
if (cartItem && cartItem.options && cartItem.options.length) {
cartItem.options.map(option => {
this.changeOption(option.option_id, option.option_value);
})
}
}
},
preselectQuerystringItems() {
// pre-select option like ?size=167
const urlQueryParams = new URLSearchParams(window.location.search.replace('?',''));
this.preselectItemsBasedOnLocation(attribute => urlQueryParams.get(attribute.code));
},
preselectLocationHashItems() {
// pre-select option like #144=167
const urlHashParams = new URLSearchParams(window.location.hash.replace('#',''));
this.preselectItemsBasedOnLocation(attribute => urlHashParams.get(attribute.id));
},
preselectItemsBasedOnLocation(getLocationValue) {
Object.values(this.optionConfig.attributes).map(attribute => {
const v = getLocationValue(attribute);
v && this.changeOption(attribute.id, v)
});
}
}
}
</script>
<script>
function initSwatchOptions(swatchConfig,configurableOptions) {
return {
swatchConfig,
getAttributeSwatchData(attributeId) {
const swatchConfig = Object.assign({}, this.swatchConfig[attributeId]);
swatchConfig['details'] = JSON.parse(swatchConfig['additional_data']);
return swatchConfig;
},
getAllAttributeOptions(attributeId) {
return (
this.optionConfig.attributes[attributeId] &&
this.optionConfig.attributes[attributeId].options
) || []
},
optionIsActive(attributeId, optionId) {
// return true if a product with this option is in stock
return !!this.getAllowedAttributeOptions(attributeId).find(
option => option.id === optionId
)
},
optionIsEnabled(attributeId, optionId) {
// return true if a product with this option is enabled
for (const productId in this.optionConfig.index) {
if (this.optionConfig.index[productId][attributeId] === optionId) {
return true;
}
}
return false;
},
mapSwatchTypeNumberToTypeCode(typeNumber) {
switch ("" + typeNumber) {
case "1":
return "color"
case "2":
return "image"
case "3":
return "empty"
case "0":
default:
return "text"
}
},
getTypeOfFirstOption(attributeId) {
for (const optionId in this.swatchConfig[attributeId]) {
const option = this.swatchConfig[attributeId][optionId];
if (typeof option.type !== 'undefined') {
return this.mapSwatchTypeNumberToTypeCode(option.type);
}
}
},
getVisualSwatchType(attributeId, targetOptionId) {
// If a type configuration is present for the given option id, use it
const config = this.swatchConfig[attributeId];
if (config[targetOptionId] && typeof config[targetOptionId].type !== 'undefined') {
return this.mapSwatchTypeNumberToTypeCode(config[targetOptionId].type);
}
// Otherwise - if no config is present for the target option - use the type of the first option
// with a type property from the attribute, thus assuming its the same type as the target option.
// (This edge case condition can occur on single swatch products if some options are not salable)
return this.getTypeOfFirstOption(attributeId);
},
getSwatchType(attributeId, optionId) {
// Deserialize the attribute details the first time they are used
if (this.swatchConfig[attributeId] && ! this.swatchConfig[attributeId].details) {
this.swatchConfig[attributeId] = this.getAttributeSwatchData(attributeId);
}
const type = this.swatchConfig[attributeId] &&
this.swatchConfig[attributeId].details &&
this.swatchConfig[attributeId].details.swatch_input_type ||
"empty";
return type === 'visual' ? this.getVisualSwatchType(attributeId, optionId) : type;
},
isTextSwatch(attributeId, optionId) {
return this.getSwatchType(attributeId, optionId) === 'text';
},
isVisualSwatch(attributeId, optionId) {
const type = this.getSwatchType(attributeId, optionId);
return ['image', 'color'].includes(type);
},
getSwatchBackgroundStyle(attributeId, optionId) {
const config = this.getSwatchConfig(attributeId, optionId);
const type = this.getSwatchType(attributeId, optionId);
if (type === "color") {
return 'background-color:' + config.value;
} else if (type === "image") {
return "background: #ffffff url('" + config.value + "') no-repeat center";
} else {
return '';
}
},
getSwatchText(attributeId, optionId) {
const childrenId = Object.keys(this.optionConfig.index).find(productIndex => {
const productCandidateOptions = this.optionConfig.index[productIndex];
for (const productOption in productCandidateOptions) {
if (! optionId || optionId !== productCandidateOptions[productOption]) {
return false;
}
}
return productIndex;
})
const config = this.getSwatchConfig(attributeId, optionId);
let label = config.label || config.value || this.getOptionLabelFromOptionConfig(attributeId, optionId);
if(childrenId) {
label += ' - ' + hyva.formatPrice(configurableOptions.optionPrices[childrenId].finalPrice.amount)
}
return label;
},
getOptionLabelFromOptionConfig(attributeId, optionId) {
// Fallback if no value is present in swatchConfig data
// Reference issue https://gitlab.hyva.io/hyva-themes/magento2-default-theme/-/issues/190
const option = this.getAllAttributeOptions(attributeId).filter(option => option.id === optionId);
return option && option[0] && option[0].label ||'';
},
getSwatchConfig(attributeId, optionId) {
return this.swatchConfig[attributeId] && this.swatchConfig[attributeId][optionId]
? this.swatchConfig[attributeId][optionId]
: false;
},
activeTooltipItem: false,
tooltipPositionElement: false,
isTooltipVisible() {
return this.activeTooltipItem &&
this.getSwatchConfig(
this.activeTooltipItem.attribute,
this.activeTooltipItem.item
);
},
isFirstItemCol() {
return this.activeTooltipItem.index === 0;
},
getTooltipImageStyle(attributeId, optionId) {
const config = this.getSwatchConfig(attributeId, optionId);
const type = this.getSwatchType(attributeId, optionId);
if (type === "color") {
return 'background-color:' + config.value + '; width: 110px; height: 90px;';
} else if (type === "image") {
return "background: #ffffff url('" + config.thumb +
"') center center no-repeat; width: 110px; height: 90px;";
} else {
return 'display:none';
}
},
getTooltipPosition() {
return this.tooltipPositionElement ?
`top: ${this.tooltipPositionElement.offsetTop}px;` +
`left: ${
this.tooltipPositionElement.offsetLeft - (
this.tooltipPositionElement.closest('.snap') &&
this.tooltipPositionElement.closest('.snap').scrollLeft ||
0
)
}px;` : ''
},
getTooltipLabel() {
return this.getSwatchConfig(this.activeTooltipItem.attribute, this.activeTooltipItem.item).label
},
focusedLabel: false,
focusLabel(optionId) {
this.focusedLabel = optionId;
},
blurLabel() {
this.focusedLabel = false;
},
showSwatches: false,
initShowSwatchesIntersect() {
if ('IntersectionObserver' in window && !window.scrollY) {
let io = new IntersectionObserver(
entries => {
entries.map(entry => {
if (entry.isIntersecting) {
this.showSwatches = true;
io.unobserve(this.$root);
}
})
}
);
io.observe(this.$root);
} else {
this.showSwatches = true
}
}
}
}
</script>
<script>
'use strict';
(function () {
const modals = [];
const excludedFromFocusTrapping = new Set();
function trapFocusInNextModalWithOverlay() {
for (let idx = modals.length -1; idx >= 0; idx--) {
const nextOnStack = modals[idx];
const nextDialogElement = nextOnStack.instance.$refs[nextOnStack.name];
if (! isOverlayDisabled(nextDialogElement)) {
hyva.trapFocus(nextDialogElement);
break;
}
}
}
function focusables(dialogElement) {
const selector = 'button, [href], input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
return Array.from(dialogElement.querySelectorAll(selector))
.filter(el => !el.hasAttribute('disabled'));
}
function firstVisible(elements) {
const a = Array.from(elements);
for (let i = 0; i < a.length; i++) {
if (a[i].offsetWidth || a[i].offsetHeight || a[i].getClientRects().length) return a[i];
}
return null;
}
function isInViewport(element) {
const rect = element && element.getBoundingClientRect();
return rect &&
rect.top >= 0 &&
rect.left >= 0 &&
rect.right <= window.innerWidth &&
rect.bottom <= window.innerHeight;
}
function setFocusAfterTransition(dialogElement, duration) {
const nested = Array.from(dialogElement.querySelectorAll('[role="dialog"]'));
const candidates = Array.from(dialogElement.querySelectorAll('[x-focus-first]'));
next: for (let candidate of candidates) {
for (let child of nested) {
if (child.contains(candidate)) continue next;
}
setTimeout(() => candidate.focus(), 50);
break;
}
window.setTimeout(() => {
const focusElement = firstVisible(dialogElement.querySelectorAll('[x-focus-first]')) ||
focusables(dialogElement)[0] ||
null;
focusElement && isInViewport(focusElement) && focusElement.focus();
}, Math.max(1, duration));
}
function determineTrigger($refs, dialog, trigger) {
if (typeof trigger === 'undefined' && typeof dialog === 'object' && dialog.target instanceof HTMLElement) {
return dialog.target;
}
if (typeof dialog === 'string' && typeof trigger === 'object' && trigger.target instanceof HTMLElement) {
return trigger.target;
}
if (typeof trigger === 'string') {
try {
return $refs[trigger] || document.querySelector(trigger)
} catch (e) {}
}
if (trigger instanceof Element) {
return trigger;
}
return null;
}
function isOverlayDisabled(dialog) {
return dialog && dialog.hasAttribute('x-no-overlay')
}
function areRemainingModalsWithoutOverlay(modals)
{
const overflowDisabled = modals.map(modal => modal.instance.$refs[modal.name]).filter(isOverlayDisabled);
return overflowDisabled.length === modals.length;
}
window.hyva.modal = function(options = {}) {
if (this.$el && this.$el.dataset && this.$el.dataset.options) {
try {
options = Object.assign(options, JSON.parse(this.$el.dataset.options || '{}'));
} catch (e) {
throw new Error('Cannot read the dialog options from the data-options attribute: not valid JSON');
}
}
const config = Object.assign({
dialog: 'dialog', duration: 300, transitionEnter: 'transition ease-out duration-300',
transitionEnterStart: 'opacity-0',
transitionEnterEnd: 'opacity-100',
transitionLeave: 'transition ease-in duration-300',
transitionLeaveStart: 'opacity-100',
transitionLeaveEnd: 'opacity-0',
}, options);
let lastHide = 0;
return {
opened: {},
show(dialog, trigger) {
const focusTargetAfterHide = determineTrigger(this.$refs, dialog, trigger);
const name = typeof dialog === 'string' ? dialog : config.dialog;
const dialogElement = this.$refs[name];
if (! dialogElement) {
return;
}
const useOverlay = ! dialogElement.hasAttribute('x-no-overlay');
dialogElement.scrollTop = 0;
if (this.opened[name]) {
return;
}
if (focusTargetAfterHide) {
focusTargetAfterHide.setAttribute('aria-expanded', 'true');
}
this.opened[name] = true;
useOverlay && this.$nextTick(() => hyva.trapFocus(dialogElement));
setFocusAfterTransition(dialogElement, config.duration);
const frame = {name, instance: this, focusTarget: focusTargetAfterHide, time: Date.now()};
modals.push(frame);
if (useOverlay) {
document.body.classList.add('overflow-hidden');
}
return new Promise(resolve => frame.resolve = resolve);
},
cancel() {
this.hide(false);
},
ok() {
this.hide(true);
},
hide(value) {
if (Date.now() - lastHide < config.duration) {
return;
}
lastHide = Date.now();
const modal = modals.pop() || {};
if (! modal.instance) {
return;
}
const name = modal.name;
this.opened[name] = false;
hyva.releaseFocus(modal.instance.$refs[modal.name])
trapFocusInNextModalWithOverlay();
const nextFocusAfterHide = modal.focusTarget;
nextFocusAfterHide && setTimeout(() => {
nextFocusAfterHide.setAttribute('aria-expanded', 'false');
nextFocusAfterHide.focus()
}, config.duration);
if (modals.length === 0 || areRemainingModalsWithoutOverlay(modals)) {
document.body.classList.remove('overflow-hidden');
}
modal.resolve(value);
},
overlay(dialog) {
dialog = this.$el.dataset.dialogRefName || dialog;
const name = typeof dialog === 'string' ? dialog : config.dialog;
return {
['x-show']() {
return this.opened[name]
},
['x-transition:enter']: config.transitionEnter,
['x-transition:enter-start']: config.transitionEnterStart,
['x-transition:enter-end']: config.transitionEnterEnd,
['x-transition:leave']: config.transitionLeave,
['x-transition:leave-start']: config.transitionLeaveStart,
['x-transition:leave-end']: config.transitionLeaveEnd,
['@hyva-modal-show.window'](event) {
event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide)
}
};
},
showDialogOnInit() {
const parent = this.$el.closest('[data-dialog-ref-name]');
if (parent && parent.dataset.dialogRefName) {
this.$dispatch('hyva-modal-show', {dialog: parent.dataset.dialogRefName})
}
}
};
}
window.hyva.modal.peek = () => modals.length > 0 && modals[modals.length -1]
window.hyva.modal.pop = function () {
if (modals.length > 0) {
const modal = modals[modals.length -1];
modal.instance.hide();
}
}
window.hyva.modal.excludeSelectorsFromFocusTrap = function (selectors) {
typeof selectors === 'string' || selectors instanceof String
? excludedFromFocusTrapping.add(selectors)
: selectors.map(selector => excludedFromFocusTrapping.add(selector));
}
window.hyva.modal.eventListeners = {
keydown: event => {
if (event.key === 'Escape') {
window.hyva.modal.pop();
}
},
click: event => {
if (modals.length > 0) {
const modal = modals[modals.length -1];
const dialog = modal.instance.$refs[modal.name];
if (modal.time + 50 < Date.now() && // if last click processing is more than 50ms ago
! isOverlayDisabled(dialog) && // if dialog has overlay
! dialog.contains(event.target)) { // if click is outside of dialog
modal.instance.hide();
}
}
}
};
document.addEventListener('keydown', window.hyva.modal.eventListeners.keydown);
document.addEventListener('click', window.hyva.modal.eventListeners.click);
})();
window.addEventListener('alpine:init', () => {
Alpine.data('hyvaModal', window.hyva.modal);
}, {once: true});
</script>
<script>
(() => {
function src_default(Alpine) {
Alpine.directive("intersect", Alpine.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
let evaluate = evaluateLater(expression);
let options = {
rootMargin: getRootMargin(modifiers),
threshold: getThreshold(modifiers)
};
let observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting === (value === "leave"))
return;
evaluate();
modifiers.includes("once") && observer.disconnect();
});
}, options);
observer.observe(el);
cleanup(() => {
observer.disconnect();
});
}));
}
function getThreshold(modifiers) {
if (modifiers.includes("full"))
return 0.99;
if (modifiers.includes("half"))
return 0.5;
if (!modifiers.includes("threshold"))
return 0;
let threshold = modifiers[modifiers.indexOf("threshold") + 1];
if (threshold === "100")
return 1;
if (threshold === "0")
return 0;
return Number(`.${threshold}`);
}
function getLengthValue(rawValue) {
let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/);
return match ? match[1] + (match[2] || "px") : void 0;
}
function getRootMargin(modifiers) {
const key = "margin";
const fallback = "0px 0px 0px 0px";
const index = modifiers.indexOf(key);
if (index === -1)
return fallback;
let values = [];
for (let i = 1; i < 5; i++) {
values.push(getLengthValue(modifiers[index + i] || ""));
}
values = values.filter((v) => v !== void 0);
return values.length ? values.join(" ").trim() : fallback;
}
document.addEventListener("alpine:init", () => {
window.Alpine.plugin(src_default);
});
})();
</script>
<script>
for (const [selector, deferUntil] of Object.entries({".product-slider section[x-data]":"intersect",".product-info [x-data]":"intersect","#filters-content [x-data]":"intersect","#review_form":"intersect","section[x-data^=initRecentlyViewedProductsComponent]":"intersect","div[x-data^=initBundleOptions]":"intersect","#product_addtocart_form [x-data]":"intersect","#notice-cookie-block":"idle"})) {
document.querySelectorAll(selector).forEach(el => el.setAttribute('x-defer', `${deferUntil}`));
}
</script>
<script>
(function () {
"use strict";
const hasAlpine = new Promise(resolve => {
window.addEventListener('alpine:initialized', resolve, {once: true, passive: true});
});
const hasInteract = new Promise(resolve => {
(events => {
const onInteract = () => {
resolve();
events.forEach(type => window.removeEventListener(type, onInteract));
}
events.forEach(type => window.addEventListener(type, onInteract, {once: true, passive: true}))
})(['touchstart', 'mouseover', 'wheel', 'scroll', 'keydown'])
});
const onIntersect = (el) => {
return new Promise(resolve => {
const observer = new IntersectionObserver(entries => {
for (const entry of entries) {
if (entry.isIntersecting) {
observer.disconnect()
resolve();
}
}
}, {});
observer.observe(el);
});
}
function runComponent(el) {
hasAlpine.then(() => {
el.removeAttribute('x-ignore');
queueMicrotask(() => Alpine.initTree(el));
});
}
function initDeferredComponents() {
document.querySelectorAll('[x-data][x-defer]').forEach(el => {
el.setAttribute('x-ignore', '');
const deferUntil = (el.getAttribute('x-defer') || '').trim();
switch (deferUntil) {
case 'interact':
hasInteract.then(() => runComponent(el));
break;
case 'intersect':
onIntersect(el).then(() => runComponent(el))
break;
case 'idle':
window.requestIdleCallback
? window.requestIdleCallback(() => runComponent(el), {timeout: 4000})
: setTimeout(() => runComponent(el), 4000);
break;
case 'eager':
runComponent(el);
break;
default:
if (deferUntil.startsWith('event:') && deferUntil.length > 6) {
window.addEventListener(deferUntil.substring(6), () => runComponent(el), {once: true, passive: true});
}
}
});
}
window.addEventListener('alpine:init', initDeferredComponents, {once: true, passive: true});
})()
</script>
<script>
function createAjaxLoader() {
const loader = document.createElement('div')
loader.className = 'absolute inset-0 flex justify-center items-center loader'
loader.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="35" height="35"
viewBox="0 0 60 55" xml:space="preserve">
<rect x="20" y="15" width="4" height="10" fill="#fff">
<animateTransform attributeType="xml"
attributeName="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0" dur="0.6s" repeatCount="indefinite" />
</rect>
<rect x="30" y="15" width="4" height="10" fill="#fff">
<animateTransform attributeType="xml"
attributeName="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.2s" dur="0.6s" repeatCount="indefinite" />
</rect>
<rect x="40" y="15" width="4" height="10" fill="#fff">
<animateTransform attributeType="xml"
attributeName="transform" type="translate"
values="0 0; 0 20; 0 0"
begin="0.4s" dur="0.6s" repeatCount="indefinite" />
</rect>
</svg>`
return loader
}
function addAjaxLoader(button, loader) {
button.setAttribute('data-label', button.getAttribute('aria-label'))
button.removeAttribute('aria-label')
button.prepend(loader)
button.classList.add('relative', '[&>:not(.loader)]:invisible')
button.disabled = true
}
function removeAjaxLoader(button, loader) {
button.setAttribute('aria-label', button.getAttribute('data-label'))
button.removeAttribute('data-label')
loader.remove()
button.classList.remove('[&>:not(.loader)]:invisible')
button.disabled = false
}
async function addAjaxCartForm(form, extraDelay = 500) {
if (!form) return
event.preventDefault()
if (!form.reportValidity()) {
return form.submit()
}
const formData = new FormData(form)
const button = form.querySelector('button:not([type=button], [type=reset])')
? form.querySelector('button:not([type=button], [type=reset])')
: document.getElementById('product-addtocart-button')
const loader = createAjaxLoader(button)
const formUenc = hyva.getUenc()
const postUrl = event.target.action.replace('%25uenc%25', formUenc)
let bodyUrl = new URLSearchParams(formData)
bodyUrl.append('uenc', formUenc)
addAjaxLoader(button, loader)
try {
const response = await fetch(postUrl, {
method: 'POST',
body: bodyUrl.toString(),
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest'
}
})
if (!response.ok) {
return form.submit()
}
if (response.redirected) {
return window.location.href = response.url
}
const responseData = await response.json()
if (responseData.backUrl) {
return window.location.href = responseData.backUrl
}
window.dispatchEvent(new CustomEvent('reload-customer-section-data'))
const productFormData = {
productId: formData.get('product'),
options: {}
}
for (const formEntry of formData.entries()) {
if (!formEntry[0].startsWith('super_attribute')) continue
const formEntryOption = {[formEntry[0].match(/\[(\d+)\]/)[1]]: formEntry[1]}
productFormData.options = {...productFormData.options, ...formEntryOption}
}
window.dispatchEvent(new CustomEvent('open-ajax-cart', {detail: productFormData}))
} catch (err) {
console.warn(err)
window.dispatchEvent(new CustomEvent('product-addtocart-error'))
if (typeof window.dispatchMessages === 'undefined') return
window.dispatchMessages([{
text: 'There\u0020was\u0020a\u0020problem\u0020adding\u0020your\u0020item\u0020to\u0020the\u0020cart.',
type: 'error'
}], 5000)
} finally {
setTimeout(() => removeAjaxLoader(button, loader), extraDelay)
}
}
function removeAjaxCartForm(form) {
removeEventListener('submit', form)
}
document.addEventListener('submit', function (event) {
if (!event.target.matches('#product_addtocart_form, .product_addtocart_form')) return
addAjaxCartForm(event.target, 500)
})
</script>
<dialog
class="w-[640px] bg-white backdrop:bg-black/60 cut-default"
x-data="initAjaxCartModal"
x-show="open"
x-transition.duration.500ms
@keydown.window.escape="closeDialog()"
@click="!onDialogBackdropClickHelper(event) && closeDialog()"
@open-ajax-cart.window="setNewCartData(event)"
>
<template x-if="open && cartItem">
<div>
<div class="flex gap-6 justify-between items-center p-6">
<span class="text-style-5">
Le produit a été ajouté à votre panier. </span>
<button
@click="closeDialog()"
class="button--primary button button--icon"
title="Close fullscreen"
aria-label="Close fullscreen"
type="button"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
viewbox="0 0 20 20">
<path d="m2 3 14.142 14.142h2.829L4.828 3H2Z"/>
<path d="M3.414 18.556 17.556 4.414V1.586L3.414 15.728v2.828Z"/>
</svg>
</button>
</div>
<div class="flex gap-3 sm:gap-x-6 items-start p-6 border-y border-black/35">
<div class="shrink-0 max-w-[theme(spacing.20)] sm:max-w-[theme(spacing.32)]">
<img
loading="lazy"
:src="cartItem.product_image.src"
:width="cartItem.product_image.width"
:height="cartItem.product_image.height"
:alt="hyva.str('Product\u0020\u0022\u00251\u0022', cartItem.product_name)"
>
</div>
<div class="grow flex gap-2 flex-col sm:flex-row">
<div class="grow">
<p class="text-lg">
<strong class="font-bold" x-html="cartItem.product_name"></strong>
</p>
<template x-if="(cartItem.options && cartItem.options.length > 0) || showSku">
<dl class="table mt-2 text-sm">
<template x-if="cartItem.product_sku && showSku">
<div class="table-row">
<dt class="table-cell pb-1.5 pr-2 min-w-[theme(spacing.12)] sm:min-w-[theme(spacing.24)] font-normal text-slate-500 uppercase">
SKU </dt>
<dd class="table-cell pb-1.5 font-bold" x-html="cartItem.product_sku"></dd>
</div>
</template>
<template x-for="option in cartItem.options">
<div class="table-row">
<dt class="table-cell pb-1.5 pr-2 min-w-[theme(spacing.12)] sm:min-w-[theme(spacing.24)] font-normal text-slate-500"
x-text="option.label"></dt>
<dd class="table-cell pb-1.5 font-bold" x-html="option.value"></dd>
</div>
</template>
</dl>
</template>
</div>
<div class="leading-7 shrink-0 [&_.price]:font-normal" x-html="cartItem.product_price"></div>
</div>
</div>
<div class="flex gap-2 justify-between items-end p-6">
<span class="text-label">
<span>Sous-total</span>
<span x-text="getItemCountText()"></span>
</span>
<span class="text-style-5" x-html="cart.subtotal"></span>
</div>
<div class="flex flex-col sm:flex-row lg:justify-end gap-4 p-6 bg-gray">
<button
@click="closeDialog()"
class="button"
>Continuez vos achats</button>
<a
href="https://www.arprotech.com/checkout/"
@click.prevent.stop="closeDialog(); $dispatch('toggle-authentication', { url: 'https://www.arprotech.com/checkout/' });"
class="button button--primary"
>Commander</a>
</div>
</div>
</template>
</dialog>
<script>
function initAjaxCartModal() {
return {
open: false,
cart: {},
initialTotalCartAmount: 0,
totalCartAmount: 0,
cartItem: null,
showSku: true,
init() {
window.addEventListener('private-content-loaded', (event) => {
const cartData = event.detail.data && event.detail.data.cart
if (!cartData) return
this.cart = cartData
this.totalCartAmount = this.cart.summary_count
this.initialTotalCartAmount = this.cart.summary_count
}, {once: true})
this.$watch('totalCartAmount', (value, oldValue) => {
if (this.initialTotalCartAmount === this.totalCartAmount) return
this.openDialog()
this.initialTotalCartAmount = this.totalCartAmount
})
},
sortObjectByNumberKey(obj) {
let keys = Object.keys(obj).map(Number).sort((a, b) => a - b)
let sortedObj = {}
keys.forEach(key => sortedObj[key] = obj[key])
return sortedObj
},
setNewCartData(event) {
const productData = event.detail
window.addEventListener('private-content-loaded', (event) => {
const cartData = event.detail.data && event.detail.data.cart
if (!cartData) return
this.cart = cartData
this.totalCartAmount = this.cart.summary_count
if (!productData) return
this.getCurrentProductFromCart(productData)
})
},
getCurrentProductFromCart(productData) {
if (!this.cart.items) return
this.cartItem = this.cart.items.filter((item) => {
if (item.product_id !== productData.productId) return
if (item.product_type !== 'configurable') {
return item
}
let cartItemOptions = {}
for (const option of item.options) {
const filterOptions = {[option.option_id]: option.option_value}
cartItemOptions = {...cartItemOptions, ...filterOptions}
}
const cartItemOptionsCompare = JSON.stringify(this.sortObjectByNumberKey(cartItemOptions))
const productDataOptionsCompare = JSON.stringify(this.sortObjectByNumberKey(productData.options))
if (cartItemOptionsCompare === productDataOptionsCompare) {
return item
}
})
if (this.cartItem > 1) {
this.cartItem = this.cartItem.slice(0, 1)
}
this.cartItem = this.cartItem[0]
},
getItemCountText() {
if (this.totalCartAmount > 1) {
return hyva.str('(\u00251\u0020produits)', this.totalCartAmount)
}
return hyva.str('(\u00251\u0020produit)', this.totalCartAmount)
},
openDialog() {
if (!this.cartItem) return
this.$root.showModal()
this.open = true
this.scrollLock(this.open)
},
closeDialog() {
this.$root.close()
this.open = false
this.scrollLock(this.open)
},
scrollLock(use = true) {
document.body.style.overflow = use ? 'hidden' : ''
},
onDialogBackdropClickHelper(event, target = this.$root) {
const rect = target.getBoundingClientRect()
const isInDialog =
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width
return isInDialog
}
}
}
</script>
<script>
// x-teleport implementation
(_ => {
document.addEventListener('DOMContentLoaded', event => {
// x-teleport available only for template
if (!Alpine.version.startsWith('2')) {
return;
}
const teleportDirective = (el, expression) => {
let target = document.querySelector(expression)
let clone = el.content.cloneNode(true).firstElementChild;
target.appendChild(clone);
setTimeout(() => {
target.querySelectorAll('[x-data]')
.forEach(el => Alpine.initializeComponent(el));
}, 0)
};
document.querySelectorAll('template').forEach(el => {
if (!el.hasAttribute('x-teleport')) {
return;
}
teleportDirective(el, el.getAttribute('x-teleport'));
});
document.querySelectorAll('[x-data]').forEach(el => {
if (el.hasAttribute('x-init')) {
return;
}
setTimeout(() => {
Alpine.initializeComponent(el);
}, 0);
});
});
})()
</script>
<script type="module"
src="https://www.arprotech.com/static/frontend/Arprotech/default/fr_FR/Hyva_Theme/js/alpine3.min.js"
defer
crossorigin
></script>
<script>
'use strict';
function dispatchMessages(messages, hideAfter) {
const messagesEvent = new CustomEvent("messages-loaded", {
detail: {
messages: messages,
hideAfter: hideAfter
}
});
window.dispatchEvent(messagesEvent);
}
if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) {
console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
}
(function( hyva, undefined ) {
hyva.initFormKey = () => {
const inputSelector = 'input[name="form_key"]',
formKey = hyva.getFormKey();
Array.from(document.querySelectorAll(inputSelector)).map(function (input) {
input.value = formKey
});
}
hyva.initMessages = () => {
try {
const messages = hyva.getCookie('mage-messages');
window.mageMessages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : [];
dispatchMessages(window.mageMessages);
// empty `mage-messages` cookie
const skipSetDomain = true;
hyva.setCookie('mage-messages','', -1, skipSetDomain);
} catch (error) {
console.warn('Error parsing Cookie Messages:', error);
}
}
window.addEventListener('DOMContentLoaded', hyva.initFormKey);
hyva.alpineInitialized(hyva.initMessages)
}( window.hyva = window.hyva || {} ));
</script>
<script>
'use strict';
{
const private_content_key = 'mage-cache-storage';
const private_content_expire_key = 'mage-cache-timeout';
const private_content_version_key = 'private_content_version';
const section_data_ids_key = 'section_data_ids';
const mage_cache_session_id_key = 'mage-cache-sessid';
const last_visited_store_key = 'last_visited_store';
const ttl = 43200;
if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) {
console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
}
function loadSectionData () {
const browserStorage = hyva.getBrowserStorage();
if (!browserStorage) {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "warning",
text: "Please enable LocalStorage in your browser."
}]
);
return;
}
try {
let isInvalid = false;
if (hyva.getCookie(last_visited_store_key) !== CURRENT_STORE_CODE) {
isInvalid = true;
}
hyva.setCookie(last_visited_store_key, CURRENT_STORE_CODE, false, false);
if (!hyva.getCookie(mage_cache_session_id_key)) {
isInvalid = true;
browserStorage.removeItem(private_content_key);
const skipSetDomain = true;
const days = false;
hyva.setCookie(mage_cache_session_id_key, true, days, skipSetDomain)
}
const cookieVersion = hyva.getCookie(private_content_version_key);
const storageVersion = browserStorage.getItem(private_content_version_key);
if (cookieVersion && !storageVersion || cookieVersion !== storageVersion) {
isInvalid = true;
}
const privateContentExpires = browserStorage.getItem(private_content_expire_key);
if (privateContentExpires && new Date(privateContentExpires) < new Date()) {
browserStorage.removeItem(private_content_key);
}
if (isInvalid && cookieVersion) {
fetchPrivateContent([]);
} else if (cookieVersion && storageVersion && cookieVersion === storageVersion) {
const privateContent = JSON.parse(browserStorage.getItem(private_content_key));
if (
privateContent &&
privateContentExpires &&
privateContent.cart &&
privateContent.customer
) {
dispatchPrivateContent(privateContent);
} else {
fetchPrivateContent([]);
}
} else {
if (document.getElementById('default-section-data')) {
const privateContent = JSON.parse(document.getElementById('default-section-data').innerText.trim());
dispatchPrivateContent(privateContent);
} else {
dispatchPrivateContent({});
}
}
} catch (error) {
console.warn('Error retrieving Private Content:', error);
}
}
hyva.alpineInitialized(loadSectionData)
window.addEventListener('reload-customer-section-data', loadSectionData);
window.processSectionDataBeforeDispatch = window.processSectionDataBeforeDispatch || (data => data);
function dispatchPrivateContent(data) {
const privateContentEvent = new CustomEvent("private-content-loaded", {
detail: {
data: window.processSectionDataBeforeDispatch(data)
}
});
window.dispatchEvent(privateContentEvent);
}
function fetchPrivateContent(sections) {
fetch(`${BASE_URL}customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.ok && response.json())
.then(
data => {
if (data) {
try {
const browserStorage = hyva.getBrowserStorage();
// merge new data preserving non-invalidated sections
const oldSectionData = JSON.parse(browserStorage.getItem(private_content_key) || '{}') || {};
if ((! data.cart || ! data.cart.cartId) && oldSectionData['checkout-data']) {
delete oldSectionData['checkout-data'];
}
const newSectionData = Object.assign(oldSectionData, data);
dispatchPrivateContent(newSectionData);
// don't persist messages, they've been dispatched already
if (newSectionData.messages && newSectionData.messages.messages ) {
newSectionData.messages.messages = [];
}
browserStorage.setItem(private_content_key, JSON.stringify(newSectionData));
const expiresAt = new Date(Date.now() + (ttl * 1000)).toISOString();
browserStorage.setItem(private_content_expire_key, expiresAt);
const newCookieVersion = hyva.getCookie(private_content_version_key);
browserStorage.setItem(private_content_version_key, newCookieVersion);
// We don't need the section_data_ids in Hyvä, but we store them for compatibility
// with Luma Fallback. Otherwise, not all sections are loaded in Luma Checkout
hyva.setCookie(
section_data_ids_key,
JSON.stringify(
Object.keys(data).reduce((sectionDataIds, sectionKey) => {
sectionDataIds[sectionKey] = data[sectionKey]['data_id'];
return sectionDataIds;
}, {})
),
false,
true
);
} catch (error) {
console.warn("Couldn't store privateContent", error);
}
}
}
);
}
}
</script>
<script>
(() => {
document.addEventListener('submit', event => event.target.action = event.target.action.replace('%25uenc%25', hyva.getUenc()));
})()
</script>
<script>
(events => {
const dispatchUserInteractionEvent = () => {
events.forEach(type => window.removeEventListener(type, dispatchUserInteractionEvent))
window.dispatchEvent(new Event('init-external-scripts'))
};
events.forEach(type => window.addEventListener(type, dispatchUserInteractionEvent, {once: true, passive: true}))
})(['touchstart', 'mousemove', 'wheel', 'scroll', 'keydown'])
</script>
<script>
'use strict';
const grecaptchaV2LoadCallbacks = [];
function executeRecaptchaLoadCallbacks () {
while (window.grecaptcha && grecaptchaV2LoadCallbacks.length > 0) {
const callback = grecaptchaV2LoadCallbacks.pop();
typeof callback === 'string' ? window[callback]() : callback();
}
}
(function() {
const loadRecaptchaScript = (event) => {
if (window.grecaptcha || !event.target.form) {
return;
}
const url = 'https://www.google.com/recaptcha/api.js?onload=executeRecaptchaLoadCallbacks';
const siteKey = '6LeUktkZAAAAAKAyW_ydkVjPVjvJ4N48E7p2pBoh';
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = siteKey ? `${url}&render=${siteKey}` : `${url}&render=explicit`;
script.async = true;
document.head.appendChild(script);
script.addEventListener('load', () => {
Array.from(document.querySelectorAll('button[data-recaptcha-btn]:disabled')).forEach(btn => btn.removeAttribute('disabled'));
});
}
window.forceLoadRecaptchaScript = (form) => {
loadRecaptchaScript({target: {form: form || 'dummy'}});
executeRecaptchaLoadCallbacks();
};
document.body.addEventListener('input', loadRecaptchaScript, { once: true });
document.body.addEventListener('focus', loadRecaptchaScript, { once: true });
}());
</script>
<script>
function initAmBundlePackGallery() {
return {
"active": 0,
"initialImages": [],
"images": [],
"isSelected" : false,
"currentElement": false,
"appendOnReceiveImages": false,
receiveImages(images) {
if (this.appendOnReceiveImages) {
const initialUrls = this.initialImages.map(image => image.full);
const newImages = images.filter(image => ! initialUrls.includes(image.full));
this.images = [].concat(this.initialImages, newImages);
this.setActive(newImages.length ? this.initialImages.length : 0);
} else {
this.images = images;
}
},
init() {
this.appendOnReceiveImages = this.$el.dataset.appendOnReceiveImages;
this.currentElement = this.$el;
let active = this.images.findIndex(function(image) {
return image.isMain === true
});
if (active === -1) {
active = 0;
}
this.setActive(active);
},
setActive(index) {
this.active = index;
},
resetGallery() {
this.images = this.initialImages;
this.setActive(0);
},
imageCaption() {
return this.image.caption || this.$el.dataset.productName;
},
imageSrc() {
return this.image.img;
},
typeLoading() {
return this.active !== this.index ? 'lazy' : 'eager';
},
showImg() {
return this.active === this.index;
},
eventListeners: {
['@update-gallery.window'](event) {
setTimeout(() => {
if (this.isSelected) {
this.receiveImages(event.detail);
}
this.isSelected = false;
}, 0)
},
['@bundle-popup-gallery-option-selected.window'](event) {
let product = this.currentElement.closest('.amrelated-product-info');
let currentId = event.detail.getAttribute('id');
if (product.querySelector('#' + currentId)){
this.isSelected = true;
}
},
['@reset-gallery.window'](event) {
this.resetGallery();
}
}
}
}
window.addEventListener(
'alpine:init',
() => Alpine.data('initAmBundlePackGallery', initAmBundlePackGallery),
{ once: true }
);
</script>
<script>
function amBundlePackAddPopupData() {
return {
popupData: '',
forms: false,
formsData: '',
popupWrapper: '',
selectors: {
forms: '.amrelated-product-info form.info-container-form',
innerForm: 'form[id*="product_addtocart_form"]',
body: 'body',
productPageClass: 'catalog-product-view',
cartPageClass: 'checkout-cart-index',
popupWrapper: '[x-ref="bundlePopup"]',
hidePopupButtonClass: '.hide-bundle-popup',
swatchInputs: '.amrelated-product-info.configurable .product-option-value-input, .amrelated-product-info.configurable select'
},
init() {
this.popupData = JSON.parse(this.$el.dataset.config);
this.isOsnHyvaEnabled = Boolean(Number(this.$el.dataset.isOsnHyvaEnabled));
this.forms = this.$el.querySelectorAll(this.selectors.forms);
this.popupWrapper = this.$el.closest(this.selectors.popupWrapper);
this.$nextTick(() => {
this.$el.addEventListener('change', (event) => {
if (event.target.closest(this.selectors.swatchInputs)) {
window.dispatchEvent(new CustomEvent('bundle-popup-gallery-option-selected', { detail: event.target }));
}
});
})
},
serializeForm(form) {
const data = new FormData(form)
let array = [];
this._setInputsToArray(data, array);
if (this.isOsnHyvaEnabled) {
if (form.querySelector(this.selectors.innerForm)) {
const data = new FormData(form.querySelector(this.selectors.innerForm));
this._setInputsToArray(data, array);
}
}
return array;
},
_setInputsToArray(data, arrayToSet) {
for (let [key, value] of data) {
arrayToSet.push({
name: key,
value: value
});
}
},
getIsProductPage() {
return !!document.querySelector(this.selectors.body)
.classList.contains(this.selectors.productPageClass);
},
getIsCartPage() {
return !!document.querySelector(this.selectors.body)
.classList.contains(this.selectors.cartPageClass);
},
scrollToElement(el) {
el.scrollIntoView({
behavior: "smooth",
block: "start"
});
},
scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
},
validateProductForm(form) {
let flag = false;
let isValid = form.reportValidity();
if (isValid) {
flag = true;
} else {
this.scrollToElement(form);
}
return flag;
},
prepareData() {
const inCartResponse = this.popupData.productsInCart;
let data = false;
let serializedForms = [];
let formsData = '';
let isFormsValid = true;
this.forms.forEach((form) => {
if (this.isOsnHyvaEnabled) {
if (form.querySelector(this.selectors.innerForm)) {
if (!this.validateProductForm(form.querySelector(this.selectors.innerForm))) {
isFormsValid = false;
return false;
}
}
}
if (!this.validateProductForm(form)) {
isFormsValid = false;
return false;
}
});
if (isFormsValid) {
//forms data collect
this.forms.forEach((form) => {
serializedForms.push(this.serializeForm(form));
});
serializedForms.forEach((form) => {
formsData += 'amrelated_products_popup[]=';
form.forEach((fileld, index, currentForm) => {
formsData += fileld.name + '=' + fileld.value
+ (currentForm.length > (index + 1) ? encodeURIComponent('&') : '');
})
formsData += '&';
})
data = formsData;
//product in cart data
for (let productId in inCartResponse) {
data += 'products_in_cart[' + productId + '][qty]=' + inCartResponse[productId]['qty'] + '&';
}
data += 'ajax_cart=' + this.popupData.isAjaxCartEnabled;
data += '&form_key=' + hyva.getFormKey();
data += '&product_page=' + this.getIsProductPage();
data += '&pack_id=' + this.popupData.packId;
}
return data;
},
addToCart() {
const data = this.prepareData();
if (!data) {
return;
}
this.isLoading = true;
fetch(this.popupData.url, {
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
},
body: new URLSearchParams(data),
method: "POST",
mode: "cors",
credentials: "include"
}).then(
response => response.json()
).then((result) => {
if (result.backUrl) {
window.location.href = result.backUrl;
} else {
window.dispatchEvent(new CustomEvent('mostviewed-items-added'));
const ref = this.$el.closest('[x-ref]').getAttribute('x-ref');
if (ref) {
window.dispatchEvent(new CustomEvent('amrelated-modal-hide', {detail: ref}));
}
}
}).catch(() => {
dispatchMessages([{
type: "error",
text: "Une erreur s'est produite. Merci d'essayer ultérieurement."
}], 2000);
const ref = this.$el.closest('[x-ref]').getAttribute('x-ref');
if (ref) {
window.dispatchEvent(new CustomEvent('amrelated-modal-hide', {detail: ref}));
}
}).finally(() => {
this.isLoading = false;
this.scrollToTop();
})
}
}
}
window.addEventListener(
'alpine:init',
() => Alpine.data('amBundlePackAddPopupData', amBundlePackAddPopupData),
{ once: true }
);
</script>
<script>
function initAmBundlePackWishlist() {
return {
addToWishlist() {
const productId = this.$el.dataset.productId;
const postParams = {
action: BASE_URL + "wishlist/index/add/",
data: {
product: productId,
uenc: hyva.getUenc()
}
}
postParams.data['form_key'] = hyva.getFormKey();
postParams.data['qty'] = document.getElementById(`qty[${productId}]`)
? document.getElementById(`qty[${productId}]`).value || 1
: 1;
let postData = Object.keys(postParams.data).map(key => {
return `${key}=${postParams.data[key]}`;
}).join('&');
// take the all the input fields that configure this product
// includes custom, configurable, grouped and bundled options
Array.from(document.querySelectorAll(
'[name^=options], [name^=super_attribute], [name^=bundle_option], [name^=super_group], [name^=links]')
).map(input => {
if (input.type === "select-multiple") {
Array.from(input.selectedOptions).forEach(option => {
postData += `&${input.name}=${option.value}`
})
} else {
// skip "checkable inputs" that are not checked
if(!(['radio', 'checkbox', 'select'].includes(input.type) && !input.checked)) {
postData += `&${input.name}=${input.value}`
}
}
});
fetch(postParams.action, {
"headers": {
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
},
"body": postData,
"method": "POST",
"mode": "cors",
"credentials": "include"
}).then((response) => {
if (response.redirected) {
window.location.href = response.url;
} else if (response.ok) {
return response.json();
} else {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "warning",
text: "Could not add item to wishlist."
}], 5000
);
}
}).then((response) => {
if (!response) {
return;
}
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: (response.success) ? "success" : "error",
text: (response.success)
? "Produit a été ajouté à votre liste d'achats."
: response.error_message
}], 5000
);
const reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data");
window.dispatchEvent(reloadCustomerDataEvent);
}).catch((error) => {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "error",
text: error
}], 5000
);
});
}
}
}
window.addEventListener('alpine:init', () => Alpine.data('initAmBundlePackWishlist', initAmBundlePackWishlist), {once: true})
</script>
<script>
function initAmBundlePackCompareOnProductView() {
return {
addToCompare: function () {
const productId = 1;
const formKey = hyva.getFormKey();
const postUrl = BASE_URL + 'catalog/product_compare/add/';
fetch(postUrl, {
"headers": {
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
},
"body": "form_key=" + formKey + "&product=" + productId + "&uenc=" + hyva.getUenc(),
"method": "POST",
"mode": "cors",
"credentials": "include"
}).then(function (response) {
if (response.redirected) {
window.location.href = response.url;
}
}).catch(function (error) {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "error",
text: error
}], 5000
);
});
}
};
}
window.addEventListener('alpine:init', () => Alpine.data('initAmBundlePackCompareOnProductView', initAmBundlePackCompareOnProductView), {once: true})
</script>
<script>
'use strict';
function amNotificationProductViewComponent_30525() {
return {
isAvailable: "",
isAvailableConfigurableSimple: false,
isOutofstockConfigurable: "0",
title: "Disponibilité",
options: {},
productIndex: "30525",
hideAddToCartBtn: "",
addToCartButton: "",
notificationLabel: "M’avertir quand ce produit est en stock",
productId: "30525",
/**
* Overridden method for Product Alert View Model to output url according to product id in js
*
* @param productIndex
* @param type
* @returns {*}
*/
getSubscriptionUrl(productIndex, type) {
const urlParts = [
'xnotif/email/',
type,
'/product_id/',
productIndex,
(parseInt(productIndex) !== parseInt(this.productId)) ? '/parent_id/' + this.productId : '',
'/uenc/',
'aHR0cHM6Ly93d3cuYXJwcm90ZWNoLmNvbS9ib21iZS1sYWNyeW1vZ2VuZS1nZWwtcG9pdnJlLXVtYXJleC1wMnAtcGRnLTYwLmh0bWw~'
];
return BASE_URL + urlParts.join('');
},
getSimpleProduct(data, el) {
let children = JSON.parse('[]');
this.addToCartButton = document.getElementById('product-addtocart-button')?.closest('div');
const swatchesComponent = document.querySelector(`[x-data="initConfigurableSwatchOptions_${data.productId}()"]`)
|| document.querySelector(`[x-data="initAmastyXnotifCatalogSwatchesMixin_${data.productId}()"]`)
|| document.querySelector(`[x-data="initAmastyCustomStockStatusOptions_${data.productId}()"]`);
const swatchesCount = swatchesComponent?.querySelector('div')?.children?.length || 0;
let componentElement = document.querySelector(`[x-data="amNotificationProductViewComponent_${data.productId}()"]`)
|| document.querySelector(`#stock_notification_${data.productId}`);
let parentElement = componentElement.closest('.product-info');
for (const [key, value] of Object.entries(children[data.productIndex] || {})) {
const previousIndex = this.productIndex;
this.productIndex = data.productIndex;
if (Object.keys(data.selectedValues).length >= swatchesCount) {
this.isAvailable = Boolean(Number(value));
this.isAvailableConfigurableSimple = Boolean(Number(value));
}
if (this.hideAddToCartBtn) {
this.hideAddToCartBtn.style.display = this.isAvailable ? 'flex' : 'none';
}
if (this.addToCartButton) {
this.addToCartButton.style.display = this.isAvailable ? 'flex' : 'none';
}
if(this.isAvailable) {
parentElement.querySelector('.product-cart-info').classList.add('is-saleable')
} else {
parentElement.querySelector('.product-cart-info').classList.remove('is-saleable')
}
if (el && (previousIndex === this.productIndex) && !this.isAvailable) {
el.closest('.product-info').querySelector('.btn.btn-primary:not(.subscribe-button)').style.display = 'none';
}
}
},
getAvailable() {
return this.options = {
additionalClass: this.isAvailable ? 'bg-green-500' : 'bg-red-500',
label: this.isAvailable ? 'En stock'
: ' Nous contacter',
categoryNotificationLabel: this.isAvailable ? '' : this.notificationLabel,
isAvailable: this.isAvailable
};
},
eventListeners: {
['@configurable-selection-changed.window']() {
const addToCartButton = document.getElementById('product-addtocart-button')?.closest('div');
if (addToCartButton) {
addToCartButton.style.display = this.isAvailableConfigurableSimple ? 'flex' : 'none';
}
},
['@configurable-select-changed.window']({ detail }) {
let componentElement = document.querySelector(`[x-data="amNotificationProductViewComponent_${detail.productId}()"]`)
|| document.querySelector(`#stock_notification_${detail.productId}`);
let parentElement = componentElement.closest('.product-info');
this.hideAddToCartBtn = parentElement.querySelector('.btn.btn-primary:not(.subscribe-button)');
}
},
}
}
</script>
<script>
'use strict';
function amXnotifSubscribeComponent_30525() {
return {
emailInput: '',
mutationPriceSubscription: `mutation AmxnotifPriceSubscribe($input: AmxnotifSubscribeInput) {
AmxnotifPriceSubscribe(input: $input) {
response_message
}
}`,
mutationStockSubscription: `mutation AmxnotifStockSubscribe($input: AmxnotifSubscribeInput) {
AmxnotifStockSubscribe(input: $input) {
response_message
}
}`,
isGDPREnabled: '0' == '1' ? true : false,
isGdprChecked: false,
isInStock: '',
isConfigurable: '',
productIdentifier: '30525',
groupedIndex: '30525',
isLoading: false,
buttonDisabled: false,
isLoggedIn: false,
getSimpleOfGroupedProduct(el) {
let parent = '[for*="super_group"]';
let element = el.closest(parent);
this.groupedIndex = element ? element.getAttribute('for').split('[')[1].split(']')[0] : this.productIdentifier;
},
/**
* Get mutation type according to subscription type
*
* @param type
* @returns {string}
*/
getMutationType(type) {
return type === 'price' ? this.mutationPriceSubscription : this.mutationStockSubscription
},
dispatchHyvaMessage(messages = []) {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(messages);
},
/**
* Fetch the mutation
*
* @param type
* @param productId
*/
fetchSubscribe(type, productId) {
if (!this.validateForm()) {
return false;
}
let variables = {
input: {
product_uid: btoa(productId),
parent_uid: this.isConfigurable ? btoa(this.productIdentifier) : '',
email: String(this.emailInput),
gdpr_agreement: this.isGDPREnabled
}
};
this.buttonDisabled = true;
fetch(BASE_URL + 'graphql', {
method: 'POST',
headers: {
'Store': 'default',
'Content-Type': 'application/json',
},
body: JSON.stringify({query: this.getMutationType(type), variables}),
mode: "cors",
credentials: "include"
})
.then((response) => response.json())
.then((result) => {
if (result?.data?.AmxnotifPriceSubscribe || result?.data?.AmxnotifStockSubscribe) {
this.dispatchHyvaMessage( [{
type: "success",
text: type === 'price'
? result.data.AmxnotifPriceSubscribe.response_message
: result.data.AmxnotifStockSubscribe.response_message
}]);
if (this.isConfigurable && type !== 'price') {
this.buttonDisabled = false;
setTimeout(() => {
this.isLoading = true;
window.location.reload()
}, 2000)
}
} else {
let message = result?.errors ? result.errors[0].message : "Un problème est survenu.";
this.dispatchHyvaMessage(
[{
type: "error",
text: message
}], 3000
)
}
})
.catch(error => {
console.error(error)
})
.finally(()=> {
this.emailInput = '';
this.isGdprChecked = false;
this.buttonDisabled = false;
})
},
validateForm() {
const emailField = this.$refs.emailElement;
if (this.isLoggedIn) {
return true
}
if (!emailField) {
return false;
}
const validateEmailsRegex = /^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i;
if (!validateEmailsRegex.test(emailField.value)) {
emailField.setCustomValidity("Please enter a valid email address (Ex: johndoe@domain.com)");
emailField.reportValidity();
return false;
}
emailField.setCustomValidity("");
if (this.isGDPREnabled) {
const gdprField = this.$refs.gdprElement;
if (!gdprField.checked) {
gdprField.setCustomValidity("Please agree with the Privacy Policy");
gdprField.reportValidity();
return false;
}
gdprField.setCustomValidity("");
}
return true;
},
}
}
</script>
<script>
'use strict';
function initAmRelatedSwiper() {
return {
countSlides: Number(this.$el.dataset.countItems),
swiperInstance: null,
isLoading: true,
init() {
window.addEventListener('amswiper-loaded', () => {
this.initializeSwiper();
}, {once: true});
window.dispatchEvent(new CustomEvent('load-amswiper'));
},
initializeSwiper() {
const self = this;
if (!this.countSlides) {
this.isLoading = false;
return false;
} else {
const swiperContainer = document.getElementById(`swiperContainer${this.$el.dataset.uniqId}`);
this.swiperInstance = new Swiper(swiperContainer, {
slidesPerView: 1,
slidesPerGroup: 1,
direction: 'horizontal',
spaceBetween: 5,
pagination: {
el: `.am-swiper-pagination-${this.$el.dataset.uniqId}`,
clickable: true,
},
breakpoints: {
1024: {
slidesPerView: Number(this.$el.dataset.slidesPerView),
slidesPerGroup: Number(this.$el.dataset.slidesPerView),
spaceBetween: 5
},
},
on: {
init: function () {
self.isLoading = false;
}
}
});
}
},
slideNext() {
if (this.swiperInstance) {
this.swiperInstance.slideNext();
}
},
slidePrev() {
if (this.swiperInstance) {
this.swiperInstance.slidePrev();
}
},
destroy() {
if (this.swiperInstance) {
this.swiperInstance.destroy();
}
},
isNotLoading() {
return !this.isLoading;
},
countSlidesClasses() {
return {
'hidden': this.swiperInstance?.params?.slidesPerView >= this.countSlides
}
},
slidePrevClasses() {
return {
'opacity-25': this.swiperInstance?.isBeginning
}
},
slideNextClasses() {
return {
'opacity-25': this.swiperInstance?.isEnd
}
},
swiperPaginationStyles() {
return {
'--swiper-pagination-bullet-inactive-color': 'transparent',
'--swiper-pagination-bullet-width': 'auto',
'--swiper-pagination-bullet-height': 'auto',
'--swiper-pagination-color': 'transparent',
'--swiper-pagination-bullet-horizontal-gap': '0',
'--swiper-pagination-bottom': '0'
}
}
};
}
window.addEventListener(
'alpine:init',
() => Alpine.data('initAmRelatedSwiper', initAmRelatedSwiper),
{ once: true }
);
</script>
<script type="application/ld+json">{"@context":"https:\/\/schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"https:\/\/www.arprotech.com\/","name":"Accueil"}},{"@type":"ListItem","position":2,"item":{"@id":"https:\/\/www.arprotech.com\/bombe-lacrymogene-gel-poivre-umarex-p2p-pdg-60.html","name":"Bombe lacrymog\u00e8ne gel poivre Umarex P2P PDG-60 38ml"}}]}</script><script type="application/ld+json">{"@context":"https:\/\/schema.org","@type":"Organization","url":"https:\/\/www.arprotech.com\/","name":"ARprotech","logo":"https:\/\/www.arprotech.com\/media\/logo\/websites\/1\/arprotech-logo.png","description":"L'armurerie en ligne ARprotech, armurerie Fran\u00e7aise, vous propose des armes \u00e0 air comprim\u00e9, des armes de cat\u00e9gorie B, des armes de d\u00e9fense. Le st...","contactPoint":[{"@type":"ContactPoint","telephone":"+33(0)967596803","contactType":"sales"}],"address":{"addressCountry":"FR","postalCode":"34560","addressRegion":"Occitanie","addressLocality":"Villeveyrac","streetAddress":"37 Rue Sautaroch - Z.A.E Malpasset"},"sameAs":["https:\/\/www.facebook.com\/pages\/ARprotech\/429691143749474","https:\/\/twitter.com\/ARprotech","https:\/\/www.instagram.com\/arprotech\/","https:\/\/www.youtube.com\/channel\/UCbsbKI0TUDDK83j4MA3MdDg"]}</script><script type="text/json" id="default-section-data">
{"messages":[],"customer":[],"compare-products":[],"last-ordered-items":[],"cart":[],"directory-data":{"AD":{"name":"Andorre"},"AE":{"name":"\u00c9mirats arabes unis"},"AF":{"name":"Afghanistan"},"AG":{"name":"Antigua-et-Barbuda"},"AI":{"name":"Anguilla"},"AL":{"name":"Albanie","regions":{"737":{"code":"AL-01","name":"Berat"},"738":{"code":"AL-09","name":"Dib\u00ebr"},"739":{"code":"AL-02","name":"Durr\u00ebs"},"740":{"code":"AL-03","name":"Elbasan"},"741":{"code":"AL-04","name":"Fier"},"742":{"code":"AL-05","name":"Gjirokast\u00ebr"},"743":{"code":"AL-06","name":"Kor\u00e7\u00eb"},"744":{"code":"AL-07","name":"Kuk\u00ebs"},"745":{"code":"AL-08","name":"Lezh\u00eb"},"746":{"code":"AL-10","name":"Shkod\u00ebr"},"747":{"code":"AL-11","name":"Tiran\u00eb"},"748":{"code":"AL-12","name":"Vlor\u00eb"}}},"AM":{"name":"Arm\u00e9nie"},"AO":{"name":"Angola"},"AQ":{"name":"Antarctique"},"AR":{"name":"Argentine","regions":{"750":{"code":"AR-B","name":"Buenos Aires"},"751":{"code":"AR-K","name":"Catamarca"},"752":{"code":"AR-H","name":"Chaco"},"753":{"code":"AR-U","name":"Chubut"},"749":{"code":"AR-C","name":"Ciudad Aut\u00f3noma de Buenos Aires"},"754":{"code":"AR-X","name":"C\u00f3rdoba"},"755":{"code":"AR-W","name":"Corrientes"},"756":{"code":"AR-E","name":"Entre R\u00edos"},"757":{"code":"AR-P","name":"Formosa"},"758":{"code":"AR-Y","name":"Jujuy"},"759":{"code":"AR-L","name":"La Pampa"},"760":{"code":"AR-F","name":"La Rioja"},"761":{"code":"AR-M","name":"Mendoza"},"762":{"code":"AR-N","name":"Misiones"},"763":{"code":"AR-Q","name":"Neuqu\u00e9n"},"764":{"code":"AR-R","name":"R\u00edo Negro"},"765":{"code":"AR-A","name":"Salta"},"766":{"code":"AR-J","name":"San Juan"},"767":{"code":"AR-D","name":"San Luis"},"768":{"code":"AR-Z","name":"Santa Cruz"},"769":{"code":"AR-S","name":"Santa Fe"},"770":{"code":"AR-G","name":"Santiago del Estero"},"771":{"code":"AR-V","name":"Tierra del Fuego"},"772":{"code":"AR-T","name":"Tucum\u00e1n"}}},"AS":{"name":"Samoa am\u00e9ricaines"},"AT":{"name":"Autriche","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":"Australie"},"AW":{"name":"Aruba"},"AX":{"name":"\u00celes \u00c5land"},"AZ":{"name":"Azerba\u00efdjan"},"BA":{"name":"Bosnie-Herz\u00e9govine"},"BB":{"name":"Barbade"},"BD":{"name":"Bangladesh"},"BE":{"name":"Belgique","regions":{"485":{"code":"VAN","name":"Antwerpen"},"486":{"code":"WBR","name":"Brabant wallon"},"487":{"code":"BRU","name":"Brussels-Capital Region"},"488":{"code":"WHT","name":"Hainaut"},"490":{"code":"WLG","name":"Li\u00e8ge"},"489":{"code":"VLI","name":"Limburg"},"491":{"code":"WLX","name":"Luxembourg"},"492":{"code":"WNA","name":"Namur"},"493":{"code":"VOV","name":"Oost-Vlaanderen"},"494":{"code":"VBR","name":"Vlaams-Brabant"},"495":{"code":"VWV","name":"West-Vlaanderen"}}},"BF":{"name":"Burkina Faso"},"BG":{"name":"Bulgarie","regions":{"690":{"code":"BG-01","name":"Blagoevgrad"},"691":{"code":"BG-02","name":"Burgas"},"697":{"code":"BG-08","name":"Dobrich"},"696":{"code":"BG-07","name":"Gabrovo"},"715":{"code":"BG-26","name":"Haskovo"},"698":{"code":"BG-09","name":"Kardzhali"},"699":{"code":"BG-10","name":"Kyustendil"},"700":{"code":"BG-11","name":"Lovech"},"701":{"code":"BG-12","name":"Montana"},"702":{"code":"BG-13","name":"Pazardzhik"},"703":{"code":"BG-14","name":"Pernik"},"704":{"code":"BG-15","name":"Pleven"},"705":{"code":"BG-16","name":"Plovdiv"},"706":{"code":"BG-17","name":"Razgrad"},"707":{"code":"BG-18","name":"Ruse"},"716":{"code":"BG-27","name":"Shumen"},"708":{"code":"BG-19","name":"Silistra"},"709":{"code":"BG-20","name":"Sliven"},"710":{"code":"BG-21","name":"Smolyan"},"711":{"code":"BG-22","name":"Sofia City"},"712":{"code":"BG-23","name":"Sofia Province"},"713":{"code":"BG-24","name":"Stara Zagora"},"714":{"code":"BG-25","name":"Targovishte"},"692":{"code":"BG-03","name":"Varna"},"693":{"code":"BG-04","name":"Veliko Tarnovo"},"694":{"code":"BG-05","name":"Vidin"},"695":{"code":"BG-06","name":"Vratsa"},"717":{"code":"BG-28","name":"Yambol"}}},"BH":{"name":"Bahre\u00efn"},"BI":{"name":"Burundi"},"BJ":{"name":"B\u00e9nin"},"BL":{"name":"Saint-Barth\u00e9lemy"},"BM":{"name":"Bermudes"},"BN":{"name":"Brunei"},"BO":{"name":"Bolivie","regions":{"781":{"code":"BO-H","name":"Chuquisaca"},"780":{"code":"BO-C","name":"Cochabamba"},"782":{"code":"BO-B","name":"El Beni"},"783":{"code":"BO-L","name":"La Paz"},"784":{"code":"BO-O","name":"Oruro"},"785":{"code":"BO-N","name":"Pando"},"786":{"code":"BO-P","name":"Potos\u00ed"},"787":{"code":"BO-S","name":"Santa Cruz"},"788":{"code":"BO-T","name":"Tarija"}}},"BR":{"name":"Br\u00e9sil"},"BS":{"name":"Bahamas"},"BT":{"name":"Bhoutan"},"BV":{"name":"\u00cele Bouvet"},"BW":{"name":"Botswana"},"BY":{"name":"Bi\u00e9lorussie","regions":{"773":{"code":"BY-BR","name":"Bresckaja voblas\u0107"},"774":{"code":"BY-HO","name":"Homie\u013askaja voblas\u0107"},"775":{"code":"BY-HM","name":"Horad Minsk"},"776":{"code":"BY-HR","name":"Hrodzienskaja voblas\u0107"},"777":{"code":"BY-MA","name":"Mahilio\u016dskaja voblas\u0107"},"778":{"code":"BY-MI","name":"Minskaja voblas\u0107"},"779":{"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":"\u00celes Cocos"},"CD":{"name":"Congo-Kinshasa"},"CF":{"name":"R\u00e9publique centrafricaine"},"CG":{"name":"Congo-Brazzaville"},"CH":{"name":"Suisse","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":"\u00celes Cook"},"CL":{"name":"Chili","regions":{"789":{"code":"CL-AI","name":"Ais\u00e9n del General Carlos Iba\u00f1ez del Campo"},"790":{"code":"CL-AN","name":"Antofagasta"},"791":{"code":"CL-AP","name":"Arica y Parinacota"},"793":{"code":"CL-AT","name":"Atacama"},"794":{"code":"CL-BI","name":"Biob\u00edo"},"795":{"code":"CL-CO","name":"Coquimbo"},"792":{"code":"CL-AR","name":"La Araucan\u00eda"},"796":{"code":"CL-LI","name":"Libertador General Bernardo O'Higgins"},"797":{"code":"CL-LL","name":"Los Lagos"},"798":{"code":"CL-LR","name":"Los R\u00edos"},"799":{"code":"CL-MA","name":"Magallanes"},"800":{"code":"CL-ML","name":"Maule"},"801":{"code":"CL-NB","name":"\u00d1uble"},"802":{"code":"CL-RM","name":"Regi\u00f3n Metropolitana de Santiago"},"803":{"code":"CL-TA","name":"Tarapac\u00e1"},"804":{"code":"CL-VS","name":"Valpara\u00edso"}}},"CM":{"name":"Cameroun"},"CN":{"name":"Chine","regions":{"496":{"code":"CN-AH","name":"Anhui Sheng"},"497":{"code":"CN-BJ","name":"Beijing Shi"},"498":{"code":"CN-CQ","name":"Chongqing Shi"},"499":{"code":"CN-FJ","name":"Fujian Sheng"},"500":{"code":"CN-GS","name":"Gansu Sheng"},"501":{"code":"CN-GD","name":"Guangdong Sheng"},"502":{"code":"CN-GX","name":"Guangxi Zhuangzu Zizhiqu"},"503":{"code":"CN-GZ","name":"Guizhou Sheng"},"504":{"code":"CN-HI","name":"Hainan Sheng"},"505":{"code":"CN-HE","name":"Hebei Sheng"},"506":{"code":"CN-HL","name":"Heilongjiang Sheng"},"507":{"code":"CN-HA","name":"Henan Sheng"},"508":{"code":"CN-HK","name":"Hong Kong SAR"},"509":{"code":"CN-HB","name":"Hubei Sheng"},"510":{"code":"CN-HN","name":"Hunan Sheng"},"511":{"code":"CN-JS","name":"Jiangsu Sheng"},"512":{"code":"CN-JX","name":"Jiangxi Sheng"},"513":{"code":"CN-JL","name":"Jilin Sheng"},"514":{"code":"CN-LN","name":"Liaoning Sheng"},"515":{"code":"CN-MO","name":"Macao SAR"},"516":{"code":"CN-NM","name":"Nei Mongol Zizhiqu"},"517":{"code":"CN-NX","name":"Ningxia Huizi Zizhiqu"},"518":{"code":"CN-QH","name":"Qinghai Sheng"},"519":{"code":"CN-SN","name":"Shaanxi Sheng"},"520":{"code":"CN-SD","name":"Shandong Sheng"},"521":{"code":"CN-SH","name":"Shanghai Shi"},"522":{"code":"CN-SX","name":"Shanxi Sheng"},"523":{"code":"CN-SC","name":"Sichuan Sheng"},"524":{"code":"CN-TW","name":"Taiwan Sheng"},"525":{"code":"CN-TJ","name":"Tianjin Shi"},"526":{"code":"CN-XJ","name":"Xinjiang Uygur Zizhiqu"},"527":{"code":"CN-XZ","name":"Xizang Zizhiqu"},"528":{"code":"CN-YN","name":"Yunnan Sheng"},"529":{"code":"CN-ZJ","name":"Zhejiang Sheng"}}},"CO":{"name":"Colombie","regions":{"532":{"code":"CO-AMA","name":"Amazonas"},"533":{"code":"CO-ANT","name":"Antioquia"},"534":{"code":"CO-ARA","name":"Arauca"},"535":{"code":"CO-ATL","name":"Atl\u00e1ntico"},"536":{"code":"CO-BOL","name":"Bol\u00edvar"},"537":{"code":"CO-BOY","name":"Boyac\u00e1"},"538":{"code":"CO-CAL","name":"Caldas"},"539":{"code":"CO-CAQ","name":"Caquet\u00e1"},"540":{"code":"CO-CAS","name":"Casanare"},"541":{"code":"CO-CAU","name":"Cauca"},"542":{"code":"CO-CES","name":"Cesar"},"543":{"code":"CO-CHO","name":"Choc\u00f3"},"544":{"code":"CO-COR","name":"C\u00f3rdoba"},"545":{"code":"CO-CUN","name":"Cundinamarca"},"546":{"code":"CO-GUA","name":"Guain\u00eda"},"547":{"code":"CO-GUV","name":"Guaviare"},"548":{"code":"CO-HUL","name":"Huila"},"549":{"code":"CO-LAG","name":"La Guajira"},"550":{"code":"CO-MAG","name":"Magdalena"},"551":{"code":"CO-MET","name":"Meta"},"552":{"code":"CO-NAR","name":"Nari\u00f1o"},"553":{"code":"CO-NSA","name":"Norte de Santander"},"554":{"code":"CO-PUT","name":"Putumayo"},"555":{"code":"CO-QUI","name":"Quind\u00edo"},"556":{"code":"CO-RIS","name":"Risaralda"},"557":{"code":"CO-SAP","name":"San Andr\u00e9s y Providencia"},"558":{"code":"CO-SAN","name":"Santander"},"559":{"code":"CO-SUC","name":"Sucre"},"560":{"code":"CO-TOL","name":"Tolima"},"561":{"code":"CO-VAC","name":"Valle del Cauca"},"562":{"code":"CO-VAU","name":"Vaup\u00e9s"},"563":{"code":"CO-VID","name":"Vichada"}}},"CR":{"name":"Costa Rica","regions":{"1001":{"code":"CR-AL","name":"Alajuela"},"1002":{"code":"CR-CA","name":"Cartago"},"1004":{"code":"CR-GU","name":"Guanacaste"},"1003":{"code":"CR-HE","name":"Heredia"},"1006":{"code":"CR-LI","name":"Lim\u00f3n"},"1005":{"code":"CR-PU","name":"Puntarenas"},"1000":{"code":"CR-SJ","name":"San Jos\u00e9"}}},"CU":{"name":"Cuba"},"CV":{"name":"Cap-Vert"},"CX":{"name":"\u00cele Christmas"},"CY":{"name":"Chypre"},"CZ":{"name":"Tch\u00e9quie","regions":{"807":{"code":"CZ-31","name":"Jiho\u010desk\u00fd kraj"},"815":{"code":"CZ-64","name":"Jihomoravsk\u00fd kraj"},"809":{"code":"CZ-41","name":"Karlovarsk\u00fd kraj"},"814":{"code":"CZ-63","name":"Kraj Vyso\u010dina"},"812":{"code":"CZ-52","name":"Kr\u00e1lov\u00e9hradeck\u00fd kraj"},"811":{"code":"CZ-51","name":"Libereck\u00fd kraj"},"818":{"code":"CZ-80","name":"Moravskoslezsk\u00fd kraj"},"816":{"code":"CZ-71","name":"Olomouck\u00fd kraj"},"813":{"code":"CZ-53","name":"Pardubick\u00fd kraj"},"808":{"code":"CZ-32","name":"Plze\u0148sk\u00fd kraj"},"805":{"code":"CZ-10","name":"Praha, Hlavn\u00ed m\u011bsto"},"806":{"code":"CZ-20","name":"St\u0159edo\u010desk\u00fd kraj"},"810":{"code":"CZ-42","name":"\u00dasteck\u00fd kraj"},"817":{"code":"CZ-72","name":"Zl\u00ednsk\u00fd kraj"}}},"DE":{"name":"Allemagne","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":"Danemark","regions":{"819":{"code":"DK-84","name":"Hovedstaden"},"820":{"code":"DK-82","name":"Midtjylland"},"821":{"code":"DK-81","name":"Nordjylland"},"822":{"code":"DK-85","name":"Sj\u00e6lland"},"823":{"code":"DK-83","name":"Syddanmark"}}},"DM":{"name":"Dominique"},"DO":{"name":"R\u00e9publique dominicaine"},"DZ":{"name":"Alg\u00e9rie"},"EC":{"name":"\u00c9quateur","regions":{"824":{"code":"EC-A","name":"Azuay"},"825":{"code":"EC-B","name":"Bol\u00edvar"},"826":{"code":"EC-F","name":"Ca\u00f1ar"},"827":{"code":"EC-C","name":"Carchi"},"828":{"code":"EC-H","name":"Chimborazo"},"829":{"code":"EC-X","name":"Cotopaxi"},"830":{"code":"EC-O","name":"El Oro"},"831":{"code":"EC-E","name":"Esmeraldas"},"832":{"code":"EC-W","name":"Gal\u00e1pagos"},"833":{"code":"EC-G","name":"Guayas"},"834":{"code":"EC-I","name":"Imbabura"},"835":{"code":"EC-L","name":"Loja"},"836":{"code":"EC-R","name":"Los R\u00edos"},"837":{"code":"EC-M","name":"Manab\u00ed"},"838":{"code":"EC-S","name":"Morona Santiago"},"839":{"code":"EC-N","name":"Napo"},"840":{"code":"EC-D","name":"Orellana"},"841":{"code":"EC-Y","name":"Pastaza"},"842":{"code":"EC-P","name":"Pichincha"},"843":{"code":"EC-SE","name":"Santa Elena"},"844":{"code":"EC-SD","name":"Santo Domingo de los Ts\u00e1chilas"},"845":{"code":"EC-U","name":"Sucumb\u00edos"},"846":{"code":"EC-T","name":"Tungurahua"},"847":{"code":"EC-Z","name":"Zamora Chinchipe"}}},"EE":{"name":"Estonie","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":"\u00c9gypte"},"EH":{"name":"Sahara occidental"},"ER":{"name":"\u00c9rythr\u00e9e"},"ES":{"name":"Espagne","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":"\u00c9thiopie"},"FI":{"name":"Finlande","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":"Fidji"},"FK":{"name":"\u00celes Malouines"},"FM":{"name":"Micron\u00e9sie"},"FO":{"name":"\u00celes F\u00e9ro\u00e9"},"FR":{"name":"France","regions":{"182":{"code":"1","name":"Ain"},"183":{"code":"2","name":"Aisne"},"184":{"code":"3","name":"Allier"},"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"},"531":{"code":"98","name":"Monaco"},"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"},"530":{"code":"OM","name":"Outre-Mer"},"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":"Royaume-Uni"},"GD":{"name":"Grenade"},"GE":{"name":"G\u00e9orgie"},"GF":{"name":"Guyane fran\u00e7aise"},"GG":{"name":"Guernesey"},"GH":{"name":"Ghana"},"GI":{"name":"Gibraltar"},"GL":{"name":"Groenland"},"GM":{"name":"Gambie"},"GN":{"name":"Guin\u00e9e"},"GP":{"name":"Guadeloupe"},"GQ":{"name":"Guin\u00e9e \u00e9quatoriale"},"GR":{"name":"Gr\u00e8ce","regions":{"861":{"code":"GR-69","name":"\u00c1gion \u00d3ros"},"848":{"code":"GR-A","name":"Anatolik\u00ed Makedon\u00eda kai Thr\u00e1ki"},"849":{"code":"GR-I","name":"Attik\u00ed"},"850":{"code":"GR-G","name":"Dytik\u00ed Ell\u00e1da"},"851":{"code":"GR-C","name":"Dytik\u00ed Makedon\u00eda"},"852":{"code":"GR-F","name":"Ion\u00eda N\u00edsia"},"853":{"code":"GR-D","name":"\u00cdpeiros"},"854":{"code":"GR-B","name":"Kentrik\u00ed Makedon\u00eda"},"855":{"code":"GR-M","name":"Kr\u00edti"},"856":{"code":"GR-L","name":"N\u00f3tio Aiga\u00edo"},"857":{"code":"GR-J","name":"Pelop\u00f3nnisos"},"858":{"code":"GR-H","name":"Stere\u00e1 Ell\u00e1da"},"859":{"code":"GR-E","name":"Thessal\u00eda"},"860":{"code":"GR-K","name":"V\u00f3reio Aiga\u00edo"}}},"GS":{"name":"G\u00e9orgie du Sud-et-les \u00celes Sandwich du Sud"},"GT":{"name":"Guatemala"},"GU":{"name":"Guam"},"GW":{"name":"Guin\u00e9e-Bissau"},"GY":{"name":"Guyana","regions":{"862":{"code":"GY-BA","name":"Barima-Waini"},"863":{"code":"GY-CU","name":"Cuyuni-Mazaruni"},"864":{"code":"GY-DE","name":"Demerara-Mahaica"},"865":{"code":"GY-EB","name":"East Berbice-Corentyne"},"866":{"code":"GY-ES","name":"Essequibo Islands-West Demerara"},"867":{"code":"GY-MA","name":"Mahaica-Berbice"},"868":{"code":"GY-PM","name":"Pomeroon-Supenaam"},"869":{"code":"GY-PT","name":"Potaro-Siparuni"},"870":{"code":"GY-UD","name":"Upper Demerara-Berbice"},"871":{"code":"GY-UT","name":"Upper Takutu-Upper Essequibo"}}},"HK":{"name":"R.A.S. chinoise de Hong Kong"},"HM":{"name":"\u00celes Heard-et-MacDonald"},"HN":{"name":"Honduras"},"HR":{"name":"Croatie"},"HT":{"name":"Ha\u00efti"},"HU":{"name":"Hongrie"},"ID":{"name":"Indon\u00e9sie"},"IE":{"name":"Irlande"},"IL":{"name":"Isra\u00ebl"},"IM":{"name":"\u00cele de Man"},"IN":{"name":"Inde","regions":{"1034":{"code":"LA","name":"Ladakh"}}},"IO":{"name":"Territoire britannique de l\u2019oc\u00e9an Indien"},"IQ":{"name":"Irak"},"IR":{"name":"Iran"},"IS":{"name":"Islande","regions":{"878":{"code":"IS-07","name":"Austurland"},"872":{"code":"IS-01","name":"H\u00f6fu\u00f0borgarsv\u00e6\u00f0i"},"877":{"code":"IS-06","name":"Nor\u00f0urland eystra"},"876":{"code":"IS-05","name":"Nor\u00f0urland vestra"},"879":{"code":"IS-08","name":"Su\u00f0urland"},"873":{"code":"IS-02","name":"Su\u00f0urnes"},"875":{"code":"IS-04","name":"Vestfir\u00f0ir"},"874":{"code":"IS-03","name":"Vesturland"}}},"IT":{"name":"Italie","regions":{"564":{"code":"AG","name":"Agrigento"},"565":{"code":"AL","name":"Alessandria"},"566":{"code":"AN","name":"Ancona"},"567":{"code":"AO","name":"Aosta"},"569":{"code":"AR","name":"Arezzo"},"570":{"code":"AP","name":"Ascoli-Piceno"},"571":{"code":"AT","name":"Asti"},"572":{"code":"AV","name":"Avellino"},"573":{"code":"BA","name":"Bari"},"574":{"code":"BT","name":"Barletta-Andria-Trani"},"575":{"code":"BL","name":"Belluno"},"576":{"code":"BN","name":"Benevento"},"577":{"code":"BG","name":"Bergamo"},"578":{"code":"BI","name":"Biella"},"579":{"code":"BO","name":"Bologna"},"580":{"code":"BZ","name":"Bolzano"},"581":{"code":"BS","name":"Brescia"},"582":{"code":"BR","name":"Brindisi"},"583":{"code":"CA","name":"Cagliari"},"584":{"code":"CL","name":"Caltanissetta"},"585":{"code":"CB","name":"Campobasso"},"586":{"code":"CI","name":"Carbonia Iglesias"},"587":{"code":"CE","name":"Caserta"},"588":{"code":"CT","name":"Catania"},"589":{"code":"CZ","name":"Catanzaro"},"590":{"code":"CH","name":"Chieti"},"591":{"code":"CO","name":"Como"},"592":{"code":"CS","name":"Cosenza"},"593":{"code":"CR","name":"Cremona"},"594":{"code":"KR","name":"Crotone"},"595":{"code":"CN","name":"Cuneo"},"596":{"code":"EN","name":"Enna"},"597":{"code":"FM","name":"Fermo"},"598":{"code":"FE","name":"Ferrara"},"599":{"code":"FI","name":"Firenze"},"600":{"code":"FG","name":"Foggia"},"601":{"code":"FC","name":"Forli-Cesena"},"602":{"code":"FR","name":"Frosinone"},"603":{"code":"GE","name":"Genova"},"604":{"code":"GO","name":"Gorizia"},"605":{"code":"GR","name":"Grosseto"},"606":{"code":"IM","name":"Imperia"},"607":{"code":"IS","name":"Isernia"},"568":{"code":"AQ","name":"L'Aquila"},"608":{"code":"SP","name":"La-Spezia"},"609":{"code":"LT","name":"Latina"},"610":{"code":"LE","name":"Lecce"},"611":{"code":"LC","name":"Lecco"},"612":{"code":"LI","name":"Livorno"},"613":{"code":"LO","name":"Lodi"},"614":{"code":"LU","name":"Lucca"},"615":{"code":"MC","name":"Macerata"},"616":{"code":"MN","name":"Mantova"},"617":{"code":"MS","name":"Massa-Carrara"},"618":{"code":"MT","name":"Matera"},"619":{"code":"VS","name":"Medio Campidano"},"620":{"code":"ME","name":"Messina"},"621":{"code":"MI","name":"Milano"},"622":{"code":"MO","name":"Modena"},"623":{"code":"MB","name":"Monza-Brianza"},"624":{"code":"NA","name":"Napoli"},"625":{"code":"NO","name":"Novara"},"626":{"code":"NU","name":"Nuoro"},"627":{"code":"OG","name":"Ogliastra"},"628":{"code":"OT","name":"Olbia Tempio"},"629":{"code":"OR","name":"Oristano"},"630":{"code":"PD","name":"Padova"},"631":{"code":"PA","name":"Palermo"},"632":{"code":"PR","name":"Parma"},"633":{"code":"PV","name":"Pavia"},"634":{"code":"PG","name":"Perugia"},"635":{"code":"PU","name":"Pesaro-Urbino"},"636":{"code":"PE","name":"Pescara"},"637":{"code":"PC","name":"Piacenza"},"638":{"code":"PI","name":"Pisa"},"639":{"code":"PT","name":"Pistoia"},"640":{"code":"PN","name":"Pordenone"},"641":{"code":"PZ","name":"Potenza"},"642":{"code":"PO","name":"Prato"},"643":{"code":"RG","name":"Ragusa"},"644":{"code":"RA","name":"Ravenna"},"645":{"code":"RC","name":"Reggio-Calabria"},"646":{"code":"RE","name":"Reggio-Emilia"},"647":{"code":"RI","name":"Rieti"},"648":{"code":"RN","name":"Rimini"},"649":{"code":"RM","name":"Roma"},"650":{"code":"RO","name":"Rovigo"},"651":{"code":"SA","name":"Salerno"},"652":{"code":"SS","name":"Sassari"},"653":{"code":"SV","name":"Savona"},"654":{"code":"SI","name":"Siena"},"655":{"code":"SR","name":"Siracusa"},"656":{"code":"SO","name":"Sondrio"},"657":{"code":"TA","name":"Taranto"},"658":{"code":"TE","name":"Teramo"},"659":{"code":"TR","name":"Terni"},"660":{"code":"TO","name":"Torino"},"661":{"code":"TP","name":"Trapani"},"662":{"code":"TN","name":"Trento"},"663":{"code":"TV","name":"Treviso"},"664":{"code":"TS","name":"Trieste"},"665":{"code":"UD","name":"Udine"},"666":{"code":"VA","name":"Varese"},"667":{"code":"VE","name":"Venezia"},"668":{"code":"VB","name":"Verbania"},"669":{"code":"VC","name":"Vercelli"},"670":{"code":"VR","name":"Verona"},"671":{"code":"VV","name":"Vibo-Valentia"},"672":{"code":"VI","name":"Vicenza"},"673":{"code":"VT","name":"Viterbo"}}},"JE":{"name":"Jersey"},"JM":{"name":"Jama\u00efque"},"JO":{"name":"Jordanie"},"JP":{"name":"Japon"},"KE":{"name":"Kenya"},"KG":{"name":"Kirghizstan"},"KH":{"name":"Cambodge"},"KI":{"name":"Kiribati"},"KM":{"name":"Comores"},"KN":{"name":"Saint-Christophe-et-Ni\u00e9v\u00e8s"},"KP":{"name":"Cor\u00e9e du Nord"},"KR":{"name":"Cor\u00e9e du Sud"},"KW":{"name":"Kowe\u00eft"},"KY":{"name":"\u00celes Ca\u00efmans"},"KZ":{"name":"Kazakhstan"},"LA":{"name":"Laos"},"LB":{"name":"Liban"},"LC":{"name":"Sainte-Lucie"},"LI":{"name":"Liechtenstein"},"LK":{"name":"Sri Lanka"},"LR":{"name":"Liberia"},"LS":{"name":"Lesotho"},"LT":{"name":"Lituanie","regions":{"475":{"code":"LT-AL","name":"Alytaus Apskritis"},"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":"Lettonie","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"},"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":"Libye"},"MA":{"name":"Maroc"},"MC":{"name":"Monaco"},"MD":{"name":"Moldavie"},"ME":{"name":"Mont\u00e9n\u00e9gro"},"MF":{"name":"Saint-Martin"},"MG":{"name":"Madagascar"},"MH":{"name":"\u00celes Marshall"},"MK":{"name":"Mac\u00e9doine du Nord"},"ML":{"name":"Mali"},"MM":{"name":"Myanmar (Birmanie)"},"MN":{"name":"Mongolie"},"MO":{"name":"R.A.S. chinoise de Macao"},"MP":{"name":"\u00celes Mariannes du Nord"},"MQ":{"name":"Martinique"},"MR":{"name":"Mauritanie"},"MS":{"name":"Montserrat"},"MT":{"name":"Malte"},"MU":{"name":"Maurice"},"MV":{"name":"Maldives"},"MW":{"name":"Malawi"},"MX":{"name":"Mexique"},"MY":{"name":"Malaisie"},"MZ":{"name":"Mozambique"},"NA":{"name":"Namibie"},"NC":{"name":"Nouvelle-Cal\u00e9donie"},"NE":{"name":"Niger"},"NF":{"name":"\u00cele Norfolk"},"NG":{"name":"Nigeria"},"NI":{"name":"Nicaragua"},"NL":{"name":"Pays-Bas"},"NO":{"name":"Norv\u00e8ge"},"NP":{"name":"N\u00e9pal"},"NR":{"name":"Nauru"},"NU":{"name":"Niue"},"NZ":{"name":"Nouvelle-Z\u00e9lande"},"OM":{"name":"Oman"},"PA":{"name":"Panama"},"PE":{"name":"P\u00e9rou","regions":{"899":{"code":"PE-AMA","name":"Amazonas"},"900":{"code":"PE-ANC","name":"Ancash"},"901":{"code":"PE-APU","name":"Apur\u00edmac"},"902":{"code":"PE-ARE","name":"Arequipa"},"903":{"code":"PE-AYA","name":"Ayacucho"},"904":{"code":"PE-CAJ","name":"Cajamarca"},"905":{"code":"PE-CUS","name":"Cusco"},"906":{"code":"PE-CAL","name":"El Callao"},"907":{"code":"PE-HUV","name":"Huancavelica"},"908":{"code":"PE-HUC","name":"Hu\u00e1nuco"},"909":{"code":"PE-ICA","name":"Ica"},"910":{"code":"PE-JUN","name":"Jun\u00edn"},"911":{"code":"PE-LAL","name":"La Libertad"},"912":{"code":"PE-LAM","name":"Lambayeque"},"913":{"code":"PE-LIM","name":"Lima"},"914":{"code":"PE-LOR","name":"Loreto"},"915":{"code":"PE-MDD","name":"Madre de Dios"},"916":{"code":"PE-MOQ","name":"Moquegua"},"898":{"code":"PE-LMA","name":"Municipalidad Metropolitana de Lima"},"917":{"code":"PE-PAS","name":"Pasco"},"918":{"code":"PE-PIU","name":"Piura"},"919":{"code":"PE-PUN","name":"Puno"},"920":{"code":"PE-SAM","name":"San Mart\u00edn"},"921":{"code":"PE-TAC","name":"Tacna"},"922":{"code":"PE-TUM","name":"Tumbes"},"923":{"code":"PE-UCA","name":"Ucayali"}}},"PF":{"name":"Polyn\u00e9sie fran\u00e7aise"},"PG":{"name":"Papouasie-Nouvelle-Guin\u00e9e"},"PH":{"name":"Philippines"},"PK":{"name":"Pakistan"},"PL":{"name":"Pologne","regions":{"674":{"code":"PL-02","name":"dolno\u015bl\u0105skie"},"675":{"code":"PL-04","name":"kujawsko-pomorskie"},"676":{"code":"PL-06","name":"lubelskie"},"677":{"code":"PL-08","name":"lubuskie"},"680":{"code":"PL-14","name":"mazowieckie"},"679":{"code":"PL-12","name":"ma\u0142opolskie"},"681":{"code":"PL-16","name":"opolskie"},"682":{"code":"PL-18","name":"podkarpackie"},"683":{"code":"PL-20","name":"podlaskie"},"684":{"code":"PL-22","name":"pomorskie"},"685":{"code":"PL-24","name":"\u015bl\u0105skie"},"686":{"code":"PL-26","name":"\u015bwi\u0119tokrzyskie"},"687":{"code":"PL-28","name":"warmi\u0144sko-mazurskie"},"688":{"code":"PL-30","name":"wielkopolskie"},"689":{"code":"PL-32","name":"zachodniopomorskie"},"678":{"code":"PL-10","name":"\u0142\u00f3dzkie"}}},"PM":{"name":"Saint-Pierre-et-Miquelon"},"PN":{"name":"\u00celes Pitcairn"},"PR":{"name":"Porto Rico"},"PS":{"name":"Territoires palestiniens"},"PT":{"name":"Portugal","regions":{"924":{"code":"PT-01","name":"Aveiro"},"925":{"code":"PT-02","name":"Beja"},"926":{"code":"PT-03","name":"Braga"},"927":{"code":"PT-04","name":"Bragan\u00e7a"},"928":{"code":"PT-05","name":"Castelo Branco"},"929":{"code":"PT-06","name":"Coimbra"},"930":{"code":"PT-07","name":"\u00c9vora"},"931":{"code":"PT-08","name":"Faro"},"932":{"code":"PT-09","name":"Guarda"},"933":{"code":"PT-10","name":"Leiria"},"934":{"code":"PT-11","name":"Lisboa"},"935":{"code":"PT-12","name":"Portalegre"},"936":{"code":"PT-13","name":"Porto"},"943":{"code":"PT-30","name":"Regi\u00e3o Aut\u00f3noma da Madeira"},"942":{"code":"PT-20","name":"Regi\u00e3o Aut\u00f3noma dos A\u00e7ores"},"937":{"code":"PT-14","name":"Santar\u00e9m"},"938":{"code":"PT-15","name":"Set\u00fabal"},"939":{"code":"PT-16","name":"Viana do Castelo"},"940":{"code":"PT-17","name":"Vila Real"},"941":{"code":"PT-18","name":"Viseu"}}},"PW":{"name":"Palaos"},"PY":{"name":"Paraguay","regions":{"881":{"code":"PY-16","name":"Alto Paraguay"},"882":{"code":"PY-10","name":"Alto Paran\u00e1"},"883":{"code":"PY-13","name":"Amambay"},"880":{"code":"PY-ASU","name":"Asunci\u00f3n"},"884":{"code":"PY-19","name":"Boquer\u00f3n"},"885":{"code":"PY-5","name":"Caaguaz\u00fa"},"886":{"code":"PY-6","name":"Caazap\u00e1"},"887":{"code":"PY-14","name":"Canindey\u00fa"},"888":{"code":"PY-11","name":"Central"},"889":{"code":"PY-1","name":"Concepci\u00f3n"},"890":{"code":"PY-3","name":"Cordillera"},"891":{"code":"PY-4","name":"Guair\u00e1"},"892":{"code":"PY-7","name":"Itap\u00faa"},"893":{"code":"PY-8","name":"Misiones"},"894":{"code":"PY-12","name":"\u00d1eembuc\u00fa"},"895":{"code":"PY-9","name":"Paraguar\u00ed"},"896":{"code":"PY-15","name":"Presidente Hayes"},"897":{"code":"PY-2","name":"San Pedro"}}},"QA":{"name":"Qatar"},"RE":{"name":"La R\u00e9union"},"RO":{"name":"Roumanie","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":"Serbie"},"RU":{"name":"Russie"},"RW":{"name":"Rwanda"},"SA":{"name":"Arabie saoudite"},"SB":{"name":"\u00celes Salomon"},"SC":{"name":"Seychelles"},"SD":{"name":"Soudan"},"SE":{"name":"Su\u00e8de","regions":{"954":{"code":"SE-K","name":"Blekinge l\u00e4n"},"955":{"code":"SE-W","name":"Dalarnas l\u00e4n"},"957":{"code":"SE-X","name":"G\u00e4vleborgs l\u00e4n"},"956":{"code":"SE-I","name":"Gotlands l\u00e4n"},"958":{"code":"SE-N","name":"Hallands l\u00e4n"},"959":{"code":"SE-Z","name":"J\u00e4mtlands l\u00e4n"},"960":{"code":"SE-F","name":"J\u00f6nk\u00f6pings l\u00e4n"},"961":{"code":"SE-H","name":"Kalmar l\u00e4n"},"962":{"code":"SE-G","name":"Kronobergs l\u00e4n"},"963":{"code":"SE-BD","name":"Norrbottens l\u00e4n"},"973":{"code":"SE-T","name":"\u00d6rebro l\u00e4n"},"974":{"code":"SE-E","name":"\u00d6sterg\u00f6tlands l\u00e4n"},"964":{"code":"SE-M","name":"Sk\u00e5ne l\u00e4n"},"966":{"code":"SE-D","name":"S\u00f6dermanlands l\u00e4n"},"965":{"code":"SE-AB","name":"Stockholms l\u00e4n"},"967":{"code":"SE-C","name":"Uppsala l\u00e4n"},"968":{"code":"SE-S","name":"V\u00e4rmlands l\u00e4n"},"969":{"code":"SE-AC","name":"V\u00e4sterbottens l\u00e4n"},"970":{"code":"SE-Y","name":"V\u00e4sternorrlands l\u00e4n"},"971":{"code":"SE-U","name":"V\u00e4stmanlands l\u00e4n"},"972":{"code":"SE-O","name":"V\u00e4stra G\u00f6talands l\u00e4n"}}},"SG":{"name":"Singapour"},"SH":{"name":"Sainte-H\u00e9l\u00e8ne"},"SI":{"name":"Slov\u00e9nie"},"SJ":{"name":"Svalbard et Jan Mayen"},"SK":{"name":"Slovaquie"},"SL":{"name":"Sierra Leone"},"SM":{"name":"Saint-Marin"},"SN":{"name":"S\u00e9n\u00e9gal"},"SO":{"name":"Somalie"},"SR":{"name":"Suriname","regions":{"944":{"code":"SR-BR","name":"Brokopondo"},"945":{"code":"SR-CM","name":"Commewijne"},"946":{"code":"SR-CR","name":"Coronie"},"947":{"code":"SR-MA","name":"Marowijne"},"948":{"code":"SR-NI","name":"Nickerie"},"949":{"code":"SR-PR","name":"Para"},"950":{"code":"SR-PM","name":"Paramaribo"},"951":{"code":"SR-SA","name":"Saramacca"},"952":{"code":"SR-SI","name":"Sipaliwini"},"953":{"code":"SR-WA","name":"Wanica"}}},"ST":{"name":"Sao Tom\u00e9-et-Principe"},"SV":{"name":"Salvador"},"SY":{"name":"Syrie"},"SZ":{"name":"Eswatini"},"TC":{"name":"\u00celes Turques-et-Ca\u00efques"},"TD":{"name":"Tchad"},"TF":{"name":"Terres australes fran\u00e7aises"},"TG":{"name":"Togo"},"TH":{"name":"Tha\u00eflande"},"TJ":{"name":"Tadjikistan"},"TK":{"name":"Tokelau"},"TL":{"name":"Timor oriental"},"TM":{"name":"Turkm\u00e9nistan"},"TN":{"name":"Tunisie"},"TO":{"name":"Tonga"},"TR":{"name":"Turquie"},"TT":{"name":"Trinit\u00e9-et-Tobago"},"TV":{"name":"Tuvalu"},"TW":{"name":"Ta\u00efwan"},"TZ":{"name":"Tanzanie"},"UA":{"name":"Ukraine","regions":{"1031":{"code":"UA-43","name":"Avtonomna Respublika Krym"},"1007":{"code":"UA-71","name":"Cherkaska oblast"},"1008":{"code":"UA-74","name":"Chernihivska oblast"},"1009":{"code":"UA-77","name":"Chernivetska oblast"},"1010":{"code":"UA-12","name":"Dnipropetrovska oblast"},"1011":{"code":"UA-14","name":"Donetska oblast"},"1012":{"code":"UA-26","name":"Ivano-Frankivska oblast"},"1013":{"code":"UA-63","name":"Kharkivska oblast"},"1014":{"code":"UA-65","name":"Khersonska oblast"},"1015":{"code":"UA-68","name":"Khmelnytska oblast"},"1016":{"code":"UA-35","name":"Kirovohradska oblast"},"1032":{"code":"UA-30","name":"Kyiv"},"1017":{"code":"UA-32","name":"Kyivska oblast"},"1018":{"code":"UA-09","name":"Luhanska oblast"},"1019":{"code":"UA-46","name":"Lvivska oblast"},"1020":{"code":"UA-48","name":"Mykolaivska oblast"},"1021":{"code":"UA-51","name":"Odeska oblast"},"1022":{"code":"UA-53","name":"Poltavska oblast"},"1023":{"code":"UA-56","name":"Rivnenska oblast"},"1033":{"code":"UA-40","name":"Sevastopol"},"1024":{"code":"UA-59","name":"Sumska oblast"},"1025":{"code":"UA-61","name":"Ternopilska oblast"},"1026":{"code":"UA-05","name":"Vinnytska oblast"},"1027":{"code":"UA-07","name":"Volynska oblast"},"1028":{"code":"UA-21","name":"Zakarpatska oblast"},"1029":{"code":"UA-23","name":"Zaporizka oblast"},"1030":{"code":"UA-18","name":"Zhytomyrska oblast"}}},"UG":{"name":"Ouganda"},"UM":{"name":"\u00celes mineures \u00e9loign\u00e9es des \u00c9tats-Unis"},"US":{"name":"\u00c9tats-Unis","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":"AF","name":"Armed Forces Africa"},"7":{"code":"AA","name":"Armed Forces Americas"},"8":{"code":"AC","name":"Armed Forces Canada"},"9":{"code":"AE","name":"Armed Forces Europe"},"10":{"code":"AM","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"},"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":{"718":{"code":"UY-AR","name":"Artigas"},"719":{"code":"UY-CA","name":"Canelones"},"720":{"code":"UY-CL","name":"Cerro Largo"},"721":{"code":"UY-CO","name":"Colonia"},"722":{"code":"UY-DU","name":"Durazno"},"723":{"code":"UY-FS","name":"Flores"},"724":{"code":"UY-FD","name":"Florida"},"725":{"code":"UY-LA","name":"Lavalleja"},"726":{"code":"UY-MA","name":"Maldonado"},"727":{"code":"UY-MO","name":"Montevideo"},"728":{"code":"UY-PA","name":"Paysandu"},"729":{"code":"UY-RN","name":"R\u00edo Negro"},"730":{"code":"UY-RV","name":"Rivera"},"731":{"code":"UY-RO","name":"Rocha"},"732":{"code":"UY-SA","name":"Salto"},"733":{"code":"UY-SJ","name":"San Jos\u00e9"},"734":{"code":"UY-SO","name":"Soriano"},"735":{"code":"UY-TA","name":"Tacuaremb\u00f3"},"736":{"code":"UY-TT","name":"Treinta y Tres"}}},"UZ":{"name":"Ouzb\u00e9kistan"},"VA":{"name":"\u00c9tat de la Cit\u00e9 du Vatican"},"VC":{"name":"Saint-Vincent-et-les Grenadines"},"VE":{"name":"Venezuela","regions":{"977":{"code":"VE-Z","name":"Amazonas"},"978":{"code":"VE-B","name":"Anzo\u00e1tegui"},"979":{"code":"VE-C","name":"Apure"},"980":{"code":"VE-D","name":"Aragua"},"981":{"code":"VE-E","name":"Barinas"},"982":{"code":"VE-F","name":"Bol\u00edvar"},"983":{"code":"VE-G","name":"Carabobo"},"984":{"code":"VE-H","name":"Cojedes"},"985":{"code":"VE-Y","name":"Delta Amacuro"},"975":{"code":"VE-W","name":"Dependencias Federales"},"976":{"code":"VE-A","name":"Distrito Capital"},"986":{"code":"VE-I","name":"Falc\u00f3n"},"987":{"code":"VE-J","name":"Gu\u00e1rico"},"988":{"code":"VE-K","name":"Lara"},"989":{"code":"VE-L","name":"M\u00e9rida"},"990":{"code":"VE-M","name":"Miranda"},"991":{"code":"VE-N","name":"Monagas"},"992":{"code":"VE-O","name":"Nueva Esparta"},"993":{"code":"VE-P","name":"Portuguesa"},"994":{"code":"VE-R","name":"Sucre"},"995":{"code":"VE-S","name":"T\u00e1chira"},"996":{"code":"VE-T","name":"Trujillo"},"997":{"code":"VE-X","name":"Vargas"},"998":{"code":"VE-U","name":"Yaracuy"},"999":{"code":"VE-V","name":"Zulia"}}},"VG":{"name":"\u00celes Vierges britanniques"},"VI":{"name":"\u00celes Vierges des \u00c9tats-Unis"},"VN":{"name":"Vi\u00eat Nam"},"VU":{"name":"Vanuatu"},"WF":{"name":"Wallis-et-Futuna"},"WS":{"name":"Samoa"},"YE":{"name":"Y\u00e9men"},"YT":{"name":"Mayotte"},"ZA":{"name":"Afrique du Sud"},"ZM":{"name":"Zambie"},"ZW":{"name":"Zimbabwe"},"data_id":1775777957},"captcha":[],"instant-purchase":[],"loggedAsCustomer":[],"persistent":[],"review":[],"payments":[],"wishlist":{"items":[]},"recently_viewed_product":[],"recently_compared_product":[],"product_data_storage":[],"paypal-billing-agreement":[]}</script>
<script>
'use strict';
function GoogleAnalytics () {
let self = this;
this.config = {
isCookieRestrictionModeEnabled: 1,
currentWebsite: 1,
cookieName: "user_allowed_save_cookie",
ordersTrackingData: [],
pageTrackingData: {"optPageUrl":"","isAnonymizedIpActive":false,"accountId":"UA-9921500-1"},
}
this.initGoogleAnalytics = function () {
let allowServices = false,
allowedCookies,
allowedWebsites;
if (self.config.isCookieRestrictionModeEnabled) {
allowedCookies = hyva.getCookie(self.config.cookieName);
if (allowedCookies !== null) {
allowedWebsites = JSON.parse(decodeURIComponent(allowedCookies));
if (allowedWebsites[self.config.currentWebsite] === 1) {
allowServices = true;
}
}
} else {
allowServices = true;
}
if (allowServices) {
(function (i, s, o, g, r, a, m) {
i.GoogleAnalyticsObject = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.defer = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
// Process page info
ga('create', self.config.pageTrackingData.accountId, 'auto');
if (self.config.pageTrackingData.isAnonymizedIpActive) {
ga('set', 'anonymizeIp', true);
}
// Process orders data
if (self.config.ordersTrackingData.hasOwnProperty('currency')) {
ga('require', 'ec', 'ec.js');
ga('set', 'currencyCode', self.config.ordersTrackingData.currency);
// Collect product data for GA
if (self.config.ordersTrackingData.products) {
self.config.ordersTrackingData.products.forEach(function (value) {
ga('ec:addProduct', value);
});
}
// Collect orders data for GA
if (self.config.ordersTrackingData.orders) {
self.config.ordersTrackingData.orders.forEach(function (value) {
ga('ec:setAction', 'purchase', value);
});
}
ga('send', 'pageview');
} else {
// Process Data if not orders
ga('send', 'pageview' + self.config.pageTrackingData.optPageUrl);
}
}
};
}
window.addEventListener("load", new GoogleAnalytics().initGoogleAnalytics);
</script>
<script type="application/ld+json">{"@context":"https:\/\/schema.org","@type":"Product","name":"Bombe lacrymog\u00e8ne gel poivre Umarex P2P PDG-60 38ml","description":"Bombe lacrymog\u00e8ne gel poivre Umarex P2P PDG-60","image":"https:\/\/www.arprotech.com\/media\/catalog\/product\/cache\/9378c97105d93a8cd10d61b7730cef91\/2\/_\/2_2065.jpg","offers":[{"@type":"Offer","priceCurrency":"EUR","price":7.95,"availability":"https:\/\/schema.org\/OutOfStock","itemCondition":"https:\/\/schema.org\/NewCondition","seller":{"@type":"Organization","name":"ARprotech"},"url":"https:\/\/www.arprotech.com\/bombe-lacrymogene-gel-poivre-umarex-p2p-pdg-60.html","priceValidUntil":"2032-08-11T00:00:00+00:00"}],"url":"https:\/\/www.arprotech.com\/bombe-lacrymogene-gel-poivre-umarex-p2p-pdg-60.html","aggregateRating":[],"review":[],"brand":{"@type":"Brand","name":"Umarex"},"manufacturer":{"@type":"Organization","name":"Umarex"},"sku":"2.2065-IWA26","mpn":"2.2065-IWA26"}</script><script>
(()=> {
'use strict';
const amBrandPosition = {
selectors: {
brands: '#maincontent > .container .amshopby-option-link',
productInfoTitleP: '.product-info-main p.title-font'
},
amBrandPositionInit() {
const brands = document.querySelectorAll(this.selectors.brands);
let target;
if (!brands.length) {
return;
}
target = document.querySelector(this.selectors.productInfoTitleP);
for (let brand of brands) {
brand.classList.remove('flex');
brand.classList.add('inline-flex');
this.moveElement(brand, target);
}
},
moveElement(element, target) {
const fragment = document.createDocumentFragment();
fragment.appendChild(element);
target.append(fragment);
element.classList.remove('hidden');
}
}
document.addEventListener('DOMContentLoaded', () => {
amBrandPosition.amBrandPositionInit();
})
})()
</script></div><div x-data="fpcTracking()" x-init="sendRequest()"></div>
<script>
function fpcTracking() {
return {
url: 'https://www.arprotech.com/amasty_fpc/reports/',
sendRequest() {
const ttfb = window.performance.timing.responseStart - window.performance.timing.fetchStart;
fetch(`${this.url}?` + new URLSearchParams({ ttfb }), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
}
})
}
}
}
</script>
<!-- amasty-fpc-status --><script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9ea458f13e9f9ed3',t:'MTc3NTg1MTMyOA=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v8c78df7c7c0f484497ecbca7046644da1771523124516" integrity="sha512-8DS7rgIrAmghBFwoOTujcf6D9rXvH8xm8JQ1Ja01h9QX8EzXldiszufYa4IFfKdLUKTTrnSFXLDkUEOTrZQ8Qg==" data-cf-beacon='{"version":"2024.11.0","token":"f3df215d32094fa58c19f89bfc24bf76","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>