This product may not be available anymore.

Samsung Galaxy A13 4GB/64GB (Black) Details

  • The best price of Samsung Galaxy A13 4GB/64GB (Black) by grandstores in UAE is 549 AED
  • This product is reviewed by 1 users, and its average rating is
      (4/5)
    • The first appearance of this product was on Jan 06, 2023

    grandstores's Description

    function initPrice7343() { return { regularPriceKey: 'oldPrice', finalPriceKey: 'finalPrice', activeProductsPriceData: false, initialFinalPrice: 549, 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-7343.window'](event) { this.activeProductsPriceData = event.detail; this.calculateFinalPrice(); this.calculateFinalPriceWithCustomOptions(); this.calculatePriceLabelVisibility(); }, ['@update-qty-7343.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 549.00Save 16%
    function initPrice7343() { return { regularPriceKey: 'oldPrice', finalPriceKey: 'finalPrice', activeProductsPriceData: false, initialFinalPrice: 549, 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-7343.window'](event) { this.activeProductsPriceData = event.detail; this.calculateFinalPrice(); this.calculateFinalPriceWithCustomOptions(); this.calculatePriceLabelVisibility(); }, ['@update-qty-7343.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 549.00Save 16%

    In stock

    SKU: 102-1344-001175
    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: '7343', 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); } } } }; }
    Qty
    +
    function initWishlist_641d9291d3d1a() { 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 ); }); } }; } compare
    shareable icon
    • Facebook iconFacebook
    • Tweet iconTweet
    • Email iconEmail

    Product Details

    #html-body [data-pb-style=S2JMQ1X]{justify-content:flex-start;display:flex;flex-direction:column;background-position:left top;background-size:cover;background-repeat:no-repeat;background-attachment:scroll}

    Highlights

    • 4G
    • 4GB RAM
    • Network: LTE
    • Simslots: Dual + SD card
    • 64GB (MicroSD up to 1TB)
    • 6.6" FHD+ TFT Infinity V-Displa
    • The Galaxy A13 combines Octa-core processing power with up to 4GB of RAM for fast and efficient performance for the task at hand.
    • Stay 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.
    • Galaxy A13 combines soft colours with a look and feel that’s gentle to the touch Snap memorable moments in clear detail with the 50MP Main Camera.
    • The 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.
    • Expand viewing angle with Ultra Wide Camera Similar to human eyesight, the 5MP Ultra-Wide Camera sees the world with a 123-degree angle view, adding more perspective to everything you shoot.

    Features

    Minimalist Design – Combining soft colours with a look and feel that’s gentle to the touch and comfortable to hold.

    Long Lasting Battery – A battery that won’t slow you down, the 5,000 mAh battery keeps you going for hours on end.

    Vivid display – More room to play with the 6.6-inch Infinity-V Display, FHD+ technology makes your everyday content look sharp, crisp, and clear.

    Quad Camera System – Capture memorable moments in crisp clear detail with the 50MP Main camera, expand your viewing angle with the ultra-wide camera, optimise the focus with theDepth camera, and enhance your shots with the macro camera.

    More Information

    ColoursBlack
    ColorGrey
    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; } } } }
    • compare
    • wishlist
    • account
    {"@context":"http:\/\/schema.org","@type":"Product","name":"Samsung Galaxy A13 4GB\/64GB (Black)","sku":"102-1344-001175","model":"Samsung Galaxy A13 4GB\/64GB (Black)","color":"Grey","description":"\r\n\r\n\r\n\r\nModel:\r\n\r\n\r\nSM-A137FZKGMEA\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-1344-001175","offers":{"@type":"Offer","url":"https:\/\/shop.grandstores.ae\/en\/samsung-galaxy-a13-4gb-64gb-sm-a137fzkgmea-black-1.html","price":"549.00","priceCurrency":"AED","priceValidUntil":"2030-01-01","sku":"102-1344-001175","gtin":"102-1344-001175"}}
    .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
    • 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
    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\u002Fversion1678759192\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\u002Fversion1678759192\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\u002Fversion1678759192\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\u002Fversion1678759192\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);
    Loading...
    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"; } });

    Top Products in Smartphonesmore

      Reviews of Samsung Galaxy A13 4GB/64GB (Black)

      • khaled assem

          (1 year ago)

          هاتف Samsung Galaxy A13 الهاتف الاقتصادي المثالي بل قد يكون الأفضل في فئته السعرية خاصة وأنه مقدم من سامسونج وهو ما يضعه في مكانة أعلى من المنافسين، والهاتف لا يفتقد للكثير من المواصفات التي تتمتع بها هواتف أعلى سواء من سامسونج أو أي شركة أخرى، فبغض النظر عن أن شاشته ليست AMOLED إلا أن باقي مواصفاته جيدة للغاية فالهاتف بشاشة بجودة Full HD وقطرها كبير نسبيًا، ويمتاز الهاتف بمعالج قوي بشكل ملحوظ مقابل منافسيه، كما يتمتع بكاميرا أكثر من رائعة وإن كانت تلك الروعة تقل قليلًا على مستوى الكاميرا الامامية، بطارية الهاتف أيضًا متميزة سواء على مستوى سعة البطارية أو تقنية الشحن السري وإن كانت ليست الأقوى ولكنها مقبولة

        Video Reviews of Samsung Galaxy A13 4GB/64GB (Black)

        • loading video reviews