function initPrice6323() {
return {
regularPriceKey: 'oldPrice',
finalPriceKey: 'finalPrice',
activeProductsPriceData: false,
initialFinalPrice: 589,
calculatedFinalPrice: false,
calculatedFinalPriceWithCustomOptions: false,
initialTierPrices: [],
showRegularPriceLabel: true,
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) {
if (prices) {
this.customOptionPrices = prices;
}
this.calculateFinalPriceWithCustomOptions();
},
calculateFinalPrice() {
let finalPrice = this.initialFinalPrice;
if (this.activeProductsPriceData && this.activeProductsPriceData.tierPrices) {
finalPrice = this.activeProductsPriceData.tierPrices.reduce((finalValue, tierPrice) => {
if (this.qty >= tierPrice.qty) {
return tierPrice.price < finalValue ? tierPrice.price : finalValue;
}
return finalValue;
}, this.activeProductsPriceData[this.finalPriceKey].amount);
} else {
finalPrice = Object.values(this.initialTierPrices).reduce((finalValue, tierPrice) => {
if (this.qty >= tierPrice.price_qty) {
return parseFloat(tierPrice.website_price) < finalValue ?
parseFloat(tierPrice.website_price) :
finalValue;
}
return finalValue;
}, finalPrice);
}
this.calculatedFinalPrice = finalPrice;
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() {
let finalPrice = this.calculatedFinalPrice ||
this.initialFinalPrice;
this.calculatedFinalPriceWithCustomOptions = finalPrice + this.getCustomOptionPrice();
},
getCustomOptionPrice() {
return this.activeCustomOptions.reduce((priceAccumulator, activeCustomOptionId) => {
const customOptionPrice = this.customOptionPrices[activeCustomOptionId];
if (customOptionPrice) {
return Number.parseFloat(priceAccumulator) + Number.parseFloat(customOptionPrice);
}
return priceAccumulator;
}, 0);
},
getFormattedFinalPrice() {
return hyva.formatPrice(
this.calculatedFinalPriceWithCustomOptions ||
this.calculatedFinalPrice ||
this.initialFinalPrice
)
},
isPriceHidden() {
const finalPrice = this.calculatedFinalPriceWithCustomOptions ||
this.calculatedFinalPrice ||
this.initialFinalPrice;
return false && finalPrice === 0;
},
eventListeners: {
['@update-prices-6323.window'](event) {
this.activeProductsPriceData = event.detail;
this.calculateFinalPrice();
this.calculateFinalPriceWithCustomOptions();
this.calculatePriceLabelVisibility();
},
['@update-qty-6323.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);
}
}
}
}
AED 659.00 AED 589.00Save 10%
function initPrice6323() {
return {
regularPriceKey: 'oldPrice',
finalPriceKey: 'finalPrice',
activeProductsPriceData: false,
initialFinalPrice: 589,
calculatedFinalPrice: false,
calculatedFinalPriceWithCustomOptions: false,
initialTierPrices: [],
showRegularPriceLabel: true,
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) {
if (prices) {
this.customOptionPrices = prices;
}
this.calculateFinalPriceWithCustomOptions();
},
calculateFinalPrice() {
let finalPrice = this.initialFinalPrice;
if (this.activeProductsPriceData && this.activeProductsPriceData.tierPrices) {
finalPrice = this.activeProductsPriceData.tierPrices.reduce((finalValue, tierPrice) => {
if (this.qty >= tierPrice.qty) {
return tierPrice.price < finalValue ? tierPrice.price : finalValue;
}
return finalValue;
}, this.activeProductsPriceData[this.finalPriceKey].amount);
} else {
finalPrice = Object.values(this.initialTierPrices).reduce((finalValue, tierPrice) => {
if (this.qty >= tierPrice.price_qty) {
return parseFloat(tierPrice.website_price) < finalValue ?
parseFloat(tierPrice.website_price) :
finalValue;
}
return finalValue;
}, finalPrice);
}
this.calculatedFinalPrice = finalPrice;
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() {
let finalPrice = this.calculatedFinalPrice ||
this.initialFinalPrice;
this.calculatedFinalPriceWithCustomOptions = finalPrice + this.getCustomOptionPrice();
},
getCustomOptionPrice() {
return this.activeCustomOptions.reduce((priceAccumulator, activeCustomOptionId) => {
const customOptionPrice = this.customOptionPrices[activeCustomOptionId];
if (customOptionPrice) {
return Number.parseFloat(priceAccumulator) + Number.parseFloat(customOptionPrice);
}
return priceAccumulator;
}, 0);
},
getFormattedFinalPrice() {
return hyva.formatPrice(
this.calculatedFinalPriceWithCustomOptions ||
this.calculatedFinalPrice ||
this.initialFinalPrice
)
},
isPriceHidden() {
const finalPrice = this.calculatedFinalPriceWithCustomOptions ||
this.calculatedFinalPrice ||
this.initialFinalPrice;
return false && finalPrice === 0;
},
eventListeners: {
['@update-prices-6323.window'](event) {
this.activeProductsPriceData = event.detail;
this.calculateFinalPrice();
this.calculateFinalPriceWithCustomOptions();
this.calculatePriceLabelVisibility();
},
['@update-qty-6323.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);
}
}
}
}
AED 659.00 AED 589.00Save 10%
function initQtyField() {
function findPathParam(key) {
// get all path pairs after BASE_URL/front_name/action_path/action
const baseUrl = (BASE_URL.substr(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 {
qty: 1,
itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'),
productId: '6323',
onGetCartData: function onGetCartData(data, $dispatch) {
const cart = data && data.data && data.data.cart;
if (this.itemId && cart && cart.items) {
const cartItem = cart.items.find((item) => {
return item.item_id === this.itemId && item.product_id === this.productId;
});
if (cartItem && cartItem.qty) {
this.qty = cartItem.qty;
$dispatch('update-qty-' + this.productId, this.qty);
}
}
}
};
}
function initWishlist_64546d9190180() {
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)
? "Product has been added to your Wish List."
: 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
);
});
}
}
}
function initCompareOnProductView() {
return {
addToCompare: function (productId) {
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
);
});
}
};
}
compareshareable icon- Facebook iconFacebook
- Tweet iconTweet
- Email iconEmail
Samsung Galaxy A13Minimalist design with striking styleGalaxy A13 combines soft colours with a look and feel that’s gentle to the touch. Refined curves make it comfortable to hold and provides easy screen navigation. Choose from Black, White, Blue, and Peach colours. More display means more room to playExpand your view to the 6.6-inch Infinity-V Display of Galaxy A13 and see what you've been missing. And with FHD+ technology, your everyday content looks sharp, crisp and clear. Multi Camera System Upgrade your mobile photography with Quad Camera
Snap memorable moments in clear detail with the 50MP Main Camera. Expand viewing angle with Ultra Wide Camera. Customise focus with Depth Camera, or get closer to details with Macro Camera. Front cameraStylish selfiesWith the Galaxy A13's 8MP Front Camera and bokeh effect, it's easy to snap stunning selfies that feature more you and less background. Depth CameraBring the focus to the front with Depth CameraThe 2MP Depth Camera lets you adjust the depth of field in your photos. Adjust the background blur for high-quality portrait shots that make your subject truly stand out. Macro CameraCapture smaller details with Macro CameraGalaxy A03 combines classic colors with a look and feel thats gentle to the touch. Refined curves make it comfortable to hold and provide easy screen navigation. Choose from Black, White, Red or Blue colors. Ultra Wide CameraUltra wide experiencesSimilar to human eyesight, the 5MP Ultra Wide Camera sees the world with a 123-degree angle of view, adding more perspective to everything you shoot. Multi Camera SystemUpgrade your mobile photography with Quad CameraSnap memorable moments in clear detail with the 50MP Main Camera. Expand viewing angle with Ultra Wide Camera. Customise focus with Depth Camera, or get closer to details with Macro Camera. Awesome battery, lasts two daysStay ahead of the day with a battery that won't slow you down. The 5,000mAh (typical) battery lets you keep doing what you do, for hours on end. Speed up and store moreThe Galaxy A13 combines Octa-core processing power with up to 3GB/4GB/6GB of RAM for fast and efficient performance for the task at hand. Enjoy 32GB/64GB/128GB of internal storage and add up to 1TB more with MicroSD card. Samsung MembersKeep your device in tip-top condition with usWhen you buy a Samsung Galaxy smartphone, it comes with perks. Samsung Members app gives you interactive diagnostics and optimisation features to tune up your device's performance, while our helpline talks you through troubleshooting problems when you need the extra assistance.
<
One UIYour Galaxy. Your WayOwn something truly yours. Customise your Galaxy with One UI Core 4 and give your phone an edgy look to match your vibes. Create a bespoke tool that assists your tasks seamlessly and makes your favorite features readily accessible. SecurityProtect what matters to youBuilt into the phone's hardware and software from the start, Samsung Knox protects your phone from the minute it's turned on. Offering multi-layered security, it defends your most sensitive information from malware and malicious threats. Dolby AtmosSimply plug in your earphones to be transported to the middle of your music and movies. With Dolby Atmos, you'll hear sound that's full, rich, and spatial, as if you're inside the scene. Colours | Light Blue |
---|
Item Weight | 340g |
---|
Write Your Own Review
Only registered users can write reviews. Please Sign in or create an account
"use strict";
function initMobileSticky() {
return {
cartItemCount: 0,
getCartItemCount(data) {
if (data.cart) {
this.cartItemCount = data.cart.summary_count;
}
}
}
}
{"@context":"http:\/\/schema.org","@type":"Product","name":"Samsung Galaxy A13 4GB\/64GB (Light Blue)","sku":"102-1276-000598","model":"Samsung Galaxy A13 4GB\/64GB (Light Blue)","description":"\r\n\r\n\r\n\r\nModel:\r\n\r\n\r\nSM-A137FLBGMEA\r\n\r\n\r\n\r\n\r\nBattery Capacity:\r\n\r\n\r\n5000 mAh\r\n\r\n\r\n\r\n\r\nProcessor:\r\n\r\n\r\nMediaTek G80\r\n\r\n\r\n\r\n\r\nRear \/ Front Camera:\r\n\r\n\r\n50 + 5 + 2 + 2 MP \/ 8 MP\r\n\r\n\r\n\r\n\r\nScreen Size: \r\n\r\n\r\n6.6 Inches\r\n\r\n\r\n\r\n\r\nCPU: \r\n\r\n\r\nOcta-Core 2.2 GHz\r\n\r\n\r\n\r\n","gtin8":"102-1276-000598","offers":{"@type":"Offer","url":"https:\/\/shop.grandstores.ae\/en\/samsung-galaxy-a13-4gb-64gb-sm-a137flbgmea-light-blue.html","price":"589.00","priceCurrency":"AED","priceValidUntil":"2023-05-31 ","sku":"102-1276-000598","gtin":"102-1276-000598"}}
'use strict';
function initSliderComponent() {
return {
active: 0,
itemCount: 0,
shown: false,
getSlider() {
return this.$el.querySelector('.js_slides');
},
pageSize: 4,
pageFillers: 0,
calcPageSize() {
const slider = this.getSlider();
if (slider) {
this.itemCount = slider.querySelectorAll('.js_slide').length;
this.pageSize = Math.round(slider.clientWidth / slider.querySelector('.js_slide').clientWidth);
this.pageFillers = (
this.pageSize * Math.ceil(this.itemCount / this.pageSize)
) - this.itemCount;
}
},
calcActive() {
const slider = this.getSlider();
if (slider) {
const sliderItems = this.itemCount + this.pageFillers;
const calculatedActiveSlide = slider.scrollLeft / (slider.scrollWidth / sliderItems);
this.active = Math.round(calculatedActiveSlide / this.pageSize) * this.pageSize;
}
},
scrollPrevious() {
this.scrollTo(this.active - this.pageSize);
},
scrollNext() {
this.scrollTo(this.active + 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.active = idx;
}
}
}
}
Related Products Quick View
BELKIN 1.2M Universal Cable (3 IN 1) - Lighning - Micro & Type C - BLACK
function initPriceBox__64546b8f36dd2()
{
return {
updatePrice(priceData) {
const regularPriceLabel = this.$el.querySelector('.normal-price .price-label');
const regularPriceElement = this.$el.querySelector('.normal-price .price-wrapper .price');
if (priceData.finalPrice.amount < priceData.oldPrice.amount) {
regularPriceLabel.classList.add('hidden');
} else {
regularPriceLabel.classList.remove('hidden');
}
regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount);
}
}
}
Add to Wish List
Add to Compare Free Delivery Quick View
Kenu Airframe Magnetic Car Vent Smartphone Mount - (AF5-KK-NA )
function initPriceBox__64546d91a058f()
{
return {
updatePrice(priceData) {
const regularPriceLabel = this.$el.querySelector('.normal-price .price-label');
const regularPriceElement = this.$el.querySelector('.normal-price .price-wrapper .price');
if (priceData.finalPrice.amount < priceData.oldPrice.amount) {
regularPriceLabel.classList.add('hidden');
} else {
regularPriceLabel.classList.remove('hidden');
}
regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount);
}
}
}
Add to Wish List
Add to Compare Quick View
BELKIN Boost Charge Dual USB-A Port Car Charger 24W - Black (BKN-CCB001BTBK)
function initPriceBox__64546d91a6752()
{
return {
updatePrice(priceData) {
const regularPriceLabel = this.$el.querySelector('.normal-price .price-label');
const regularPriceElement = this.$el.querySelector('.normal-price .price-wrapper .price');
if (priceData.finalPrice.amount < priceData.oldPrice.amount) {
regularPriceLabel.classList.add('hidden');
} else {
regularPriceLabel.classList.remove('hidden');
}
regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount);
}
}
}
Add to Wish List
Add to Compare Quick View
BELKIN Boost Charge Dual USB-A Car Charger 24W + 1Meter Lightning to USB-A Cable - Black (BKN-CCD001BT1MBK)
function initPriceBox__64546d91ab1fe()
{
return {
updatePrice(priceData) {
const regularPriceLabel = this.$el.querySelector('.normal-price .price-label');
const regularPriceElement = this.$el.querySelector('.normal-price .price-wrapper .price');
if (priceData.finalPrice.amount < priceData.oldPrice.amount) {
regularPriceLabel.classList.add('hidden');
} else {
regularPriceLabel.classList.remove('hidden');
}
regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount);
}
}
}
Add to Wish List
Add to Compare prev arrownext arrow
'use strict';
window.addEventListener('DOMContentLoaded', function() {
if (! window.productSliderEventHandlerInitialized) {
window.productSliderEventHandlerInitialized = true;
window.addEventListener('product-add-to-wishlist', (event) => {
const formKey = hyva.getFormKey();
const postUrl = BASE_URL + 'wishlist/index/add/';
const productId = event.detail.productId;
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;
} 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(function (result) {
if (!result) {
return
}
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: (result.success) ? "success" : "error",
text: (result.success)
? "Product has been added to your Wish List." : result.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
);
});
})
window.addEventListener('product-add-to-compare', (event) => {
const productId = event.detail.productId;
hyva.postForm({
action: BASE_URL + 'catalog/product_compare/add/',
data: {product: productId}
})
})
}
});
'use strict';
function initSliderComponent() {
return {
active: 0,
itemCount: 0,
shown: false,
getSlider() {
return this.$el.querySelector('.js_slides');
},
pageSize: 4,
pageFillers: 0,
calcPageSize() {
const slider = this.getSlider();
if (slider) {
this.itemCount = slider.querySelectorAll('.js_slide').length;
this.pageSize = Math.round(slider.clientWidth / slider.querySelector('.js_slide').clientWidth);
this.pageFillers = (
this.pageSize * Math.ceil(this.itemCount / this.pageSize)
) - this.itemCount;
}
},
calcActive() {
const slider = this.getSlider();
if (slider) {
const sliderItems = this.itemCount + this.pageFillers;
const calculatedActiveSlide = slider.scrollLeft / (slider.scrollWidth / sliderItems);
this.active = Math.round(calculatedActiveSlide / this.pageSize) * this.pageSize;
}
},
scrollPrevious() {
this.scrollTo(this.active - this.pageSize);
},
scrollNext() {
this.scrollTo(this.active + 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.active = idx;
}
}
}
}
Customer Also Viewed 11% OFF Quick View
Samsung Galaxy A53 6GB/128GB (Awesome Blue)
function initPriceBox__64546d91b1ace()
{
return {
updatePrice(priceData) {
const regularPriceLabel = this.$el.querySelector('.normal-price .price-label');
const regularPriceElement = this.$el.querySelector('.normal-price .price-wrapper .price');
if (priceData.finalPrice.amount < priceData.oldPrice.amount) {
regularPriceLabel.classList.add('hidden');
} else {
regularPriceLabel.classList.remove('hidden');
}
regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount);
}
}
}
Special PriceAED 1,376.00Regular PriceAED 1,549.00
Add to Wish List
Add to Compare Special PriceAED 1,376.00Regular PriceAED 1,549.00
Add to Cart 9% OFF Quick View
Samsung Galaxy A53 5G 8GB/256GB (Awesome Blue)
function initPriceBox__64546d91b5b84()
{
return {
updatePrice(priceData) {
const regularPriceLabel = this.$el.querySelector('.normal-price .price-label');
const regularPriceElement = this.$el.querySelector('.normal-price .price-wrapper .price');
if (priceData.finalPrice.amount < priceData.oldPrice.amount) {
regularPriceLabel.classList.add('hidden');
} else {
regularPriceLabel.classList.remove('hidden');
}
regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount);
}
}
}
Special PriceAED 1,576.00Regular PriceAED 1,749.00
Add to Wish List
Add to Compare Special PriceAED 1,576.00Regular PriceAED 1,749.00
Add to Cart 11% OFF Quick View
Samsung Galaxy A53 6GB/128GB (Awesome Black)
function initPriceBox__64546d91b9c39()
{
return {
updatePrice(priceData) {
const regularPriceLabel = this.$el.querySelector('.normal-price .price-label');
const regularPriceElement = this.$el.querySelector('.normal-price .price-wrapper .price');
if (priceData.finalPrice.amount < priceData.oldPrice.amount) {
regularPriceLabel.classList.add('hidden');
} else {
regularPriceLabel.classList.remove('hidden');
}
regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount);
}
}
}
Special PriceAED 1,376.00Regular PriceAED 1,549.00
Add to Wish List
Add to Compare Special PriceAED 1,376.00Regular PriceAED 1,549.00
Add to Cart prev arrownext arrow
'use strict';
window.addEventListener('DOMContentLoaded', function() {
if (! window.productSliderEventHandlerInitialized) {
window.productSliderEventHandlerInitialized = true;
window.addEventListener('product-add-to-wishlist', (event) => {
const formKey = hyva.getFormKey();
const postUrl = BASE_URL + 'wishlist/index/add/';
const productId = event.detail.productId;
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;
} 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(function (result) {
if (!result) {
return
}
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: (result.success) ? "success" : "error",
text: (result.success)
? "Product has been added to your Wish List." : result.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
);
});
})
window.addEventListener('product-add-to-compare', (event) => {
const productId = event.detail.productId;
hyva.postForm({
action: BASE_URL + 'catalog/product_compare/add/',
data: {product: productId}
})
})
}
});
.cmsb233-mb-4 {
margin-bottom: 1rem
}
.cmsb233-border-b {
border-bottom-width: 1px
}
.cmsb233-border-444444 {
--tw-border-opacity: 1;
border-color: rgba(68, 68, 68, var(--tw-border-opacity))
}
.cmsb233-py-6 {
padding-top: 1.5rem;
padding-bottom: 1.5rem
}
.cmsb233-pb-4 {
padding-bottom: 1rem
}
.cmsb233-text-14 {
font-size: 0.875rem
}
.cmsb233-font-bold {
font-weight: 700
}
.cmsb233-capitalize {
text-transform: capitalize
}
.cmsb233-text-888888 {
--tw-text-opacity: 1;
color: rgba(136, 136, 136, var(--tw-text-opacity))
}
.cmsb233-text-white {
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}
@media (min-width: 768px) {
.cmsb233-md\:pointer-events-none {
pointer-events: none
}
.cmsb233-md\:mb-6 {
margin-bottom: 1.5rem
}
.cmsb233-md\:border-0 {
border-width: 0px
}
.cmsb233-md\:py-0 {
padding-top: 0px;
padding-bottom: 0px
}
.cmsb233-md\:pb-0 {
padding-bottom: 0px
}
}
Categories
-
Photos and Videos
-
Mobiles
-
IT & Multimedia
-
Home Appliances
-
Luggage
.cmsb235-mb-4 {
margin-bottom: 1rem
}
.cmsb235-border-b {
border-bottom-width: 1px
}
.cmsb235-border-444444 {
--tw-border-opacity: 1;
border-color: rgba(68, 68, 68, var(--tw-border-opacity))
}
.cmsb235-py-6 {
padding-top: 1.5rem;
padding-bottom: 1.5rem
}
.cmsb235-pb-4 {
padding-bottom: 1rem
}
.cmsb235-text-14 {
font-size: 0.875rem
}
.cmsb235-font-bold {
font-weight: 700
}
.cmsb235-capitalize {
text-transform: capitalize
}
.cmsb235-text-888888 {
--tw-text-opacity: 1;
color: rgba(136, 136, 136, var(--tw-text-opacity))
}
.cmsb235-text-white {
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}
@media (min-width: 768px) {
.cmsb235-md\:pointer-events-none {
pointer-events: none
}
.cmsb235-md\:mb-6 {
margin-bottom: 1.5rem
}
.cmsb235-md\:border-0 {
border-width: 0px
}
.cmsb235-md\:border-b-0 {
border-bottom-width: 0px
}
.cmsb235-md\:py-0 {
padding-top: 0px;
padding-bottom: 0px
}
.cmsb235-md\:pb-0 {
padding-bottom: 0px
}
}
Customer Services
-
About Us
-
Contact Us
-
FAQ
-
Store Location
-
Advanced Search
.cmsb234-mb-4 {
margin-bottom: 1rem
}
.cmsb234-border-b {
border-bottom-width: 1px
}
.cmsb234-border-444444 {
--tw-border-opacity: 1;
border-color: rgba(68, 68, 68, var(--tw-border-opacity))
}
.cmsb234-py-6 {
padding-top: 1.5rem;
padding-bottom: 1.5rem
}
.cmsb234-pb-4 {
padding-bottom: 1rem
}
.cmsb234-text-14 {
font-size: 0.875rem
}
.cmsb234-font-bold {
font-weight: 700
}
.cmsb234-capitalize {
text-transform: capitalize
}
.cmsb234-text-888888 {
--tw-text-opacity: 1;
color: rgba(136, 136, 136, var(--tw-text-opacity))
}
.cmsb234-text-white {
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}
@media (min-width: 768px) {
.cmsb234-md\:pointer-events-none {
pointer-events: none
}
.cmsb234-md\:mb-6 {
margin-bottom: 1.5rem
}
.cmsb234-md\:border-0 {
border-width: 0px
}
.cmsb234-md\:border-b-0 {
border-bottom-width: 0px
}
.cmsb234-md\:py-0 {
padding-top: 0px;
padding-bottom: 0px
}
.cmsb234-md\:pb-0 {
padding-bottom: 0px
}
}
Information
-
My Account
-
Order Tracking
-
Wish List
-
Terms and Condition
-
Payment Methods
-
Grand Times Magazine
.cmsb232-mb-4 {
margin-bottom: 1rem
}
.cmsb232-py-6 {
padding-top: 1.5rem;
padding-bottom: 1.5rem
}
.cmsb232-pb-4 {
padding-bottom: 1rem
}
.cmsb232-text-14 {
font-size: 0.875rem
}
.cmsb232-font-bold {
font-weight: 700
}
.cmsb232-capitalize {
text-transform: capitalize
}
.cmsb232-text-888888 {
--tw-text-opacity: 1;
color: rgba(136, 136, 136, var(--tw-text-opacity))
}
.cmsb232-text-white {
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}
@media (min-width: 768px) {
.cmsb232-md\:pointer-events-none {
pointer-events: none
}
.cmsb232-md\:mb-6 {
margin-bottom: 1.5rem
}
.cmsb232-md\:py-0 {
padding-top: 0px;
padding-bottom: 0px
}
.cmsb232-md\:pb-0 {
padding-bottom: 0px
}
}
Policies
-
Privacy Policy
-
Exchange & Return Policy
-
Orders and Returns
.cmsb223-relative {
position: relative
}
.cmsb223-mb-5 {
margin-bottom: 1.25rem
}
.cmsb223-mb-7 {
margin-bottom: 1.75rem
}
.cmsb223-mb-4 {
margin-bottom: 1rem
}
.cmsb223-mb-1 {
margin-bottom: 0.25rem
}
.cmsb223-pl-6 {
padding-left: 1.5rem
}
.cmsb223-pl-8 {
padding-left: 2rem
}
.cmsb223-text-20 {
font-size: 1.25rem
}
.cmsb223-text-12 {
font-size: 0.75rem
}
.cmsb223-text-14 {
font-size: 0.875rem
}
.cmsb223-font-bold {
font-weight: 700
}
.cmsb223-text-white {
--tw-text-opacity: 1;
color: rgba(255, 255, 255, var(--tw-text-opacity))
}
.cmsb223-text-888888 {
--tw-text-opacity: 1;
color: rgba(136, 136, 136, var(--tw-text-opacity))
}
@media (min-width: 768px) {
.cmsb223-md\:pl-8 {
padding-left: 2rem
}
.cmsb223-md\:pl-9 {
padding-left: 2.25rem
}
.cmsb223-md\:text-24 {
font-size: 1.5rem
}
.cmsb223-md\:text-14 {
font-size: 0.875rem
}
}
Grand Stores LLC - Grand Stores, 'M'Level , Saleh Bin Lahej Building,
Al Garhoud, Dubai, UAE, P.O.Box 2144
-
hello@grandstores.ae
To inquire, please call us on
800 Grands
800 472637
Copyrights © 2023 All rights reserved for GrandStores
function initAuthenticationBss() {
return {
open: false,
openLogin : false,
openRegister : false,
openForgot : false,
openCreate : true,
passwordsMatching: true,
openMessage: false,
errors: 0,
message: "",
hasCaptchaToken: 0,
openButtonLogin : false,
openButtonRegister : false,
openSuccessMessage : false,
checkPasswordsMatch() {
if (document.getElementById('password').value ===
document.getElementById('password-confirmation').value) {
this.passwordsMatching = true;
return true;
}
this.passwordsMatching = false;
return false;
},
submitForm: function () {
const $form = document.querySelector('#login-form');
if (this.errors === 0) {
this.dispatchLoginRequest($form);
}
},
submitForgotForm : function () {
const $form = document.querySelector('#fotgot-form');
if (this.errors === 0) {
this.dispatchForgotRequest($form);
}
},
submitRegisterForm : function () {
const $form = document.querySelector('#create-form');
if (this.errors === 0) {
this.dispatchRegisterRequest($form);
}
},
validateCaptcha : function () {
return new Promise((resolve, reject) => {
var executeGreCaptcha = () => {
grecaptcha.ready(function () {
grecaptcha.execute('', {action: 'submit'}).then(function (token) {
return resolve(token);
});
});
}
if (window.grecaptcha) {
executeGreCaptcha();
} else {
const recaptchaUrl = "https://www.google.com/recaptcha/api.js?render=&hl=en";
const script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', recaptchaUrl);
document.head.appendChild(script);
script.addEventListener("load", executeGreCaptcha, false);
}
});
},
dispatchLoginRequest:async function (form) {
let token = await this.validateCaptcha();
if(token)
{
document.getElementById("g-recaptcha-response").setAttribute('value',token);
}
const username = this.$refs['customer-email'].value;
const password = this.$refs['customer-password'].value;
const recaptchaValue = document.getElementById("g-recaptcha-response").value;
const postUrl = "https://shop.grandstores.ae/en/sociallogin/popup/login/";
fetch(postUrl, {
headers: {
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
},
body: new URLSearchParams({
username: username,
password: password,
['g-recaptcha-response']: recaptchaValue,
form_key: hyva.getFormKey(),
}),
method: "POST",
mode: "cors",
credentials: "include",
}).then(response => {
return response.json()
}
).then(data => {
this.isLoading = false;
if (data.error) {
this.message = data.message;
this.openMessage = true;
this.errors = 1;
this.hasCaptchaToken = 0;
} else {
this.message = data.message;
this.openMessage = false;
this.openSuccessMessage = true;
if (data.redirect !== '' && data.redirect != null) {
window.location.href = data.redirect;
} else {
location.reload(true);
}
}
});
},
dispatchForgotRequest:async function (form) {
let token = await this.validateCaptcha();
if (token) {
document.getElementById("g-recaptcha-response").setAttribute('value', token);
}
const email = form.querySelector("#email_address").value;
const recaptchaValue = document.getElementById("g-recaptcha-response").value;
const postUrl = "https://shop.grandstores.ae/en/sociallogin/popup/forgot/";
fetch(postUrl, {
headers: {
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
},
body: new URLSearchParams({
email: email,
['g-recaptcha-response']: recaptchaValue,
form_key: hyva.getFormKey(),
}),
method: "POST",
mode: "cors",
credentials: "include",
}).then(response => {
return response.json()
}
).then(data => {
this.isLoading = false;
if (data.error) {
this.message = data.message;
this.openMessage = true;
this.errors = 1;
this.hasCaptchaToken = 0;
} else {
if (data.redirect !== '' && data.redirect != null) {
window.location.href = data.redirect;
} else {
location.reload(true);
}
}
});
},
dispatchRegisterRequest:async function (form) {
let token = await this.validateCaptcha();
if (token) {
document.getElementById("g-recaptcha-response").setAttribute('value', token);
}
const firstname = form.querySelector("#firstname").value;
const lastname = form.querySelector("#lastname").value;
const email = form.querySelector("#email_address").value;
const password = form.querySelector("#password").value;
const passwordConfirmation = form.querySelector("#password-confirmation").value;
const recaptchaValue = document.getElementById("g-recaptcha-response").value;
const postUrl = "https://shop.grandstores.ae/en/sociallogin/popup/create/";
fetch(postUrl, {
headers: {
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
},
body: new URLSearchParams({
['g-recaptcha-response']: recaptchaValue,
firstname: firstname,
lastname: lastname,
email: email,
password: password,
password_confirmation: passwordConfirmation,
form_key: hyva.getFormKey(),
}),
method: "POST",
mode: "cors",
credentials: "include",
}).then(response => {
return response.json()
}
).then(data => {
this.isLoading = false;
if (data.error) {
this.message = data.message;
this.openMessage = true;
this.hasCaptchaToken = 0;
} else {
this.message = data.message;
this.openMessage = false;
this.openSuccessMessage = true;
if (data.redirect !== '' && data.redirect != null) {
window.location.href = data.redirect;
} else {
location.reload(true);
}
}
});
}
}
}
Social Login - Login with Facebook
- Login with Google
Social Register - Register with Facebook
- Register with Google
var classLogin = ["#login-main-social-login","#login-popup-social-login","#registration-main-social-login"];
var classRegister = [".form-create-accountss"];
// classLogin = classLogin[0].trim().split(/\s+/);
classRegister = classRegister[0].trim().split(/\s+/);
if(classLogin && classLogin.length > 0 && classLogin[0]){
classLogin.forEach(element => {
var classLoginElement = document.querySelector(element);
var loginSocialButton = document.getElementById('add_button_login_byclass');
if (classLoginElement && loginSocialButton) {
const cloneLoginSocialButton = loginSocialButton.cloneNode(true);
classLoginElement.appendChild(cloneLoginSocialButton);
cloneLoginSocialButton.style.display='block';
}
});
}
if(classRegister && classRegister.length > 0 && classRegister[0]){
classRegister.forEach(element => {
var classRegisterElement = document.querySelector(element);
var registerSocialButton = document.getElementById('add_button_register_byclass');
if (classRegisterElement && registerSocialButton) {
const cloneRegisterSocialButton = registerSocialButton.cloneNode(true);
classRegisterElement.appendChild(cloneRegisterSocialButton);
cloneRegisterSocialButton.style.display='block';
}
});
}
function bssButtonSocial() {
return {
renderShowmore : function (element) {
var socialButton = element.querySelector('.sociallogin-clearfix').getElementsByTagName("li");
for (let i = 0; i <= socialButton.length - 1; i++) {
socialButton[i].style.display = 'block';
}
element.querySelector('.sociallogin-showmore').style.display = 'none';
},
popupSocial: function (element) {
var href = element.getAttribute('data-href');
var width = element.getAttribute('data-width');
var height = element.getAttribute('data-height');
var popup_window = null;
if (!width) {
width = 650;
}
if(!height) {
height = 350;
}
var left = parseInt((window.innerWidth- width) / 2);
var top = parseInt((window.innerHeight - height) / 2);
var params = [
'resizable=yes',
'scrollbars=no',
'toolbar=no',
'menubar=no',
'location=no',
'directories=no',
'status=yes',
'width='+ width,
'height='+ height,
'left='+ left,
'top='+ top
];
if(popup_window) {
popup_window.close();
}
if(href) {
popup_window = window.open(href,'',params.join(','));
popup_window.focus();
}else{
alert('This Login Application was not configured correctly. Please contact our customer support.');
}
return false;
}
}
}
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/' + "service-worker.js");
}
Add to Home Screen
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
const addBtn = document.getElementById("ad2hs-prompt");
let deferredPrompt = e;
addBtn.style.display = 'block';
addBtn.addEventListener('click', (e) => {
// hide our user interface that shows our A2HS button
addBtn.style.display = 'none';
// Show the prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('User accepted the A2HS prompt');
} else {
console.log('User dismissed the A2HS prompt');
}
deferredPrompt = null;
});
});
});
var Tawk_API={};
var Tawk_LoadStart=new Date();
(function(){
var s1=document.createElement("script"),s0=document.getElementsByTagName("script")[0];
s1.async=true;
s1.src='https://embed.tawk.to/5d52a98f77aa790be32eb2ca/default';
s1.charset='UTF-8';
s1.setAttribute('crossorigin','*');
s0.parentNode.insertBefore(s1,s0);
})();
(function () {
"use strict";
const DIRECTIVE = "intersect";
const X_ATTR_RE = /^x-([a-z-]*)\b/i;
function parseHtmlAttribute(reference) {
const name = reference.name;
const value = reference.value;
const typeMatch = name.match(X_ATTR_RE);
const valueMatch = name.match(/:([a-zA-Z0-9\-:]+)/);
const modifiers = name.match(/\.[^.\]]+(?=[^\]]*$)/g) || [];
return {
type: typeMatch ? typeMatch[1] : null,
value: valueMatch ? valueMatch[1] : null,
modifiers: modifiers.map((i) => i.replace(".", "")),
expression: value,
};
}
function getXDirectives(el) {
return Array.from(el.attributes)
.filter(function (attr) {
return X_ATTR_RE.test(attr.name);
})
.map(parseHtmlAttribute);
}
if (window.Alpine) {
console.error("Intersect plugin must be included before AlpineJs, x-intersect will not work.");
}
const getLengthValue = (rawValue) => {
// Supported: -10px, -20 (implied px), 30 (implied px), 40px, 50%
let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/)
return match ? match[1] + (match[2] || 'px') : undefined
}
const getRootMargin = (modifiers) => {
const key = 'margin'
const fallback = '0px 0px 0px 0px'
const index = modifiers.indexOf(key)
// If the modifier isn't present, use the default.
if (index === -1) return fallback
// Grab the 4 subsequent length values after it: x-intersect.margin.300px.0.50%.0
let values = []
for (let i = 1; i < 5; i++) {
values.push(getLengthValue(modifiers[index + i] || ''))
}
// Filter out undefined values (not a valid length)
values = values.filter((v) => v !== undefined)
return values.length ? values.join(' ').trim() : fallback
}
const getThreshhold = (modifiers) => {
if (modifiers.includes("full")) return 0.8;
if (modifiers.includes("half")) return 0.5;
return 0;
};
const AlpineIntersectionDirective = {
start: function start() {
Alpine.onBeforeComponentInitialized(function (component) {
const legacyResolveBoundAttributes = component.resolveBoundAttributes;
component.resolveBoundAttributes = function (el, initialUpdate, extraVars) {
if (initialUpdate === void 0) {
initialUpdate = false;
}
if (initialUpdate) {
const attrs = getXDirectives(el);
attrs.forEach(function (reference) {
const type = reference.type;
const expression = reference.expression;
const value = reference.value;
const modifiers = reference.modifiers;
if (type === DIRECTIVE) {
const options = {
rootMargin: getRootMargin(modifiers),
threshold: getThreshhold(modifiers),
};
if ("IntersectionObserver" in window) {
const observer = new IntersectionObserver((elements) => {
elements.forEach((element) => {
// Ignore element if intersecting in leave mode,
// or not intersecting in enter mode
if (element.isIntersecting === (value === 'leave')) return
component.evaluateReturnExpression(el, expression, extraVars);
modifiers.includes("once") && observer.disconnect();
});
}, options);
observer.observe(el);
} else {
component.evaluateReturnExpression(el, expression, extraVars);
}
}
});
}
return legacyResolveBoundAttributes.bind(component)(el, initialUpdate, extraVars);
};
});
},
};
const initAlpine = window.deferLoadingAlpine || ((callback) => callback());
window.deferLoadingAlpine = (callback) => {
AlpineIntersectionDirective.start();
initAlpine(callback);
};
})();
'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);
window.addEventListener('load', hyva.initMessages);
}( window.hyva = window.hyva || {} ));
'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 = 3600;
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;
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) {
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 {
dispatchPrivateContent({});
}
} catch (error) {
console.warn('Error retrieving Private Content:', error);
}
}
window.addEventListener('load', loadSectionData);
window.addEventListener('reload-customer-section-data', loadSectionData);
function dispatchPrivateContent(data) {
const privateContentEvent = new CustomEvent("private-content-loaded", {
detail: {
data: 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.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);
}
}
}
);
}
}
(() => {
document.addEventListener('submit', event => event.target.action = event.target.action.replace('%25uenc%25', hyva.getUenc()));
})()
function initCompareOnProductList() {
return {
addToCompare(productId) {
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
);
});
}
};
}
function initWishlist() {
return {
addToWishlist(productId) {
const formKey = hyva.getFormKey();
const postUrl = BASE_URL + 'wishlist/index/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;
} 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(function (response) {
if (!response) { return }
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: (response.success) ? "success" : "error",
text: (response.success)
? "Product has been added to your Wish List."
: response.error_message
}], 5000
);
const reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data");
window.dispatchEvent(reloadCustomerDataEvent);
}).catch(function (error) {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
[{
type: "error",
text: error
}], 5000
);
});
}
}
}
function initConfigurableOptions(productId, optionConfig) {
function findPathParam(key) {
const baseUrl = (BASE_URL.substr(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 [optionId, value] of Object.entries(this.optionConfig.defaultValues)) {
this.changeOption(optionId, value + '');
}
}
});
},
findSimpleIndex() {
this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues);
},
calculateSimpleIndexForPartialSelection(selectedValues) {
if (selectedValues.length === 0) return 0;
let productIndexIds = Object.keys(this.optionConfig.index);
Object.keys(this.optionConfig.attributes).forEach((attribute) => {
const productsWithAttributeMatch = selectedValues[attribute]
? productIndexIds.filter((productIndex) => {
return this.optionConfig.index[productIndex][attribute] === this.selectedValues[attribute]
})
: [];
productIndexIds = productsWithAttributeMatch.length ? productsWithAttributeMatch : productIndexIds
})
return productIndexIds[0];
},
calculateSimpleIndexForFullSelection(selectedValues) {
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;
});
},
productIndex: 0,
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 productIndexes = this.optionConfig.index;
let previousOption = false;
let availableIndexes = Object.keys(productIndexes);
const newAllowedAttributeOptions = [];
allAttributesSorted.forEach(attribute => {
if (previousOption && selectedValues[previousOption]) {
availableIndexes = availableIndexes.filter(availableIndex => {
return productIndexes[availableIndex][previousOption] ===
selectedValues[previousOption]
})
}
newAllowedAttributeOptions[attribute.id] =
allAttributes[attribute.id].options.filter(option => {
return !!option.products.find(product => {
return availableIndexes.includes(product);
})
});
previousOption = attribute.id;
});
return newAllowedAttributeOptions;
},
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] || []
},
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.productIndex)) {
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.productIndex]) {
return this.optionConfig.optionPrices[this.productIndex].finalPrice.amount
}
const cheapestForSelection = this.findCheapestProductForPartialSelection(this.selectedValues);
return this.optionConfig.optionPrices[cheapestForSelection]
? this.optionConfig.optionPrices[cheapestForSelection].finalPrice.amount
: this.optionConfig.prices.finalPrice.amount; // default price if no option selection
},
changeOption(optionId, value) {
if (value === '') {
// create new array so the length property is reset if no option is selected (avoiding delete)
this.selectedValues = this.selectedValues.reduce((newSelection, val, opt) => {
if (opt !== optionId) {
newSelection[opt] = val;
}
return newSelection;
}, []);
} else {
this.selectedValues[optionId] = value;
}
this.findSimpleIndex();
this.findAllowedAttributeOptions();
this.updatePrices();
this.updateGallery();
window.dispatchEvent(
new CustomEvent(
'configurable-selection-changed',
{
detail: {
productId: this.productId,
optionId: optionId,
value: value,
productIndex: this.productIndex,
selectedValues: this.selectedValues,
candidates: this.findProductIdsForPartialSelection(this.selectedValues),
}
}
)
);
},
calculateIsMinimalPrice() {
return (
this.selectedValues.filter(value => !!value).length <
Object.keys(this.optionConfig.attributes).length
);
},
updatePrices() {
const value = this.productIndex ?
this.optionConfig.optionPrices[this.productIndex] :
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) {
this.preselectCartItems(data);
this.preselectQuerystringItems();
this.preselectLocationHashItems();
},
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('?',''));
Object.values(this.optionConfig.attributes).map(attribute => {
urlQueryParams.get(attribute.code) &&
this.changeOption(attribute.id, urlQueryParams.get(attribute.code));
});
},
preselectLocationHashItems() {
// pre-select option like #144=167
const urlHashParams = new URLSearchParams(window.location.hash.replace('#',''));
Object.values(this.optionConfig.attributes).map(attribute => {
urlHashParams.get(attribute.id) &&
this.changeOption(attribute.id, urlHashParams.get(attribute.id));
});
}
}
}
function initSwatchOptions(swatchConfig) {
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 config = this.getSwatchConfig(attributeId, optionId);
return config.label || config.value || this.getOptionLabelFromOptionConfig(attributeId, optionId);
},
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
);
},
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) {
const io = new IntersectionObserver(
entries => {
entries.map(entry => {
if (entry.isIntersecting) {
this.showSwatches = true;
io.unobserve(this.$el);
}
})
}
);
io.observe(this.$el);
} else {
this.showSwatches = true
}
}
}
}
'use strict';
(() => {
const equalizeButtonWidths = (buttons) => {
const buttonList = buttons.querySelectorAll('[data-element="link"], [data-element="empty_link"]');
let buttonMinWidth = 0;
buttonList.forEach(button => {
const buttonWidth = button.offsetWidth;
if (buttonWidth > buttonMinWidth) {
buttonMinWidth = buttonWidth;
}
});
buttonList.forEach(button => {
button.style.minWidth = `${buttonMinWidth}px`;
});
};
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('[data-content-type="buttons"][data-same-width="true"]').forEach(buttons => {
equalizeButtonWidths(buttons);
});
});
})();
'use strict';
(() => {
const initCarousels = (elements) => {
if (!Glider) {
return;
}
const initProductCarousel = (carousel) => {
const gliderElement = carousel.querySelector('[data-role="glider-content"]');
if (!gliderElement) {
return;
}
const gliderDots = carousel.querySelector('.glider-dots');
const gliderPrev = carousel.querySelector('.glider-prev');
const gliderNext = carousel.querySelector('.glider-next');
const glider = new Glider(gliderElement, {
slidesToShow: 2,
slidesToScroll: 2,
scrollLock: true,
draggable: true,
dragVelocity: 2.5,
dots: gliderDots,
arrows: {
prev: gliderPrev,
next: gliderNext,
},
responsive: [
{
breakpoint: 768,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
}
},
{
breakpoint: 1024,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
}
},
],
});
carousel.classList.remove('overflow-x-scroll');
gliderPrev.classList.remove('hidden');
gliderNext.classList.remove('hidden');
if (carousel.dataset.autoplay !== 'false') {
gliderAutoplay(
glider,
carousel.dataset.autoplaySpeed,
carousel.dataset.infiniteLoop
);
}
};
const initSliderCarousel = (slider) => {
slider.innerHTML = `${slider.innerHTML} `;
slider.classList.add('glider-contain');
slider.insertAdjacentHTML(
'beforeend',
'\u000A\u003Cdiv\u0020class\u003D\u0022carousel\u002Dnav\u0020flex\u0020items\u002Dcenter\u0020justify\u002Dcenter\u0020flex\u002D1\u0020p\u002D4\u0022\u003E\u000A\u0020\u0020\u0020\u0020\u003Cbutton\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020aria\u002Dlabel\u003D\u0022Previous\u0022\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020class\u003D\u0022glider\u002Dprev\u0020w\u002D8\u0020h\u002D8\u0020mr\u002D1\u0020text\u002Dblack\u0020rounded\u002Dfull\u0020outline\u002Dnone\u0020focus\u003Aoutline\u002Dnone\u0020hidden\u0022\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003Csvg\u0020xmlns\u003D\u0022http\u003A\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\u0022\u0020fill\u003D\u0022none\u0022\u0020viewBox\u003D\u00220\u00200\u002024\u002024\u0022\u0020stroke\u003D\u0022currentColor\u0022\u0020width\u003D\u002224\u0022\u0020height\u003D\u002224\u0022\u003E\u000A\u0020\u0020\u003Cpath\u0020stroke\u002Dlinecap\u003D\u0022round\u0022\u0020stroke\u002Dlinejoin\u003D\u0022round\u0022\u0020stroke\u002Dwidth\u003D\u00222\u0022\u0020d\u003D\u0022M15\u002019l\u002D7\u002D7\u00207\u002D7\u0022\u002F\u003E\u000A\u003C\u002Fsvg\u003E\u000A\u0020\u0020\u0020\u0020\u003C\u002Fbutton\u003E\u000A\u0020\u0020\u0020\u0020\u003Cdiv\u0020role\u003D\u0022tablist\u0022\u0020class\u003D\u0022glider\u002Ddots\u0020select\u002Dnone\u0020flex\u0020flex\u002Dwrap\u0020mx\u002D1\u0020justify\u002Dcenter\u0020p\u002D0\u0020focus\u003Aoutline\u002Dnone\u0022\u003E\u003C\u002Fdiv\u003E\u000A\u0020\u0020\u0020\u0020\u003Cbutton\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020aria\u002Dlabel\u003D\u0022Next\u0022\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020class\u003D\u0022glider\u002Dnext\u0020w\u002D8\u0020h\u002D8\u0020ml\u002D1\u0020text\u002Dblack\u0020rounded\u002Dfull\u0020outline\u002Dnone\u0020focus\u003Aoutline\u002Dnone\u0020hidden\u0022\u003E\u000A\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u003Csvg\u0020xmlns\u003D\u0022http\u003A\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\u0022\u0020fill\u003D\u0022none\u0022\u0020viewBox\u003D\u00220\u00200\u002024\u002024\u0022\u0020stroke\u003D\u0022currentColor\u0022\u0020width\u003D\u002224\u0022\u0020height\u003D\u002224\u0022\u003E\u000A\u0020\u0020\u003Cpath\u0020stroke\u002Dlinecap\u003D\u0022round\u0022\u0020stroke\u002Dlinejoin\u003D\u0022round\u0022\u0020stroke\u002Dwidth\u003D\u00222\u0022\u0020d\u003D\u0022M9\u00205l7\u00207\u002D7\u00207\u0022\u002F\u003E\u000A\u003C\u002Fsvg\u003E\u000A\u0020\u0020\u0020\u0020\u003C\u002Fbutton\u003E\u000A\u003C\u002Fdiv\u003E\u000A'
);
const gliderElement = slider.querySelector('[data-role="glider-content"]');
const gliderDots = slider.querySelector('.glider-dots');
const gliderPrev = slider.querySelector('.glider-prev');
const gliderNext = slider.querySelector('.glider-next');
const glider = new Glider(gliderElement, {
slidesToShow: 1,
slidesToScroll: 1,
scrollLock: true,
scrollLockDelay: 250,
draggable: true,
dragVelocity: 2.5,
dots: gliderDots,
arrows: {
prev: gliderPrev,
next: gliderNext,
},
});
slider.classList.add('glider-initialized');
if (slider.dataset.showArrows === 'true') {
gliderPrev.classList.remove('hidden');
gliderNext.classList.remove('hidden');
}
if (slider.dataset.autoplay !== 'false') {
gliderAutoplay(
glider,
slider.dataset.autoplaySpeed,
slider.dataset.infiniteLoop
);
}
};
const gliderAutoplay = (glider, milliseconds, loop) => {
const pagesCount = glider.track.childElementCount;
let slideTimeout = null;
let nextIndex = 1;
let paused = false;
const slide = () => {
slideTimeout = setTimeout(
() => {
if (loop && nextIndex >= pagesCount) {
nextIndex = 0;
}
glider.scrollItem(nextIndex);
},
parseInt(milliseconds)
);
};
glider.ele.addEventListener('glider-animated', () => {
nextIndex = glider.slide + glider.opt.slidesToScroll;
window.clearInterval(slideTimeout);
if (!paused && (loop || nextIndex < pagesCount)) {
slide();
}
});
const pause = () => {
if (!paused) {
clearInterval(slideTimeout);
paused = true;
}
};
const unpause = () => {
if (paused) {
slide();
paused = false;
}
};
glider.ele.parentElement.addEventListener('mouseover', pause, {passive: true});
glider.ele.parentElement.addEventListener('touchstart', pause, {passive: true});
glider.ele.parentElement.addEventListener('mouseout', unpause, {passive: true});
glider.ele.parentElement.addEventListener('touchend', unpause, {passive: true});
slide();
};
elements.forEach(element => {
if (element.dataset.contentType === 'products') {
initProductCarousel(element);
}
if (element.dataset.contentType === 'slider') {
initSliderCarousel(element);
}
});
};
window.addEventListener('DOMContentLoaded', () => {
const carouselElements = document.querySelectorAll(
`[data-content-type="products"][data-appearance="carousel"],
[data-content-type="slider"]`
);
if (carouselElements.length > 0) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.addEventListener('load', () => {
initCarousels(carouselElements);
});
script.src = 'https\u003A\u002F\u002Fshop.grandstores.ae\u002Fstatic\u002Fversion1679967781\u002Ffrontend\u002FAureatelabs\u002Fgrandstores\u002Fen_US\u002FMagento_PageBuilder\u002Fjs\u002Fglider.min.js';
document.head.appendChild(script);
}
});
})();
'use strict';
(() => {
const initMaps = (elements) => {
const renderMap = (element) => {
const dataLocations = element.dataset.locations;
// Hide map if no locations set
if (!dataLocations || dataLocations === '[]') {
element.classList.add('hidden');
return;
}
const map = new google.maps.Map(
element,
getMapOptions(
element.dataset.showControls !== 'true',
element.dataset.showControls === 'true'
)
);
const locations = JSON.parse(dataLocations);
const latitudeLongitudeBounds = new google.maps.LatLngBounds();
const bounds = [];
locations.forEach(location => {
const position = {
lat: parseFloat(location.position.latitude),
lng: parseFloat(location.position.longitude),
};
bounds.push(position);
const infowindow = new google.maps.InfoWindow({
content: getInfoWindowContent(location),
});
const marker = new google.maps.Marker({
position: position,
map,
title: location.location_name,
});
marker.addListener('click', () => {
infowindow.open(map, marker);
});
});
// Set bounds if multiple locations
if (bounds.length > 1) {
bounds.forEach(function (bound) {
latitudeLongitudeBounds.extend(bound);
});
map.fitBounds(latitudeLongitudeBounds);
}
// Center if single location
if (bounds.length === 1) {
map.setCenter(bounds[0]);
}
};
const getMapOptions = (disableDefaultUI, mapTypeControl) => {
const style = '';
return {
zoom: 8,
scrollwheel: false,
disableDoubleClickZoom: false,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DEFAULT,
},
styles: style ? JSON.parse(style) : [],
disableDefaultUI: disableDefaultUI,
mapTypeControl: mapTypeControl,
};
};
const getInfoWindowContent = (location) => {
const title = location.location_name ?
`${location.location_name}` : '';
const comment = location.comment ? `${location.comment} ` : '';
const phone = location.phone ? `Phone: ${location.phone} ` : '';
const street = location.address ? `${location.address}` : '';
const city = location.city ? `${location.city}` : '';
const state = location.state ? `${location.state}` : '';
const zipCode = location.zipcode ? `${location.zipcode}` : '';
const country = location.country ? location.country : '';
return `
${title}
${comment}
${phone}
${street}
${city}
${state}
${zipCode}
${country}
`;
};
const hideAllMaps = () => {
document.querySelectorAll('[data-content-type="map"]').forEach(element => {
element.classList.add('hidden');
});
};
window.gm_authFailure = () => {
hideAllMaps();
};
if (typeof google.maps === 'undefined') {
hideAllMaps();
return;
}
elements.forEach(element => {
if (element.dataset.contentType === 'map') {
renderMap(element);
}
});
};
window.addEventListener('DOMContentLoaded', () => {
const mapElements = document.querySelectorAll('[data-content-type="map"]');
if (mapElements.length > 0) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.addEventListener('load', () => {
initMaps(mapElements);
});
script.src = 'https\u003A\u002F\u002Fmaps.googleapis.com\u002Fmaps\u002Fapi\u002Fjs\u003Fv\u003D3\u0026key\u003D';
document.head.appendChild(script);
}
});
})();
'use strict';
(() => {
const initParallaxImage = (element) => {
if (!window.jarallax) {
return;
}
element.classList.add('jarallax');
element.dataset.jarallax = '';
const parallaxSpeed = parseFloat(element.dataset.parallaxSpeed) || 0.5;
const elementStyle = window.getComputedStyle(element);
window.jarallax(element, {
imgPosition: elementStyle.backgroundPosition || '50% 50%',
imgRepeat: elementStyle.backgroundRepeat || 'no-repeat',
imgSize: elementStyle.backgroundSize || 'cover',
speed: parallaxSpeed,
});
};
const initVideoBackground = (element) => {
if (!window.jarallax) {
return;
}
let slider = null;
if (element.classList.contains('pagebuilder-slide-wrapper')) {
const viewportElement = document.createElement('div');
slider = element.closest('[data-content-type=slider]');
viewportElement.classList.add('jarallax-viewport-element');
element.dataset.elementInViewport = '.jarallax-viewport-element';
element.appendChild(viewportElement);
}
element.classList.add('jarallax');
element.dataset.jarallax = '';
const parallaxSpeed = parseFloat(element.dataset.parallaxSpeed) || 0.5;
window.jarallax(element, {
imgSrc: element.dataset.videoFallbackSrc,
speed: parallaxSpeed,
videoLoop: element.dataset.videoLoop,
videoPlayOnlyVisible: element.dataset.videoPlayOnlyVisible,
videoLazyLoading: element.dataset.videoLazyLoad,
disableVideo: false,
elementInViewport: element.dataset.elementInViewport &&
element.querySelector(element.dataset.elementInViewport),
});
if (slider) {
if (slider.dataset.afterChangeIsSet) {
return;
}
slider.addEventListener('glider-loaded', () => {
slider.querySelectorAll('.jarallax').forEach(videoSlide => {
videoSlide.jarallax && videoSlide.jarallax.onScroll();
});
});
slider.addEventListener('glider-animated', () => {
slider.querySelectorAll('.jarallax').forEach(videoSlide => {
videoSlide.jarallax && videoSlide.jarallax.onScroll();
});
});
slider.dataset.afterChangeIsSet = true;
}
};
window.addEventListener('DOMContentLoaded', () => {
const parallaxImageElements = document.querySelectorAll(
`[data-content-type="row"][data-background-type="image"][data-enable-parallax="1"],
[data-content-type="row"] > [data-background-type="image"][data-enable-parallax="1"]`
);
const videoBackgroundsElements = document.querySelectorAll(
`[data-content-type="row"][data-background-type="video"][data-enable-parallax="1"],
[data-content-type="row"] > [data-background-type="video"][data-enable-parallax="1"],
[data-content-type="banner"] [data-background-type="video"],
[data-content-type="slide"] [data-background-type="video"]`
);
if (parallaxImageElements.length > 0 || videoBackgroundsElements.length > 0) {
const jarallaxScript = document.createElement('script');
jarallaxScript.type = 'text/javascript';
jarallaxScript.addEventListener('load', () => {
parallaxImageElements.forEach(row => {
initParallaxImage(row);
});
const jarallaxVideoScript = document.createElement('script');
jarallaxVideoScript.type = 'text/javascript';
jarallaxVideoScript.addEventListener('load', () => {
videoBackgroundsElements.forEach(element => {
initVideoBackground(element);
});
});
jarallaxVideoScript.src = 'https\u003A\u002F\u002Fshop.grandstores.ae\u002Fstatic\u002Fversion1679967781\u002Ffrontend\u002FAureatelabs\u002Fgrandstores\u002Fen_US\u002FMagento_PageBuilder\u002Fjs\u002Fjarallax\u002Dvideo.min.js';
document.head.appendChild(jarallaxVideoScript);
});
jarallaxScript.src = 'https\u003A\u002F\u002Fshop.grandstores.ae\u002Fstatic\u002Fversion1679967781\u002Ffrontend\u002FAureatelabs\u002Fgrandstores\u002Fen_US\u002FMagento_PageBuilder\u002Fjs\u002Fjarallax.min.js';
document.head.appendChild(jarallaxScript);
}
});
})();
'use strict';
(() => {
const applyShowOnHover = (element) => {
const showOverlayOnHover = (element) => {
const overlay = element.querySelector('.pagebuilder-overlay');
const color = overlay.dataset.overlayColor;
element.addEventListener('mouseover', () => {
overlay.style.backgroundColor = color;
});
element.addEventListener('mouseout', () => {
overlay.style.backgroundColor = 'transparent';
});
};
const showButtonOnHover = (element) => {
const button = element.querySelector('.pagebuilder-banner-button');
element.addEventListener('mouseover', () => {
button.style.opacity = '1';
button.style.visibility = 'visible';
});
element.addEventListener('mouseout', () => {
button.style.opacity = '0';
button.style.visibility = 'hidden';
});
};
if (element.dataset.showOverlay === 'hover') {
showOverlayOnHover(element);
}
if (element.dataset.showButton === 'hover') {
showButtonOnHover(element);
}
};
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('[data-content-type="banner"],[data-content-type="slider"]').forEach(element => {
applyShowOnHover(element);
});
});
})();
'use strict';
(() => {
document.querySelectorAll('[data-content-type="tab-item"]').forEach(tabItem => {
tabItem.setAttribute('x-show', `tab === '${tabItem.id}'`);
});
document.querySelectorAll('[data-content-type="tabs"]').forEach(tab => {
const defaultActiveTab = parseInt(tab.dataset.activeTab) || 0;
tab.querySelectorAll('.tab-header').forEach((tabHeader, index) => {
const tabLink = tabHeader.querySelector('a');
const tabId = tabLink.getAttribute('href').replace('#', '');
tabHeader.setAttribute(':class', `{ 'active': tab === '${tabId}' }`);
tabLink.setAttribute('x-on:click.prevent', `tab = '${tabId}'`);
if (index === defaultActiveTab) {
tab.setAttribute('x-data', `{ tab: '${tabId}' }`);
}
});
});
})();
'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 = '';
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);
if (event.target.form.querySelector) {
script.addEventListener('load', () => {
Array.from(event.target.form.querySelectorAll('button[disabled]')).forEach(btn => btn.disabled && 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 });
}());
'use strict';
(function () {
const modals = [];
const excludedFromFocusTrapping = new Set();
function loadInertPolyfill(callback) {
// undocumented "feature", should not be used unless inert attribute support is guaranteed
if (window.hyva.modal.disableInertPolyfill) {
callback && callback();
} else {
const polyfill = document.createElement('script');
polyfill.src = 'https\u003A\u002F\u002Fshop.grandstores.ae\u002Fstatic\u002Fversion1679967781\u002Ffrontend\u002FAureatelabs\u002Fgrandstores\u002Fen_US\u002FHyva_Theme\u002Fjs\u002Fwicg\u002Dinert\u002D3.1.1\u002Finert.min.js';
callback && polyfill.addEventListener('load', callback);
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(polyfill, firstScriptTag);
}
}
let isInertPolyfillLoaded = 0;
function setSiblingsInert(dialogElement, toState) {
if (isInertPolyfillLoaded === 0) {
isInertPolyfillLoaded = 1;
loadInertPolyfill(() => {
isInertPolyfillLoaded = 2;
setSiblingsInert(dialogElement, toState)
})
return;
}
if (isInertPolyfillLoaded === 1) {
return;
}
// Walk up the DOM, toggle inert attribute the siblings at each level
let el = dialogElement;
while (el && (el = el.parentElement)) {
if (el === document.body || el.parentElement === null) continue;
Array.from(el.parentElement.children).forEach(sibling => {
if (sibling !== el) {
sibling.inert = toState;
}
})
}
// Walk down the DOM, toggle inert attribute to opposite of toState.
// This is needed if a nested dialog is rendered as a sibling of the opening dialog.
(function setChildrenInert(el, toState) {
if (el) {
el.inert = toState;
Array.from(el.children).forEach(child => setChildrenInert(child, toState));
}
})(findParentWithOverlaySpread(dialogElement), ! toState)
excludedFromFocusTrapping.forEach(selector => {
Array.from(document.querySelectorAll(selector)).map(el => el.inert = false);
})
}
function findParentWithOverlaySpread(el) {
while (el && (el = el.parentElement)) {
if (el === document.body || el.parentElement === null) continue;
if (el.hasAttribute('x-spread') && el.getAttribute('x-spread').indexOf('overlay(') !== -1) {
return el;
}
}
}
function freeFocusFromModalTrap(modal) {
const dialogElement = modal.viewModel.$refs[modal.name];
isOverlayDisabled(dialogElement) || modal.viewModel.$nextTick(() => setSiblingsInert(dialogElement, false));
}
function trapFocusInNextModalWithOverlay() {
for (let idx = modals.length -1; idx >= 0; idx--) {
const nextOnStack = modals[idx];
const nextDialogElement = nextOnStack.viewModel.$refs[nextOnStack.name];
if (! isOverlayDisabled(nextDialogElement)) {
nextOnStack.viewModel.$nextTick(() => setSiblingsInert(nextDialogElement, true));
break;
}
}
}
function focusables(dialogElement) {
const selector = 'a, button, 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) {
window.setTimeout(() => {
const focusElement = firstVisible(dialogElement.querySelectorAll('[x-focus-first]')) ||
focusables(dialogElement)[0] ||
null;
focusElement && isInViewport(focusElement) && focusElement.focus();
}, duration + 1);
}
function ucFirst(s) {
return s.substr(0, 1).toUpperCase() + s.substr(1);
}
function isOpenProp(dialogName) {
return 'is' + ucFirst(dialogName) + 'Open';
}
function determineTrigger($refs, dialog, trigger) {
// if show() was called without arguments use the event target as open trigger
if (typeof trigger === 'undefined' && typeof dialog === 'object' && dialog.target && dialog.target.focus) {
return dialog.target;
}
// if show('name', $event) was called with the event as the second argument use the event target as trigger
if (typeof dialog === 'string' && typeof trigger === 'object' && trigger.target && trigger.target.focus) {
return trigger.target;
}
// if show('name', 'trigger') was called with the ref name of the trigger element use that as the trigger
if (typeof trigger === 'string' && $refs[trigger]) {
return $refs[trigger];
} else {
// unknown trigger - no focus will be set when the dialog is hidden.
return null;
}
}
function isOverlayDisabled(dialog) {
return dialog && dialog.hasAttribute('x-no-overlay')
}
function areRemainingModalsWithoutOverlay(modals)
{
const overflowDisabled = modals.map(modal => modal.viewModel.$refs[modal.name]).filter(isOverlayDisabled);
return overflowDisabled.length === modals.length;
}
window.hyva.modal = function(options) {
const config = Object.assign({
dialog: 'dialog', // default dialog ref name
duration: 300, // ms before allowing subsequent hiding of modals for nested modals (see transition duration)
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 {
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;
// Prevent adding the same modal on the stack twice
if (this[isOpenProp(name)]) {
return;
}
this[isOpenProp(name)] = true;
useOverlay && this.$nextTick(() => setSiblingsInert(dialogElement, true));
setFocusAfterTransition(dialogElement, config.duration);
const frame = {name, viewModel: 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) {
// Guard against Escape being pressed multiple times before a transition is finished, otherwise
// this function will pop further dialogs from the stack but the display will not update.
if (Date.now() - lastHide < config.duration) {
return;
}
lastHide = Date.now();
const modal = modals.pop() || {};
const name = modal.name;
this[isOpenProp(name)] = false;
freeFocusFromModalTrap(modal)
trapFocusInNextModalWithOverlay();
const nextFocusAfterHide = modal.focusTarget;
nextFocusAfterHide && this.$nextTick(() => nextFocusAfterHide.focus());
if (modals.length === 0 || areRemainingModalsWithoutOverlay(modals)) {
document.body.classList.remove('overflow-hidden');
}
modal.resolve(value);
},
[isOpenProp(config.dialog)]: false,
overlay(dialog) {
const name = typeof dialog === 'string' ? dialog : config.dialog;
return {
['x-show']() {
return this[isOpenProp(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'](event) {
event.detail && event.detail.dialog === name && this.show(name)
}
};
}
};
}
window.hyva.modal.pop = function () {
if (modals.length > 0) {
const modal = modals[modals.length -1];
modal.viewModel.hide();
}
}
window.hyva.modal.excludeSelectorsFromFocusTrap = function (selectors) {
typeof selectors === 'string' || selectors instanceof String
? excludedFromFocusTrapping.add(selector)
: selectors.map(selector => excludedFromFocusTrapping.add(selector));
}
window.hyva.modal.eventListeners = {
keydown: event => {
if (event.key === 'Escape') {
window.hyva.modal.pop();
}
},
// generic modal @click.away handler
click: event => {
if (modals.length > 0) {
const modal = modals[modals.length -1];
const dialog = modal.viewModel.$refs[modal.name];
if (modal.time + 10 < Date.now() && // if last click processing is more than 10ms ago
! isOverlayDisabled(dialog) && // if dialog has overlay
! dialog.contains(event.target)) { // if click is outside of dialog
modal.viewModel.hide();
}
}
}
};
document.addEventListener('keydown', window.hyva.modal.eventListeners.keydown);
document.addEventListener('click', window.hyva.modal.eventListeners.click);
})();
.is-loading > :not(.loader) {
visibility: hidden;
}
function initAddToCart() {
return {
showLoader: false,
showBox: false,
addToCart(formID, productID) {
let outerThis = this;
const delay = 500;
let form = document.querySelector('#' + formID + "[product-id='" + productID + "']");
const data = new URLSearchParams(new FormData(form).entries()),
button = this.$el;
let cartText = button.querySelector('#add-to-cart-btn').__x.$data.btnText;
button.querySelector('#add-to-cart-btn').__x.$data.btnText = '';
outerThis.showLoader = true;
button.disabled = true;
data.set('uenc', hyva.getUenc());
data.set('form_key', hyva.getFormKey());
fetch(BASE_URL + "checkout/cart/add/product/" + productID, {
method: 'POST',
body: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest'
},
"mode": "cors",
"credentials": "include"
})
.then(res => {
if (!res.ok) {
return form.submit();
}
if (res.redirected) {
return [];
}
return res.json();
})
.then(data => {
if (data.length == 0) {
outerThis.showLoader = false;
outerThis.showBox = true;
setTimeout(() => {
const reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data");
window.dispatchEvent(reloadCustomerDataEvent);
button.querySelector('#add-to-cart-btn').__x.$data.btnText = 'Added to cart';
setTimeout(() => {
button.querySelector('#add-to-cart-btn').__x.$data.btnText = cartText;
outerThis.showLoader = false;
outerThis.showBox = false;
document.getElementById('menu-cart-icon').click();
}, 2000);
}, 1000);
} else {
const reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data");
window.dispatchEvent(reloadCustomerDataEvent);
button.querySelector('#add-to-cart-btn').__x.$data.btnText = 'Not available';
outerThis.showLoader = false;
setTimeout(() => {
button.querySelector('#add-to-cart-btn').__x.$data.btnText = cartText;
}, 2000);
}
})
.catch(err => {
window.dispatchEvent(new CustomEvent('product-addtocart-error'));
setMessage({
text: 'There was a problem adding your item to the cart.',
type: 'error'
});
})
.finally(() => {
try {
var messages = hyva.getCookie('mage-messages');
messages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : [];
document.cookie = 'mage-messages=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
} catch (error) {
console.warn('Error parsing Cookie Messages:', error);
return;
}
setTimeout(() => {
button.disabled = false;
messages.forEach(message => {
setMessage(message);
});
}, delay);
});
}
}
}
/**
* Set Message
*/
function setMessage(message) {
typeof window.dispatchMessages !== "undefined" && window.dispatchMessages([
message
], 1000);
}
'use strict';
function GoogleAnalytics () {
let self = this;
this.config = {
isCookieRestrictionModeEnabled: 0,
currentWebsite: 1,
cookieName: "user_allowed_save_cookie",
ordersTrackingData: [],
pageTrackingData: {"optPageUrl":"","isAnonymizedIpActive":false,"accountId":"UA-161894558-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);
document.addEventListener( 'DOMContentLoaded', function () {
var quickViewModal = document.getElementById("quickview-modal-popup");
var quickViewCloseButton = document.getElementById("quickview-close-btn");
var quickviewOverlay = document.getElementById("quickview-overlay");
var quickviewContent = document.getElementById("quickview-content");
var quickLoading = document.getElementById("quick-loading");
var isNone = quickLoading.style.display == "none";
initializeQuickView = function (event) {
if(isNone) {
quickLoading.style.display = "block";
}
fetch("https://shop.grandstores.ae/en/alquickview/catalog_product/view/", {
method: 'POST',
"body": "product_id=" + event.getAttribute('data-product-id'),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
"X-Requested-With": "XMLHttpRequest",
'Accept': '*/*'
},
isAjax: true,
}).then(function (response) {
return response.text();
}).then(function (response) {
// Replaced the product form from quickview response to fix the quickview add to cart issue in product detail page
quickviewContent.innerHTML = response.replace(/product_addtocart_form/g, 'quickview_product_addtocart_form');
// Remove all the old quick view popup scripts with class name quick-view-product-js before initializing
document.querySelectorAll('head .quick-view-product-js').forEach(e => e.remove());
// Run the javascript codes in quick view popup by adding in head
var scriptElements = quickviewContent.getElementsByTagName('script');
for (let i = 0; i < scriptElements.length; i ++) {
var scriptElement = document.createElement('script');
scriptElement.classList.add('quick-view-product-js');
if (!scriptElements[i].src) {
scriptElement.innerHTML = scriptElements[i].innerHTML;
} else {
scriptElement.src = scriptElements[i].src;
}
document.head.appendChild(scriptElement);
}
quickviewOverlay.style.display = "flex";
quickViewModal.style.display = "flex";
quickLoading.style.display = "none";
quickViewModal.classList.add('overflow-y-auto');
});
// When the user clicks on close button, close the modal
quickViewCloseButton.onclick = function() {
closeQuickViewModal();
var element = document.getElementById('html-body');
element.classList.remove('overflow-hidden');
quickViewModal.classList.remove('overflow-y-auto');
}
quickviewOverlay.onclick = function() {
// TODO: Need to fix overlay design issue to get proper click outside modal to get modal closed
closeQuickViewModal();
}
}
// Close Quick view popup modal
function closeQuickViewModal() {
quickviewOverlay.style.display = "none";
quickViewModal.style.display = "none";
}
});
|