define('Born_Buynow/js/buy-now',[
    'jquery',
    'Magento_Customer/js/model/authentication-popup',
    'Magento_Customer/js/customer-data'
], function ($, authenticationPopup, customerData) {
    "use strict";
    return function (config, element) {
        $(element).click(function () {
            var form = $(config.form),
                baseUrl = form.attr('action'),
                addToCartUrl = 'checkout/cart/add',
                buyNowCartUrl = 'buynow/cart/add',
                buyNowUrl = baseUrl.replace(addToCartUrl, buyNowCartUrl),
                isGuestCheckoutAllow = config.isGuestCheckoutAllow,
                    customer = customerData.get('customer');
            event.preventDefault();
            if (!customer().firstname && isGuestCheckoutAllow == 0) {
                authenticationPopup.showModal();

                return false;
            } else {
                if (form.valid()) {
                    $.ajax({
                        type: form.attr('method'),
                        url: buyNowUrl,
                        data: form.serialize(),
                        success: function (data) {
                            form.attr('action', baseUrl);
                            if (data.hasOwnProperty('backUrl')) {
                                window.location.href = data.backUrl;
                            }
                        },
                        error: function (error){
                            window.location.reload(true);
                        }
                    });
                }
            }
            return false;
        });
    }
});

(function(root) {
define("magnifier/magnifier", ["jquery"], function() {
  return (function() {
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

(function ($) {
    $.fn.magnify = function (options) {
        'use strict';

        var magnify = new Magnify($(this), options);

        /* events must be tracked here */

        /**
         * Return that from _init function
         *
         */
        return magnify;
    };

    function Magnify(element, options) {
        var customUserOptions = options || {},
            $box = $(element),
            $thumb,
            that = this,
            largeWrapper = options.largeWrapper || '.magnifier-preview',
            $magnifierPreview = $(largeWrapper);

        curThumb = null,
        magnifierOptions = {
            x: 0,
            y: 0,
            w: 0,
            h: 0,
            lensW: 0,
            lensH: 0,
            lensBgX: 0,
            lensBgY: 0,
            largeW: 0,
            largeH: 0,
            largeL: 0,
            largeT: 0,
            zoom: 2,
            zoomMin: 1.1,
            zoomMax: 5,
            mode: 'outside',
            eventType: 'click',
            status: 0,
            zoomAttached: false,
            zoomable: customUserOptions.zoomable !== undefined ?
                customUserOptions.zoomable
                : false,
            onthumbenter: customUserOptions.onthumbenter !== undefined ?
                customUserOptions.onthumbenter
                : null,
            onthumbmove: customUserOptions.onthumbmove !== undefined ?
                customUserOptions.onthumbmove
                : null,
            onthumbleave: customUserOptions.onthumbleave !== undefined ?
                customUserOptions.onthumbleave
                : null,
            onzoom: customUserOptions.onzoom !== undefined ?
                customUserOptions.onzoom
                : null
        },
        pos = {
            t: 0,
            l: 0,
            x: 0,
            y: 0
        },
        gId = 0,
        status = 0,
        curIdx = '',
        curLens = null,
        curLarge = null,
        lensbg = customUserOptions.bg !== undefined ?
            customUserOptions.lensbg
            : true,
        gZoom = customUserOptions.zoom !== undefined ?
            customUserOptions.zoom
            : magnifierOptions.zoom,
        gZoomMin = customUserOptions.zoomMin !== undefined ?
            customUserOptions.zoomMin
            : magnifierOptions.zoomMin,
        gZoomMax = customUserOptions.zoomMax !== undefined ?
            customUserOptions.zoomMax
            : magnifierOptions.zoomMax,
        gMode = customUserOptions.mode || magnifierOptions.mode,
        gEventType = customUserOptions.eventType || magnifierOptions.eventType,
        data = {},
        inBounds = false,
        isOverThumb = false,
        rate = 1,
        paddingX = 0,
        paddingY = 0,
        enabled = true,
        showWrapper = true;

        var MagnifyCls = {
            magnifyHidden: 'magnify-hidden',
            magnifyOpaque: 'magnify-opaque',
            magnifyFull: 'magnify-fullimage'
        };

        /**
         * Update Lens positon on.
         *
         */
        that.update = function () {
            updateLensOnLoad();
        };

        /**
         * Init new Magnifier
         *
         */
        that.init = function () {
            _init($box, options);
        };

        function _toBoolean(str) {
            if (typeof str === 'string') {
                if (str === 'true') {
                    return true;
                } else if (str === 'false' || '') {
                    return false;
                }
                console.warn('Wrong type: can\'t be transformed to Boolean');

            } else if (typeof str === 'boolean') {
                return str;
            }
        }

        function createLens(thumb) {
            if ($(thumb).siblings('.magnify-lens').length) {
                return false;
            }
            var lens = $('<div class="magnify-lens magnify-hidden" data-gallery-role="magnifier-zoom"></div>');

            $(thumb).parent().append(lens);
        }

        function updateLensOnLoad(idSelectorMainImg, thumb, largeImgInMagnifyLens, largeWrapper) {
            var magnifyLensElement= $box.find('.magnify-lens'),
                textWrapper;

            if (data[idSelectorMainImg].status === 1) {
                textWrapper = $('<div class="magnifier-loader-text"></div>');
                magnifyLensElement.className = 'magnifier-loader magnify-hidden';
                textWrapper.html('Loading...');
                magnifyLensElement.html('').append(textWrapper);
            } else if (data[idSelectorMainImg].status === 2) {
                magnifyLensElement.addClass(MagnifyCls.magnifyHidden);
                magnifyLensElement.html('');

                largeImgInMagnifyLens.id = idSelectorMainImg + '-large';
                largeImgInMagnifyLens.style.width = data[idSelectorMainImg].largeImgInMagnifyLensWidth + 'px';
                largeImgInMagnifyLens.style.height = data[idSelectorMainImg].largeImgInMagnifyLensHeight + 'px';
                largeImgInMagnifyLens.className = 'magnifier-large magnify-hidden';

                if (data[idSelectorMainImg].mode === 'inside') {
                    magnifyLensElement.append(largeImgInMagnifyLens);
                } else {
                    largeWrapper.html('').append(largeImgInMagnifyLens);
                }
            }

            data[idSelectorMainImg].lensH = data[idSelectorMainImg].lensH > $thumb.height() ? $thumb.height() : data[idSelectorMainImg].lensH;

            if (Math.round(data[idSelectorMainImg].lensW) === 0) {
                magnifyLensElement.css('display', 'none');
            } else {
                magnifyLensElement.css({
                    width: Math.round(data[idSelectorMainImg].lensW) + 'px',
                    height: Math.round(data[idSelectorMainImg].lensH) + 'px',
                    display: ''
                });
            }
        }

        function getMousePos() {
            var xPos = pos.x - magnifierOptions.x,
                yPos = pos.y - magnifierOptions.y,
                t,
                l;

            inBounds =  xPos < 0 || yPos < 0 || xPos > magnifierOptions.w || yPos > magnifierOptions.h  ? false : true;

            l = xPos - magnifierOptions.lensW / 2;
            t = yPos - magnifierOptions.lensH / 2;

            if (xPos < magnifierOptions.lensW / 2) {
                l = 0;
            }

            if (yPos < magnifierOptions.lensH / 2) {
                t = 0;
            }

            if (xPos - magnifierOptions.w + Math.ceil(magnifierOptions.lensW / 2) > 0) {
                l = magnifierOptions.w - Math.ceil(magnifierOptions.lensW + 2);
            }

            if (yPos - magnifierOptions.h + Math.ceil(magnifierOptions.lensH / 2) > 0) {
                t = magnifierOptions.h - Math.ceil(magnifierOptions.lensH);
            }

            pos.l = l;
            pos.t = t;

            magnifierOptions.lensBgX = pos.l;
            magnifierOptions.lensBgY = pos.t;

            if (magnifierOptions.mode === 'inside') {
                magnifierOptions.largeL = Math.round(xPos * (magnifierOptions.zoom - magnifierOptions.lensW / magnifierOptions.w));
                magnifierOptions.largeT = Math.round(yPos * (magnifierOptions.zoom - magnifierOptions.lensH / magnifierOptions.h));
            } else {
                magnifierOptions.largeL = Math.round(magnifierOptions.lensBgX * magnifierOptions.zoom * (magnifierOptions.largeWrapperW / magnifierOptions.w));
                magnifierOptions.largeT = Math.round(magnifierOptions.lensBgY * magnifierOptions.zoom * (magnifierOptions.largeWrapperH / magnifierOptions.h));
            }
        }

        function onThumbEnter() {
            if (_toBoolean(enabled)) {
                magnifierOptions = data[curIdx];
                curLens = $box.find('.magnify-lens');

                if (magnifierOptions.status === 2) {
                    curLens.removeClass(MagnifyCls.magnifyOpaque);
                    curLarge = $('#' + curIdx + '-large');
                    curLarge.removeClass(MagnifyCls.magnifyHidden);
                } else if (magnifierOptions.status === 1) {
                    curLens.className = 'magnifier-loader';
                }
            }
        }

        function onThumbLeave() {
            if (magnifierOptions.status > 0) {
                var handler = magnifierOptions.onthumbleave;

                if (handler !== null) {
                    handler({
                        thumb: curThumb,
                        lens: curLens,
                        large: curLarge,
                        x: pos.x,
                        y: pos.y
                    });
                }

                if (!curLens.hasClass(MagnifyCls.magnifyHidden)) {
                    curLens.addClass(MagnifyCls.magnifyHidden);

                    //$curThumb.removeClass(MagnifyCls.magnifyOpaque);
                    if (curLarge !== null) {
                        curLarge.addClass(MagnifyCls.magnifyHidden);
                    }
                }
            }
        }

        function move() {
            if (_toBoolean(enabled)) {
                if (status !== magnifierOptions.status) {
                    onThumbEnter();
                }

                if (magnifierOptions.status > 0) {
                    curThumb.className = magnifierOptions.thumbCssClass + ' magnify-opaque';

                    if (magnifierOptions.status === 1) {
                        curLens.className = 'magnifier-loader';
                    } else if (magnifierOptions.status === 2) {
                        curLens.removeClass(MagnifyCls.magnifyHidden);
                        curLarge.removeClass(MagnifyCls.magnifyHidden);
                        curLarge.css({
                            left: '-' + magnifierOptions.largeL + 'px',
                            top: '-' + magnifierOptions.largeT + 'px'
                        });
                    }

                    var borderOffset = 2; // Offset for magnify-lens border
                    pos.t = pos.t <= 0 ? 0 : pos.t - borderOffset;

                    curLens.css({
                        left: pos.l + paddingX + 'px',
                        top: pos.t + paddingY + 'px'
                    });

                    if (lensbg) {
                        curLens.css({
                            'background-color': 'rgba(f,f,f,.5)'
                        });
                    } else {
                        curLens.get(0).style.backgroundPosition = '-' +
                        magnifierOptions.lensBgX + 'px -' +
                        magnifierOptions.lensBgY + 'px';
                    }
                    var handler = magnifierOptions.onthumbmove;

                    if (handler !== null) {
                        handler({
                            thumb: curThumb,
                            lens: curLens,
                            large: curLarge,
                            x: pos.x,
                            y: pos.y
                        });
                    }
                }

                status = magnifierOptions.status;
            }
        }

        function setThumbData(mainImage, mainImageData) {
            var thumbBounds = mainImage.getBoundingClientRect(),
                w = 0,
                h = 0;

            mainImageData.x = Math.round(thumbBounds.left);
            mainImageData.y = Math.round(thumbBounds.top);
            mainImageData.w = Math.round(thumbBounds.right - mainImageData.x);
            mainImageData.h = Math.round(thumbBounds.bottom - mainImageData.y);

            if (mainImageData.mode === 'inside') {
                w = mainImageData.w;
                h = mainImageData.h;
            } else {
                w = mainImageData.largeWrapperW;
                h = mainImageData.largeWrapperH;
            }

            mainImageData.largeImgInMagnifyLensWidth = Math.round(mainImageData.zoom * w);
            mainImageData.largeImgInMagnifyLensHeight = Math.round(mainImageData.zoom * h);

            mainImageData.lensW = Math.round(mainImageData.w / mainImageData.zoom);
            mainImageData.lensH = Math.round(mainImageData.h / mainImageData.zoom);
        }

        function _init($box, options) {
            var opts = {};

            if (options.thumb === undefined) {
                return false;
            }

            $thumb = $box.find(options.thumb);

            if ($thumb.length) {
                for (var key in options) {
                    opts[key] = options[key];
                }

                opts.thumb = $thumb;
                enabled = opts.enabled;

                if (_toBoolean(enabled)) {

                    $magnifierPreview.show().css('display', '');
                    $magnifierPreview.addClass(MagnifyCls.magnifyHidden);
                    set(opts);
                } else {
                    $magnifierPreview.empty().hide();
                }
            }

            return that;
        }

        function hoverEvents(thumb) {
            $(thumb).on('mouseover', function (e) {

                if (showWrapper) {

                    if (magnifierOptions.status !== 0) {
                        onThumbLeave();
                    }
                    handleEvents(e);
                    isOverThumb = inBounds;
                }
            }).trigger('mouseover');
        }

        function clickEvents(thumb) {
            $(thumb).on('click', function (e) {

                if (showWrapper) {
                    if (!isOverThumb) {
                        if (magnifierOptions.status !== 0) {
                            onThumbLeave();
                        }
                        handleEvents(e);
                        isOverThumb = true;
                    }
                }
            });
        }

        function bindEvents(eType, thumb) {
            var eventFlag = 'hasBoundEvent_' + eType;
            if (thumb[eventFlag]) {
                // Events are already bound, no need to bind in duplicate
                return;
            }
            thumb[eventFlag] = true;

            switch (eType) {
                case 'hover':
                    hoverEvents(thumb);
                    break;

                case 'click':
                    clickEvents(thumb);
                    break;
            }
        }

        function handleEvents(e) {
            var src = e.target;

            curIdx = src.id;
            curThumb = src;

            onThumbEnter(src);

            setThumbData(curThumb, magnifierOptions);

            pos.x = e.clientX;
            pos.y = e.clientY;

            getMousePos();
            move();

            var handler = magnifierOptions.onthumbenter;

            if (handler !== null) {
                handler({
                    thumb: curThumb,
                    lens: curLens,
                    large: curLarge,
                    x: pos.x,
                    y: pos.y
                });
            }
        }

        function set(options) {
            if (data[options.thumb.id] !== undefined) {
                curThumb = options.thumb;

                return false;
            }

            var thumbObj = new Image(),
                largeObj = new Image(),
                $thumb = options.thumb,
                thumb = $thumb.get(0),
                idx = thumb.id,
                largeUrl,
                largeWrapper = $(options.largeWrapper),
                zoom = options.zoom || thumb.getAttribute('data-zoom') || gZoom,
                zoomMin = options.zoomMin || gZoomMin,
                zoomMax = options.zoomMax || gZoomMax,
                mode = options.mode || thumb.getAttribute('data-mode') || gMode,
                eventType = options.eventType || thumb.getAttribute('data-eventType') || gEventType,
                onthumbenter = options.onthumbenter !== undefined ?
                    options.onthumbenter
                    : magnifierOptions.onthumbenter,
                onthumbleave = options.onthumbleave !== undefined ?
                    options.onthumbleave
                    : magnifierOptions.onthumbleave,
                onthumbmove = options.onthumbmove !== undefined ?
                    options.onthumbmove
                    : magnifierOptions.onthumbmove;

            largeUrl = $thumb.data('original') || customUserOptions.full || $thumb.attr('src');

            if (thumb.id === '') {
                idx = thumb.id = 'magnifier-item-' + gId;
                gId += 1;
            }

            createLens(thumb, idx);

            if (options.width) {
                largeWrapper.width(options.width);
            }

            if (options.height) {
                largeWrapper.height(options.height);
            }

            if (options.top) {
                if (typeof options.top == 'function') {
                    var top = options.top() + 'px';
                } else {
                    var top = options.top + 'px';
                }

                if (largeWrapper.length) {
                    largeWrapper[0].style.top = top.replace('%px', '%');
                }
            }

            if (options.left) {
                if (typeof options.left == 'function') {
                    var left = options.left() + 'px';
                } else {
                    var left = options.left + 'px';
                }

                if (largeWrapper.length) {
                    largeWrapper[0].style.left = left.replace('%px', '%');
                }
            }

            data[idx] = {
                zoom: zoom,
                zoomMin: zoomMin,
                zoomMax: zoomMax,
                mode: mode,
                eventType: eventType,
                thumbCssClass: thumb.className,
                zoomAttached: false,
                status: 0,
                largeUrl: largeUrl,
                largeWrapperId: mode === 'outside' ? largeWrapper.attr('id') : null,
                largeWrapperW: mode === 'outside' ? largeWrapper.width() : null,
                largeWrapperH: mode === 'outside' ? largeWrapper.height() : null,
                onthumbenter: onthumbenter,
                onthumbleave: onthumbleave,
                onthumbmove: onthumbmove
            };

            paddingX = ($thumb.parent().width() - $thumb.width()) / 2;
            paddingY = ($thumb.parent().height() - $thumb.height()) / 2;

            showWrapper = false;
            $(thumbObj).on('load', function () {
                if (data.length > 0) {
                    data[idx].status = 1;

                    $(largeObj).on('load', function () {

                        if (largeObj.width > largeWrapper.width() || largeObj.height > largeWrapper.height()) {
                            showWrapper = true;
                            bindEvents(eventType, thumb);
                            data[idx].status = 2;
                            if (largeObj.width > largeObj.height) {
                                data[idx].zoom = largeObj.width / largeWrapper.width();
                            } else {
                                data[idx].zoom = largeObj.height / largeWrapper.height();
                            }
                            setThumbData(thumb, data[idx]);
                            updateLensOnLoad(idx, thumb, largeObj, largeWrapper);
                        }
                    });

                    largeObj.src = data[idx].largeUrl;
                }
            });

            thumbObj.src = thumb.src;
        }

        /**
         * Hide magnifier when mouse exceeds image bounds.
         */
        function onMouseLeave() {
            onThumbLeave();
            isOverThumb = false;
            $magnifierPreview.addClass(MagnifyCls.magnifyHidden);
        }

        function onMousemove(e) {
            pos.x = e.clientX;
            pos.y = e.clientY;

            getMousePos();

            if (gEventType === 'hover') {
                isOverThumb = inBounds;
            }

            if (inBounds && isOverThumb) {
                if (gMode === 'outside') {
                    $magnifierPreview.removeClass(MagnifyCls.magnifyHidden);
                }
                move();
            }
        }

        function onScroll() {
            if (curThumb !== null) {
                setThumbData(curThumb, magnifierOptions);
            }
        }

        $(window).on('scroll', onScroll);
        $(window).on('resize', function () {
            _init($box, customUserOptions);
        });

        $box.on('mousemove', onMousemove);
        $box.on('mouseleave', onMouseLeave);

        _init($box, customUserOptions);
    }
}(jQuery));


  }).apply(root, arguments);
});
}(this));

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define('magnifier/magnify',[
    'jquery',
    'underscore',
    'magnifier/magnifier'
], function ($, _) {
    'use strict';

    return function (config, element) {

        var isTouchEnabled = 'ontouchstart' in document.documentElement,
            gallerySelector = '[data-gallery-role="gallery"]',
            magnifierSelector = '[data-gallery-role="magnifier"]',
            magnifierZoomSelector = '[data-gallery-role="magnifier-zoom"]',
            zoomInButtonSelector = '[data-gallery-role="fotorama__zoom-in"]',
            zoomOutButtonSelector = '[data-gallery-role="fotorama__zoom-out"]',
            fullscreenImageSelector = '[data-gallery-role="stage-shaft"] [data-active="true"] .fotorama__img--full',
            imageDraggableClass = 'fotorama__img--draggable',
            imageZoommable = 'fotorama__img--zoommable',
            zoomInLoaded = 'zoom-in-loaded',
            zoomOutLoaded = 'zoom-out-loaded',
            zoomInDisabled = 'fotorama__zoom-in--disabled',
            zoomOutDisabled = 'fotorama__zoom-out--disabled',
            keyboardNavigation,
            videoContainerClass = 'fotorama-video-container',
            hideMagnifier,
            dragFlag,
            endX,
            transitionEnabled,
            transitionActive = false,
            tapFlag = 0,
            allowZoomOut = false,
            allowZoomIn = true;

        transitionEnabled = document.documentElement.style.transition !== undefined ||
            document.documentElement.style.WebkitTransition !== undefined ||
            document.documentElement.style.MozTransition !== undefined ||
            document.documentElement.style.MsTransition !== undefined ||
            document.documentElement.style.OTransition !== undefined;

        /**
         * Return width and height of original image
         * @param img original image node
         * @returns {{rw: number, rh: number}}
         */
        function getImageSize(img) {
            return {
                rw: img.naturalWidth,
                rh: img.naturalHeight
            };
        }

        /**
         * Sets min-height and min-width for image to avoid transition bug
         * @param $image - fullscreen image
         */
        function calculateMinSize($image) {

            var minHeight,
                minWidth,
                height = $image.height(),
                width = $image.width(),
                parentHeight = $image.parent().height(),
                parentWidth = $image.parent().width();

            if (width > parentWidth || height > parentHeight) {

                if (width / height < parentWidth / parentHeight) {
                    minHeight = parentHeight;
                    minWidth = width * (parentHeight / height);
                } else {
                    minWidth = parentWidth;
                    minHeight = height * parentWidth / width;
                }
                $image.css({
                    'min-width': minWidth,
                    'min-height': minHeight
                });
            }
        }

        function toggleZoomable($image, flag) {
            if (flag) {
                $image.css({
                    'min-width': $image.width(),
                    'min-height': $image.height(),
                    'width': $image.width(),
                    'height': $image.height()
                }).addClass(imageZoommable);
            } else {
                $image.css({
                    width: '',
                    height: '',
                    top: '',
                    left: '',
                    right: '',
                    bottom: ''
                }).removeClass(imageZoommable);
                calculateMinSize($image);
            }
        }

        function resetVars($image) {
            allowZoomIn = true;
            allowZoomOut = dragFlag = transitionActive = false;
            $image.hasClass(imageDraggableClass) && $image.removeClass(imageDraggableClass);
            toggleZoomable($image, false);
        }

        /**
         * Set state for zoom controls.
         * If state is true, zoom controls will be visible.
         * IF state is false, zoom controls will be hidden.
         * @param isHide
         */
        function hideZoomControls(isHide) {
            if (isHide) {
                $(zoomInButtonSelector).addClass(zoomInDisabled);
                $(zoomOutButtonSelector).addClass(zoomOutDisabled);
            } else {
                $(zoomInButtonSelector).removeClass(zoomInDisabled);
                $(zoomOutButtonSelector).removeClass(zoomOutDisabled);
            }
        }

        /**
         * Asynchronus control visibility of zoom buttons.
         * If image bigger than her wrapper. Zoom controls must visible.
         * @param path - image source path
         * @param $image
         */
        function asyncToggleZoomButtons(path, $image) {
            var img = new Image();

            img.onload = function () {
                this.height > $image.parent().height() || this.width > $image.parent().width() ?
                    hideZoomControls(false) : hideZoomControls(true);
            };
            img.src = path;
        }

        /**
         * Control visibility of zoom buttons.
         * Zoom controls must be invisible for video content and touch devices.
         * On touch devices active pinchIn/pinchOut.
         * @param $image
         * @param isTouchScreen - true for touch devices
         * @param isVideoActiveFrame - true for active video frame
         */
        function toggleZoomButtons($image, isTouchScreen, isVideoActiveFrame) {
            var path = $image.attr('src');

            if (path && !isTouchScreen && !isVideoActiveFrame) {
                asyncToggleZoomButtons(path, $image);
            } else {
                hideZoomControls(true);
            }
        }

        /**
         * Handle resize event in fullscreen.
         * @param $image - Fullscreen image.
         * @param e - Event.
         */
        function resizeHandler(e, $image) {
            var imageSize,
                parentWidth,
                parentHeight,
                isImageSmall,
                isImageFit;

            if (!e.data.$image || !e.data.$image.length)
                return;

            imageSize = getImageSize($(fullscreenImageSelector)[0]);
            parentWidth = e.data.$image.parent().width();
            parentHeight = e.data.$image.parent().height();
            isImageSmall = parentWidth >= imageSize.rw && parentHeight >= imageSize.rh;
            isImageFit = parentWidth > e.data.$image.width() && parentHeight > e.data.$image.height();

            toggleZoomButtons(e.data.$image, isTouchEnabled, checkForVideo(e.data.fotorama.activeFrame.$stageFrame));
            calculateMinSize(e.data.$image);

            if (e.data.$image.hasClass(imageZoommable) && !allowZoomOut || isImageSmall || isImageFit) {
                resetVars(e.data.$image);
            }

            if (!isImageSmall) {
                toggleStandartNavigation();
            }
        }

        function getTopValue($image, topProp, step, height, containerHeight) {
            var top;

            if (parseInt($image.css('marginTop')) || parseInt($image.css('marginLeft'))) {
                top = dragFlag ? topProp - step / 4 : 0;
                top = top < containerHeight - height ? containerHeight - height : top;
                top = top > height - containerHeight ? height - containerHeight : top;
            } else {
                top = topProp + step / 2;
                top = top < containerHeight - height ? containerHeight - height : top;
                top = top > 0 ? 0 : top;

                if (!dragFlag && step < 0) {
                    top = top < (containerHeight - height) / 2 ? (containerHeight - height) / 2 : top;
                }
            }

            return top;
        }

        function getLeftValue(leftProp, step, width, containerWidth) {
            var left;

            left = leftProp + step / 2;
            left = left < containerWidth - width ? containerWidth - width : left;
            left = left > 0 ? 0 : left;

            if (!dragFlag && step < 0) {
                left = left < (containerWidth - width) / 2 ? (containerWidth - width) / 2 : left;
            }

            return left;
        }

        function checkFullscreenImagePosition($image, dimentions, widthStep, heightStep) {
            var $imageContainer,
                containerWidth,
                containerHeight,
                settings,
                top,
                left,
                right,
                bottom,
                ratio;

            if ($(gallerySelector).data('fotorama').fullScreen) {
                transitionActive = true;
                $imageContainer = $image.parent();
                containerWidth = $imageContainer.width();
                containerHeight = $imageContainer.height();
                top = $image.position().top;
                left = $image.position().left;
                ratio = $image.width() / $image.height();
                dimentions.height = isNaN(dimentions.height) ? dimentions.width / ratio : dimentions.height;
                dimentions.width = isNaN(dimentions.width) ? dimentions.height * ratio : dimentions.width;

                top = dimentions.height >= containerHeight ?
                    getTopValue($image, top, heightStep, dimentions.height, containerHeight) : 0;

                left = dimentions.width >= containerWidth ?
                    getLeftValue(left, widthStep, dimentions.width, containerWidth) : 0;

                right = dragFlag && left < (containerWidth - dimentions.width) / 2 ? 0 : left;
                bottom = dragFlag ? 0 : top;

                settings = $.extend(dimentions, {
                    top: top,
                    left: left,
                    right: right
                });

                $image.css(settings);
            }
        }

        /**
         * Toggles fotorama's keyboard and mouse/touch navigation.
         */
        function toggleStandartNavigation() {
            var $selectable =
                    $('a[href], area[href], input, select, textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]')
                    .not('[tabindex=-1], [disabled], :hidden'),
                fotorama = $(gallerySelector).data('fotorama'),
                $focus = $(':focus'),
                index;

            if (fotorama.fullScreen) {

                $selectable.each(function (number) {

                    if ($(this).is($focus)) {
                        index = number;
                    }
                });

                fotorama.setOptions({
                    swipe: !allowZoomOut,
                    keyboard: !allowZoomOut
                });

                if (_.isNumber(index)) {
                    $selectable.eq(index).trigger('focus');
                }
            }
        }

        function zoomIn(e, xStep, yStep) {
            var $image,
                imgOriginalSize,
                imageWidth,
                imageHeight,
                zoomWidthStep,
                zoomHeightStep,
                widthResult,
                heightResult,
                ratio,
                dimentions = {};

            if (allowZoomIn && (!transitionEnabled || !transitionActive) && (isTouchEnabled ||
                !$(zoomInButtonSelector).hasClass(zoomInDisabled))) {
                $image = $(fullscreenImageSelector);
                imgOriginalSize = getImageSize($image[0]);
                imageWidth = $image.width();
                imageHeight = $image.height();
                ratio = imageWidth / imageHeight;
                allowZoomOut = true;
                toggleStandartNavigation();

                if (!$image.hasClass(imageZoommable)) {
                    toggleZoomable($image, true);
                }

                e.preventDefault();

                if (imageWidth >= imageHeight) {
                    zoomWidthStep = xStep || Math.ceil(imageWidth * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);
                    widthResult = imageWidth + zoomWidthStep;

                    if (widthResult >= imgOriginalSize.rw) {
                        widthResult = imgOriginalSize.rw;
                        zoomWidthStep = xStep || widthResult - imageWidth;
                        allowZoomIn = false;
                    }
                    heightResult = widthResult / ratio;
                    zoomHeightStep = yStep || heightResult - imageHeight;
                } else {
                    zoomHeightStep = yStep || Math.ceil(imageHeight * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);
                    heightResult = imageHeight + zoomHeightStep;

                    if (heightResult >= imgOriginalSize.rh) {
                        heightResult = imgOriginalSize.rh;
                        zoomHeightStep = yStep || heightResult - imageHeight;
                        allowZoomIn = false;
                    }
                    widthResult = heightResult * ratio;
                    zoomWidthStep = xStep || widthResult - imageWidth;
                }

                if (imageWidth >= imageHeight && imageWidth !== imgOriginalSize.rw) {
                    dimentions = $.extend(dimentions, {
                        width: widthResult,
                        height: 'auto'
                    });
                    checkFullscreenImagePosition($image, dimentions, -zoomWidthStep, -zoomHeightStep);

                } else if (imageWidth < imageHeight && imageHeight !== imgOriginalSize.rh) {
                    dimentions = $.extend(dimentions, {
                        width: 'auto',
                        height: heightResult
                    });
                    checkFullscreenImagePosition($image, dimentions, -zoomWidthStep, -zoomHeightStep);
                }
            }

            return false;
        }

        function zoomOut(e, xStep, yStep) {
            var $image,
                widthResult,
                heightResult,
                dimentions,
                parentWidth,
                parentHeight,
                imageWidth,
                imageHeight,
                zoomWidthStep,
                zoomHeightStep,
                ratio,
                fitIntoParent;

            if (allowZoomOut && (!transitionEnabled || !transitionActive) && (isTouchEnabled ||
                !$(zoomOutButtonSelector).hasClass(zoomOutDisabled))) {
                allowZoomIn = true;
                $image = $(fullscreenImageSelector);
                parentWidth = $image.parent().width();
                parentHeight = $image.parent().height();
                imageWidth = $image.width();
                imageHeight = $image.height();
                ratio = imageWidth / imageHeight;

                e.preventDefault();

                if (imageWidth >= imageHeight) {
                    zoomWidthStep = xStep || Math.ceil(imageWidth * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);
                    widthResult = imageWidth - zoomWidthStep;
                    heightResult = widthResult / ratio;
                    zoomHeightStep = yStep || imageHeight - heightResult;
                } else {
                    zoomHeightStep = yStep || Math.ceil(imageHeight * parseFloat(config.magnifierOpts.fullscreenzoom) / 100);
                    heightResult = imageHeight - zoomHeightStep;
                    widthResult = heightResult * ratio;
                    zoomWidthStep = xStep || imageWidth - widthResult;
                }

                fitIntoParent = function () {
                    if (ratio > parentWidth / parentHeight) {
                        widthResult = parentWidth;
                        zoomWidthStep = imageWidth - widthResult;
                        heightResult = widthResult / ratio;
                        zoomHeightStep = imageHeight - heightResult;
                        dimentions = {
                            width: widthResult,
                            height: 'auto'
                        };
                    } else {
                        heightResult = parentHeight;
                        zoomHeightStep = imageHeight - heightResult;
                        widthResult = heightResult * ratio;
                        zoomWidthStep = imageWidth - widthResult;
                        dimentions = {
                            width: 'auto',
                            height: heightResult
                        };
                    }
                    checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);
                };

                if (imageWidth >= imageHeight) {
                    if (widthResult > parentWidth) {
                        dimentions = {
                            width: widthResult,
                            height: 'auto'
                        };
                        checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);
                    } else if (heightResult > parentHeight) {
                        dimentions = {
                            width: widthResult,
                            height: 'auto'
                        };
                        checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);
                    } else {
                        allowZoomOut = dragFlag = false;
                        toggleStandartNavigation();
                        fitIntoParent();
                    }
                } else if (heightResult > parentHeight) {
                    dimentions = {
                        width: 'auto',
                        height: heightResult
                    };
                    checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);
                } else if (widthResult > parentWidth) {
                    dimentions = {
                        width: 'auto',
                        height: heightResult
                    };
                    checkFullscreenImagePosition($image, dimentions, zoomWidthStep, zoomHeightStep);
                } else {
                    allowZoomOut = dragFlag = false;
                    toggleStandartNavigation();
                    fitIntoParent();
                }
            }

            return false;
        }

        /**
         * Bind event on scroll on active item in fotorama
         * @param e
         * @param fotorama - object of fotorama
         */
        function mousewheel(e, fotorama, element) {
            var $fotoramaStage = fotorama.activeFrame.$stageFrame,
                fotoramaStage = $fotoramaStage.get(0);

            function onWheel(e) {
                var delta = e.deltaY || e.wheelDelta,
                    ev = e || window.event;

                if ($(gallerySelector).data('fotorama').fullScreen) {

                    if (e.deltaY) {
                        if (delta > 0) {
                            zoomOut(ev);
                        } else {
                            zoomIn(ev);
                        }
                    } else if (delta > 0) {
                        zoomIn(ev);
                    } else {
                        zoomOut(ev);
                    }

                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
                }
            }

            if (!$fotoramaStage.hasClass('magnify-wheel-loaded')) {
                if (fotoramaStage && fotoramaStage.addEventListener) {
                    if ('onwheel' in document) {
                        fotoramaStage.addEventListener('wheel', onWheel, { passive: true });
                    } else if ('onmousewheel' in document) {
                        fotoramaStage.addEventListener('mousewheel', onWheel);
                    } else {
                        fotoramaStage.addEventListener('MozMousePixelScroll', onWheel);
                    }
                    $fotoramaStage.addClass('magnify-wheel-loaded');
                }
            }
        }

        /**
         * Method which makes draggable picture. Also work on touch devices.
         */
        function magnifierFullscreen(fotorama) {
            var isDragActive = false,
                startX,
                startY,
                imagePosX,
                imagePosY,
                touch,
                swipeSlide,
                $gallery = $(gallerySelector),
                $image = $(fullscreenImageSelector, $gallery),
                $imageContainer = $('[data-gallery-role="stage-shaft"] [data-active="true"]'),
                gallery = $gallery.data('fotorama'),
                pinchDimention;

            swipeSlide = _.throttle(function (direction) {
                $(gallerySelector).data('fotorama').show(direction);
            }, 500, {
                trailing: false
            });

            /**
             * Returns top position value for passed jQuery object.
             *
             * @param $el
             * @return {number}
             */
            function getTop($el) {
                return parseInt($el.get(0).style.top);
            }

            function shiftImage(dx, dy, e) {
                var top = +imagePosY + dy,
                    left = +imagePosX + dx,
                    swipeCondition = $image.width() / 10 + 20;

                dragFlag = true;

                if ($image.offset().left === $imageContainer.offset().left + $imageContainer.width() - $image.width() && e.keyCode === 39 ||
                    endX - 1 < $imageContainer.offset().left + $imageContainer.width() - $image.width() && dx < 0 &&
                    _.isNumber(endX) &&
                    (e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove')) {
                    endX = null;
                    swipeSlide('>');

                    return;
                }

                if ($image.offset().left === $imageContainer.offset().left && dx !== 0 && e.keyCode === 37 ||
                    endX === $imageContainer.offset().left && dx > 0 &&
                    (e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove')) {
                    endX = null;
                    swipeSlide('<');

                    return;
                }

                if ($image.height() > $imageContainer.height()) {
                    if ($imageContainer.height() > $image.height() + top) {
                        $image.css('top', $imageContainer.height() - $image.height());
                    } else {
                        top = $image.height() - getTop($image) - $imageContainer.height();
                        dy = dy < top ? dy : top;
                        $image.css('top', getTop($image) + dy);
                    }
                }

                if ($image.width() > $imageContainer.width()) {

                    if ($imageContainer.offset().left + $imageContainer.width() > left + $image.width()) {
                        left = $imageContainer.offset().left + $imageContainer.width() - $image.width();
                    } else {
                        left = $imageContainer.offset().left < left ? $imageContainer.offset().left : left;
                    }
                    $image.offset({
                        'left': left
                    });
                    $image.css('right', '');
                } else if (Math.abs(dy) < 1 && allowZoomOut &&
                    !(e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove')) {
                    dx < 0 ? $(gallerySelector).data('fotorama').show('>') : $(gallerySelector).data('fotorama').show('<');
                }

                if ($image.width() <= $imageContainer.width() && allowZoomOut &&
                    (e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'pointermove' || e.type === 'MSPointerMove') &&
                    Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > swipeCondition) {
                    dx < 0 ? swipeSlide('>') : swipeSlide('<');
                }
            }

            /**
             * Sets image size to original or fit in parent block
             * @param e - event object
             */
            function dblClickHandler(e) {
                var imgOriginalSize = getImageSize($image[0]),
                    proportions;

                if (imgOriginalSize.rh < $image.parent().height() && imgOriginalSize.rw < $image.parent().width()) {
                    return;
                }

                proportions = imgOriginalSize.rw / imgOriginalSize.rh;

                if (allowZoomIn) {
                    zoomIn(e, imgOriginalSize.rw - $image.width(), imgOriginalSize.rh - $image.height());
                } else if (proportions > $imageContainer.width() / $imageContainer.height()) {
                    zoomOut(e, imgOriginalSize.rw - $imageContainer.width(), imgOriginalSize.rw / proportions);
                } else {
                    zoomOut(e, imgOriginalSize.rw * proportions, imgOriginalSize.rh - $imageContainer.height());
                }
            }

            function detectDoubleTap(e) {
                var now = new Date().getTime(),
                    timesince = now - tapFlag;

                if (timesince < 400 && timesince > 0) {
                    transitionActive = false;
                    tapFlag = 0;
                    dblClickHandler(e);
                } else {
                    tapFlag = new Date().getTime();
                }
            }

            if (isTouchEnabled) {
                $image.off('tap');
                $image.on('tap', function (e) {
                    if (e.originalEvent.originalEvent.touches.length === 0) {
                        detectDoubleTap(e);
                    }
                });
            } else {
                $image.off('dblclick');
                $image.on('dblclick', dblClickHandler);
            }

            if (gallery.fullScreen) {
                toggleZoomButtons($image, isTouchEnabled, checkForVideo(fotorama.activeFrame.$stageFrame));
            }

            function getDimention(event) {
                return Math.sqrt(
                    (event.touches[0].clientX - event.touches[1].clientX) * (event.touches[0].clientX - event.touches[1].clientX) +
                    (event.touches[0].clientY - event.touches[1].clientY) * (event.touches[0].clientY - event.touches[1].clientY));
            }

            $image.off(isTouchEnabled ? 'touchstart' : 'pointerdown mousedown MSPointerDown');
            $image.on(isTouchEnabled ? 'touchstart' : 'pointerdown mousedown MSPointerDown', function (e) {
                if (e && e.originalEvent.touches && e.originalEvent.touches.length >= 2) {
                    e.preventDefault();
                    pinchDimention = getDimention(e.originalEvent);
                    isDragActive = false;

                    if ($image.hasClass(imageDraggableClass)) {
                        $image.removeClass(imageDraggableClass);
                    }
                } else if (gallery.fullScreen && (!transitionEnabled || !transitionActive)) {
                    imagePosY = getTop($image);
                    imagePosX = $image.offset().left;

                    if (isTouchEnabled) {
                        touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
                        e.clientX = touch.pageX;
                        e.clientY = touch.pageY;
                    }
                    startX = e.clientX || e.originalEvent.clientX;
                    startY = e.clientY || e.originalEvent.clientY;
                    isDragActive = true;
                }

                if ($image.offset() && $image.width() > $imageContainer.width()) {
                    endX = $image.offset().left;
                }
            });

            $image.off(isTouchEnabled ? 'touchmove' : 'mousemove pointermove MSPointerMove');
            $image.on(isTouchEnabled ? 'touchmove' : 'mousemove pointermove MSPointerMove', function (e) {
                if (e && e.originalEvent.touches && e.originalEvent.touches.length >= 2) {
                    e.preventDefault();
                    var currentDimention = getDimention(e.originalEvent);

                    if ($image.hasClass(imageDraggableClass)) {
                        $image.removeClass(imageDraggableClass);
                    }

                    if (currentDimention < pinchDimention) {
                        zoomOut(e);
                        pinchDimention = currentDimention;
                    } else if (currentDimention > pinchDimention) {
                        zoomIn(e);
                        pinchDimention = currentDimention;
                    }
                } else {
                    var clientX,
                        clientY;

                    if (gallery.fullScreen && isDragActive && (!transitionEnabled || !transitionActive)) {

                        if (allowZoomOut && !$image.hasClass(imageDraggableClass)) {
                            $image.addClass(imageDraggableClass);
                        }
                        clientX = e.clientX || e.originalEvent.clientX;
                        clientY = e.clientY || e.originalEvent.clientY;

                        e.preventDefault();

                        if (isTouchEnabled) {
                            touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
                            clientX = touch.pageX;
                            clientY = touch.pageY;
                        }

                        if (allowZoomOut) {
                            imagePosY = getTop($(fullscreenImageSelector, $gallery));
                            shiftImage(clientX - startX, clientY - startY, e);
                        }
                    }
                }
            });

            $image.off('transitionend webkitTransitionEnd mozTransitionEnd msTransitionEnd ');
            $image.on('transitionend webkitTransitionEnd mozTransitionEnd msTransitionEnd', function () {
                transitionActive = false;
            });

            if (keyboardNavigation) {
                $(document).off('keydown', keyboardNavigation);
            }

            /**
             * Replaces original navigations with better one
             * @param e - event object
             */
            keyboardNavigation = function (e) {
                var step = 40,
                    $focus = $(':focus'),
                    isFullScreen = $(gallerySelector).data('fotorama').fullScreen,
                    initVars = function () {
                        imagePosX = $(fullscreenImageSelector, $gallery).offset().left;
                        imagePosY = getTop($(fullscreenImageSelector, $gallery));
                    };

                if (($focus.attr('data-gallery-role') || !$focus.length) && allowZoomOut) {
                    if (isFullScreen) {
                        imagePosX = $(fullscreenImageSelector, $(gallerySelector)).offset().left;
                        imagePosY = getTop($(fullscreenImageSelector, $(gallerySelector)));
                    }

                    if (e.keyCode === 39) {

                        if (isFullScreen) {
                            initVars();
                            shiftImage(-step, 0, e);
                        }
                    }

                    if (e.keyCode === 38) {

                        if (isFullScreen) {
                            initVars();
                            shiftImage(0, step, e);
                        }
                    }

                    if (e.keyCode === 37) {

                        if (isFullScreen) {
                            initVars();
                            shiftImage(step, 0, e);
                        }
                    }

                    if (e.keyCode === 40) {

                        if (isFullScreen) {
                            e.preventDefault();
                            initVars();
                            shiftImage(0, -step, e);
                        }
                    }
                }

                if (e.keyCode === 27 && isFullScreen && allowZoomOut) {
                    $(gallerySelector).data('fotorama').cancelFullScreen();
                }
            };

            /**
             * @todo keyboard navigation through Fotorama Api.
             */
            $(document).on('keydown', keyboardNavigation);

            $(document).on(isTouchEnabled ? 'touchend' : 'mouseup pointerup MSPointerUp', function (e) {
                if (gallery.fullScreen) {

                    if ($image.offset() && $image.width() > $imageContainer.width()) {
                        endX = $image.offset().left;
                    }

                    isDragActive = false;
                    $image.removeClass(imageDraggableClass);
                }
            });

            $(window).off('resize', resizeHandler);
            $(window).on('resize', {
                $image: $image,
                fotorama: fotorama
            }, resizeHandler);
        }

        /**
         * Hides magnifier preview and zoom blocks.
         */
        hideMagnifier = function () {
            $(magnifierSelector).empty().hide();
            $(magnifierZoomSelector).remove();
        };

        /**
         * Check is active frame in gallery include video content.
         * If true activeFrame contain video.
         * @param $stageFrame - active frame in gallery
         * @returns {*|Boolean}
         */
        function checkForVideo($stageFrame) {
            return $stageFrame.hasClass(videoContainerClass);
        }

        /**
         * Hides magnifier on drag and while arrow click.
         */
        function behaveOnDrag(e, initPos) {
            var pos = [e.pageX, e.pageY],
                isArrow = $(e.target).data('gallery-role') === 'arrow',
                isClick = initPos[0] === pos[0] && initPos[1] === pos[1],
                isImg = $(e.target).parent().data('active');

            if (isArrow || isImg && !isClick) {
                hideMagnifier();
            }
        }

        if (config.magnifierOpts.enabled) {
            $(element).on('pointerdown mousedown MSPointerDown', function (e) {
                var pos = [e.pageX, e.pageY];

                $(element).on('mousemove pointermove MSPointerMove', function (ev) {
                    navigator.msPointerEnabled ? hideMagnifier() : behaveOnDrag(ev, pos);
                });
                $(document).on('mouseup pointerup MSPointerUp', function () {
                    $(element).off('mousemove pointermove MSPointerMove');
                });
            });
        }

        $.extend(config.magnifierOpts, {
            zoomable: false,
            thumb: '.fotorama__img',
            largeWrapper: '[data-gallery-role="magnifier"]',
            height: config.magnifierOpts.height || function () {
                return $('[data-active="true"]').height();
            },
            width: config.magnifierOpts.width || function () {
                var productMedia = $(gallerySelector).parent().parent();

                return productMedia.parent().width() - productMedia.width() - 20;
            },
            left: config.magnifierOpts.left || function () {
                return $(gallerySelector).offset().left + $(gallerySelector).width() + 20;
            },
            top: config.magnifierOpts.top || function () {
                return $(gallerySelector).offset().top;
            }
        });

        $(element).on('fotorama:load fotorama:showend fotorama:fullscreenexit fotorama:ready', function (e, fotorama) {
            var $activeStageFrame = $(gallerySelector).data('fotorama').activeFrame.$stageFrame;

            if (!$activeStageFrame.find(magnifierZoomSelector).length) {
                hideMagnifier();

                if (config.magnifierOpts) {
                    config.magnifierOpts.large = $(gallerySelector).data('fotorama').activeFrame.img;
                    config.magnifierOpts.full = fotorama.data[fotorama.activeIndex].original;
                    !checkForVideo($activeStageFrame) && $($activeStageFrame).magnify(config.magnifierOpts);
                }
            }
        });

        $(element).on('gallery:loaded', function (e) {
            var $prevImage;

            $(element).find(gallerySelector)
                .on('fotorama:ready', function (e, fotorama) {
                    var $zoomIn = $(zoomInButtonSelector),
                        $zoomOut = $(zoomOutButtonSelector);

                    if (!$zoomIn.hasClass(zoomInLoaded)) {
                        $zoomIn.on('click touchstart', zoomIn);
                        $zoomIn.on('mousedown', function (e) {
                            e.stopPropagation();
                        });

                        $zoomIn.on('keyup', function (e) {

                            if (e.keyCode === 13) {
                                zoomIn(e);
                            }
                        });

                        $(window).on('keyup', function (e) {

                            if (e.keyCode === 107 || fotorama.fullscreen) {
                                zoomIn(e);
                            }
                        });

                        $zoomIn.addClass(zoomInLoaded);
                    }

                    if (!$zoomOut.hasClass(zoomOutLoaded)) {
                        $zoomOut.on('click touchstart', zoomOut);
                        $zoomOut.on('mousedown', function (e) {
                            e.stopPropagation();
                        });

                        $zoomOut.on('keyup', function (e) {

                            if (e.keyCode === 13) {
                                zoomOut(e);
                            }
                        });

                        $(window).on('keyup', function (e) {

                            if (e.keyCode === 109 || fotorama.fullscreen) {
                                zoomOut(e);
                            }
                        });

                        $zoomOut.addClass(zoomOutLoaded);
                    }
                })
                .on('fotorama:fullscreenenter fotorama:showend', function (e, fotorama) {
                    hideMagnifier();

                    if (!$(fullscreenImageSelector).is($prevImage)) {
                        resetVars($(fullscreenImageSelector));
                    }
                    magnifierFullscreen(fotorama);
                    mousewheel(e, fotorama, element);

                    if ($prevImage) {
                        calculateMinSize($prevImage);

                        if (!$(fullscreenImageSelector).is($prevImage)) {
                            resetVars($prevImage);
                        }
                    }

                    toggleStandartNavigation();
                })
                .on('fotorama:load', function (e, fotorama) {
                    if ($(gallerySelector).data('fotorama').fullScreen) {
                        toggleZoomButtons($(fullscreenImageSelector), isTouchEnabled,
                            checkForVideo(fotorama.activeFrame.$stageFrame));
                    }
                    magnifierFullscreen(fotorama);
                })
                .on('fotorama:show', function (e, fotorama) {
                    $prevImage = _.clone($(fullscreenImageSelector));
                    hideMagnifier();
                })
                .on('fotorama:fullscreenexit', function (e, fotorama) {
                    resetVars($(fullscreenImageSelector));
                    hideMagnifier();
                    hideZoomControls(true);
                });
        });

        return config;
    };
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define('Magento_Catalog/js/product/view/provider',[
    'underscore',
    'uiElement',
    'Magento_Catalog/js/product/storage/storage-service'
], function (_, Element, storage) {
    'use strict';

    return Element.extend({
        defaults: {
            identifiersConfig: {
                namespace: 'recently_viewed_product'
            },
            productStorageConfig: {
                namespace: 'product_data_storage',
                updateRequestConfig: {
                    method: 'GET',
                    dataType: 'json'
                },
                className: 'DataStorage'
            }
        },

        /**
         * Initializes
         *
         * @returns {Object} Chainable.
         */
        initialize: function () {
            this._super();

            if (window.checkout && window.checkout.baseUrl) {
                this.initIdsStorage();
            }

            this.initDataStorage();

            return this;
        },

        /**
         * Init ids storage
         *
         * @returns {Object} Chainable.
         */
        initIdsStorage: function () {
            storage.onStorageInit(this.identifiersConfig.namespace, this.idsStorageHandler.bind(this));

            return this;
        },

        /**
         * Init data storage
         *
         * @returns {Object} Chainable.
         */
        initDataStorage: function () {
            storage.onStorageInit(this.productStorageConfig.namespace, this.dataStorageHandler.bind(this));

            return this;
        },

        /**
         * Init data storage handler
         *
         * @param {Object} dataStorage - storage instance
         */
        dataStorageHandler: function (dataStorage) {
            this.productStorage = dataStorage;
            this.productStorage.add(this.data.items);
        },

        /**
         * Init ids storage handler
         *
         * @param {Object} idsStorage - storage instance
         */
        idsStorageHandler: function (idsStorage) {
            this.idsStorage = idsStorage;
            this.idsStorage.add(this.getIdentifiers());
        },

        /**
         * Gets ids from items
         *
         * @returns {Object}
         */
        getIdentifiers: function () {
            var result = {},
                productCurrentScope = this.data.productCurrentScope,
                scopeId = productCurrentScope === 'store' ? window.checkout.storeId :
                    productCurrentScope === 'group' ? window.checkout.storeGroupId :
                        window.checkout.websiteId;

            _.each(this.data.items, function (item, key) {
                result[productCurrentScope + '-' + scopeId + '-' + key] = {
                    'added_at': new Date().getTime() / 1000,
                    'product_id': key,
                    'scope_id': scopeId
                };
            }, this);

            return result;
        }
    });
});

define('Amasty_GdprFrontendUi/js/action/cookie-decliner',[
    'jquery',
    'Amasty_GdprFrontendUi/js/action/cookie-setter',
    'jquery/jquery-storageapi'
], function ($, cookieSetter) {
    'use strict';

    return function (_super) {
        $.cookieStorage.set = cookieSetter($.cookieStorage.set, $.cookieStorage);

        return _super.call(this);
    };
});

define('Amasty_GdprFrontendUi/js/mixins/disposable-customer-data-mixin',[
    'jquery',
    'Amasty_GdprFrontendUi/js/action/cookie-decliner'
], function ($, cookieDecliner) {
    'use strict';

    var mixin = {
        initialize: function () {
            return cookieDecliner.call(this, this._super);
        }
    };

    return function (target) {
        return target.extend(mixin);
    };
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Review/js/validate-review',[
    'jquery',
    'jquery/validate',
    'mage/translate'
], function ($) {
    'use strict';

    $.validator.addMethod(
        'rating-required', function (value) {
            return value !== undefined;
        }, $.mage.__('Please select one of each of the ratings above.'));
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
require([
    'jquery'
], function ($) {
    'use strict';

    /**
     * Add selected swatch attributes to redirect url
     *
     * @see Magento_Catalog/js/catalog-add-to-cart
     */
    $('body').on('catalogCategoryAddToCartRedirect', function (event, data) {
        $(data.form).find('[name*="super"]').each(function (index, item) {
            var $item = $(item),
                attr;

            if ($item.attr('data-attr-name')) {
                attr = $item.attr('data-attr-name');
            } else {
                attr = $item.parent().attr('attribute-code');
            }
            data.redirectParameters.push(attr + '=' + $item.val());

        });
    });
});

define("Magento_Swatches/js/catalog-add-to-cart", function(){});

/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

define('Magento_Customer/js/view/customer',[
    'uiComponent',
    'Magento_Customer/js/customer-data'
], function (Component, customerData) {
    'use strict';

    return Component.extend({
        /** @inheritdoc */
        initialize: function () {
            this._super();

            this.customer = customerData.get('customer');
        }
    });
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Review/js/view/review',[
    'uiComponent',
    'Magento_Customer/js/customer-data',
    'Magento_Customer/js/view/customer'
], function (Component, customerData) {
    'use strict';

    return Component.extend({
        /** @inheritdoc */
        initialize: function () {
            this._super();

            this.review = customerData.get('review').extend({
                disposableCustomerData: 'review'
            });
        },

        /**
         * @return {*}
         */
        nickname: function () {
            return this.review().nickname || customerData.get('customer')().firstname;
        }
    });
});

/*!
 * Fotorama 4.6.4 | http://fotorama.io/license/
 */
define('fotorama/fotorama',['jquery'], function($) {
    "use strict";

    return {
        initialize: function () {
            var fotoramaVersion = '4.6.4';
            var _fotoramaClass = 'fotorama',
                _fullscreenClass = 'fotorama__fullscreen',

                wrapClass = _fotoramaClass + '__wrap',
                wrapCss2Class = wrapClass + '--css2',
                wrapCss3Class = wrapClass + '--css3',
                wrapVideoClass = wrapClass + '--video',
                wrapFadeClass = wrapClass + '--fade',
                wrapSlideClass = wrapClass + '--slide',
                wrapNoControlsClass = wrapClass + '--no-controls',
                wrapNoShadowsClass = wrapClass + '--no-shadows',
                wrapPanYClass = wrapClass + '--pan-y',
                wrapRtlClass = wrapClass + '--rtl',
                wrapOnlyActiveClass = wrapClass + '--only-active',
                wrapNoCaptionsClass = wrapClass + '--no-captions',
                wrapToggleArrowsClass = wrapClass + '--toggle-arrows',

                stageClass = _fotoramaClass + '__stage',
                stageFrameClass = stageClass + '__frame',
                stageFrameVideoClass = stageFrameClass + '--video',
                stageShaftClass = stageClass + '__shaft',

                grabClass = _fotoramaClass + '__grab',
                pointerClass = _fotoramaClass + '__pointer',

                arrClass = _fotoramaClass + '__arr',
                arrDisabledClass = arrClass + '--disabled',
                arrPrevClass = arrClass + '--prev',
                arrNextClass = arrClass + '--next',

                navClass = _fotoramaClass + '__nav',
                navWrapClass = navClass + '-wrap',
                navShaftClass = navClass + '__shaft',
                navShaftVerticalClass = navWrapClass + '--vertical',
                navShaftListClass = navWrapClass + '--list',
                navShafthorizontalClass = navWrapClass + '--horizontal',
                navDotsClass = navClass + '--dots',
                navThumbsClass = navClass + '--thumbs',
                navFrameClass = navClass + '__frame',

                fadeClass = _fotoramaClass + '__fade',
                fadeFrontClass = fadeClass + '-front',
                fadeRearClass = fadeClass + '-rear',

                shadowClass = _fotoramaClass + '__shadow',
                shadowsClass = shadowClass + 's',
                shadowsLeftClass = shadowsClass + '--left',
                shadowsRightClass = shadowsClass + '--right',
                shadowsTopClass = shadowsClass + '--top',
                shadowsBottomClass = shadowsClass + '--bottom',

                activeClass = _fotoramaClass + '__active',
                selectClass = _fotoramaClass + '__select',

                hiddenClass = _fotoramaClass + '--hidden',

                fullscreenClass = _fotoramaClass + '--fullscreen',
                fullscreenIconClass = _fotoramaClass + '__fullscreen-icon',

                errorClass = _fotoramaClass + '__error',
                loadingClass = _fotoramaClass + '__loading',
                loadedClass = _fotoramaClass + '__loaded',
                loadedFullClass = loadedClass + '--full',
                loadedImgClass = loadedClass + '--img',

                grabbingClass = _fotoramaClass + '__grabbing',

                imgClass = _fotoramaClass + '__img',
                imgFullClass = imgClass + '--full',

                thumbClass = _fotoramaClass + '__thumb',
                thumbArrLeft = thumbClass + '__arr--left',
                thumbArrRight = thumbClass + '__arr--right',
                thumbBorderClass = thumbClass + '-border',

                htmlClass = _fotoramaClass + '__html',

                videoContainerClass = _fotoramaClass + '-video-container',
                videoClass = _fotoramaClass + '__video',
                videoPlayClass = videoClass + '-play',
                videoCloseClass = videoClass + '-close',


                horizontalImageClass = _fotoramaClass + '_horizontal_ratio',
                verticalImageClass = _fotoramaClass + '_vertical_ratio',
                fotoramaSpinnerClass = _fotoramaClass + '__spinner',
                spinnerShowClass = fotoramaSpinnerClass + '--show';
            var JQUERY_VERSION = $ && $.fn.jquery.split('.');

            if (!JQUERY_VERSION
                || JQUERY_VERSION[0] < 1
                || (JQUERY_VERSION[0] == 1 && JQUERY_VERSION[1] < 8)) {
                throw 'Fotorama requires jQuery 1.8 or later and will not run without it.';
            }

            var _ = {};
            /* Modernizr 2.8.3 (Custom Build) | MIT & BSD
             * Build: http://modernizr.com/download/#-csstransforms3d-csstransitions-touch-prefixed
             */

            var Modernizr = (function (window, document, undefined) {
                var version = '2.8.3',
                    Modernizr = {},


                    docElement = document.documentElement,

                    mod = 'modernizr',
                    modElem = document.createElement(mod),
                    mStyle = modElem.style,
                    inputElem,


                    toString = {}.toString,

                    prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),


                    omPrefixes = 'Webkit Moz O ms',

                    cssomPrefixes = omPrefixes.split(' '),

                    domPrefixes = omPrefixes.toLowerCase().split(' '),


                    tests = {},
                    inputs = {},
                    attrs = {},

                    classes = [],

                    slice = classes.slice,

                    featureName,


                    injectElementWithStyles = function (rule, callback, nodes, testnames) {

                        var style, ret, node, docOverflow,
                            div = document.createElement('div'),
                            body = document.body,
                            fakeBody = body || document.createElement('body');

                        if (parseInt(nodes, 10)) {
                            while (nodes--) {
                                node = document.createElement('div');
                                node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
                                div.appendChild(node);
                            }
                        }

                        style = ['&#173;', '<style id="s', mod, '">', rule, '</style>'].join('');
                        div.id = mod;
                        (body ? div : fakeBody).innerHTML += style;
                        fakeBody.appendChild(div);
                        if (!body) {
                            fakeBody.style.background = '';
                            fakeBody.style.overflow = 'hidden';
                            docOverflow = docElement.style.overflow;
                            docElement.style.overflow = 'hidden';
                            docElement.appendChild(fakeBody);
                        }

                        ret = callback(div, rule);
                        if (!body) {
                            fakeBody.parentNode.removeChild(fakeBody);
                            docElement.style.overflow = docOverflow;
                        } else {
                            div.parentNode.removeChild(div);
                        }

                        return !!ret;

                    },
                    _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;

                if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {
                    hasOwnProp = function (object, property) {
                        return _hasOwnProperty.call(object, property);
                    };
                }
                else {
                    hasOwnProp = function (object, property) {
                        return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
                    };
                }


                if (!Function.prototype.bind) {
                    Function.prototype.bind = function bind(that) {

                        var target = this;

                        if (typeof target != "function") {
                            throw new TypeError();
                        }

                        var args = slice.call(arguments, 1),
                            bound = function () {

                                if (this instanceof bound) {

                                    var F = function () {
                                    };
                                    F.prototype = target.prototype;
                                    var self = new F();

                                    var result = target.apply(
                                        self,
                                        args.concat(slice.call(arguments))
                                    );
                                    if (Object(result) === result) {
                                        return result;
                                    }
                                    return self;

                                } else {

                                    return target.apply(
                                        that,
                                        args.concat(slice.call(arguments))
                                    );

                                }

                            };

                        return bound;
                    };
                }

                function setCss(str) {
                    mStyle.cssText = str;
                }

                function setCssAll(str1, str2) {
                    return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
                }

                function is(obj, type) {
                    return typeof obj === type;
                }

                function contains(str, substr) {
                    return !!~('' + str).indexOf(substr);
                }

                function testProps(props, prefixed) {
                    for (var i in props) {
                        var prop = props[i];
                        if (!contains(prop, "-") && mStyle[prop] !== undefined) {
                            return prefixed == 'pfx' ? prop : true;
                        }
                    }
                    return false;
                }

                function testDOMProps(props, obj, elem) {
                    for (var i in props) {
                        var item = obj[props[i]];
                        if (item !== undefined) {

                            if (elem === false) return props[i];

                            if (is(item, 'function')) {
                                return item.bind(elem || obj);
                            }

                            return item;
                        }
                    }
                    return false;
                }

                function testPropsAll(prop, prefixed, elem) {

                    var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
                        props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');

                    if (is(prefixed, "string") || is(prefixed, "undefined")) {
                        return testProps(props, prefixed);

                    } else {
                        props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
                        return testDOMProps(props, prefixed, elem);
                    }
                }

                tests['touch'] = function () {
                    var bool;

                    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
                        bool = true;
                    } else {
                        injectElementWithStyles(['@media (', prefixes.join('touch-enabled),('), mod, ')', '{#modernizr{top:9px;position:absolute}}'].join(''), function (node) {
                            bool = node.offsetTop === 9;
                        });
                    }

                    return bool;
                };
                tests['csstransforms3d'] = function () {

                    var ret = !!testPropsAll('perspective');

                    if (ret && 'webkitPerspective' in docElement.style) {

                        injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function (node, rule) {
                            ret = node.offsetLeft === 9 && node.offsetHeight === 3;
                        });
                    }
                    return ret;
                };


                tests['csstransitions'] = function () {
                    return testPropsAll('transition');
                };


                for (var feature in tests) {
                    if (hasOwnProp(tests, feature)) {
                        featureName = feature.toLowerCase();
                        Modernizr[featureName] = tests[feature]();

                        classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
                    }
                }


                Modernizr.addTest = function (feature, test) {
                    if (typeof feature == 'object') {
                        for (var key in feature) {
                            if (hasOwnProp(feature, key)) {
                                Modernizr.addTest(key, feature[key]);
                            }
                        }
                    } else {

                        feature = feature.toLowerCase();

                        if (Modernizr[feature] !== undefined) {
                            return Modernizr;
                        }

                        test = typeof test == 'function' ? test() : test;

                        if (typeof enableClasses !== "undefined" && enableClasses) {
                            docElement.className += ' ' + (test ? '' : 'no-') + feature;
                        }
                        Modernizr[feature] = test;

                    }

                    return Modernizr;
                };


                setCss('');
                modElem = inputElem = null;


                Modernizr._version = version;

                Modernizr._prefixes = prefixes;
                Modernizr._domPrefixes = domPrefixes;
                Modernizr._cssomPrefixes = cssomPrefixes;


                Modernizr.testProp = function (prop) {
                    return testProps([prop]);
                };

                Modernizr.testAllProps = testPropsAll;
                Modernizr.testStyles = injectElementWithStyles;
                Modernizr.prefixed = function (prop, obj, elem) {
                    if (!obj) {
                        return testPropsAll(prop, 'pfx');
                    } else {
                        return testPropsAll(prop, obj, elem);
                    }
                };
                return Modernizr;
            })(window, document);

            var fullScreenApi = {
                    ok: false,
                    is: function () {
                        return false;
                    },
                    request: function () {
                    },
                    cancel: function () {
                    },
                    event: '',
                    prefix: ''
                },
                browserPrefixes = 'webkit moz o ms khtml'.split(' ');

// check for native support
            if (typeof document.cancelFullScreen != 'undefined') {
                fullScreenApi.ok = true;
            } else {
                // check for fullscreen support by vendor prefix
                for (var i = 0, il = browserPrefixes.length; i < il; i++) {
                    fullScreenApi.prefix = browserPrefixes[i];
                    if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
                        fullScreenApi.ok = true;
                        break;
                    }
                }
            }

// update methods to do something useful
            if (fullScreenApi.ok) {
                fullScreenApi.event = fullScreenApi.prefix + 'fullscreenchange';
                fullScreenApi.is = function () {
                    switch (this.prefix) {
                        case '':
                            return document.fullScreen;
                        case 'webkit':
                            return document.webkitIsFullScreen;
                        default:
                            return document[this.prefix + 'FullScreen'];
                    }
                };
                fullScreenApi.request = function (el) {
                    return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
                };
                fullScreenApi.cancel = function (el) {
                    if (!this.is()) {
                        return false;
                    }
                    return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
                };
            }
            /* Bez v1.0.10-g5ae0136
     * http://github.com/rdallasgray/bez
     *
     * A plugin to convert CSS3 cubic-bezier co-ordinates to jQuery-compatible easing functions
     *
     * With thanks to Nikolay Nemshilov for clarification on the cubic-bezier maths
     * See http://st-on-it.blogspot.com/2011/05/calculating-cubic-bezier-function.html
     *
     * Copyright 2011 Robert Dallas Gray. All rights reserved.
     * Provided under the FreeBSD license: https://github.com/rdallasgray/bez/blob/master/LICENSE.txt
     */
            function bez(coOrdArray) {
                var encodedFuncName = "bez_" + $.makeArray(arguments).join("_").replace(".", "p");
                if (typeof $['easing'][encodedFuncName] !== "function") {
                    var polyBez = function (p1, p2) {
                        var A = [null, null],
                            B = [null, null],
                            C = [null, null],
                            bezCoOrd = function (t, ax) {
                                C[ax] = 3 * p1[ax];
                                B[ax] = 3 * (p2[ax] - p1[ax]) - C[ax];
                                A[ax] = 1 - C[ax] - B[ax];
                                return t * (C[ax] + t * (B[ax] + t * A[ax]));
                            },
                            xDeriv = function (t) {
                                return C[0] + t * (2 * B[0] + 3 * A[0] * t);
                            },
                            xForT = function (t) {
                                var x = t, i = 0, z;
                                while (++i < 14) {
                                    z = bezCoOrd(x, 0) - t;
                                    if (Math.abs(z) < 1e-3) break;
                                    x -= z / xDeriv(x);
                                }
                                return x;
                            };
                        return function (t) {
                            return bezCoOrd(xForT(t), 1);
                        }
                    };
                    $['easing'][encodedFuncName] = function (x, t, b, c, d) {
                        return c * polyBez([coOrdArray[0], coOrdArray[1]], [coOrdArray[2], coOrdArray[3]])(t / d) + b;
                    }
                }
                return encodedFuncName;
            }

            var $WINDOW = $(window),
                $DOCUMENT = $(document),
                $HTML,
                $BODY,

                QUIRKS_FORCE = location.hash.replace('#', '') === 'quirks',
                TRANSFORMS3D = Modernizr.csstransforms3d,
                CSS3 = TRANSFORMS3D && !QUIRKS_FORCE,
                COMPAT = TRANSFORMS3D || document.compatMode === 'CSS1Compat',
                FULLSCREEN = fullScreenApi.ok,

                MOBILE = navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i),
                SLOW = !CSS3 || MOBILE,

                MS_POINTER = navigator.msPointerEnabled,

                WHEEL = "onwheel" in document.createElement("div") ? "wheel" : document.onmousewheel !== undefined ? "mousewheel" : "DOMMouseScroll",

                TOUCH_TIMEOUT = 250,
                TRANSITION_DURATION = 300,

                SCROLL_LOCK_TIMEOUT = 1400,

                AUTOPLAY_INTERVAL = 5000,
                MARGIN = 2,
                THUMB_SIZE = 64,

                WIDTH = 500,
                HEIGHT = 333,

                STAGE_FRAME_KEY = '$stageFrame',
                NAV_DOT_FRAME_KEY = '$navDotFrame',
                NAV_THUMB_FRAME_KEY = '$navThumbFrame',

                AUTO = 'auto',

                BEZIER = bez([.1, 0, .25, 1]),

                MAX_WIDTH = 1200,

                /**
                 * Number of thumbnails in slide. Calculated only on setOptions and resize.
                 * @type {number}
                 */
                thumbsPerSlide = 1,

                OPTIONS = {

                    /**
                     * Set width for gallery.
                     * Default value - width of first image
                     * Number - set value in px
                     * String - set value in quotes
                     *
                     */
                    width: null,

                    /**
                     * Set min-width for gallery
                     *
                     */
                    minwidth: null,

                    /**
                     * Set max-width for gallery
                     *
                     */
                    maxwidth: '100%',

                    /**
                     * Set height for gallery
                     * Default value - height of first image
                     * Number - set value in px
                     * String - set value in quotes
                     *
                     */
                    height: null,

                    /**
                     * Set min-height for gallery
                     *
                     */
                    minheight: null,

                    /**
                     * Set max-height for gallery
                     *
                     */
                    maxheight: null,

                    /**
                     * Set proportion ratio for gallery depends of image
                     *
                     */
                    ratio: null, // '16/9' || 500/333 || 1.5

                    margin: MARGIN,

                    nav: 'dots', // 'thumbs' || false
                    navposition: 'bottom', // 'top'
                    navwidth: null,
                    thumbwidth: THUMB_SIZE,
                    thumbheight: THUMB_SIZE,
                    thumbmargin: MARGIN,
                    thumbborderwidth: MARGIN,

                    allowfullscreen: false, // true || 'native'

                    transition: 'slide', // 'crossfade' || 'dissolve'
                    clicktransition: null,
                    transitionduration: TRANSITION_DURATION,

                    captions: true,

                    startindex: 0,

                    loop: false,

                    autoplay: false,
                    stopautoplayontouch: true,

                    keyboard: false,

                    arrows: true,
                    click: true,
                    swipe: false,
                    trackpad: false,

                    shuffle: false,

                    direction: 'ltr', // 'rtl'

                    shadows: true,

                    showcaption: true,

                    /**
                     * Set type of thumbnail navigation
                     */
                    navdir: 'horizontal',

                    /**
                     * Set configuration to show or hide arrows in thumb navigation
                     */
                    navarrows: true,

                    /**
                     * Set type of navigation. Can be thumbs or slides
                     */
                    navtype: 'thumbs'

                },

                KEYBOARD_OPTIONS = {
                    left: true,
                    right: true,
                    down: true,
                    up: true,
                    space: false,
                    home: false,
                    end: false
                };

            function noop() {
            }

            function minMaxLimit(value, min, max) {
                return Math.max(isNaN(min) ? -Infinity : min, Math.min(isNaN(max) ? Infinity : max, value));
            }

            function readTransform(css, dir) {
                return css.match(/ma/) && css.match(/-?\d+(?!d)/g)[css.match(/3d/) ?
                    (dir === 'vertical' ? 13 : 12) : (dir === 'vertical' ? 5 : 4)
                    ]
            }

            function readPosition($el, dir) {
                if (CSS3) {
                    return +readTransform($el.css('transform'), dir);
                } else {
                    return +$el.css(dir === 'vertical' ? 'top' : 'left').replace('px', '');
                }
            }

            function getTranslate(pos, direction) {
                var obj = {};

                if (CSS3) {

                    switch (direction) {
                        case 'vertical':
                            obj.transform = 'translate3d(0, ' + (pos) + 'px,0)';
                            break;
                        case 'list':
                            break;
                        default :
                            obj.transform = 'translate3d(' + (pos) + 'px,0,0)';
                            break;
                    }
                } else {
                    direction === 'vertical' ?
                        obj.top = pos :
                        obj.left = pos;
                }
                return obj;
            }

            function getDuration(time) {
                return {'transition-duration': time + 'ms'};
            }

            function unlessNaN(value, alternative) {
                return isNaN(value) ? alternative : value;
            }

            function numberFromMeasure(value, measure) {
                return unlessNaN(+String(value).replace(measure || 'px', ''));
            }

            function numberFromPercent(value) {
                return /%$/.test(value) ? numberFromMeasure(value, '%') : undefined;
            }

            function numberFromWhatever(value, whole) {
                return unlessNaN(numberFromPercent(value) / 100 * whole, numberFromMeasure(value));
            }

            function measureIsValid(value) {
                return (!isNaN(numberFromMeasure(value)) || !isNaN(numberFromMeasure(value, '%'))) && value;
            }

            function getPosByIndex(index, side, margin, baseIndex) {

                return (index - (baseIndex || 0)) * (side + (margin || 0));
            }

            function getIndexByPos(pos, side, margin, baseIndex) {
                return -Math.round(pos / (side + (margin || 0)) - (baseIndex || 0));
            }

            function bindTransitionEnd($el) {
                var elData = $el.data();

                if (elData.tEnd) return;

                var el = $el[0],
                    transitionEndEvent = {
                        WebkitTransition: 'webkitTransitionEnd',
                        MozTransition: 'transitionend',
                        OTransition: 'oTransitionEnd otransitionend',
                        msTransition: 'MSTransitionEnd',
                        transition: 'transitionend'
                    };
                addEvent(el, transitionEndEvent[Modernizr.prefixed('transition')], function (e) {
                    elData.tProp && e.propertyName.match(elData.tProp) && elData.onEndFn();
                });
                elData.tEnd = true;
            }

            function afterTransition($el, property, fn, time) {
                var ok,
                    elData = $el.data();

                if (elData) {
                    elData.onEndFn = function () {
                        if (ok) return;
                        ok = true;
                        clearTimeout(elData.tT);
                        fn();
                    };
                    elData.tProp = property;

                    // Passive call, just in case of fail of native transition-end event
                    clearTimeout(elData.tT);
                    elData.tT = setTimeout(function () {
                        elData.onEndFn();
                    }, time * 1.5);

                    bindTransitionEnd($el);
                }
            }


            function stop($el, pos/*, _001*/) {
                var dir = $el.navdir || 'horizontal';
                if ($el.length) {
                    var elData = $el.data();
                    if (CSS3) {
                        $el.css(getDuration(0));
                        elData.onEndFn = noop;
                        clearTimeout(elData.tT);
                    } else {
                        $el.stop();
                    }
                    var lockedPos = getNumber(pos, function () {
                        return readPosition($el, dir);
                    });

                    $el.css(getTranslate(lockedPos, dir/*, _001*/));//.width(); // `.width()` for reflow
                    return lockedPos;
                }
            }

            function getNumber() {
                var number;
                for (var _i = 0, _l = arguments.length; _i < _l; _i++) {
                    number = _i ? arguments[_i]() : arguments[_i];
                    if (typeof number === 'number') {
                        break;
                    }
                }

                return number;
            }

            function edgeResistance(pos, edge) {
                return Math.round(pos + ((edge - pos) / 1.5));
            }

            function getProtocol() {
                getProtocol.p = getProtocol.p || (location.protocol === 'https:' ? 'https://' : 'http://');
                return getProtocol.p;
            }

            function parseHref(href) {
                var a = document.createElement('a');
                a.href = href;
                return a;
            }

            function findVideoId(href, forceVideo) {
                if (typeof href !== 'string') return href;
                href = parseHref(href);

                var id,
                    type;

                if (href.host.match(/youtube\.com/) && href.search) {
                    //.log();
                    id = href.search.split('v=')[1];
                    if (id) {
                        var ampersandPosition = id.indexOf('&');
                        if (ampersandPosition !== -1) {
                            id = id.substring(0, ampersandPosition);
                        }
                        type = 'youtube';
                    }
                } else if (href.host.match(/youtube\.com|youtu\.be|youtube-nocookie.com/)) {
                    id = href.pathname.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, '');
                    type = 'youtube';
                } else if (href.host.match(/vimeo\.com/)) {
                    type = 'vimeo';
                    id = href.pathname.replace(/^\/(video\/)?/, '').replace(/\/.*/, '');
                }

                if ((!id || !type) && forceVideo) {
                    id = href.href;
                    type = 'custom';
                }

                return id ? {id: id, type: type, s: href.search.replace(/^\?/, ''), p: getProtocol()} : false;
            }

            function getVideoThumbs(dataFrame, data, fotorama) {
                var img, thumb, video = dataFrame.video;
                if (video.type === 'youtube') {
                    thumb = getProtocol() + 'img.youtube.com/vi/' + video.id + '/default.jpg';
                    img = thumb.replace(/\/default.jpg$/, '/hqdefault.jpg');
                    dataFrame.thumbsReady = true;
                } else if (video.type === 'vimeo') {
                    $.ajax({
                        url: getProtocol() + 'vimeo.com/api/v2/video/' + video.id + '.json',
                        dataType: 'jsonp',
                        success: function (json) {
                            dataFrame.thumbsReady = true;
                            updateData(data, {
                                img: json[0].thumbnail_large,
                                thumb: json[0].thumbnail_small
                            }, dataFrame.i, fotorama);
                        }
                    });
                } else {
                    dataFrame.thumbsReady = true;
                }

                return {
                    img: img,
                    thumb: thumb
                }
            }

            function updateData(data, _dataFrame, i, fotorama) {
                for (var _i = 0, _l = data.length; _i < _l; _i++) {
                    var dataFrame = data[_i];

                    if (dataFrame.i === i && dataFrame.thumbsReady) {
                        var clear = {videoReady: true};
                        clear[STAGE_FRAME_KEY] = clear[NAV_THUMB_FRAME_KEY] = clear[NAV_DOT_FRAME_KEY] = false;

                        fotorama.splice(_i, 1, $.extend(
                            {},
                            dataFrame,
                            clear,
                            _dataFrame
                        ));

                        break;
                    }
                }
            }

            function getDataFromHtml($el) {
                var data = [];

                function getDataFromImg($img, imgData, checkVideo) {
                    var $child = $img.children('img').eq(0),
                        _imgHref = $img.attr('href'),
                        _imgSrc = $img.attr('src'),
                        _thumbSrc = $child.attr('src'),
                        _video = imgData.video,
                        video = checkVideo ? findVideoId(_imgHref, _video === true) : false;

                    if (video) {
                        _imgHref = false;
                    } else {
                        video = _video;
                    }

                    getDimensions($img, $child, $.extend(imgData, {
                        video: video,
                        img: imgData.img || _imgHref || _imgSrc || _thumbSrc,
                        thumb: imgData.thumb || _thumbSrc || _imgSrc || _imgHref
                    }));
                }

                function getDimensions($img, $child, imgData) {
                    var separateThumbFLAG = imgData.thumb && imgData.img !== imgData.thumb,
                        width = numberFromMeasure(imgData.width || $img.attr('width')),
                        height = numberFromMeasure(imgData.height || $img.attr('height'));

                    $.extend(imgData, {
                        width: width,
                        height: height,
                        thumbratio: getRatio(imgData.thumbratio || (numberFromMeasure(imgData.thumbwidth || ($child && $child.attr('width')) || separateThumbFLAG || width) / numberFromMeasure(imgData.thumbheight || ($child && $child.attr('height')) || separateThumbFLAG || height)))
                    });
                }

                $el.children().each(function () {
                    var $this = $(this),
                        dataFrame = optionsToLowerCase($.extend($this.data(), {id: $this.attr('id')}));
                    if ($this.is('a, img')) {
                        getDataFromImg($this, dataFrame, true);
                    } else if (!$this.is(':empty')) {
                        getDimensions($this, null, $.extend(dataFrame, {
                            html: this,
                            _html: $this.html() // Because of IE
                        }));
                    } else return;

                    data.push(dataFrame);
                });

                return data;
            }

            function isHidden(el) {
                return el.offsetWidth === 0 && el.offsetHeight === 0;
            }

            function isDetached(el) {
                return !$.contains(document.documentElement, el);
            }

            function waitFor(test, fn, timeout, i) {
                if (!waitFor.i) {
                    waitFor.i = 1;
                    waitFor.ii = [true];
                }

                i = i || waitFor.i;

                if (typeof waitFor.ii[i] === 'undefined') {
                    waitFor.ii[i] = true;
                }

                if (test()) {
                    fn();
                } else {
                    waitFor.ii[i] && setTimeout(function () {
                        waitFor.ii[i] && waitFor(test, fn, timeout, i);
                    }, timeout || 100);
                }

                return waitFor.i++;
            }

            waitFor.stop = function (i) {
                waitFor.ii[i] = false;
            };

            function fit($el, measuresToFit) {
                var elData = $el.data(),
                    measures = elData.measures;

                if (measures && (!elData.l ||
                    elData.l.W !== measures.width ||
                    elData.l.H !== measures.height ||
                    elData.l.r !== measures.ratio ||
                    elData.l.w !== measuresToFit.w ||
                    elData.l.h !== measuresToFit.h)) {

                    var height = minMaxLimit(measuresToFit.h, 0, measures.height),
                        width = height * measures.ratio;

                    UTIL.setRatio($el, width, height);

                    elData.l = {
                        W: measures.width,
                        H: measures.height,
                        r: measures.ratio,
                        w: measuresToFit.w,
                        h: measuresToFit.h
                    };
                }

                return true;
            }

            function setStyle($el, style) {
                var el = $el[0];
                if (el.styleSheet) {
                    el.styleSheet.cssText = style;
                } else {
                    $el.html(style);
                }
            }

            function findShadowEdge(pos, min, max, dir) {
                return min === max ? false :
                    dir === 'vertical' ?
                        (pos <= min ? 'top' : pos >= max ? 'bottom' : 'top bottom') :
                        (pos <= min ? 'left' : pos >= max ? 'right' : 'left right');
            }

            function smartClick($el, fn, _options) {
                _options = _options || {};

                $el.each(function () {
                    var $this = $(this),
                        thisData = $this.data(),
                        startEvent;

                    if (thisData.clickOn) return;

                    thisData.clickOn = true;

                    $.extend(touch($this, {
                        onStart: function (e) {
                            startEvent = e;
                            (_options.onStart || noop).call(this, e);
                        },
                        onMove: _options.onMove || noop,
                        onTouchEnd: _options.onTouchEnd || noop,
                        onEnd: function (result) {
                            if (result.moved) return;
                            fn.call(this, startEvent);
                        }
                    }), {noMove: true});
                });
            }

            function div(classes, child) {
                return '<div class="' + classes + '">' + (child || '') + '</div>';
            }


            /**
             * Function transforming into valid classname
             * @param className - name of the class
             * @returns {string} - dom format of class name
             */
            function cls(className) {
                return "." + className;
            }

            /**
             *
             * @param {json-object} videoItem Parsed object from data.video item or href from link a in input dates
             * @returns {string} DOM view of video iframe
             */
            function createVideoFrame(videoItem) {
                var frame = '<iframe src="' + videoItem.p + videoItem.type + '.com/embed/' + videoItem.id + '" frameborder="0" allowfullscreen></iframe>';
                return frame;
            }

// Fisher–Yates Shuffle
// http://bost.ocks.org/mike/shuffle/
            function shuffle(array) {
                // While there remain elements to shuffle
                var l = array.length;
                while (l) {
                    // Pick a remaining element
                    var i = Math.floor(Math.random() * l--);

                    // And swap it with the current element
                    var t = array[l];
                    array[l] = array[i];
                    array[i] = t;
                }

                return array;
            }

            function clone(array) {
                return Object.prototype.toString.call(array) == '[object Array]'
                    && $.map(array, function (frame) {
                        return $.extend({}, frame);
                    });
            }

            function lockScroll($el, left, top) {
                $el
                    .scrollLeft(left || 0)
                    .scrollTop(top || 0);
            }

            function optionsToLowerCase(options) {
                if (options) {
                    var opts = {};
                    $.each(options, function (key, value) {
                        opts[key.toLowerCase()] = value;
                    });

                    return opts;
                }
            }

            function getRatio(_ratio) {
                if (!_ratio) return;
                var ratio = +_ratio;
                if (!isNaN(ratio)) {
                    return ratio;
                } else {
                    ratio = _ratio.split('/');
                    return +ratio[0] / +ratio[1] || undefined;
                }
            }

            function addEvent(el, e, fn, bool) {
                if (!e) return;
                el.addEventListener ? el.addEventListener(e, fn, !!bool) : el.attachEvent('on' + e, fn);
            }

            /**
             *
             * @param position guess position for navShaft
             * @param restriction object contains min and max values for position
             * @returns {*} filtered value of position
             */
            function validateRestrictions(position, restriction) {
                if (position > restriction.max) {
                    position = restriction.max;
                } else {
                    if (position < restriction.min) {
                        position = restriction.min;
                    }
                }
                return position;
            }

            function validateSlidePos(opt, navShaftTouchTail, guessIndex, offsetNav, $guessNavFrame, $navWrap, dir) {
                var position,
                    size,
                    wrapSize;
                if (dir === 'horizontal') {
                    size = opt.thumbwidth;
                    wrapSize = $navWrap.width();
                } else {
                    size = opt.thumbheight;
                    wrapSize = $navWrap.height();
                }
                if ( (size + opt.margin) * (guessIndex + 1) >= (wrapSize - offsetNav) ) {
                    if (dir === 'horizontal') {
                        position = -$guessNavFrame.position().left;
                    } else {
                        position = -$guessNavFrame.position().top;
                    }
                } else {
                    if ((size + opt.margin) * (guessIndex) <= Math.abs(offsetNav)) {
                        if (dir === 'horizontal') {
                            position = -$guessNavFrame.position().left + wrapSize - (size + opt.margin);
                        } else {
                            position = -$guessNavFrame.position().top + wrapSize - (size + opt.margin);
                        }
                    } else {
                        position = offsetNav;
                    }
                }
                position = validateRestrictions(position, navShaftTouchTail);

                return position || 0;
            }

            function elIsDisabled(el) {
                return !!el.getAttribute('disabled');
            }

            function disableAttr(FLAG, disable) {
                if (disable) {
                    return {disabled: FLAG};
                } else {
                    return {tabindex: FLAG * -1 + '', disabled: FLAG};

                }
            }

            function addEnterUp(el, fn) {
                addEvent(el, 'keyup', function (e) {
                    elIsDisabled(el) || e.keyCode == 13 && fn.call(el, e);
                });
            }

            function addFocus(el, fn) {
                addEvent(el, 'focus', el.onfocusin = function (e) {
                    fn.call(el, e);
                }, true);
            }

            function stopEvent(e, stopPropagation) {
                e.preventDefault ? e.preventDefault() : (e.returnValue = false);
                stopPropagation && e.stopPropagation && e.stopPropagation();
            }

            function stubEvent($el, eventType) {
                var isIOS = /ip(ad|hone|od)/i.test(window.navigator.userAgent);

                if (isIOS && eventType === 'touchend') {
                    $el.on('touchend', function(e){
                        $DOCUMENT.trigger('mouseup', e);
                    })
                }

                $el.on(eventType, function (e) {
                    stopEvent(e, true);

                    return false;
                });
            }

            function getDirectionSign(forward) {
                return forward ? '>' : '<';
            }

            var UTIL = (function () {

                function setRatioClass($el, wh, ht) {
                    var rateImg = wh / ht;

                    if (rateImg <= 1) {
                        $el.parent().removeClass(horizontalImageClass);
                        $el.parent().addClass(verticalImageClass);
                    } else {
                        $el.parent().removeClass(verticalImageClass);
                        $el.parent().addClass(horizontalImageClass);
                    }
                }

                /**
                 * Set specific attribute in thumbnail template
                 * @param $frame DOM item of specific thumbnail
                 * @param value Value which must be setted into specific attribute
                 * @param searchAttr Name of attribute where value must be included
                 */
                function setThumbAttr($frame, value, searchAttr) {
                    var attr = searchAttr;

                    if (!$frame.attr(attr) && $frame.attr(attr) !== undefined) {
                        $frame.attr(attr, value);
                    }

                    if ($frame.find("[" + attr + "]").length) {
                        $frame.find("[" + attr + "]")
                            .each(function () {
                                $(this).attr(attr, value);
                            });
                    }
                }

                /**
                 * Method describe behavior need to render caption on preview or not
                 * @param frameItem specific item from data
                 * @param isExpected {bool} if items with caption need render them or not
                 * @returns {boolean} if true then caption should be rendered
                 */
                function isExpectedCaption(frameItem, isExpected, undefined) {
                    var expected = false,
                        frameExpected;

                    frameItem.showCaption === undefined || frameItem.showCaption === true ? frameExpected = true : frameExpected = false;

                    if (!isExpected) {
                        return false;
                    }

                    if (frameItem.caption && frameExpected) {
                        expected = true;
                    }

                    return expected;
                }

                return {
                    setRatio: setRatioClass,
                    setThumbAttr: setThumbAttr,
                    isExpectedCaption: isExpectedCaption
                };

            }(UTIL || {}, jQuery));

            function slide($el, options) {
                var elData = $el.data(),
                    elPos = Math.round(options.pos),
                    onEndFn = function () {
                        if (elData && elData.sliding) {
                            elData.sliding = false;
                        }
                        (options.onEnd || noop)();
                    };

                if (typeof options.overPos !== 'undefined' && options.overPos !== options.pos) {
                    elPos = options.overPos;
                }

                var translate = $.extend(getTranslate(elPos, options.direction), options.width && {width: options.width}, options.height && {height: options.height});
                if (elData && elData.sliding) {
                    elData.sliding = true;
                }

                if (CSS3) {
                    $el.css($.extend(getDuration(options.time), translate));

                    if (options.time > 10) {
                        afterTransition($el, 'transform', onEndFn, options.time);
                    } else {
                        onEndFn();
                    }
                } else {
                    $el.stop().animate(translate, options.time, BEZIER, onEndFn);
                }
            }

            function fade($el1, $el2, $frames, options, fadeStack, chain) {
                var chainedFLAG = typeof chain !== 'undefined';
                if (!chainedFLAG) {
                    fadeStack.push(arguments);
                    Array.prototype.push.call(arguments, fadeStack.length);
                    if (fadeStack.length > 1) return;
                }

                $el1 = $el1 || $($el1);
                $el2 = $el2 || $($el2);

                var _$el1 = $el1[0],
                    _$el2 = $el2[0],
                    crossfadeFLAG = options.method === 'crossfade',
                    onEndFn = function () {
                        if (!onEndFn.done) {
                            onEndFn.done = true;
                            var args = (chainedFLAG || fadeStack.shift()) && fadeStack.shift();
                            args && fade.apply(this, args);
                            (options.onEnd || noop)(!!args);
                        }
                    },
                    time = options.time / (chain || 1);

                $frames.removeClass(fadeRearClass + ' ' + fadeFrontClass);

                $el1
                    .stop()
                    .addClass(fadeRearClass);
                $el2
                    .stop()
                    .addClass(fadeFrontClass);

                crossfadeFLAG && _$el2 && $el1.fadeTo(0, 0);

                $el1.fadeTo(crossfadeFLAG ? time : 0, 1, crossfadeFLAG && onEndFn);
                $el2.fadeTo(time, 0, onEndFn);

                (_$el1 && crossfadeFLAG) || _$el2 || onEndFn();
            }

            var lastEvent,
                moveEventType,
                preventEvent,
                preventEventTimeout,
                dragDomEl;

            function extendEvent(e) {
                var touch = (e.touches || [])[0] || e;
                e._x = touch.pageX || touch.originalEvent.pageX;
                e._y = touch.clientY || touch.originalEvent.clientY;
                e._now = $.now();
            }

            function touch($el, options) {
                var el = $el[0],
                    tail = {},
                    touchEnabledFLAG,
                    startEvent,
                    $target,
                    controlTouch,
                    touchFLAG,
                    targetIsSelectFLAG,
                    targetIsLinkFlag,
                    isDisabledSwipe,
                    tolerance,
                    moved;

                function onStart(e) {
                    $target = $(e.target);
                    tail.checked = targetIsSelectFLAG = targetIsLinkFlag = isDisabledSwipe = moved = false;

                    if (touchEnabledFLAG
                        || tail.flow
                        || (e.touches && e.touches.length > 1)
                        || e.which > 1
                        || (lastEvent && lastEvent.type !== e.type && preventEvent)
                        || (targetIsSelectFLAG = options.select && $target.is(options.select, el))) return targetIsSelectFLAG;

                    touchFLAG = e.type === 'touchstart';
                    targetIsLinkFlag = $target.is('a, a *', el);
                    isDisabledSwipe = $target.hasClass('disableSwipe');
                    controlTouch = tail.control;

                    tolerance = (tail.noMove || tail.noSwipe || controlTouch) ? 16 : !tail.snap ? 4 : 0;

                    extendEvent(e);

                    startEvent = lastEvent = e;
                    moveEventType = e.type.replace(/down|start/, 'move').replace(/Down/, 'Move');

                    (options.onStart || noop).call(el, e, {control: controlTouch, $target: $target});

                    touchEnabledFLAG = tail.flow = true;

                    if (!isDisabledSwipe && (!touchFLAG || tail.go)) stopEvent(e);
                }

                function onMove(e) {
                    if ((e.touches && e.touches.length > 1)
                        || (MS_POINTER && !e.isPrimary)
                        || moveEventType !== e.type
                        || !touchEnabledFLAG) {
                        touchEnabledFLAG && onEnd();
                        (options.onTouchEnd || noop)();
                        return;
                    }

                    isDisabledSwipe = $(e.target).hasClass('disableSwipe');

                    if (isDisabledSwipe) {
                        return;
                    }

                    extendEvent(e);

                    var xDiff = Math.abs(e._x - startEvent._x), // opt _x → _pageX
                        yDiff = Math.abs(e._y - startEvent._y),
                        xyDiff = xDiff - yDiff,
                        xWin = (tail.go || tail.x || xyDiff >= 0) && !tail.noSwipe,
                        yWin = xyDiff < 0;

                    if (touchFLAG && !tail.checked) {
                        if (touchEnabledFLAG = xWin) {
                            stopEvent(e);
                        }
                    } else {
                        stopEvent(e);
                        if (movedEnough(xDiff,yDiff)) {
                            (options.onMove || noop).call(el, e, {touch: touchFLAG});
                        }
                    }

                    if (!moved && movedEnough(xDiff, yDiff) && Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)) > tolerance) {
                        moved = true;
                    }

                    tail.checked = tail.checked || xWin || yWin;
                }

                function movedEnough(xDiff, yDiff) {
                    return xDiff > yDiff && xDiff > 1.5;
                }

                function onEnd(e) {
                    (options.onTouchEnd || noop)();

                    var _touchEnabledFLAG = touchEnabledFLAG;
                    tail.control = touchEnabledFLAG = false;

                    if (_touchEnabledFLAG) {
                        tail.flow = false;
                    }

                    if (!_touchEnabledFLAG || (targetIsLinkFlag && !tail.checked)) return;

                    e && stopEvent(e);

                    preventEvent = true;
                    clearTimeout(preventEventTimeout);
                    preventEventTimeout = setTimeout(function () {
                        preventEvent = false;
                    }, 1000);

                    (options.onEnd || noop).call(el, {
                        moved: moved,
                        $target: $target,
                        control: controlTouch,
                        touch: touchFLAG,
                        startEvent: startEvent,
                        aborted: !e || e.type === 'MSPointerCancel'
                    });
                }

                function onOtherStart() {
                    if (tail.flow) return;
                    tail.flow = true;
                }

                function onOtherEnd() {
                    if (!tail.flow) return;
                    tail.flow = false;
                }

                if (MS_POINTER) {
                    addEvent(el, 'MSPointerDown', onStart);
                    addEvent(document, 'MSPointerMove', onMove);
                    addEvent(document, 'MSPointerCancel', onEnd);
                    addEvent(document, 'MSPointerUp', onEnd);
                } else {
                    addEvent(el, 'touchstart', onStart);
                    addEvent(el, 'touchmove', onMove);
                    addEvent(el, 'touchend', onEnd);

                    addEvent(document, 'touchstart', onOtherStart);
                    addEvent(document, 'touchend', onOtherEnd);
                    addEvent(document, 'touchcancel', onOtherEnd);

                    $WINDOW.on('scroll', onOtherEnd);

                    $el.on('mousedown', onStart);
                    $DOCUMENT
                        .on('mousemove', onMove)
                        .on('mouseup', onEnd);
                    $('.fotorama__arr__arr, .fotorama__fullscreen-icon').on('pointerup', onEnd);
                }

                if (Modernizr.touch) {
                    dragDomEl = 'a';
                } else {
                    dragDomEl = 'div';
                }
                $el.on('click', dragDomEl, function (e) {
                    tail.checked && stopEvent(e);
                });

                return tail;
            }

            function moveOnTouch($el, options) {
                var el = $el[0],
                    elData = $el.data(),
                    tail = {},
                    startCoo,
                    coo,
                    startElPos,
                    moveElPos,
                    edge,
                    moveTrack,
                    startTime,
                    endTime,
                    min,
                    max,
                    snap,
                    dir,
                    slowFLAG,
                    controlFLAG,
                    moved,
                    tracked;

                function startTracking(e, noStop) {
                    tracked = true;
                    startCoo = coo = (dir === 'vertical') ? e._y : e._x;
                    startTime = e._now;

                    moveTrack = [
                        [startTime, startCoo]
                    ];

                    startElPos = moveElPos = tail.noMove || noStop ? 0 : stop($el, (options.getPos || noop)()/*, options._001*/);

                    (options.onStart || noop).call(el, e);
                }

                function onStart(e, result) {
                    min = tail.min;
                    max = tail.max;
                    snap = tail.snap,
                        dir = tail.direction || 'horizontal',
                        $el.navdir = dir;

                    slowFLAG = e.altKey;
                    tracked = moved = false;

                    controlFLAG = result.control;

                    if (!controlFLAG && !elData.sliding) {
                        startTracking(e);
                    }
                }

                function onMove(e, result) {
                    if (!tail.noSwipe) {
                        if (!tracked) {
                            startTracking(e);
                        }
                        coo = (dir === 'vertical') ? e._y : e._x;

                        moveTrack.push([e._now, coo]);

                        moveElPos = startElPos - (startCoo - coo);

                        edge = findShadowEdge(moveElPos, min, max, dir);

                        if (moveElPos <= min) {
                            moveElPos = edgeResistance(moveElPos, min);
                        } else if (moveElPos >= max) {
                            moveElPos = edgeResistance(moveElPos, max);
                        }

                        if (!tail.noMove) {
                            $el.css(getTranslate(moveElPos, dir));
                            if (!moved) {
                                moved = true;
                                // only for mouse
                                result.touch || MS_POINTER || $el.addClass(grabbingClass);
                            }

                            (options.onMove || noop).call(el, e, {pos: moveElPos, edge: edge});
                        }
                    }
                }

                function onEnd(result) {
                    if (tail.noSwipe && result.moved) return;

                    if (!tracked) {
                        startTracking(result.startEvent, true);
                    }

                    result.touch || MS_POINTER || $el.removeClass(grabbingClass);

                    endTime = $.now();

                    var _backTimeIdeal = endTime - TOUCH_TIMEOUT,
                        _backTime,
                        _timeDiff,
                        _timeDiffLast,
                        backTime = null,
                        backCoo,
                        virtualPos,
                        limitPos,
                        newPos,
                        overPos,
                        time = TRANSITION_DURATION,
                        speed,
                        friction = options.friction;

                    for (var _i = moveTrack.length - 1; _i >= 0; _i--) {
                        _backTime = moveTrack[_i][0];
                        _timeDiff = Math.abs(_backTime - _backTimeIdeal);
                        if (backTime === null || _timeDiff < _timeDiffLast) {
                            backTime = _backTime;
                            backCoo = moveTrack[_i][1];
                        } else if (backTime === _backTimeIdeal || _timeDiff > _timeDiffLast) {
                            break;
                        }
                        _timeDiffLast = _timeDiff;
                    }

                    newPos = minMaxLimit(moveElPos, min, max);

                    var cooDiff = backCoo - coo,
                        forwardFLAG = cooDiff >= 0,
                        timeDiff = endTime - backTime,
                        longTouchFLAG = timeDiff > TOUCH_TIMEOUT,
                        swipeFLAG = !longTouchFLAG && moveElPos !== startElPos && newPos === moveElPos;

                    if (snap) {
                        newPos = minMaxLimit(Math[swipeFLAG ? (forwardFLAG ? 'floor' : 'ceil') : 'round'](moveElPos / snap) * snap, min, max);
                        min = max = newPos;
                    }

                    if (swipeFLAG && (snap || newPos === moveElPos)) {
                        speed = -(cooDiff / timeDiff);
                        time *= minMaxLimit(Math.abs(speed), options.timeLow, options.timeHigh);
                        virtualPos = Math.round(moveElPos + speed * time / friction);

                        if (!snap) {
                            newPos = virtualPos;
                        }

                        if (!forwardFLAG && virtualPos > max || forwardFLAG && virtualPos < min) {
                            limitPos = forwardFLAG ? min : max;
                            overPos = virtualPos - limitPos;
                            if (!snap) {
                                newPos = limitPos;
                            }
                            overPos = minMaxLimit(newPos + overPos * .03, limitPos - 50, limitPos + 50);
                            time = Math.abs((moveElPos - overPos) / (speed / friction));
                        }
                    }

                    time *= slowFLAG ? 10 : 1;

                    (options.onEnd || noop).call(el, $.extend(result, {
                        moved: result.moved || longTouchFLAG && snap,
                        pos: moveElPos,
                        newPos: newPos,
                        overPos: overPos,
                        time: time,
                        dir: dir
                    }));
                }

                tail = $.extend(touch(options.$wrap, $.extend({}, options, {
                    onStart: onStart,
                    onMove: onMove,
                    onEnd: onEnd
                })), tail);

                return tail;
            }

            function wheel($el, options) {
                var el = $el[0],
                    lockFLAG,
                    lastDirection,
                    lastNow,
                    tail = {
                        prevent: {}
                    };

                addEvent(el, WHEEL, function (e) {
                    var yDelta = e.wheelDeltaY || -1 * e.deltaY || 0,
                        xDelta = e.wheelDeltaX || -1 * e.deltaX || 0,
                        xWin = Math.abs(xDelta) && !Math.abs(yDelta),
                        direction = getDirectionSign(xDelta < 0),
                        sameDirection = lastDirection === direction,
                        now = $.now(),
                        tooFast = now - lastNow < TOUCH_TIMEOUT;

                    lastDirection = direction;
                    lastNow = now;

                    if (!xWin || !tail.ok || tail.prevent[direction] && !lockFLAG) {
                        return;
                    } else {
                        stopEvent(e, true);
                        if (lockFLAG && sameDirection && tooFast) {
                            return;
                        }
                    }

                    if (options.shift) {
                        lockFLAG = true;
                        clearTimeout(tail.t);
                        tail.t = setTimeout(function () {
                            lockFLAG = false;
                        }, SCROLL_LOCK_TIMEOUT);
                    }

                    (options.onEnd || noop)(e, options.shift ? direction : xDelta);

                });

                return tail;
            }

            jQuery.Fotorama = function ($fotorama, opts) {
                $HTML = $('html');
                $BODY = $('body');

                var that = this,
                    stamp = $.now(),
                    stampClass = _fotoramaClass + stamp,
                    fotorama = $fotorama[0],
                    data,
                    dataFrameCount = 1,
                    fotoramaData = $fotorama.data(),
                    size,

                    $style = $('<style></style>'),

                    $anchor = $(div(hiddenClass)),
                    $wrap = $fotorama.find(cls(wrapClass)),
                    $stage = $wrap.find(cls(stageClass)),
                    stage = $stage[0],

                    $stageShaft = $fotorama.find(cls(stageShaftClass)),
                    $stageFrame = $(),
                    $arrPrev = $fotorama.find(cls(arrPrevClass)),
                    $arrNext = $fotorama.find(cls(arrNextClass)),
                    $arrs = $fotorama.find(cls(arrClass)),
                    $navWrap = $fotorama.find(cls(navWrapClass)),
                    $nav = $navWrap.find(cls(navClass)),
                    $navShaft = $nav.find(cls(navShaftClass)),
                    $navFrame,
                    $navDotFrame = $(),
                    $navThumbFrame = $(),

                    stageShaftData = $stageShaft.data(),
                    navShaftData = $navShaft.data(),

                    $thumbBorder = $fotorama.find(cls(thumbBorderClass)),
                    $thumbArrLeft = $fotorama.find(cls(thumbArrLeft)),
                    $thumbArrRight = $fotorama.find(cls(thumbArrRight)),

                    $fullscreenIcon = $fotorama.find(cls(fullscreenIconClass)),
                    fullscreenIcon = $fullscreenIcon[0],
                    $videoPlay = $(div(videoPlayClass)),
                    $videoClose = $fotorama.find(cls(videoCloseClass)),
                    videoClose = $videoClose[0],

                    $spinner = $fotorama.find(cls(fotoramaSpinnerClass)),

                    $videoPlaying,

                    activeIndex = false,
                    activeFrame,
                    activeIndexes,
                    repositionIndex,
                    dirtyIndex,
                    lastActiveIndex,
                    prevIndex,
                    nextIndex,
                    nextAutoplayIndex,
                    startIndex,

                    o_loop,
                    o_nav,
                    o_navThumbs,
                    o_navTop,
                    o_allowFullScreen,
                    o_nativeFullScreen,
                    o_fade,
                    o_thumbSide,
                    o_thumbSide2,
                    o_transitionDuration,
                    o_transition,
                    o_shadows,
                    o_rtl,
                    o_keyboard,
                    lastOptions = {},

                    measures = {},
                    measuresSetFLAG,

                    stageShaftTouchTail = {},
                    stageWheelTail = {},
                    navShaftTouchTail = {},
                    navWheelTail = {},

                    scrollTop,
                    scrollLeft,

                    showedFLAG,
                    pausedAutoplayFLAG,
                    stoppedAutoplayFLAG,

                    toDeactivate = {},
                    toDetach = {},

                    measuresStash,

                    touchedFLAG,

                    hoverFLAG,

                    navFrameKey,
                    stageLeft = 0,

                    fadeStack = [];

                $wrap[STAGE_FRAME_KEY] = $('<div class="' + stageFrameClass + '"></div>');
                $wrap[NAV_THUMB_FRAME_KEY] = $($.Fotorama.jst.thumb());
                $wrap[NAV_DOT_FRAME_KEY] = $($.Fotorama.jst.dots());

                toDeactivate[STAGE_FRAME_KEY] = [];
                toDeactivate[NAV_THUMB_FRAME_KEY] = [];
                toDeactivate[NAV_DOT_FRAME_KEY] = [];
                toDetach[STAGE_FRAME_KEY] = {};

                $wrap.addClass(CSS3 ? wrapCss3Class : wrapCss2Class);

                fotoramaData.fotorama = this;

                /**
                 * Search video items in incoming data and transform object for video layout.
                 *
                 */
                function checkForVideo() {
                    $.each(data, function (i, dataFrame) {
                        if (!dataFrame.i) {
                            dataFrame.i = dataFrameCount++;
                            var video = findVideoId(dataFrame.video, true);
                            if (video) {
                                var thumbs = {};
                                dataFrame.video = video;
                                if (!dataFrame.img && !dataFrame.thumb) {
                                    thumbs = getVideoThumbs(dataFrame, data, that);
                                } else {
                                    dataFrame.thumbsReady = true;
                                }
                                updateData(data, {img: thumbs.img, thumb: thumbs.thumb}, dataFrame.i, that);
                            }
                        }
                    });
                }

                function allowKey(key) {
                    return o_keyboard[key];
                }

                function setStagePosition() {
                    if ($stage !== undefined) {

                        if (opts.navdir == 'vertical') {
                            var padding = opts.thumbwidth + opts.thumbmargin;

                            $stage.css('left', padding);
                            $arrNext.css('right', padding);
                            $fullscreenIcon.css('right', padding);
                            $wrap.css('width', $wrap.css('width') + padding);
                            $stageShaft.css('max-width', $wrap.width() - padding);
                        } else {
                            $stage.css('left', '');
                            $arrNext.css('right', '');
                            $fullscreenIcon.css('right', '');
                            $wrap.css('width', $wrap.css('width') + padding);
                            $stageShaft.css('max-width', '');
                        }
                    }
                }

                function bindGlobalEvents(FLAG) {
                    var keydownCommon = 'keydown.' + _fotoramaClass,
                        localStamp = _fotoramaClass + stamp,
                        keydownLocal = 'keydown.' + localStamp,
                        keyupLocal = 'keyup.' + localStamp,
                        resizeLocal = 'resize.' + localStamp + ' ' + 'orientationchange.' + localStamp,
                        showParams;

                    if (FLAG) {
                        $DOCUMENT
                            .on(keydownLocal, function (e) {
                                var catched,
                                    index;

                                if ($videoPlaying && e.keyCode === 27) {
                                    catched = true;
                                    unloadVideo($videoPlaying, true, true);
                                } else if (that.fullScreen || (opts.keyboard && !that.index)) {
                                    if (e.keyCode === 27) {
                                        catched = true;
                                        that.cancelFullScreen();
                                    } else if ((e.shiftKey && e.keyCode === 32 && allowKey('space')) || (!e.altKey && !e.metaKey && e.keyCode === 37 && allowKey('left')) || (e.keyCode === 38 && allowKey('up') && $(':focus').attr('data-gallery-role'))) {
                                        that.longPress.progress();
                                        index = '<';
                                    } else if ((e.keyCode === 32 && allowKey('space')) || (!e.altKey && !e.metaKey && e.keyCode === 39 && allowKey('right')) || (e.keyCode === 40 && allowKey('down') && $(':focus').attr('data-gallery-role'))) {
                                        that.longPress.progress();
                                        index = '>';
                                    } else if (e.keyCode === 36 && allowKey('home')) {
                                        that.longPress.progress();
                                        index = '<<';
                                    } else if (e.keyCode === 35 && allowKey('end')) {
                                        that.longPress.progress();
                                        index = '>>';
                                    }
                                }

                                (catched || index) && stopEvent(e);
                                showParams = {index: index, slow: e.altKey, user: true};
                                index && (that.longPress.inProgress ?
                                    that.showWhileLongPress(showParams) :
                                    that.show(showParams));
                            });

                        if (FLAG) {
                            $DOCUMENT
                                .on(keyupLocal, function (e) {
                                    if (that.longPress.inProgress) {
                                        that.showEndLongPress({user: true});
                                    }
                                    that.longPress.reset();
                                });
                        }

                        if (!that.index) {
                            $DOCUMENT
                                .off(keydownCommon)
                                .on(keydownCommon, 'textarea, input, select', function (e) {
                                    !$BODY.hasClass(_fullscreenClass) && e.stopPropagation();
                                });
                        }

                        $WINDOW.on(resizeLocal, that.resize);
                    } else {
                        $DOCUMENT.off(keydownLocal);
                        $WINDOW.off(resizeLocal);
                    }
                }

                function appendElements(FLAG) {
                    if (FLAG === appendElements.f) return;

                    if (FLAG) {
                        $fotorama
                            .addClass(_fotoramaClass + ' ' + stampClass)
                            .before($anchor)
                            .before($style);
                        addInstance(that);
                    } else {
                        $anchor.detach();
                        $style.detach();
                        $fotorama
                            .html(fotoramaData.urtext)
                            .removeClass(stampClass);

                        hideInstance(that);
                    }

                    bindGlobalEvents(FLAG);
                    appendElements.f = FLAG;
                }

                /**
                 * Set and install data from incoming @param {JSON} options or takes data attr from data-"name"=... values.
                 */
                function setData() {
                    data = that.data = data || clone(opts.data) || getDataFromHtml($fotorama);
                    size = that.size = data.length;

                    ready.ok && opts.shuffle && shuffle(data);

                    checkForVideo();

                    activeIndex = limitIndex(activeIndex);

                    size && appendElements(true);
                }

                function stageNoMove() {
                    var _noMove = size < 2 || $videoPlaying;
                    stageShaftTouchTail.noMove = _noMove || o_fade;
                    stageShaftTouchTail.noSwipe = _noMove || !opts.swipe;

                    !o_transition && $stageShaft.toggleClass(grabClass, !opts.click && !stageShaftTouchTail.noMove && !stageShaftTouchTail.noSwipe);
                    MS_POINTER && $wrap.toggleClass(wrapPanYClass, !stageShaftTouchTail.noSwipe);
                }

                function setAutoplayInterval(interval) {
                    if (interval === true) interval = '';
                    opts.autoplay = Math.max(+interval || AUTOPLAY_INTERVAL, o_transitionDuration * 1.5);
                }

                function updateThumbArrow(opt) {
                    if (opt.navarrows && opt.nav === 'thumbs') {
                        $thumbArrLeft.show();
                        $thumbArrRight.show();
                    } else {
                        $thumbArrLeft.hide();
                        $thumbArrRight.hide();
                    }

                }

                function getThumbsInSlide($el, opts) {
                    return Math.floor($wrap.width() / (opts.thumbwidth + opts.thumbmargin));
                }

                /**
                 * Options on the fly
                 * */
                function setOptions() {
                    if (!opts.nav || opts.nav === 'dots') {
                        opts.navdir = 'horizontal'
                    }

                    that.options = opts = optionsToLowerCase(opts);
                    thumbsPerSlide = getThumbsInSlide($wrap, opts);

                    o_fade = (opts.transition === 'crossfade' || opts.transition === 'dissolve');

                    o_loop = opts.loop && (size > 2 || (o_fade && (!o_transition || o_transition !== 'slide')));

                    o_transitionDuration = +opts.transitionduration || TRANSITION_DURATION;

                    o_rtl = opts.direction === 'rtl';

                    o_keyboard = $.extend({}, opts.keyboard && KEYBOARD_OPTIONS, opts.keyboard);
                    updateThumbArrow(opts);
                    var classes = {add: [], remove: []};

                    function addOrRemoveClass(FLAG, value) {
                        classes[FLAG ? 'add' : 'remove'].push(value);
                    }

                    if (size > 1) {
                        o_nav = opts.nav;
                        o_navTop = opts.navposition === 'top';
                        classes.remove.push(selectClass);

                        $arrs.toggle(!!opts.arrows);
                    } else {
                        o_nav = false;
                        $arrs.hide();
                    }

                    arrsUpdate();
                    stageWheelUpdate();
                    thumbArrUpdate();
                    if (opts.autoplay) setAutoplayInterval(opts.autoplay);

                    o_thumbSide = numberFromMeasure(opts.thumbwidth) || THUMB_SIZE;
                    o_thumbSide2 = numberFromMeasure(opts.thumbheight) || THUMB_SIZE;

                    stageWheelTail.ok = navWheelTail.ok = opts.trackpad && !SLOW;

                    stageNoMove();

                    extendMeasures(opts, [measures]);

                    o_navThumbs = o_nav === 'thumbs';

                    if ($navWrap.filter(':hidden') && !!o_nav) {
                        $navWrap.show();
                    }
                    if (o_navThumbs) {
                        frameDraw(size, 'navThumb');

                        $navFrame = $navThumbFrame;
                        navFrameKey = NAV_THUMB_FRAME_KEY;

                        setStyle($style, $.Fotorama.jst.style({
                            w: o_thumbSide,
                            h: o_thumbSide2,
                            b: opts.thumbborderwidth,
                            m: opts.thumbmargin,
                            s: stamp,
                            q: !COMPAT
                        }));

                        $nav
                            .addClass(navThumbsClass)
                            .removeClass(navDotsClass);
                    } else if (o_nav === 'dots') {
                        frameDraw(size, 'navDot');

                        $navFrame = $navDotFrame;
                        navFrameKey = NAV_DOT_FRAME_KEY;

                        $nav
                            .addClass(navDotsClass)
                            .removeClass(navThumbsClass);
                    } else {
                        $navWrap.hide();
                        o_nav = false;
                        $nav.removeClass(navThumbsClass + ' ' + navDotsClass);
                    }

                    if (o_nav) {
                        if (o_navTop) {
                            $navWrap.insertBefore($stage);
                        } else {
                            $navWrap.insertAfter($stage);
                        }
                        frameAppend.nav = false;

                        frameAppend($navFrame, $navShaft, 'nav');
                    }

                    o_allowFullScreen = opts.allowfullscreen;

                    if (o_allowFullScreen) {
                        $fullscreenIcon.prependTo($stage);
                        o_nativeFullScreen = FULLSCREEN && o_allowFullScreen === 'native';

                        // Due 300ms click delay on mobile devices
                        // we stub touchend and fallback to click.
                        // MAGETWO-69567
                        stubEvent($fullscreenIcon, 'touchend');
                    } else {
                        $fullscreenIcon.detach();
                        o_nativeFullScreen = false;
                    }

                    addOrRemoveClass(o_fade, wrapFadeClass);
                    addOrRemoveClass(!o_fade, wrapSlideClass);
                    addOrRemoveClass(!opts.captions, wrapNoCaptionsClass);
                    addOrRemoveClass(o_rtl, wrapRtlClass);
                    addOrRemoveClass(opts.arrows, wrapToggleArrowsClass);

                    o_shadows = opts.shadows && !SLOW;
                    addOrRemoveClass(!o_shadows, wrapNoShadowsClass);

                    $wrap
                        .addClass(classes.add.join(' '))
                        .removeClass(classes.remove.join(' '));

                    lastOptions = $.extend({}, opts);
                    setStagePosition();
                }

                function normalizeIndex(index) {
                    return index < 0 ? (size + (index % size)) % size : index >= size ? index % size : index;
                }

                function limitIndex(index) {
                    return minMaxLimit(index, 0, size - 1);
                }

                function edgeIndex(index) {
                    return o_loop ? normalizeIndex(index) : limitIndex(index);
                }

                function getPrevIndex(index) {
                    return index > 0 || o_loop ? index - 1 : false;
                }

                function getNextIndex(index) {
                    return index < size - 1 || o_loop ? index + 1 : false;
                }

                function setStageShaftMinmaxAndSnap() {
                    stageShaftTouchTail.min = o_loop ? -Infinity : -getPosByIndex(size - 1, measures.w, opts.margin, repositionIndex);
                    stageShaftTouchTail.max = o_loop ? Infinity : -getPosByIndex(0, measures.w, opts.margin, repositionIndex);
                    stageShaftTouchTail.snap = measures.w + opts.margin;
                }

                function setNavShaftMinMax() {

                    var isVerticalDir = (opts.navdir === 'vertical');
                    var param = isVerticalDir ? $navShaft.height() : $navShaft.width();
                    var mainParam = isVerticalDir ? measures.h : measures.nw;
                    navShaftTouchTail.min = Math.min(0, mainParam - param);
                    navShaftTouchTail.max = 0;
                    navShaftTouchTail.direction = opts.navdir;
                    $navShaft.toggleClass(grabClass, !(navShaftTouchTail.noMove = navShaftTouchTail.min === navShaftTouchTail.max));
                }

                function eachIndex(indexes, type, fn) {
                    if (typeof indexes === 'number') {
                        indexes = new Array(indexes);
                        var rangeFLAG = true;
                    }
                    return $.each(indexes, function (i, index) {
                        if (rangeFLAG) index = i;
                        if (typeof index === 'number') {
                            var dataFrame = data[normalizeIndex(index)];

                            if (dataFrame) {
                                var key = '$' + type + 'Frame',
                                    $frame = dataFrame[key];

                                fn.call(this, i, index, dataFrame, $frame, key, $frame && $frame.data());
                            }
                        }
                    });
                }

                function setMeasures(width, height, ratio, index) {
                    if (!measuresSetFLAG || (measuresSetFLAG === '*' && index === startIndex)) {

                        width = measureIsValid(opts.width) || measureIsValid(width) || WIDTH;
                        height = measureIsValid(opts.height) || measureIsValid(height) || HEIGHT;
                        that.resize({
                            width: width,
                            ratio: opts.ratio || ratio || width / height
                        }, 0, index !== startIndex && '*');
                    }
                }

                function loadImg(indexes, type, specialMeasures, again) {

                    eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) {

                        if (!$frame) return;

                        var fullFLAG = that.fullScreen && !frameData.$full && type === 'stage';

                        if (frameData.$img && !again && !fullFLAG) return;

                        var img = new Image(),
                            $img = $(img),
                            imgData = $img.data();

                        frameData[fullFLAG ? '$full' : '$img'] = $img;

                        var srcKey = type === 'stage' ? (fullFLAG ? 'full' : 'img') : 'thumb',
                            src = dataFrame[srcKey],
                            dummy = fullFLAG ? dataFrame['img'] : dataFrame[type === 'stage' ? 'thumb' : 'img'];

                        if (type === 'navThumb') $frame = frameData.$wrap;

                        function triggerTriggerEvent(event) {
                            var _index = normalizeIndex(index);
                            triggerEvent(event, {
                                index: _index,
                                src: src,
                                frame: data[_index]
                            });
                        }

                        function error() {
                            $img.remove();

                            $.Fotorama.cache[src] = 'error';

                            if ((!dataFrame.html || type !== 'stage') && dummy && dummy !== src) {
                                dataFrame[srcKey] = src = dummy;
                                frameData.$full = null;
                                loadImg([index], type, specialMeasures, true);
                            } else {
                                if (src && !dataFrame.html && !fullFLAG) {
                                    $frame
                                        .trigger('f:error')
                                        .removeClass(loadingClass)
                                        .addClass(errorClass);

                                    triggerTriggerEvent('error');
                                } else if (type === 'stage') {
                                    $frame
                                        .trigger('f:load')
                                        .removeClass(loadingClass + ' ' + errorClass)
                                        .addClass(loadedClass);

                                    triggerTriggerEvent('load');
                                    setMeasures();
                                }

                                frameData.state = 'error';

                                if (size > 1 && data[index] === dataFrame && !dataFrame.html && !dataFrame.deleted && !dataFrame.video && !fullFLAG) {
                                    dataFrame.deleted = true;
                                    that.splice(index, 1);
                                }
                            }
                        }

                        function loaded() {
                            $.Fotorama.measures[src] = imgData.measures = $.Fotorama.measures[src] || {
                                width: img.width,
                                height: img.height,
                                ratio: img.width / img.height
                            };

                            setMeasures(imgData.measures.width, imgData.measures.height, imgData.measures.ratio, index);

                            $img
                                .off('load error')
                                .addClass('' + (fullFLAG ? imgFullClass: imgClass))
                                .attr('aria-hidden', 'false')
                                .prependTo($frame);

                            if ($frame.hasClass(stageFrameClass) && !$frame.hasClass(videoContainerClass)) {
                                $frame.attr("href", $img.attr("src"));
                            }

                            fit($img, (
                                $.isFunction(specialMeasures) ? specialMeasures() : specialMeasures) || measures);

                            $.Fotorama.cache[src] = frameData.state = 'loaded';

                            setTimeout(function () {
                                $frame
                                    .trigger('f:load')
                                    .removeClass(loadingClass + ' ' + errorClass)
                                    .addClass(loadedClass + ' ' + (fullFLAG ? loadedFullClass : loadedImgClass));

                                if (type === 'stage') {
                                    triggerTriggerEvent('load');
                                } else if (dataFrame.thumbratio === AUTO || !dataFrame.thumbratio && opts.thumbratio === AUTO) {
                                    // danger! reflow for all thumbnails
                                    dataFrame.thumbratio = imgData.measures.ratio;
                                    reset();
                                }
                            }, 0);
                        }

                        if (!src) {
                            error();
                            return;
                        }

                        function waitAndLoad() {
                            var _i = 10;
                            waitFor(function () {
                                return !touchedFLAG || !_i-- && !SLOW;
                            }, function () {
                                loaded();
                            });
                        }

                        if (!$.Fotorama.cache[src]) {
                            $.Fotorama.cache[src] = '*';

                            $img
                                .on('load', waitAndLoad)
                                .on('error', error);
                        } else {
                            (function justWait() {
                                if ($.Fotorama.cache[src] === 'error') {
                                    error();
                                } else if ($.Fotorama.cache[src] === 'loaded') {
                                    setTimeout(waitAndLoad, 0);
                                } else {
                                    setTimeout(justWait, 100);
                                }
                            })();
                        }

                        frameData.state = '';
                        img.src = src;

                        if (frameData.data.caption) {
                            img.alt = frameData.data.caption || "";
                        }

                        if (frameData.data.full) {
                            $(img).data('original', frameData.data.full);
                        }

                        if (UTIL.isExpectedCaption(dataFrame, opts.showcaption)) {
                            $(img).attr('aria-labelledby', dataFrame.labelledby);
                        }
                    });
                }

                function updateFotoramaState() {
                    var $frame = activeFrame[STAGE_FRAME_KEY];

                    if ($frame && !$frame.data().state) {
                        $spinner.addClass(spinnerShowClass);
                        $frame.on('f:load f:error', function () {
                            $frame.off('f:load f:error');
                            $spinner.removeClass(spinnerShowClass);
                        });
                    }
                }

                function addNavFrameEvents(frame) {
                    addEnterUp(frame, onNavFrameClick);
                    addFocus(frame, function () {

                        setTimeout(function () {
                            lockScroll($nav);
                        }, 0);
                        slideNavShaft({time: o_transitionDuration, guessIndex: $(this).data().eq, minMax: navShaftTouchTail});
                    });
                }

                function frameDraw(indexes, type) {
                    eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) {
                        if ($frame) return;

                        $frame = dataFrame[key] = $wrap[key].clone();
                        frameData = $frame.data();
                        frameData.data = dataFrame;
                        var frame = $frame[0],
                            labelledbyValue = "labelledby" + $.now();

                        if (type === 'stage') {

                            if (dataFrame.html) {
                                $('<div class="' + htmlClass + '"></div>')
                                    .append(
                                        dataFrame._html ? $(dataFrame.html)
                                                .removeAttr('id')
                                                .html(dataFrame._html) // Because of IE
                                            : dataFrame.html
                                    )
                                    .appendTo($frame);
                            }

                            if (dataFrame.id) {
                                labelledbyValue = dataFrame.id || labelledbyValue;
                            }
                            dataFrame.labelledby = labelledbyValue;

                            if (UTIL.isExpectedCaption(dataFrame, opts.showcaption)) {
                                $($.Fotorama.jst.frameCaption({
                                    caption: dataFrame.caption,
                                    labelledby: labelledbyValue
                                })).appendTo($frame);
                            }

                            dataFrame.video && $frame
                                .addClass(stageFrameVideoClass)
                                .append($videoPlay.clone());

                            // This solves tabbing problems
                            addFocus(frame, function (e) {
                                setTimeout(function () {
                                    lockScroll($stage);
                                }, 0);
                                clickToShow({index: frameData.eq, user: true}, e);
                            });

                            $stageFrame = $stageFrame.add($frame);
                        } else if (type === 'navDot') {
                            addNavFrameEvents(frame);
                            $navDotFrame = $navDotFrame.add($frame);
                        } else if (type === 'navThumb') {
                            addNavFrameEvents(frame);
                            frameData.$wrap = $frame.children(':first');

                            $navThumbFrame = $navThumbFrame.add($frame);
                            if (dataFrame.video) {
                                frameData.$wrap.append($videoPlay.clone());
                            }
                        }
                    });
                }

                function callFit($img, measuresToFit) {
                    return $img && $img.length && fit($img, measuresToFit);
                }

                function stageFramePosition(indexes) {
                    eachIndex(indexes, 'stage', function (i, index, dataFrame, $frame, key, frameData) {
                        if (!$frame) return;

                        var normalizedIndex = normalizeIndex(index);
                        frameData.eq = normalizedIndex;

                        toDetach[STAGE_FRAME_KEY][normalizedIndex] = $frame.css($.extend({left: o_fade ? 0 : getPosByIndex(index, measures.w, opts.margin, repositionIndex)}, o_fade && getDuration(0)));

                        if (isDetached($frame[0])) {
                            $frame.appendTo($stageShaft);
                            unloadVideo(dataFrame.$video);
                        }

                        callFit(frameData.$img, measures);
                        callFit(frameData.$full, measures);

                        if ($frame.hasClass(stageFrameClass) && !($frame.attr('aria-hidden') === "false" && $frame.hasClass(activeClass))) {
                            $frame.attr('aria-hidden', 'true');
                        }
                    });
                }

                function thumbsDraw(pos, loadFLAG) {
                    var leftLimit,
                        rightLimit,
                        exceedLimit;


                    if (o_nav !== 'thumbs' || isNaN(pos)) return;

                    leftLimit = -pos;
                    rightLimit = -pos + measures.nw;

                    if (opts.navdir === 'vertical') {
                        pos = pos - opts.thumbheight;
                        rightLimit = -pos + measures.h;
                    }

                    $navThumbFrame.each(function () {
                        var $this = $(this),
                            thisData = $this.data(),
                            eq = thisData.eq,
                            getSpecialMeasures = function () {
                                return {
                                    h: o_thumbSide2,
                                    w: thisData.w
                                }
                            },
                            specialMeasures = getSpecialMeasures(),
                            exceedLimit = opts.navdir === 'vertical' ?
                                thisData.t > rightLimit : thisData.l > rightLimit;
                        specialMeasures.w = thisData.w;

                        if ((opts.navdir !== 'vertical' && thisData.l + thisData.w < leftLimit)
                            || exceedLimit
                            || callFit(thisData.$img, specialMeasures)) return;

                        loadFLAG && loadImg([eq], 'navThumb', getSpecialMeasures);
                    });
                }

                function frameAppend($frames, $shaft, type) {
                    if (!frameAppend[type]) {

                        var thumbsFLAG = type === 'nav' && o_navThumbs,
                            left = 0,
                            top = 0;

                        $shaft.append(
                            $frames
                                .filter(function () {
                                    var actual,
                                        $this = $(this),
                                        frameData = $this.data();
                                    for (var _i = 0, _l = data.length; _i < _l; _i++) {
                                        if (frameData.data === data[_i]) {
                                            actual = true;
                                            frameData.eq = _i;
                                            break;
                                        }
                                    }
                                    return actual || $this.remove() && false;
                                })
                                .sort(function (a, b) {
                                    return $(a).data().eq - $(b).data().eq;
                                })
                                .each(function () {
                                    var $this = $(this),
                                        frameData = $this.data();
                                    UTIL.setThumbAttr($this, frameData.data.caption, "aria-label");
                                })
                                .each(function () {

                                    if (!thumbsFLAG) return;

                                    var $this = $(this),
                                        frameData = $this.data(),
                                        thumbwidth = Math.round(o_thumbSide2 * frameData.data.thumbratio) || o_thumbSide,
                                        thumbheight = Math.round(o_thumbSide / frameData.data.thumbratio) || o_thumbSide2;
                                    frameData.t = top;
                                    frameData.h = thumbheight;
                                    frameData.l = left;
                                    frameData.w = thumbwidth;

                                    $this.css({width: thumbwidth});

                                    top += thumbheight + opts.thumbmargin;
                                    left += thumbwidth + opts.thumbmargin;
                                })
                        );

                        frameAppend[type] = true;
                    }
                }

                function getDirection(x) {
                    return x - stageLeft > measures.w / 3;
                }

                function disableDirrection(i) {
                    return !o_loop && (!(activeIndex + i) || !(activeIndex - size + i)) && !$videoPlaying;
                }

                function arrsUpdate() {
                    var disablePrev = disableDirrection(0),
                        disableNext = disableDirrection(1);
                    $arrPrev
                        .toggleClass(arrDisabledClass, disablePrev)
                        .attr(disableAttr(disablePrev, false));
                    $arrNext
                        .toggleClass(arrDisabledClass, disableNext)
                        .attr(disableAttr(disableNext, false));
                }

                function thumbArrUpdate() {
                    var isLeftDisable = false,
                        isRightDisable = false;
                    if (opts.navtype === 'thumbs' && !opts.loop) {
                        (activeIndex == 0) ? isLeftDisable = true : isLeftDisable = false;
                        (activeIndex == opts.data.length - 1) ? isRightDisable = true : isRightDisable = false;
                    }
                    if (opts.navtype === 'slides') {
                        var pos = readPosition($navShaft, opts.navdir);
                        pos >= navShaftTouchTail.max ? isLeftDisable = true : isLeftDisable = false;
                        pos <= navShaftTouchTail.min ? isRightDisable = true : isRightDisable = false;
                    }
                    $thumbArrLeft
                        .toggleClass(arrDisabledClass, isLeftDisable)
                        .attr(disableAttr(isLeftDisable, true));
                    $thumbArrRight
                        .toggleClass(arrDisabledClass, isRightDisable)
                        .attr(disableAttr(isRightDisable, true));
                }

                function stageWheelUpdate() {
                    if (stageWheelTail.ok) {
                        stageWheelTail.prevent = {'<': disableDirrection(0), '>': disableDirrection(1)};
                    }
                }

                function getNavFrameBounds($navFrame) {
                    var navFrameData = $navFrame.data(),
                        left,
                        top,
                        width,
                        height;

                    if (o_navThumbs) {
                        left = navFrameData.l;
                        top = navFrameData.t;
                        width = navFrameData.w;
                        height = navFrameData.h;
                    } else {
                        left = $navFrame.position().left;
                        width = $navFrame.width();
                    }

                    var horizontalBounds = {
                        c: left + width / 2,
                        min: -left + opts.thumbmargin * 10,
                        max: -left + measures.w - width - opts.thumbmargin * 10
                    };

                    var verticalBounds = {
                        c: top + height / 2,
                        min: -top + opts.thumbmargin * 10,
                        max: -top + measures.h - height - opts.thumbmargin * 10
                    };

                    return opts.navdir === 'vertical' ? verticalBounds : horizontalBounds;
                }

                function slideThumbBorder(time) {
                    var navFrameData = activeFrame[navFrameKey].data();
                    slide($thumbBorder, {
                        time: time * 1.2,
                        pos: (opts.navdir === 'vertical' ? navFrameData.t : navFrameData.l),
                        width: navFrameData.w,
                        height: navFrameData.h,
                        direction: opts.navdir
                    });
                }

                function slideNavShaft(options) {
                    var $guessNavFrame = data[options.guessIndex][navFrameKey],
                        typeOfAnimation = opts.navtype;

                    var overflowFLAG,
                        time,
                        minMax,
                        boundTop,
                        boundLeft,
                        l,
                        pos,
                        x;

                    if ($guessNavFrame) {
                        if (typeOfAnimation === 'thumbs') {
                            overflowFLAG = navShaftTouchTail.min !== navShaftTouchTail.max;
                            minMax = options.minMax || overflowFLAG && getNavFrameBounds(activeFrame[navFrameKey]);
                            boundTop = overflowFLAG && (options.keep && slideNavShaft.t ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max));
                            boundLeft = overflowFLAG && (options.keep && slideNavShaft.l ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max));
                            l = (opts.navdir === 'vertical' ? boundTop : boundLeft);
                            pos = overflowFLAG && minMaxLimit(l, navShaftTouchTail.min, navShaftTouchTail.max) || 0;
                            time = options.time * 1.1;
                            slide($navShaft, {
                                time: time,
                                pos: pos,
                                direction: opts.navdir,
                                onEnd: function () {
                                    thumbsDraw(pos, true);
                                    thumbArrUpdate();
                                }
                            });

                            setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max, opts.navdir));
                            slideNavShaft.l = l;
                        } else {
                            x = readPosition($navShaft, opts.navdir);
                            time = options.time * 1.11;

                            pos = validateSlidePos(opts, navShaftTouchTail, options.guessIndex, x, $guessNavFrame, $navWrap, opts.navdir);

                            slide($navShaft, {
                                time: time,
                                pos: pos,
                                direction: opts.navdir,
                                onEnd: function () {
                                    thumbsDraw(pos, true);
                                    thumbArrUpdate();
                                }
                            });
                            setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max, opts.navdir));
                        }
                    }
                }

                function navUpdate() {
                    deactivateFrames(navFrameKey);
                    toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass).attr('data-active', true));
                }

                function deactivateFrames(key) {
                    var _toDeactivate = toDeactivate[key];

                    while (_toDeactivate.length) {
                        _toDeactivate.shift().removeClass(activeClass).attr('data-active', false);
                    }
                }

                function detachFrames(key) {
                    var _toDetach = toDetach[key];

                    $.each(activeIndexes, function (i, index) {
                        delete _toDetach[normalizeIndex(index)];
                    });

                    $.each(_toDetach, function (index, $frame) {
                        delete _toDetach[index];
                        $frame.detach();
                    });
                }

                function stageShaftReposition(skipOnEnd) {

                    repositionIndex = dirtyIndex = activeIndex;

                    var $frame = activeFrame[STAGE_FRAME_KEY];

                    if ($frame) {
                        deactivateFrames(STAGE_FRAME_KEY);
                        toDeactivate[STAGE_FRAME_KEY].push($frame.addClass(activeClass).attr('data-active', true));

                        if ($frame.hasClass(stageFrameClass)) {
                            $frame.attr('aria-hidden', 'false');
                        }

                        skipOnEnd || that.showStage.onEnd(true);
                        stop($stageShaft, 0, true);

                        detachFrames(STAGE_FRAME_KEY);
                        stageFramePosition(activeIndexes);
                        setStageShaftMinmaxAndSnap();
                        setNavShaftMinMax();
                        addEnterUp($stageShaft[0], function () {
                            if (!$fotorama.hasClass(fullscreenClass)) {
                                that.requestFullScreen();
                                $fullscreenIcon.focus();
                            }
                        });
                    }
                }

                function extendMeasures(options, measuresArray) {
                    if (!options) return;

                    $.each(measuresArray, function (i, measures) {
                        if (!measures) return;

                        $.extend(measures, {
                            width: options.width || measures.width,
                            height: options.height,
                            minwidth: options.minwidth,
                            maxwidth: options.maxwidth,
                            minheight: options.minheight,
                            maxheight: options.maxheight,
                            ratio: getRatio(options.ratio)
                        })
                    });
                }

                function triggerEvent(event, extra) {
                    $fotorama.trigger(_fotoramaClass + ':' + event, [that, extra]);
                }

                function onTouchStart() {
                    clearTimeout(onTouchEnd.t);
                    touchedFLAG = 1;

                    if (opts.stopautoplayontouch) {
                        that.stopAutoplay();
                    } else {
                        pausedAutoplayFLAG = true;
                    }
                }

                function onTouchEnd() {
                    if (!touchedFLAG) return;
                    if (!opts.stopautoplayontouch) {
                        releaseAutoplay();
                        changeAutoplay();
                    }

                    onTouchEnd.t = setTimeout(function () {
                        touchedFLAG = 0;
                    }, TRANSITION_DURATION + TOUCH_TIMEOUT);
                }

                function releaseAutoplay() {
                    pausedAutoplayFLAG = !!($videoPlaying || stoppedAutoplayFLAG);
                }

                function changeAutoplay() {

                    clearTimeout(changeAutoplay.t);
                    waitFor.stop(changeAutoplay.w);

                    if (!opts.autoplay || pausedAutoplayFLAG) {
                        if (that.autoplay) {
                            that.autoplay = false;
                            triggerEvent('stopautoplay');
                        }

                        return;
                    }

                    if (!that.autoplay) {
                        that.autoplay = true;
                        triggerEvent('startautoplay');
                    }

                    var _activeIndex = activeIndex;


                    var frameData = activeFrame[STAGE_FRAME_KEY].data();
                    changeAutoplay.w = waitFor(function () {
                        return frameData.state || _activeIndex !== activeIndex;
                    }, function () {
                        changeAutoplay.t = setTimeout(function () {

                            if (pausedAutoplayFLAG || _activeIndex !== activeIndex) return;

                            var _nextAutoplayIndex = nextAutoplayIndex,
                                nextFrameData = data[_nextAutoplayIndex][STAGE_FRAME_KEY].data();

                            changeAutoplay.w = waitFor(function () {

                                return nextFrameData.state || _nextAutoplayIndex !== nextAutoplayIndex;
                            }, function () {
                                if (pausedAutoplayFLAG || _nextAutoplayIndex !== nextAutoplayIndex) return;
                                that.show(o_loop ? getDirectionSign(!o_rtl) : nextAutoplayIndex);
                            });
                        }, opts.autoplay);
                    });

                }

                that.startAutoplay = function (interval) {
                    if (that.autoplay) return this;
                    pausedAutoplayFLAG = stoppedAutoplayFLAG = false;
                    setAutoplayInterval(interval || opts.autoplay);
                    changeAutoplay();

                    return this;
                };

                that.stopAutoplay = function () {
                    if (that.autoplay) {
                        pausedAutoplayFLAG = stoppedAutoplayFLAG = true;
                        changeAutoplay();
                    }
                    return this;
                };

                that.showSlide = function (slideDir) {
                    var currentPosition = readPosition($navShaft, opts.navdir),
                        pos,
                        time = 500 * 1.1,
                        size = opts.navdir === 'horizontal' ? opts.thumbwidth : opts.thumbheight,
                        onEnd = function () {
                            thumbArrUpdate();
                        };
                    if (slideDir === 'next') {
                        pos = currentPosition - (size + opts.margin) * thumbsPerSlide;
                    }
                    if (slideDir === 'prev') {
                        pos = currentPosition + (size + opts.margin) * thumbsPerSlide;
                    }
                    pos = validateRestrictions(pos, navShaftTouchTail);
                    thumbsDraw(pos, true);
                    slide($navShaft, {
                        time: time,
                        pos: pos,
                        direction: opts.navdir,
                        onEnd: onEnd
                    });
                };

                that.showWhileLongPress = function (options) {
                    if (that.longPress.singlePressInProgress) {
                        return;
                    }

                    var index = calcActiveIndex(options);
                    calcGlobalIndexes(index);
                    var time = calcTime(options) / 50;
                    var _activeFrame = activeFrame;
                    that.activeFrame = activeFrame = data[activeIndex];
                    var silent = _activeFrame === activeFrame && !options.user;

                    that.showNav(silent, options, time);

                    return this;
                };

                that.showEndLongPress = function (options) {
                    if (that.longPress.singlePressInProgress) {
                        return;
                    }

                    var index = calcActiveIndex(options);
                    calcGlobalIndexes(index);
                    var time = calcTime(options) / 50;
                    var _activeFrame = activeFrame;
                    that.activeFrame = activeFrame = data[activeIndex];

                    var silent = _activeFrame === activeFrame && !options.user;

                    that.showStage(silent, options, time);

                    showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex;
                    lastActiveIndex = activeIndex;
                    return this;
                };

                function calcActiveIndex (options) {
                    var index;

                    if (typeof options !== 'object') {
                        index = options;
                        options = {};
                    } else {
                        index = options.index;
                    }

                    index = index === '>' ? dirtyIndex + 1 : index === '<' ? dirtyIndex - 1 : index === '<<' ? 0 : index === '>>' ? size - 1 : index;
                    index = isNaN(index) ? undefined : index;
                    index = typeof index === 'undefined' ? activeIndex || 0 : index;

                    return index;
                }

                function calcGlobalIndexes (index) {
                    that.activeIndex = activeIndex = edgeIndex(index);
                    prevIndex = getPrevIndex(activeIndex);
                    nextIndex = getNextIndex(activeIndex);
                    nextAutoplayIndex = normalizeIndex(activeIndex + (o_rtl ? -1 : 1));
                    activeIndexes = [activeIndex, prevIndex, nextIndex];

                    dirtyIndex = o_loop ? index : activeIndex;
                }

                function calcTime (options) {
                    var diffIndex = Math.abs(lastActiveIndex - dirtyIndex),
                        time = getNumber(options.time, function () {
                            return Math.min(o_transitionDuration * (1 + (diffIndex - 1) / 12), o_transitionDuration * 2);
                        });

                    if (options.slow) {
                        time *= 10;
                    }

                    return time;
                }

                that.showStage = function (silent, options, time, e) {
                    if (e !== undefined && e.target.tagName == 'IFRAME') {
                        return;
                    }
                    unloadVideo($videoPlaying, activeFrame.i !== data[normalizeIndex(repositionIndex)].i);
                    frameDraw(activeIndexes, 'stage');
                    stageFramePosition(SLOW ? [dirtyIndex] : [dirtyIndex, getPrevIndex(dirtyIndex), getNextIndex(dirtyIndex)]);
                    updateTouchTails('go', true);

                    silent || triggerEvent('show', {
                        user: options.user,
                        time: time
                    });

                    pausedAutoplayFLAG = true;

                    var overPos = options.overPos;
                    var onEnd = that.showStage.onEnd = function (skipReposition) {
                        if (onEnd.ok) return;
                        onEnd.ok = true;

                        skipReposition || stageShaftReposition(true);

                        if (!silent) {
                            triggerEvent('showend', {
                                user: options.user
                            });
                        }

                        if (!skipReposition && o_transition && o_transition !== opts.transition) {
                            that.setOptions({transition: o_transition});
                            o_transition = false;
                            return;
                        }

                        updateFotoramaState();
                        loadImg(activeIndexes, 'stage');

                        updateTouchTails('go', false);
                        stageWheelUpdate();

                        stageCursor();
                        releaseAutoplay();
                        changeAutoplay();

                        if (that.fullScreen) {
                            activeFrame[STAGE_FRAME_KEY].find('.' + imgFullClass).attr('aria-hidden', false);
                            activeFrame[STAGE_FRAME_KEY].find('.' + imgClass).attr('aria-hidden', true)
                        } else {
                            activeFrame[STAGE_FRAME_KEY].find('.' + imgFullClass).attr('aria-hidden', true);
                            activeFrame[STAGE_FRAME_KEY].find('.' + imgClass).attr('aria-hidden', false)
                        }
                    };

                    if (!o_fade) {
                        slide($stageShaft, {
                            pos: -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex),
                            overPos: overPos,
                            time: time,
                            onEnd: onEnd
                        });
                    } else {
                        var $activeFrame = activeFrame[STAGE_FRAME_KEY],
                            $prevActiveFrame = data[lastActiveIndex] && activeIndex !== lastActiveIndex ? data[lastActiveIndex][STAGE_FRAME_KEY] : null;

                        fade($activeFrame, $prevActiveFrame, $stageFrame, {
                            time: time,
                            method: opts.transition,
                            onEnd: onEnd
                        }, fadeStack);
                    }

                    arrsUpdate();
                };

                that.showNav = function(silent, options, time){
                    thumbArrUpdate();
                    if (o_nav) {
                        navUpdate();

                        var guessIndex = limitIndex(activeIndex + minMaxLimit(dirtyIndex - lastActiveIndex, -1, 1));
                        slideNavShaft({
                            time: time,
                            coo: guessIndex !== activeIndex && options.coo,
                            guessIndex: typeof options.coo !== 'undefined' ? guessIndex : activeIndex,
                            keep: silent
                        });
                        if (o_navThumbs) slideThumbBorder(time);
                    }
                };

                that.show = function (options, e) {
                    that.longPress.singlePressInProgress = true;

                    var index = calcActiveIndex(options);
                    calcGlobalIndexes(index);
                    var time = calcTime(options);
                    var _activeFrame = activeFrame;
                    that.activeFrame = activeFrame = data[activeIndex];

                    var silent = _activeFrame === activeFrame && !options.user;

                    that.showStage(silent, options, time, e);
                    that.showNav(silent, options, time);

                    showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex;
                    lastActiveIndex = activeIndex;
                    that.longPress.singlePressInProgress = false;

                    return this;
                };

                that.requestFullScreen = function () {
                    if (o_allowFullScreen && !that.fullScreen) {

                        //check that this is not video
                        var isVideo = $((that.activeFrame || {}).$stageFrame || {}).hasClass('fotorama-video-container');
                        if(isVideo) {
                            return;
                        }

                        scrollTop = $WINDOW.scrollTop();
                        scrollLeft = $WINDOW.scrollLeft();

                        lockScroll($WINDOW);

                        updateTouchTails('x', true);

                        measuresStash = $.extend({}, measures);

                        $fotorama
                            .addClass(fullscreenClass)
                            .appendTo($BODY.addClass(_fullscreenClass));

                        $HTML.addClass(_fullscreenClass);

                        unloadVideo($videoPlaying, true, true);

                        that.fullScreen = true;

                        if (o_nativeFullScreen) {
                            fullScreenApi.request(fotorama);
                        }

                        that.resize();
                        loadImg(activeIndexes, 'stage');
                        updateFotoramaState();
                        triggerEvent('fullscreenenter');

                        if (!('ontouchstart' in window)) {
                            $fullscreenIcon.focus();
                        }
                    }

                    return this;
                };

                function cancelFullScreen() {
                    if (that.fullScreen) {
                        that.fullScreen = false;

                        if (FULLSCREEN) {
                            fullScreenApi.cancel(fotorama);
                        }

                        $BODY.removeClass(_fullscreenClass);
                        $HTML.removeClass(_fullscreenClass);

                        $fotorama
                            .removeClass(fullscreenClass)
                            .insertAfter($anchor);

                        measures = $.extend({}, measuresStash);

                        unloadVideo($videoPlaying, true, true);

                        updateTouchTails('x', false);

                        that.resize();
                        loadImg(activeIndexes, 'stage');

                        lockScroll($WINDOW, scrollLeft, scrollTop);

                        triggerEvent('fullscreenexit');
                    }
                }

                that.cancelFullScreen = function () {
                    if (o_nativeFullScreen && fullScreenApi.is()) {
                        fullScreenApi.cancel(document);
                    } else {
                        cancelFullScreen();
                    }

                    return this;
                };

                that.toggleFullScreen = function () {
                    return that[(that.fullScreen ? 'cancel' : 'request') + 'FullScreen']();
                };

                that.resize = function (options) {
                    if (!data) return this;

                    var time = arguments[1] || 0,
                        setFLAG = arguments[2];

                    thumbsPerSlide = getThumbsInSlide($wrap, opts);
                    extendMeasures(!that.fullScreen ? optionsToLowerCase(options) : {
                        width: $(window).width(),
                        maxwidth: null,
                        minwidth: null,
                        height: $(window).height(),
                        maxheight: null,
                        minheight: null
                    }, [measures, setFLAG || that.fullScreen || opts]);

                    var width = measures.width,
                        height = measures.height,
                        ratio = measures.ratio,
                        windowHeight = $WINDOW.height() - (o_nav ? $nav.height() : 0);

                    if (measureIsValid(width)) {
                        $wrap.css({width: ''});
                        $wrap.css({height: ''});
                        $stage.css({width: ''});
                        $stage.css({height: ''});
                        $stageShaft.css({width: ''});
                        $stageShaft.css({height: ''});
                        $nav.css({width: ''});
                        $nav.css({height: ''});
                        $wrap.css({minWidth: measures.minwidth || 0, maxWidth: measures.maxwidth || MAX_WIDTH});

                        if (o_nav === 'dots') {
                            $navWrap.hide();
                        }
                        width = measures.W = measures.w = $wrap.width();
                        measures.nw = o_nav && numberFromWhatever(opts.navwidth, width) || width;

                        $stageShaft.css({width: measures.w, marginLeft: (measures.W - measures.w) / 2});

                        height = numberFromWhatever(height, windowHeight);

                        height = height || (ratio && width / ratio);

                        if (height) {
                            width = Math.round(width);
                            height = measures.h = Math.round(minMaxLimit(height, numberFromWhatever(measures.minheight, windowHeight), numberFromWhatever(measures.maxheight, windowHeight)));
                            $stage.css({'width': width, 'height': height});

                            if (opts.navdir === 'vertical' && !that.fullscreen) {
                                $nav.width(opts.thumbwidth + opts.thumbmargin * 2);
                            }

                            if (opts.navdir === 'horizontal' && !that.fullscreen) {
                                $nav.height(opts.thumbheight + opts.thumbmargin * 2);
                            }

                            if (o_nav === 'dots') {
                                $nav.width(width)
                                    .height('auto');
                                $navWrap.show();
                            }

                            if (opts.navdir === 'vertical' && that.fullScreen) {
                                $stage.css('height', $WINDOW.height());
                            }

                            if (opts.navdir === 'horizontal' && that.fullScreen) {
                                $stage.css('height', $WINDOW.height() - $nav.height());
                            }

                            if (o_nav) {
                                switch (opts.navdir) {
                                    case 'vertical':
                                        $navWrap.removeClass(navShafthorizontalClass);
                                        $navWrap.removeClass(navShaftListClass);
                                        $navWrap.addClass(navShaftVerticalClass);
                                        $nav
                                            .stop()
                                            .animate({height: measures.h, width: opts.thumbwidth}, time);
                                        break;
                                    case 'list':
                                        $navWrap.removeClass(navShaftVerticalClass);
                                        $navWrap.removeClass(navShafthorizontalClass);
                                        $navWrap.addClass(navShaftListClass);
                                        break;
                                    default:
                                        $navWrap.removeClass(navShaftVerticalClass);
                                        $navWrap.removeClass(navShaftListClass);
                                        $navWrap.addClass(navShafthorizontalClass);
                                        $nav
                                            .stop()
                                            .animate({width: measures.nw}, time);
                                        break;
                                }

                                stageShaftReposition();
                                slideNavShaft({guessIndex: activeIndex, time: time, keep: true});
                                if (o_navThumbs && frameAppend.nav) slideThumbBorder(time);
                            }

                            measuresSetFLAG = setFLAG || true;

                            ready.ok = true;
                            ready();
                        }
                    }

                    stageLeft = $stage.offset().left;
                    setStagePosition();

                    return this;
                };

                that.setOptions = function (options) {
                    $.extend(opts, options);
                    reset();
                    return this;
                };

                that.shuffle = function () {
                    data && shuffle(data) && reset();
                    return this;
                };

                function setShadow($el, edge) {
                    if (o_shadows) {
                        $el.removeClass(shadowsLeftClass + ' ' + shadowsRightClass);
                        $el.removeClass(shadowsTopClass + ' ' + shadowsBottomClass);
                        edge && !$videoPlaying && $el.addClass(edge.replace(/^|\s/g, ' ' + shadowsClass + '--'));
                    }
                }

                that.longPress = {
                    threshold: 1,
                    count: 0,
                    thumbSlideTime: 20,
                    progress: function(){
                        if (!this.inProgress) {
                            this.count++;
                            this.inProgress = this.count > this.threshold;
                        }
                    },
                    end: function(){
                        if(this.inProgress) {
                            this.isEnded = true
                        }
                    },
                    reset: function(){
                        this.count = 0;
                        this.inProgress = false;
                        this.isEnded = false;
                    }
                };

                that.destroy = function () {
                    that.cancelFullScreen();
                    that.stopAutoplay();

                    data = that.data = null;

                    appendElements();

                    activeIndexes = [];
                    detachFrames(STAGE_FRAME_KEY);

                    reset.ok = false;

                    return this;
                };

                /**
                 *
                 * @returns {jQuery.Fotorama}
                 */
                that.playVideo = function () {
                    var dataFrame = activeFrame,
                        video = dataFrame.video,
                        _activeIndex = activeIndex;

                    if (typeof video === 'object' && dataFrame.videoReady) {
                        o_nativeFullScreen && that.fullScreen && that.cancelFullScreen();

                        waitFor(function () {
                            return !fullScreenApi.is() || _activeIndex !== activeIndex;
                        }, function () {
                            if (_activeIndex === activeIndex) {
                                dataFrame.$video = dataFrame.$video || $(div(videoClass)).append(createVideoFrame(video));
                                dataFrame.$video.appendTo(dataFrame[STAGE_FRAME_KEY]);

                                $wrap.addClass(wrapVideoClass);
                                $videoPlaying = dataFrame.$video;

                                stageNoMove();

                                $arrs.blur();
                                $fullscreenIcon.blur();

                                triggerEvent('loadvideo');
                            }
                        });
                    }

                    return this;
                };

                that.stopVideo = function () {
                    unloadVideo($videoPlaying, true, true);
                    return this;
                };

                that.spliceByIndex = function (index, newImgObj) {
                    newImgObj.i = index + 1;
                    newImgObj.img && $.ajax({
                        url: newImgObj.img,
                        type: 'HEAD',
                        success: function () {
                            data.splice(index, 1, newImgObj);
                            reset();
                        }
                    });
                };

                function unloadVideo($video, unloadActiveFLAG, releaseAutoplayFLAG) {
                    if (unloadActiveFLAG) {
                        $wrap.removeClass(wrapVideoClass);
                        $videoPlaying = false;

                        stageNoMove();
                    }

                    if ($video && $video !== $videoPlaying) {
                        $video.remove();
                        triggerEvent('unloadvideo');
                    }

                    if (releaseAutoplayFLAG) {
                        releaseAutoplay();
                        changeAutoplay();
                    }
                }

                function toggleControlsClass(FLAG) {
                    $wrap.toggleClass(wrapNoControlsClass, FLAG);
                }

                function stageCursor(e) {
                    if (stageShaftTouchTail.flow) return;

                    var x = e ? e.pageX : stageCursor.x,
                        pointerFLAG = x && !disableDirrection(getDirection(x)) && opts.click;

                    if (stageCursor.p !== pointerFLAG
                        && $stage.toggleClass(pointerClass, pointerFLAG)) {
                        stageCursor.p = pointerFLAG;
                        stageCursor.x = x;
                    }
                }

                $stage.on('mousemove', stageCursor);

                function clickToShow(showOptions, e) {
                    clearTimeout(clickToShow.t);

                    if (opts.clicktransition && opts.clicktransition !== opts.transition) {
                        setTimeout(function () {
                            var _o_transition = opts.transition;

                            that.setOptions({transition: opts.clicktransition});

                            // now safe to pass base transition to o_transition, so that.show will restor it
                            o_transition = _o_transition;
                            // this timeout is here to prevent jerking in some browsers
                            clickToShow.t = setTimeout(function () {
                                that.show(showOptions);
                            }, 10);
                        }, 0);
                    } else {
                        that.show(showOptions, e);
                    }
                }

                function onStageTap(e, toggleControlsFLAG) {
                    var target = e.target,
                        $target = $(target);
                    if ($target.hasClass(videoPlayClass)) {
                        that.playVideo();
                    } else if (target === fullscreenIcon) {
                        that.toggleFullScreen();
                    } else if ($videoPlaying) {
                        target === videoClose && unloadVideo($videoPlaying, true, true);
                    } else if (!$fotorama.hasClass(fullscreenClass)) {
                        that.requestFullScreen();
                    }
                }

                function updateTouchTails(key, value) {
                    stageShaftTouchTail[key] = navShaftTouchTail[key] = value;
                }

                stageShaftTouchTail = moveOnTouch($stageShaft, {
                    onStart: onTouchStart,
                    onMove: function (e, result) {
                        setShadow($stage, result.edge);
                    },
                    onTouchEnd: onTouchEnd,
                    onEnd: function (result) {
                        var toggleControlsFLAG;

                        setShadow($stage);
                        toggleControlsFLAG = (MS_POINTER && !hoverFLAG || result.touch) &&
                            opts.arrows;

                        if ((result.moved || (toggleControlsFLAG && result.pos !== result.newPos && !result.control)) && result.$target[0] !== $fullscreenIcon[0]) {
                            var index = getIndexByPos(result.newPos, measures.w, opts.margin, repositionIndex);

                            that.show({
                                index: index,
                                time: o_fade ? o_transitionDuration : result.time,
                                overPos: result.overPos,
                                user: true
                            });
                        } else if (!result.aborted && !result.control) {
                            onStageTap(result.startEvent, toggleControlsFLAG);
                        }
                    },
                    timeLow: 1,
                    timeHigh: 1,
                    friction: 2,
                    select: '.' + selectClass + ', .' + selectClass + ' *',
                    $wrap: $stage,
                    direction: 'horizontal'

                });

                navShaftTouchTail = moveOnTouch($navShaft, {
                    onStart: onTouchStart,
                    onMove: function (e, result) {
                        setShadow($nav, result.edge);
                    },
                    onTouchEnd: onTouchEnd,
                    onEnd: function (result) {

                        function onEnd() {
                            slideNavShaft.l = result.newPos;
                            releaseAutoplay();
                            changeAutoplay();
                            thumbsDraw(result.newPos, true);
                            thumbArrUpdate();
                        }

                        if (!result.moved) {
                            var target = result.$target.closest('.' + navFrameClass, $navShaft)[0];
                            target && onNavFrameClick.call(target, result.startEvent);
                        } else if (result.pos !== result.newPos) {
                            pausedAutoplayFLAG = true;
                            slide($navShaft, {
                                time: result.time,
                                pos: result.newPos,
                                overPos: result.overPos,
                                direction: opts.navdir,
                                onEnd: onEnd
                            });
                            thumbsDraw(result.newPos);
                            o_shadows && setShadow($nav, findShadowEdge(result.newPos, navShaftTouchTail.min, navShaftTouchTail.max, result.dir));
                        } else {
                            onEnd();
                        }
                    },
                    timeLow: .5,
                    timeHigh: 2,
                    friction: 5,
                    $wrap: $nav,
                    direction: opts.navdir
                });

                stageWheelTail = wheel($stage, {
                    shift: true,
                    onEnd: function (e, direction) {
                        onTouchStart();
                        onTouchEnd();
                        that.show({index: direction, slow: e.altKey})
                    }
                });

                navWheelTail = wheel($nav, {
                    onEnd: function (e, direction) {
                        onTouchStart();
                        onTouchEnd();
                        var newPos = stop($navShaft) + direction * .25;
                        $navShaft.css(getTranslate(minMaxLimit(newPos, navShaftTouchTail.min, navShaftTouchTail.max), opts.navdir));
                        o_shadows && setShadow($nav, findShadowEdge(newPos, navShaftTouchTail.min, navShaftTouchTail.max, opts.navdir));
                        navWheelTail.prevent = {'<': newPos >= navShaftTouchTail.max, '>': newPos <= navShaftTouchTail.min};
                        clearTimeout(navWheelTail.t);
                        navWheelTail.t = setTimeout(function () {
                            slideNavShaft.l = newPos;
                            thumbsDraw(newPos, true)
                        }, TOUCH_TIMEOUT);
                        thumbsDraw(newPos);
                    }
                });

                $wrap.hover(
                    function () {
                        setTimeout(function () {
                            if (touchedFLAG) return;
                            toggleControlsClass(!(hoverFLAG = true));
                        }, 0);
                    },
                    function () {
                        if (!hoverFLAG) return;
                        toggleControlsClass(!(hoverFLAG = false));
                    }
                );

                function onNavFrameClick(e) {
                    var index = $(this).data().eq;

                    if (opts.navtype === 'thumbs') {
                        clickToShow({index: index, slow: e.altKey, user: true, coo: e._x - $nav.offset().left});
                    } else {
                        clickToShow({index: index, slow: e.altKey, user: true});
                    }
                }

                function onArrClick(e) {
                    clickToShow({index: $arrs.index(this) ? '>' : '<', slow: e.altKey, user: true});
                }

                smartClick($arrs, function (e) {
                    stopEvent(e);
                    onArrClick.call(this, e);
                }, {
                    onStart: function () {
                        onTouchStart();
                        stageShaftTouchTail.control = true;
                    },
                    onTouchEnd: onTouchEnd
                });

                smartClick($thumbArrLeft, function (e) {
                    stopEvent(e);
                    if (opts.navtype === 'thumbs') {

                        that.show('<');
                    } else {
                        that.showSlide('prev')
                    }
                });

                smartClick($thumbArrRight, function (e) {
                    stopEvent(e);
                    if (opts.navtype === 'thumbs') {
                        that.show('>');
                    } else {
                        that.showSlide('next')
                    }

                });


                function addFocusOnControls(el) {
                    addFocus(el, function () {
                        setTimeout(function () {
                            lockScroll($stage);
                        }, 0);
                        toggleControlsClass(false);
                    });
                }

                $arrs.each(function () {
                    addEnterUp(this, function (e) {
                        onArrClick.call(this, e);
                    });
                    addFocusOnControls(this);
                });

                addEnterUp(fullscreenIcon, function () {
                    if ($fotorama.hasClass(fullscreenClass)) {
                        that.cancelFullScreen();
                        $stageShaft.focus();
                    } else {
                        that.requestFullScreen();
                        $fullscreenIcon.focus();
                    }

                });
                addFocusOnControls(fullscreenIcon);

                function reset() {
                    setData();
                    setOptions();

                    if (!reset.i) {
                        reset.i = true;
                        // Only once
                        var _startindex = opts.startindex;
                        activeIndex = repositionIndex = dirtyIndex = lastActiveIndex = startIndex = edgeIndex(_startindex) || 0;
                        /*(o_rtl ? size - 1 : 0)*///;
                    }

                    if (size) {
                        if (changeToRtl()) return;

                        if ($videoPlaying) {
                            unloadVideo($videoPlaying, true);
                        }

                        activeIndexes = [];
                        detachFrames(STAGE_FRAME_KEY);

                        reset.ok = true;

                        that.show({index: activeIndex, time: 0});
                        that.resize();
                    } else {
                        that.destroy();
                    }
                }

                function changeToRtl() {

                    if (!changeToRtl.f === o_rtl) {
                        changeToRtl.f = o_rtl;
                        activeIndex = size - 1 - activeIndex;
                        that.reverse();

                        return true;
                    }
                }

                $.each('load push pop shift unshift reverse sort splice'.split(' '), function (i, method) {
                    that[method] = function () {
                        data = data || [];
                        if (method !== 'load') {
                            Array.prototype[method].apply(data, arguments);
                        } else if (arguments[0] && typeof arguments[0] === 'object' && arguments[0].length) {
                            data = clone(arguments[0]);
                        }
                        reset();
                        return that;
                    }
                });

                function ready() {
                    if (ready.ok) {
                        ready.ok = false;
                        triggerEvent('ready');
                    }
                }

                reset();
            };
            $.fn.fotorama = function (opts) {
                return this.each(function () {
                    var that = this,
                        $fotorama = $(this),
                        fotoramaData = $fotorama.data(),
                        fotorama = fotoramaData.fotorama;

                    if (!fotorama) {
                        waitFor(function () {
                            return !isHidden(that);
                        }, function () {
                            fotoramaData.urtext = $fotorama.html();
                            new $.Fotorama($fotorama,
                                $.extend(
                                    {},
                                    OPTIONS,
                                    window.fotoramaDefaults,
                                    opts,
                                    fotoramaData
                                )
                            );
                        });
                    } else {
                        fotorama.setOptions(opts, true);
                    }
                });
            };
            $.Fotorama.instances = [];

            function calculateIndexes() {
                $.each($.Fotorama.instances, function (index, instance) {
                    instance.index = index;
                });
            }

            function addInstance(instance) {
                $.Fotorama.instances.push(instance);
                calculateIndexes();
            }

            function hideInstance(instance) {
                $.Fotorama.instances.splice(instance.index, 1);
                calculateIndexes();
            }

            $.Fotorama.cache = {};
            $.Fotorama.measures = {};
            $ = $ || {};
            $.Fotorama = $.Fotorama || {};
            $.Fotorama.jst = $.Fotorama.jst || {};

            $.Fotorama.jst.dots = function (v) {
                var __t, __p = '', __e = _.escape;
                __p += '<div class="fotorama__nav__frame fotorama__nav__frame--dot" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n    <div class="fotorama__dot"></div>\r\n</div>';
                return __p
            };

            $.Fotorama.jst.frameCaption = function (v) {
                var __t, __p = '', __e = _.escape;
                __p += '<div class="fotorama__caption" aria-hidden="true">\r\n    <div class="fotorama__caption__wrap" id="' +
                    ((__t = ( v.labelledby )) == null ? '' : __t) +
                    '">' +
                    ((__t = ( v.caption )) == null ? '' : __t) +
                    '</div>\r\n</div>\r\n';
                return __p
            };

            $.Fotorama.jst.style = function (v) {
                var __t, __p = '', __e = _.escape;
                __p += '.fotorama' +
                    ((__t = ( v.s )) == null ? '' : __t) +
                    ' .fotorama__nav--thumbs .fotorama__nav__frame{\r\npadding:' +
                    ((__t = ( v.m )) == null ? '' : __t) +
                    'px;\r\nheight:' +
                    ((__t = ( v.h )) == null ? '' : __t) +
                    'px}\r\n.fotorama' +
                    ((__t = ( v.s )) == null ? '' : __t) +
                    ' .fotorama__thumb-border{\r\nheight:' +
                    ((__t = ( v.h )) == null ? '' : __t) +
                    'px;\r\nborder-width:' +
                    ((__t = ( v.b )) == null ? '' : __t) +
                    'px;\r\nmargin-top:' +
                    ((__t = ( v.m )) == null ? '' : __t) +
                    'px}';
                return __p
            };

            $.Fotorama.jst.thumb = function (v) {
                var __t, __p = '', __e = _.escape;
                __p += '<div class="fotorama__nav__frame fotorama__nav__frame--thumb" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n    <div class="fotorama__thumb">\r\n    </div>\r\n</div>';
                return __p
            };
        }
    }
});


define('text!mage/gallery/gallery.html',[],function () { return '<!--\n/**\n * Copyright © Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n-->\n<div class="fotorama-item" data-gallery-role="gallery">\n    <div data-gallery-role="fotorama__focusable-start" tabindex="-1"></div>\n    <div class="fotorama__wrap fotorama__wrap--css3 fotorama__wrap--slide fotorama__wrap--toggle-arrows">\n        <div class="fotorama__stage" data-fotorama-stage="fotorama__stage">\n            <div class="fotorama__arr fotorama__arr--prev" tabindex="0" role="button" aria-label="Previous" data-gallery-role="arrow">\n                <div class="fotorama__arr__arr"></div>\n            </div>\n            <div class="fotorama__stage__shaft" tabindex="0" data-gallery-role="stage-shaft">\n            </div>\n            <div class="fotorama__arr fotorama__arr--next fotorama__arr--disabled" tabindex="-1" role="button"\n                 aria-label="Next" data-gallery-role="arrow">\n                <div class="fotorama__arr__arr"></div>\n            </div>\n            <div class="fotorama__video-close"></div>\n            <div class="fotorama__zoom-in" data-gallery-role="fotorama__zoom-in" aria-label="Zoom in" role="button" tabindex="0"></div>\n            <div class="fotorama__zoom-out" data-gallery-role="fotorama__zoom-out" aria-label="Zoom out" role="button" tabindex="0"></div>\n            <div class="fotorama__spinner"></div>\n        </div>\n        <div class="fotorama__nav-wrap" data-gallery-role="nav-wrap">\n            <div class="fotorama__nav fotorama__nav--thumbs">\n                <div class="fotorama__fullscreen-icon" data-gallery-role="fotorama__fullscreen-icon" tabindex="0" aria-label="Exit fullscreen" role="button"></div>\n                <div class="fotorama__thumb__arr fotorama__thumb__arr--left" role="button" aria-label="Previous" data-gallery-role="arrow" tabindex = "-1">\n                    <div class="fotorama__thumb--icon"></div>\n                </div>\n                <div class="fotorama__nav__shaft">\n                    <div class="fotorama__thumb-border"></div>\n                </div>\n                <div class="fotorama__thumb__arr fotorama__thumb__arr--right" role="button" aria-label="Next" data-gallery-role="arrow" tabindex = "-1">\n                    <div class="fotorama__thumb--icon"></div>\n                </div>\n            </div>\n        </div>\n    </div>\n    <div data-gallery-role="fotorama__focusable-end" tabindex="-1"></div>\n</div>\n<div class="magnifier-preview" data-gallery-role="magnifier" id="preview"></div>\n';});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('mage/gallery/gallery',[
    'jquery',
    'fotorama/fotorama',
    'underscore',
    'matchMedia',
    'mage/template',
    'text!mage/gallery/gallery.html',
    'uiClass',
    'mage/translate'
], function ($, fotorama, _, mediaCheck, template, galleryTpl, Class, $t) {
    'use strict';

    /* Init Fotorama to resolve the product page bundle issue*/
    fotorama.initialize();

    /**
     * Retrieves index if the main item.
     * @param {Array.<Object>} data - Set of gallery items.
     */
    var getMainImageIndex = function (data) {
            var mainIndex;

            if (_.every(data, function (item) {
                    return _.isObject(item);
                })
            ) {
                mainIndex = _.findIndex(data, function (item) {
                    return item.isMain;
                });
            }

            return mainIndex > 0 ? mainIndex : 0;
        },

        /**
         * Helper for parse translate property
         *
         * @param {Element} el - el that to parse
         * @returns {Array} - array of properties.
         */
        getTranslate = function (el) {
            var slideTransform = $(el).attr('style').split(';');

            slideTransform = $.map(slideTransform, function (style) {
                style = style.trim();

                if (style.startsWith('transform: translate3d')) {
                    return style.match(/transform: translate3d\((.+)px,(.+)px,(.+)px\)/);
                }

                return false;
            });

            return slideTransform.filter(Boolean);
        },

        /**
         * @param {*} str
         * @return {*}
         * @private
         */
        _toNumber = function (str) {
            var type = typeof str;

            if (type === 'string') {
                return parseInt(str); //eslint-disable-line radix
            }

            return str;
        };

    return Class.extend({

        defaults: {
            settings: {},
            config: {},
            startConfig: {}
        },

        /**
         * Checks if device has touch interface.
         * @return {Boolean} The result of searching touch events on device.
         */
        isTouchEnabled: (function () {
            return 'ontouchstart' in document.documentElement;
        })(),

        /**
         * Initializes gallery.
         * @param {Object} config - Gallery configuration.
         * @param {String} element - String selector of gallery DOM element.
         */
        initialize: function (config, element) {
            var self = this;

            this._super();

            _.bindAll(this,
                '_focusSwitcher'
            );

            /*turn off arrows for touch devices*/
            if (this.isTouchEnabled) {
                config.options.arrows = false;

                if (config.fullscreen) {
                    config.fullscreen.arrows = false;
                }
            }

            config.options.width = _toNumber(config.options.width);
            config.options.height = _toNumber(config.options.height);
            config.options.thumbwidth = _toNumber(config.options.thumbwidth);
            config.options.thumbheight = _toNumber(config.options.thumbheight);

            config.options.swipe = true;
            this.config = config;

            this.settings = {
                $element: $(element),
                $pageWrapper: $('body>.page-wrapper'),
                currentConfig: config,
                defaultConfig: _.clone(config),
                fullscreenConfig: _.clone(config.fullscreen),
                breakpoints: config.breakpoints,
                activeBreakpoint: {},
                fotoramaApi: null,
                isFullscreen: false,
                api: null,
                data: _.clone(config.data)
            };
            config.options.ratio = config.options.width / config.options.height;
            config.options.height = null;

            $.extend(true, this.startConfig, config);

            this.initGallery();
            this.initApi();
            this.setupBreakpoints();
            this.initFullscreenSettings();

            this.settings.$element.on('click', '.fotorama__stage__frame', function () {
                if (
                    !$(this).parents('.fotorama__shadows--left, .fotorama__shadows--right').length &&
                    !$(this).hasClass('fotorama-video-container')
                ) {
                    self.openFullScreen();
                }
            });

            if (this.isTouchEnabled && this.settings.isFullscreen) {
                this.settings.$element.on('tap', '.fotorama__stage__frame', function () {
                    var translate = getTranslate($(this).parents('.fotorama__stage__shaft'));

                    if (translate[1] === '0' && !$(this).hasClass('fotorama-video-container')) {
                        self.openFullScreen();
                        self.settings.$pageWrapper.hide();
                    }
                });
            }
        },

        /**
         * Open gallery fullscreen
         */
        openFullScreen: function () {
            this.settings.api.fotorama.requestFullScreen();
            this.settings.$fullscreenIcon.css({
                opacity: 1,
                visibility: 'visible',
                display: 'block'
            });
        },

        /**
         * Gallery fullscreen settings.
         */
        initFullscreenSettings: function () {
            var settings = this.settings,
                self = this;

            settings.$gallery = this.settings.$element.find('[data-gallery-role="gallery"]');
            settings.$fullscreenIcon = this.settings.$element.find('[data-gallery-role="fotorama__fullscreen-icon"]');
            settings.focusableStart = this.settings.$element.find('[data-gallery-role="fotorama__focusable-start"]');
            settings.focusableEnd = this.settings.$element.find('[data-gallery-role="fotorama__focusable-end"]');
            settings.closeIcon = this.settings.$element.find('[data-gallery-role="fotorama__fullscreen-icon"]');
            settings.fullscreenConfig.swipe = true;

            settings.$gallery.on('fotorama:fullscreenenter', function () {
                settings.closeIcon.show();
                settings.focusableStart.attr('tabindex', '0');
                settings.focusableEnd.attr('tabindex', '0');
                settings.focusableStart.bind('focusin', self._focusSwitcher);
                settings.focusableEnd.bind('focusin', self._focusSwitcher);
                settings.api.updateOptions(settings.defaultConfig.options, true);
                settings.api.updateOptions(settings.fullscreenConfig, true);

                if (!_.isEqual(settings.activeBreakpoint, {}) && settings.breakpoints) {
                    settings.api.updateOptions(settings.activeBreakpoint.options, true);
                }
                settings.isFullscreen = true;
            });

            settings.$gallery.on('fotorama:fullscreenexit', function () {
                /**
                 * Fixes to avoid open full screen image on clicking on the navigation arrows.
                 * Refer bug ticket for for info: FS-193
                 */
                $(".page-wrapper").scroll();
                settings.closeIcon.hide();
                settings.focusableStart.attr('tabindex', '-1');
                settings.focusableEnd.attr('tabindex', '-1');
                settings.api.updateOptions(settings.defaultConfig.options, true);
                settings.focusableStart.unbind('focusin', this._focusSwitcher);
                settings.focusableEnd.unbind('focusin', this._focusSwitcher);
                settings.closeIcon.hide();

                if (!_.isEqual(settings.activeBreakpoint, {}) && settings.breakpoints) {
                    settings.api.updateOptions(settings.activeBreakpoint.options, true);
                }
                settings.isFullscreen = false;
                settings.$element.data('gallery').updateOptions({
                    swipe: true
                });
            });
        },

        /**
         * Switcher focus.
         */
        _focusSwitcher: function (e) {
            var target = $(e.target),
                settings = this.settings;

            if (target.is(settings.focusableStart)) {
                this._setFocus('start');
            } else if (target.is(settings.focusableEnd)) {
                this._setFocus('end');
            }
        },

        /**
         * Set focus to element.
         * @param {String} position - can be "start" and "end"
         *      positions.
         *      If position is "end" - sets focus to first
         *      focusable element in modal window scope.
         *      If position is "start" - sets focus to last
         *      focusable element in modal window scope
         */
        _setFocus: function (position) {
            var settings = this.settings,
                focusableElements,
                infelicity;

            if (position === 'end') {
                settings.$gallery.find(settings.closeIcon).focus();
            } else if (position === 'start') {
                infelicity = 3; //Constant for find last focusable element
                focusableElements = settings.$gallery.find(':focusable');
                focusableElements.eq(focusableElements.length - infelicity).focus();
            }
        },

        /**
         * Initializes gallery with configuration options.
         */
        initGallery: function () {
            var breakpoints = {},
                settings = this.settings,
                config = this.config,
                tpl = template(galleryTpl, {
                    next: $t('Next'),
                    previous: $t('Previous')
                }),
                mainImageIndex;

            if (settings.breakpoints) {
                _.each(_.values(settings.breakpoints), function (breakpoint) {
                    var conditions;

                    _.each(_.pairs(breakpoint.conditions), function (pair) {
                        conditions = conditions ? conditions + ' and (' + pair[0] + ': ' + pair[1] + ')' :
                        '(' + pair[0] + ': ' + pair[1] + ')';
                    });
                    breakpoints[conditions] = breakpoint.options;
                });
                settings.breakpoints = breakpoints;
            }

            _.extend(config, config.options);
            config.options = undefined;

            config.click = false;
            config.breakpoints = null;
            settings.currentConfig = config;
            settings.$element.html(tpl);
            settings.$element.removeClass('_block-content-loading');
            settings.$elementF = $(settings.$element.children()[0]);
            settings.$elementF.fotorama(config);
            settings.fotoramaApi = settings.$elementF.data('fotorama');
            $.extend(true, config, this.startConfig);

            mainImageIndex = getMainImageIndex(config.data);

            if (mainImageIndex) {
                this.settings.fotoramaApi.show({
                    index: mainImageIndex,
                    time: 0
                });
            }
        },

        /**
         * Creates breakpoints for gallery.
         */
        setupBreakpoints: function () {
            var pairs,
                settings = this.settings,
                config = this.config,
                startConfig = this.startConfig,
                isTouchEnabled = this.isTouchEnabled;

            if (_.isObject(settings.breakpoints)) {
                pairs = _.pairs(settings.breakpoints);
                _.each(pairs, function (pair) {
                    mediaCheck({
                        media: pair[0],

                        /**
                         * Is triggered when breakpoint enties.
                         */
                        entry: function () {
                            $.extend(true, config, _.clone(startConfig));

                            settings.api.updateOptions(settings.defaultConfig.options, true);

                            if (settings.isFullscreen) {
                                settings.api.updateOptions(settings.fullscreenConfig, true);
                            }

                            if (isTouchEnabled) {
                                settings.breakpoints[pair[0]].options.arrows = false;

                                if (settings.breakpoints[pair[0]].options.fullscreen) {
                                    settings.breakpoints[pair[0]].options.fullscreen.arrows = false;
                                }
                            }

                            settings.api.updateOptions(settings.breakpoints[pair[0]].options, true);
                            $.extend(true, config, settings.breakpoints[pair[0]]);
                            settings.activeBreakpoint = settings.breakpoints[pair[0]];
                        },

                        /**
                         * Is triggered when breakpoint exits.
                         */
                        exit: function () {
                            $.extend(true, config, _.clone(startConfig));
                            settings.api.updateOptions(settings.defaultConfig.options, true);

                            if (settings.isFullscreen) {
                                settings.api.updateOptions(settings.fullscreenConfig, true);
                            }
                            settings.activeBreakpoint = {};
                        }
                    });
                });
            }
        },

        /**
         * Creates gallery's API.
         */
        initApi: function () {
            var settings = this.settings,
                config = this.config,
                api = {

                    /**
                     * Contains fotorama's API methods.
                     */
                    fotorama: settings.fotoramaApi,

                    /**
                     * Displays the last image on preview.
                     */
                    last: function () {
                        settings.fotoramaApi.show('>>');
                    },

                    /**
                     * Displays the first image on preview.
                     */
                    first: function () {
                        settings.fotoramaApi.show('<<');
                    },

                    /**
                     * Displays previous element on preview.
                     */
                    prev: function () {
                        settings.fotoramaApi.show('<');
                    },

                    /**
                     * Displays next element on preview.
                     */
                    next: function () {
                        settings.fotoramaApi.show('>');
                    },

                    /**
                     * Displays image with appropriate count number on preview.
                     * @param {Number} index - Number of image that should be displayed.
                     */
                    seek: function (index) {
                        if (_.isNumber(index) && index !== 0) {

                            if (index > 0) {
                                index -= 1;
                            }
                            settings.fotoramaApi.show(index);
                        }
                    },

                    /**
                     * Updates gallery with new set of options.
                     * @param {Object} configuration - Standart gallery configuration object.
                     * @param {Boolean} isInternal - Is this function called via breakpoints.
                     */
                    updateOptions: function (configuration, isInternal) {

                        var $selectable = $('a[href], area[href], input, select, ' +
                                'textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]')
                                .not('[tabindex=-1], [disabled], :hidden'),
                            $focus = $(':focus'),
                            index;

                        if (_.isObject(configuration)) {

                            //Saves index of focus
                            $selectable.each(function (number) {
                                if ($(this).is($focus)) {
                                    index = number;
                                }
                            });

                            if (this.isTouchEnabled) {
                                configuration.arrows = false;
                            }
                            configuration.click = false;
                            configuration.breakpoints = null;

                            if (!isInternal) {
                                !_.isEqual(settings.activeBreakpoint, {} && settings.brekpoints) ?
                                    $.extend(true, settings.activeBreakpoint.options, configuration) :

                                    settings.isFullscreen ?
                                        $.extend(true, settings.fullscreenConfig, configuration) :
                                        $.extend(true, settings.defaultConfig.options, configuration);

                            }
                            $.extend(true, settings.currentConfig.options, configuration);
                            settings.fotoramaApi.setOptions(settings.currentConfig.options);

                            if (_.isNumber(index)) {
                                $selectable.eq(index).focus();
                            }
                        }
                    },

                    /**
                     * Updates gallery with specific set of items.
                     * @param {Array.<Object>} data - Set of gallery items to update.
                     */
                    updateData: function (data) {
                        var mainImageIndex;

                        if (_.isArray(data)) {
                            settings.fotoramaApi.load(data);
                            mainImageIndex = getMainImageIndex(data);

                            if (mainImageIndex) {
                                settings.fotoramaApi.show({
                                    index: mainImageIndex,
                                    time: 0
                                });
                            }

                            $.extend(false, settings, {
                                data: data,
                                defaultConfig: data
                            });
                            $.extend(false, config, {
                                data: data
                            });
                        }
                    },

                    /**
                     * Returns current images list
                     *
                     * @returns {Array}
                     */
                    returnCurrentImages: function () {
                        var images = [];

                        _.each(this.fotorama.data, function (item) {
                            images.push(_.omit(item, '$navThumbFrame', '$navDotFrame', '$stageFrame', 'labelledby'));
                        });

                        return images;
                    },

                    /**
                     * Updates gallery data partially by index
                     * @param {Number} index - Index of image in data array to be updated.
                     * @param {Object} item - Standart gallery image object.
                     *
                     */
                    updateDataByIndex: function (index, item) {
                        settings.fotoramaApi.spliceByIndex(index, item);
                    }
                };

            settings.$element.data('gallery', api);
            settings.api = settings.$element.data('gallery');
            settings.$element.trigger('gallery:loaded');
        }
    });
});

define(
    'WeltPixel_OwlCarouselSlider/js/owlAjax',[
        'underscore',
        'jquery',
        'uiComponent',
        'Magento_Catalog/js/storage-manager',
        'Magento_Customer/js/customer-data',
        'mage/url'
    ],
    function (_, $, Component, storageManager, customerData, urlBuilder) {
        'use strict';

        return function(optionConfig){
            var recentlyViewedProductIds = [],
                currentTime = new Date().getTime() / 1000,
                recentlyViewedProductData = {},
                recentlyViewedProducts = storageManager().recently_viewed_product;
            if (recentlyViewedProducts) {
                recentlyViewedProductData = recentlyViewedProducts.get();
            }
            _.each(_.sortBy(recentlyViewedProductData, 'added_at'), function (id) {
                if (
                    currentTime - id['added_at'] < ~~recentlyViewedProducts.lifetime
                ) {
                    if (optionConfig.productId != id['product_id']) {
                        recentlyViewedProductIds.push(id['product_id'])
                    }
                }
            }, this);
            $.ajax({
                url: optionConfig.ajaxUrl,
                method: 'GET',
                cache: false,
                data: {
                    is_ajax: 1,
                    request_type: optionConfig.requestType,
                    productId: optionConfig.productId,
                    product_ids: recentlyViewedProductIds
                },
                success: function (result) {
                    $('#' + optionConfig.requestType).removeClass('products-loading');
                    if(result.errors) {
                        //$('#' + optionConfig.requestType).remove();
                    }
                    $('#' + optionConfig.requestType).html(result.block);

                    var checkWishlist = setInterval(function () {
                        var wishlist = customerData.get('wishlist')();

                        if (!_.isEmpty(wishlist) && _.isArray(wishlist.items) && wishlist.items.length) {

                            var wishlistIcons = $('#' + optionConfig.requestType).find('.towishlist');
                            wishlistIcons.each(function (index, item) {
                                item = $(item);
                                var productId = item.data('product-id');
                                var wishlistedItem = wishlist.items.find(function (item) {
                                    return parseInt(item.product_id) === productId;
                                });

                                if (wishlistedItem) {
                                    var url = window.location.origin + '/customer/wishlist/remove/item/' + wishlistedItem.wishlist_item_id;
                                    item.addClass('added-to-wishlist wishlisted test')
                                        .removeAttr('data-action')
                                        .removeAttr('data-post')
                                        .attr('href', url);
                                }
                            });
                            clearInterval(checkWishlist);
                        }
                    }, 100);
                }
            });
        };
    });

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Review/js/submit-review',[
    'jquery'
], function ($) {
    'use strict';

    return function (config, element) {
        $(element).on('submit', function () {
            if ($(this).valid()) {
                $(this).find('.submit').attr('disabled', true);
            }
        });
    };
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

/**
 @version 0.0.1
 @requires jQuery & jQuery UI
 */
define('Magento_ProductVideo/js/load-player',[
    'jquery',
    'jquery-ui-modules/widget'
], function ($) {
    'use strict';

    var videoRegister = {
        _register: {},

        /**
         * Checks, if api is already registered
         *
         * @param {String} api
         * @returns {bool}
         */
        isRegistered: function (api) {
            return this._register[api] !== undefined;
        },

        /**
         * Checks, if api is loaded
         *
         * @param {String} api
         * @returns {bool}
         */
        isLoaded: function (api) {
            return this._register[api] !== undefined && this._register[api] === true;
        },

        /**
         * Register new video api
         * @param {String} api
         * @param {bool} loaded
         */
        register: function (api, loaded) {
            loaded = loaded || false;
            this._register[api] = loaded;
        }
    };

    $.widget('mage.productVideoLoader', {

        /**
         * @private
         */
        _create: function () {
            switch (this.element.data('type')) {
                case 'youtube':
                    this.element.videoYoutube();
                    this._player = this.element.data('mageVideoYoutube');
                    break;

                case 'vimeo':
                    this.element.videoVimeo();
                    this._player = this.element.data('mageVideoVimeo');
                    break;
                default:
                    throw {
                        name: 'Video Error',
                        message: 'Unknown video type',

                        /**
                         * join name with message
                         */
                        toString: function () {
                            return this.name + ': ' + this.message;
                        }
                    };
            }
        },

        /**
         * Initializes variables
         * @private
         */
        _initialize: function () {
            this._params = this.element.data('params') || {};
            this._code = this.element.data('code');
            this._width = this.element.data('width');
            this._height = this.element.data('height');
            this._autoplay = !!this.element.data('autoplay');
            this._playing = this._autoplay || false;
            this._loop = this.element.data('loop');
            this._rel = this.element.data('related');
            this.useYoutubeNocookie = this.element.data('youtubenocookie') || false;

            this._responsive = this.element.data('responsive') !== false;

            if (this._responsive === true) {
                this.element.addClass('responsive');
            }

            this._calculateRatio();
        },

        /**
         * Abstract play command
         */
        play: function () {
            this._player.play();
        },

        /**
         * Abstract pause command
         */
        pause: function () {
            this._player.pause();
        },

        /**
         * Abstract stop command
         */
        stop: function () {
            this._player.stop();
        },

        /**
         * Abstract playing command
         */
        playing: function () {
            return this._player.playing();
        },

        /**
         * Destroyer
         */
        destroy: function () {
            this._player.destroy();
        },

        /**
         * Calculates ratio for responsive videos
         * @private
         */
        _calculateRatio: function () {
            if (!this._responsive) {
                return;
            }
            this.element.css('paddingBottom', this._height / this._width * 100 + '%');
        }
    });

    $.widget('mage.videoYoutube', $.mage.productVideoLoader, {

        /**
         * Initialization of the Youtube widget
         * @private
         */
        _create: function () {
            var self = this;

            this._initialize();

            this.element.append('<div/>');

            this._on(window, {

                /**
                 * Handle event
                 */
                'youtubeapiready': function () {
                    var host = 'https://www.youtube.com';

                    if (self.useYoutubeNocookie) {
                        host = 'https://www.youtube-nocookie.com';
                    }

                    if (self._player !== undefined) {
                        return;
                    }
                    self._autoplay = true;

                    if (self._autoplay) {
                        self._params.autoplay = 1;
                    }

                    if (!self._rel) {
                        self._params.rel = 0;
                    }

                    self._player = new window.YT.Player(self.element.children(':first')[0], {
                        height: self._height,
                        width: self._width,
                        videoId: self._code,
                        playerVars: self._params,
                        host: host,
                        events: {

                            /**
                             * Get duration
                             */
                            'onReady': function onPlayerReady() {
                                self._player.getDuration();
                                self.element.closest('.fotorama__stage__frame')
                                    .addClass('fotorama__product-video--loaded');
                            },

                            /**
                             * Event observer
                             */
                            onStateChange: function (data) {
                                switch (window.parseInt(data.data, 10)) {
                                    case 1:
                                        self._playing = true;
                                        break;
                                    default:
                                        self._playing = false;
                                        break;
                                }

                                self._trigger('statechange', {}, data);

                                if (data.data === window.YT.PlayerState.ENDED && self._loop) {
                                    self._player.playVideo();
                                }
                            }
                        }

                    });
                }
            });

            this._loadApi();
        },

        /**
         * Loads Youtube API and triggers event, when loaded
         * @private
         */
        _loadApi: function () {
            var element,
                scriptTag;

            if (videoRegister.isRegistered('youtube')) {
                if (videoRegister.isLoaded('youtube')) {
                    $(window).trigger('youtubeapiready');
                }

                return;
            }
            videoRegister.register('youtube');

            element = document.createElement('script');
            scriptTag = document.getElementsByTagName('script')[0];

            element.async = true;
            element.src = 'https://www.youtube.com/iframe_api';
            scriptTag.parentNode.insertBefore(element, scriptTag);

            /**
             * Event observe and handle
             */
            window.onYouTubeIframeAPIReady = function () {
                $(window).trigger('youtubeapiready');
                videoRegister.register('youtube', true);
            };
        },

        /**
         * Play command for Youtube
         */
        play: function () {
            this._player.playVideo();
            this._playing = true;
        },

        /**
         * Pause command for Youtube
         */
        pause: function () {
            this._player.pauseVideo();
            this._playing = false;
        },

        /**
         * Stop command for Youtube
         */
        stop: function () {
            this._player.stopVideo();
            this._playing = false;
        },

        /**
         * Playing command for Youtube
         */
        playing: function () {
            return this._playing;
        },

        /**
         * stops and unloads player
         * @private
         */
        destroy: function () {
            this.stop();
            this._player.destroy();
        }
    });

    $.widget('mage.videoVimeo', $.mage.productVideoLoader, {

        /**
         * Initialize the Vimeo widget
         * @private
         */
        _create: function () {
            var timestamp,
                additionalParams = '',
                src;

            this._initialize();
            timestamp = new Date().getTime();
            this._autoplay = true;

            if (this._autoplay) {
                additionalParams += '&autoplay=1';
            }

            if (this._loop) {
                additionalParams += '&loop=1';
            }
            src = 'https://player.vimeo.com/video/' +
                this._code + '?api=1&player_id=vimeo' +
                this._code +
                timestamp +
                additionalParams;
            this.element.append(
                $('<iframe/>')
                    .attr('frameborder', 0)
                    .attr('id', 'vimeo' + this._code + timestamp)
                    .attr('width', this._width)
                    .attr('height', this._height)
                    .attr('src', src)
                    .attr('webkitallowfullscreen', '')
                    .attr('mozallowfullscreen', '')
                    .attr('allowfullscreen', '')
                    .attr('referrerPolicy', 'origin')
            );
            this._player = window.$f(this.element.children(':first')[0]);

            // Froogaloop throws error without a registered ready event
            this._player.addEvent('ready', function (id) {
                $('#' + id).closest('.fotorama__stage__frame').addClass('fotorama__product-video--loaded');
            });
        },

        /**
         * Play command for Vimeo
         */
        play: function () {
            this._player.api('play');
            this._playing = true;
        },

        /**
         * Pause command for Vimeo
         */
        pause: function () {
            this._player.api('pause');
            this._playing = false;
        },

        /**
         * Stop command for Vimeo
         */
        stop: function () {
            this._player.api('unload');
            this._playing = false;
        },

        /**
         * Playing command for Vimeo
         */
        playing: function () {
            return this._playing;
        }
    });
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Catalog/js/product/view/product-ids',[
    'ko'
], function (ko) {
    'use strict';

    return ko.observableArray([]);
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define('Magento_Catalog/js/product/view/product-ids-resolver',[
    'underscore',
    'Magento_Catalog/js/product/view/product-ids'
], function (_, productIds) {
    'use strict';

    /**
     * Returns id's of products in form.
     *
     * @param {jQuery} $form
     * @return {Array}
     */
    return function ($form) {
        var idSet = productIds(),
            product = _.findWhere($form.serializeArray(), {
            name: 'product'
        });

        if (!_.isUndefined(product)) {
            idSet.push(product.value);
        }

        return _.uniq(idSet);
    };
});


define('text!Magento_InstantPurchase/template/instant-purchase.html',[],function () { return '<!--\n/**\n * Copyright © Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n-->\n<if args="showButton()">\n    <button type="button"\n            class="action primary instant-purchase"\n            click="instantPurchase"\n            attr="title: $t(buttonText)">\n        <span translate="buttonText"></span>\n    </button>\n    <input if="paymentToken()"\n           type="hidden"\n           name="instant_purchase_payment_token"\n           ko-value="paymentToken().publicHash" />\n    <input if="shippingAddress()"\n           type="hidden"\n           name="instant_purchase_shipping_address"\n           ko-value="shippingAddress().id" />\n    <input if="billingAddress()"\n           type="hidden"\n           name="instant_purchase_billing_address"\n           ko-value="billingAddress().id" />\n    <if args="shippingMethod()">\n        <input type="hidden"\n               name="instant_purchase_carrier"\n               ko-value="shippingMethod().carrier" />\n        <input type="hidden"\n               name="instant_purchase_shipping"\n               ko-value="shippingMethod().method" />\n    </if>\n</if>\n';});

define('Born_Bopis/js/product/stores-service',[
    'jquery',
    'mage/translate',
    'jquery/validate'
], function ($, $t) {
    "use strict";

    /**
     * return store common methods in the object.
     */
    return {
        map: false,
        markers: new Array(),
        infowindow: false,
        /**
         * search stores by term and return.
         * @param data
         * @param event
         */
        storeSearch: function (data, event) {
            let searchTerm = $.trim($(event.target).val().toLowerCase()),
                searchItems = new Array();
            $.each(data.items, function (key, item) {
                if (
                    item.city.toLowerCase().indexOf(searchTerm) !== -1
                    || item.zipCode.toLowerCase().indexOf(searchTerm) !== -1
                ) {
                    searchItems.push(item);
                }
            });
            if (!searchTerm) {
                data.storeItems(data.items);
            } else {
                data.storeItems(searchItems);
            }
            data.storesCountText($.mage.__('Available in %1 stores').replace('%1', searchItems.length.toString()));
        },

        /**
         * Add selected class to the item.
         * @param data
         * @param event
         */
        selectItem: function (item) {
            $('ul.stores-list li.store-item.selected').each(function (i) {
                $(this).removeClass('selected');
            });
            let $target = $('[data-store-code="' + item.storeCode + '"]');
            $target.addClass('selected');
            if ($('#pickup_store').length) {
                $('#pickup_store').val(item.storeCode);
                this.storeAddressToShippingAddress(item);
            }
            if ($('body').hasClass('bopis__checkout--container')) {
                $('html, body').animate({
                    scrollTop: $(".bopis__checkout--container #stores-map").offset().top
                }, 2000);
            }
            this.highlightStore(item.storeCode, 16);
        },

        /**
         * Fill shipping address.
         * @param storeitem
         */
        storeAddressToShippingAddress: function (storeitem) {
            const storeName = storeitem.storeName;
            var sname = storeName.replace(/[^a-zA-Z ]/g, "");
            let regionId = $('option[data-title="' + storeitem.state + '"]').attr('value'),
                telephone = (storeitem.storePhone) ? storeitem.storePhone : window.bopisConfig.customer_service_number,
                shippingFieldsMap = [
                    ['input[name="firstname"]', sname],
                    ['input[name="lastname"]', storeitem.storeCode],
                    ['input[name="street[0]"]', storeitem.address1],
                    ['select[name="region_id"]', regionId],
                    ['input[name="region"]', storeitem.state],
                    ['select[name="city_id"]', storeitem.city],
                    ['input[name="city"]', storeitem.city],
                    ['select[name="district_id"]', storeitem.district],
                    ['input[name="district"]', storeitem.district],
                    ['input[name="postcode"]', storeitem.zipCode],
                    ['input[name="telephone"]', telephone]
                ];
            $.each(shippingFieldsMap, function (key, shippingElement) {
                $(shippingElement[0]).val(shippingElement[1]);
                if (shippingElement[0] === 'select[name="city_id"]'
                    || shippingElement[0] === 'select[name="district_id"]'
                ) {
                    $(shippingElement[0] + ' option:eq(1)').attr('selected', 'selected');
                    $(shippingElement[0]).change();
                }
                $(shippingElement[0]).keyup();
            });
        },

        /**
         * initialize the google map.
         * @param stores
         */
        initMap: function (stores) {
            this.map = new window.google.maps.Map(document.getElementById('stores-map'), {
                zoom: parseInt(window.bopisConfig.default_zoom),
                center: new window.google.maps.LatLng(parseFloat(window.bopisConfig.default_lat), parseFloat(window.bopisConfig.default_lng)),
                disableDefaultUI: true
            });

            this.infowindow = new window.google.maps.InfoWindow();

            var marker, i, self = this;
            $.each(stores, function (key, store) {
                marker = new window.google.maps.Marker({
                    position: new window.google.maps.LatLng(parseFloat(store.latitude), parseFloat(store.longitude)),
                    map: self.map
                });
                self.markers[store.storeCode] = marker;
                window.google.maps.event.addListener(marker, 'click', (function (marker, i) {
                    return function () {
                        infowindow.setContent(store.storeName);
                        infowindow.open(self.map, marker);
                    }
                })(marker, i));
            });
        },

        /**
         * Highlight store on google map.
         * @param storeCode
         */
        highlightStore: function (storeCode, zoom) {
            var self = this;
            self.markers[storeCode].setAnimation(window.google.maps.Animation.BOUNCE);
            setTimeout(function () {
                self.markers[storeCode].setAnimation(null);
            }, 1000);
            self.map.setCenter(this.markers[storeCode].getPosition());
            self.map.setZoom(zoom);
        },

        /**
         * set current location.
         * @returns {boolean}
         */
        setCurrentLocation: function () {
            var self = this;
            if (!self.map) {
                return false;
            }
            if (window.navigator.geolocation) {
                window.navigator.geolocation.getCurrentPosition(function (position) {
                    var pos = {
                        lat: position.coords.latitude,
                        lng: position.coords.longitude
                    };

                    self.infowindow.setPosition(pos);
                    self.map.setCenter(pos);
                    self.map.setZoom(10);
                }, function () {
                    self.handleLocationError(true);
                });
            } else {
                self.handleLocationError(false);
            }
        },
        handleLocationError: function (browserHasGeolocation) {
            this.infowindow.setContent(browserHasGeolocation ?
                'Error: The Geolocation service failed.' :
                'Error: Your browser doesn\'t support geolocation.');
            this.infowindow.open(this.map);
        },

        /**
         * Find selected swatch and fetch product id from json configuration.
         * @returns {[]}
         */
        getSelectedProducts: function () {
            var foundIds = [];
            $('.swatch-error-notice').remove();
            let selected_options = {};
            if ($('.swatch-attribute').length) {
                $('.swatch-attribute .swatch-option').removeClass('error');
                $('div.swatch-attribute').each(function (k, v) {
                    let attribute_id    = $(v).attr('attribute-id'),
                        option_selected = $(v).attr('option-selected');
                    if (!attribute_id || !option_selected) {
                        return;
                    }
                    selected_options[attribute_id] = option_selected;
                });
                let product_id_index = $('[data-role=swatch-options]').data('mage-SwatchRenderer').options.jsonConfig.index;
                $.each(product_id_index, function (product_id, attributes) {
                    let productIsSelected = function (attributes, selected_options) {
                        return _.isEqual(attributes, selected_options);
                    };
                    if (productIsSelected(attributes, selected_options)) {
                        foundIds.push(product_id);
                    }
                });
            } else if ($('.product-options-wrapper  .field.configurable .control .super-attribute-select').length) {
               if ($("input[name=selected_configurable_option]").val()) {
                   let product_id = $("input[name=selected_configurable_option]").val();
                   foundIds.push(product_id);
               } else{
                   $('.product-options-wrapper  .field.configurable .control .super-attribute-select').removeClass('mage-error');
                   $('.product-options-wrapper  .field.configurable .control .super-attribute-select').each(function (k, v) {
                       let attribute_id    = $(v).attr('attribute-id'),
                           option_selected = $(v).val();
                       if (!attribute_id || !option_selected) {
                           return;
                       }
                       selected_options[attribute_id] = option_selected;
                   });

                   let product_id_index = $('#product_addtocart_form').data('mage-configurable').option('spConfig').childJson;
                   $.each(product_id_index, function (product_id, attributes) {
                       let productIsSelected = function (attributes, selected_options) {
                           return _.isEqual(attributes, selected_options);
                       };
                       if (productIsSelected(attributes, selected_options)) {
                           foundIds.push(product_id);
                       }
                   });
               }
            }


            return foundIds;
        }
    };
});

define('Born_Bopis/js/product/available-stores',[
    'jquery',
    'uiComponent',
    'ko',
    'mage/translate',
    'Magento_Ui/js/modal/modal',
    'Born_Bopis/js/map-loader',
    'Born_Bopis/js/product/stores-service'
], function ($, Component, ko, $t, popupModal, MapLoader, storeService) {
    'use strict';

    let self;
    return Component.extend({
        /**
         * observable store items
         */
        storeItems: ko.observable(null),

        /**
         * observable total count string
         */
        storesCountText: ko.observable(null),

        /**
         * set default options.
         */
        defaults: {
            items : [],
            template: 'Born_Bopis/available-stores/container',
            storeListTemplate: 'Born_Bopis/available-stores/storeList',
            product_qty: false,
            product_id: false
        },

        /**
         * init app
         */
        initialize: function () {
            self = this;
            this._super();
            popupModal({
                type: 'popup',
                responsive: true,
                innerScroll: true,
                buttons: []
            }, $('#available-stores-popup'));
            $(window).on('available.stores.change', this.updateAvailableStoresBlock.bind(this));
            if (this.product_qty) {
                let boxQty = this.product_qty, qtyBoxHtml = '', i;
                if (this.product_qty > 10) {
                    boxQty = 10;
                }
                for (i = 1; i <= boxQty; i++) {
                    qtyBoxHtml += '<option value="' + i + '">' + i + '</option>';
                }
                $('#product_addtocart_form #qty').html(qtyBoxHtml);
            }
        },

        /**
         * update fetched stores in list
         * @param e
         * @param params
         */
        updateAvailableStoresBlock: function (e, params) {
            if (params) {
                self.processStoreItems(params.data);
                self.items = params.data;
            } else {
                self.processStoreItems([]);
                self.items = params.data;
            }
        },

        /**
         * open popup modal and init google map
         * @param items
         */
        processStoreItems: function (items) {
            $("#available-stores-popup").modal("openModal");
            self.storesCountText($.mage.__('Available in %1 stores').replace('%1', items.length.toString()));
            self.storeItems(items);
            MapLoader.done($.proxy(storeService.initMap(items), this)).fail(function() {
                console.error("ERROR: Google maps library failed to load");
            });
        },

        /**
         * set current location on google map
         */
        setCurrentLocation: function () {
          storeService.setCurrentLocation();
        },

        /**
         *
         * @param item
         */
        selectItem: function (item) {
            storeService.selectItem(item);
            $('.search-result [role="alert"]').hide();
        },

        /**
         * On click of pick and collect delivery process
         * @param data
         * @param event
         */
        storeSearch: function (data, event) {
            storeService.storeSearch(data, event)
        },

        /**
         * prepare address format to show
         * @param item
         * @returns {string}
         */
        prepareAddress: function (item) {
            return item.address1 + ', ' + item.state + ', ' + item.city;
        },

        /**
         * Do nothing on store item render.
         * @param ele
         */
        restoreStoredQuoteData: function (ele) {
            return null;
        }
    });
});

define('Aheadworks_AdvancedReports/js/aw-advancedreports-ajax',[
    'jquery'
], function($) {
    "use strict";

    $.widget('mage.awAdvancedReportsAjax', {
        options: {
            url: '/'
        },

        /**
         * Initialize widget
         */
        _create: function () {
            this.ajax();
        },

        /**
         * Send AJAX request
         */
        ajax: function () {
            var data = {};

            $.ajax({
                url: this.options.url,
                data: data,
                type: 'GET',
                cache: false,
                dataType: 'json',
                context: this,
            });
        },
    });

    return $.mage.awAdvancedReportsAjax;
});

/**
 * jquery.stickOnScroll.js
 * A jQuery plugin for making element fixed on the page.
 *
 * Created by Paul Tavares on 2012-10-19.
 * Copyright 2012 Paul Tavares. All rights reserved.
 * Licensed under the terms of the MIT License
 *
 */

;(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define('stickyonScroll',['jquery'], factory);
    } else {
        factory(jQuery);
    }
}(function($){

    "use strict";
    /*jslint plusplus: true */
    /*global $,jQuery */

    var
        // Check if we're working in IE. Will control the animation
        // on the fixed elements.
        isIE = ($.support.optSelected === false ? true : false),

        // List of viewports and associated array of bound sticky elements
        viewports = {},

        // Local variable to hold methods
        fn = {};

    /**
     * Function bound to viewport's scroll event. Loops through
     * the list of elements that needs to be sticked for the
     * given viewport.
     * "this" keyword is assumed to be the viewport.
     *
     * @param {eventObject} jQuery's event object.
     *
     * @return {Object} The viewport (this keyword)
     *
     */
    function processElements(ev) {

        var elements = viewports[$(this).prop("stickOnScroll")],
            i,j;

        // Loop through all elements bound to this viewport.
        for( i=0,j=elements.length; i<j; i++ ){

            // Scope in the variables
            // We call this anonymous funnction with the
            // current array element ( elements[i] )
            (function(o){

                var scrollTop,
                    maxTop,
                    cssPosition,
                    footerTop,
                    eleHeight,
                    yAxis;

                // get this viewport options
                o = elements[i];

                // FIXME: Should the clean up of reference to removed element store the position in the array and delete it later?

                // If element has no parent, then it must have been removed from DOM...
                // Remove reference to it
                if (o !== null) {

                    // jquery contains works on dom object; not jquery selections
                    if (!$.contains(document.documentElement, o.ele[0])) {

                        elements[i] = o = null;

                    }

                }
                if (o !== null) {

                    // Get the scroll top position on the view port
                    scrollTop   = o.viewport.scrollTop();

                    // set the maxTop before we stick the element
                    // to be it's "normal" topPosition minus offset
                    maxTop      = o.getEleMaxTop();

                    // TODO: What about calculating top values with margin's set?
                    // pt.params.footer.css('marginTop').replace(/auto/, 0)

                    // If not using the window object, then stop any IE animation
                    if (o.isWindow === false && isIE) {
                        o.ele.stop();
                    }

                    // If the current scrollTop position is greater
                    // than our maxTop value, then make element stick on the page.
                    if (scrollTop >= maxTop){

                        cssPosition = {
                            position:   "fixed",
                            top:        ( o.topOffset - o.eleTopMargin )
                        };

                        if (o.isWindow === false) {

                            cssPosition = {
                                position:   "absolute",
                                top:        ( ( scrollTop + o.topOffset ) -  o.eleTopMargin )
                            };

                        }

                        o.isStick = true;

                        // ---> HAS FOOTER ELEMENT?
                        // check to see if it we're reaching the footer element,
                        // and if so, scroll the item up with the page
                        if  (o.footerElement.length) {

                            // Calculate the distance from the *bottom* of the fixed
                            // element to the footer element, taking into consideration
                            // the bottomOffset that may have been set by the user.
                            footerTop   = o.getEleTopPosition(o.footerElement);
                            eleHeight   = o.ele.outerHeight();
                            yAxis       = ( cssPosition.top + eleHeight +
                                            o.bottomOffset + o.topOffset );

                            if (o.isWindow === false) {

                                yAxis = (eleHeight + o.bottomOffset + o.topOffset);

                            } else {

                                yAxis = ( cssPosition.top + scrollTop +
                                          eleHeight + o.bottomOffset );

                                footerTop = o.getElementDistanceFromViewport(o.footerElement);

                            }

                            // If the footer element is overstopping the sticky element
                            // position, then adjust it so that we make room for the
                            // fotoer element.
                            if (yAxis > footerTop) {

                                if (o.isWindow === true) {

                                    cssPosition.top = (
                                            footerTop - ( scrollTop + eleHeight + o.bottomOffset )
                                        );

                                // Absolute positioned element
                                } else {

                                    cssPosition.top = (scrollTop - (yAxis - footerTop));

                                }

                            }

                        }

                        // If o.setParentOnStick is true, then set the
                        // height to this node's parent.
                        if (o.setParentOnStick === true) {

                            o.eleParent.css("height", o.eleParent.height());

                        }

                        // If o.setWidthOnStick is true, then set the width on the
                        // element that is about to be Sticky.
                        if (o.setWidthOnStick === true) {

                            o.ele.css("width", o.ele.css("width"));

                        }

                        // If we have additional stick offset, apply it now
                        if (!o.isViewportOffsetParent) {

                            cssPosition.top = (
                                cssPosition.top - o.getElementDistanceFromViewport(o.eleOffsetParent)
                            );

                        }

                        // Stick the element
                        if (isIE && o.isWindow === false) {

                            o.ele
                                .addClass(o.stickClass)
                                .css("position", cssPosition.position)
                                .animate({top: cssPosition.top}, 150);

                        } else {

                            o.ele
                                .css(cssPosition)
                                .addClass(o.stickClass);

                        }

                        // If making element stick now, then trigger
                        // onStick callback if any
                        if (o.wasStickCalled === false) {

                            o.wasStickCalled = true;

                            setTimeout(function(){

                                if (o.isOnStickSet === true) {

                                    o.onStick.call(o.ele, o.ele);

                                }

                                o.ele.trigger("stickOnScroll:onStick", [o.ele]);

                            }, 20);

                        }

                    // ELSE, If the scrollTop of the view port is
                    // less than the maxTop, then throw the element back into the
                    // page normal flow
                    } else if (scrollTop <= maxTop) {

                        if (o.isStick) {

                            // reset element
                            o.ele
                                .css({
                                    position: "",
                                    top: ""
                                })
                                .removeClass(o.stickClass);

                            o.isStick = false;

                            // Reset parent if o.setParentOnStick is true
                            if (o.setParentOnStick === true) {

                                o.eleParent.css("height", "");

                            }

                            // Reset the element's width if o.setWidthOnStick is true
                            if (o.setWidthOnStick === true) {

                                o.ele.css("width", "");

                            }

                            o.wasStickCalled = false;

                            setTimeout(function(){

                                // Execute the onUnStick if defined
                                if (o.isOnUnStickSet) {

                                    o.onUnStick.call( o.ele, o.ele );

                                }

                                o.ele.trigger("stickOnScroll:onUnStick", [o.ele]);

                            }, 20);

                        }
                    }

                    // Recalculate the original top position of the element...
                    // this could have changed from when element was initialized
                    // - ex. elements were inserted into DOM. We re-calculate only
                    // if the we're at the very top of the viewport, so that we can
                    // get a good position.
                    if (scrollTop === 0) {

                        o.setEleTop();

                    }

                }// is element setup null?

            })( elements[i] );

        }//end: for()

        return this;

    }//end: processElements()


    /**
     * Make the selected items stick to the top of the viewport
     * upon reaching a scrolling offset.
     * This method manipulates the following css properties on
     * the element that is to be sticky: top, position.
     * Elements also receive a css class named 'hasStickOnScroll'.
     *
     * @param {Object} options
     * @param {Integer} [options.topOffset=0]
     * @param {Integer} [options.bottomOffset=5]
     * @param {Object|HTMLElement|jQuery} [options.footerElement=null]
     * @param {Object|HTMLElement|jQuery} [options.viewport=window]
     * @param {String} [options.stickClass="stickOnScroll-on"]
     * @param {Boolean} [options.setParentOnStick=false]
     * @param {Boolean} [options.setWidthOnStick=false]
     * @param {Function} [options.onStick=null]
     * @param {Function} [options.onUnStick=null]
     *
     * @return {jQuery} this
     *
     */
    $.fn.stickOnScroll = function(options) {
        return this.each(function(){

            // If element already has stickonscroll, exit.
            if ($(this).hasClass("hasStickOnScroll")) {
                return this;
            }

            // Setup options for tis instance
            var o   = $.extend({}, {
                            topOffset:          0,
                            bottomOffset:       5,
                            footerElement:      null,
                            viewport:           window,
                            stickClass:         'stickOnScroll-on',
                            setParentOnStick:   false,
                            setWidthOnStick:    false,
                            onStick:            null,
                            onUnStick:          null
                        }, options),
                viewportKey,
                setIntID,
                setIntTries = 1800; // 1800 tries * 100 milliseconds = 3 minutes

            o.isStick                   = false;
            o.ele                       = $(this).addClass("hasStickOnScroll");
            o.eleParent                 = o.ele.parent();
            o.eleOffsetParent           = o.ele.offsetParent();
            o.viewport                  = $(o.viewport);
            o.eleTop                    = 0;
            o.eleTopMargin              = parseFloat(
                                            (o.ele.css("margin-top") || 0)
                                        ) || 0;
            o.footerElement             = $(o.footerElement);
            o.isWindow                  = true;
            o.isOnStickSet              = $.isFunction(o.onStick);
            o.isOnUnStickSet            = $.isFunction(o.onUnStick);
            o.wasStickCalled            = false;
            o.isViewportOffsetParent    = true;

            /**
             * Retrieves the element's top position based on the type of viewport
             * and sets on the options object for the instance. This Top position
             * is the element top position relative to the the viewport.
             *
             * @return {Integer}
             */
            o.setEleTop = function(){

                if (o.isStick === false) {

                    if (o.isWindow) {

                        o.eleTop = o.ele.offset().top;

                    } else {

                        o.eleTop = ( o.ele.offset().top - o.viewport.offset().top );

                    }

                }

            }; //end: o.setEleTop()

            /**
             * REturns an elements top position in relation
             * to the viewport's Top Position.
             *
             * @param {jQuery} $ele
             *          This element must be inside the viewport
             *
             * @return {Integer}
             *
             */
            o.getEleTopPosition = function($ele) {

                var pos = 0;

                if (o.isWindow) {

                    pos = $ele.offset().top;

                } else {

                    pos = ( $ele.offset().top - o.viewport.offset().top );

                }

                return pos;

            }; /* o.getEleTopPosition() */

            /**
             * Get's the MAX top position for the element before it
             * is made sticky. In some cases the max could be less
             * than the original position of the element, which means
             * the element would always be sticky... in these instances
             * the max top will be set to the element's top position.
             *
             * @return {Integer}
             */
            o.getEleMaxTop = function() {

                var max = ( ( o.eleTop - o.topOffset ));

                if (!o.isWindow) {

                    max = (max + o.eleTopMargin);

                    // If ele parent is not the viewport, then adjust the max top


                }

                return max;

            }; //end: o.getEleMaxTop()

            /**
             * Gets the distance between the top of the element and the
             * top of the viewport. Basically the offset from the top of
             * the "page" inside the viewport. This distance is alwasy the
             * same even if the viewport is scrolled. The only time it
             * changes is when elements are inserted or removed above the
             * the Element or item above it are hidden/displayed.
             * Methods uses the Position() values until it reaches the
             * viewport
             */
            o.getElementDistanceFromViewport = function($ele) {

                var distance    = $ele.position().top,
                    $parent     = $ele.offsetParent();

                // If the parent element is the root body element, then
                // we've reached the last possible offsetParent(). Exit
                if ($parent.is("body") || $parent.is("html")) {

                    return distance;

                }

                // If the positioned parent of this element is NOT
                // the viewport, then add the distance of that element's
                // top position
                if ($parent[0] !== o.viewport[0] ) {

                    distance = (
                        distance +
                        o.getElementDistanceFromViewport( $parent )
                    );

                // ELSE, this is the viewport... Adjust the elements
                // Distance by adding on the amount of scroll the element
                // currently has
                } else {

                    distance = (distance + o.viewport.scrollTop());

                }

                return distance;

            }; /* end: .getElementDistanceFromViewport() */

            // If setParentOnStick is true, and the parent element
            // is the <body>, then set setParentOnStick to false.
            if (o.setParentOnStick === true && o.eleParent.is("body")){

                o.setParentOnStick = false;

            }

            if (!$.isWindow(o.viewport[0])) {

                o.isWindow  = false;

            }

            /**
             * Adds this sticky element to the list of element for the viewport.
             *
             */
            function addThisEleToViewportList() {

                o.setEleTop();

                viewportKey = o.viewport.prop("stickOnScroll");

                // If the viewport is not the Window element, and the view port is not the
                // stick element's imediate offset parent, then we need to adjust the
                // top-offset so that element are position correctly.
                // See issue #3 on github
                if (!o.isWindow) {

                    o.isViewportOffsetParent    = ( o.eleOffsetParent[0] === o.viewport[0] );

                }

                // If this viewport is not yet defined, set it up now
                if (!viewportKey) {

                    viewportKey = "stickOnScroll" + String(Math.random()).replace(/\D/g,"");
                    o.viewport.prop("stickOnScroll", viewportKey);
                    viewports[viewportKey] = [];
                    o.viewport.on("scroll", processElements);

                }

                // Push this element's data to this view port's array
                viewports[viewportKey].push(o);

                // Trigger a scroll even
                o.viewport.scroll();

            } /* end: addThisEleToViewportList() */

            // If Element is not visible, then we have to wait until it is
            // in order to set it up. We need to obtain the top position of
            // the element in order to make the right decision when it comes
            // to making the element sticky.
            if (o.ele.is(":visible")) {

                addThisEleToViewportList();

            } else {

                setIntID = setInterval(function(){

                    if (o.ele.is(":visible") || !setIntTries) {

                        clearInterval(setIntID);
                        addThisEleToViewportList();

                    }

                    --setIntTries;

                }, 100);

            }

            return this;

        });//end: each()

    };//end: $.fn.stickOnScroll()

}));

/*
Author  : Born Group.
main jQuery widget of Fpmini
*/

define('Born_PerformanceFixes/js/product_page',[
    'jquery',
    'jquery/ui',
    'mage/translate',
    'Born_WeltPixelGtm/js/born_gtm',
    'mage/gallery/gallery',
    'owl_carousel',
    'slick',
    'fancybox',
    'stickyonScroll'
], function ($, ui, _responsive, born_gtm, gallery) {
    'use strict';

    $.widget('planetsports.initProductPage', {

        _create: function () {
            this.initProductPage();
        },

        initProductPage: function () {

            if ($('body.catalog-product-view').length) {
                var checkInterval = setInterval(function () {
                    var loaderContainer = $('.swatch-attribute');

                    //Return if loader still load
                    if (loaderContainer.length == 0) {
                        return;
                    }

                    /* FTLCKR-166: Fixed-qty dropdown update issue on PDP based on swatch selection*/
                    $('[class*="swatch-opt"]').on('click', '.swatch-option', function() {
                        let selectedProduct = (jQuery('[data-role=swatch-options]').data('mage-SwatchRenderer').getProduct());
                        if (selectedProduct.length) {
                            let allProductQty = $('[data-role=swatch-options]').data('mage-SwatchRenderer').options.jsonConfig.qty,
                                qtyBoxHtml = '', i, boxQty = 0;
                            boxQty = allProductQty[selectedProduct];
                            if (boxQty > window.maxQtyLimit) {
                                boxQty = window.maxQtyLimit;
                            }
                            for (i = 1; i <= boxQty; i++) {
                                qtyBoxHtml += '<option value="' + i + '">' + i + '</option>';
                            }
                            $('#product_addtocart_form #qty').html(qtyBoxHtml);
                        }
                    });

                    //On Page load, select the default size
                    var swatchLength = $('.swatch-option').length;
                    if(swatchLength == 1){
                        if($('.swatch-attribute').hasClass("size")){
                            $('.swatch-option').first().trigger('click');
                            $('.product-addtocart-button-cls').attr('enabled', true);
                        }
                    }

                    //Remove loader and clear update interval if content loaded
                    if (loaderContainer.length > 0) {
                        clearInterval(checkInterval);
                        var chartTitle = $.mage.__('Size Chart');
                        var swatchErrorTitle = $.mage.__('Choose Your Size');
                        var size_guide_info = '';
                        if ($('[data-size-guide="size_guide_info"]').length) {
                            size_guide_info = $.mage.__($('[data-size-guide="size_guide_info"]').text());
                        }

                        if(document.getElementById("sizechart-id") != null) {
                            var $widget = $('#volumental-widget-container').show();
                            var $notice = $('#volumental-notice').show();

                            var hasVolumental = $('#volumental-widget-container').length ? 'has_volumental' : '';

                            var $infoGuide = $('<div>', { class: 'swatch-size-info-guide' })
                                .append($widget)
                                .append($('<div>', { class: 'swatch-error-notice', text: swatchErrorTitle }))
                                .append($('<span>', { class: 'size-guide-info', text: size_guide_info }))
                                .append($('<a>', { href: '#', class: 'open-chart', text: chartTitle }))
                                .append($notice).addClass(hasVolumental);
                            $('.swatch-attribute[class*=size] .swatch-attribute-label').first().before($infoGuide);
                        }

                        $('.swatch-error-notice').hide();

                        $('.product-options-wrapper .open-chart').click(function (e) {
                            $.fancybox.open('#sizechart-id');
                        });
                        born_gtm.triggerChartTrack();
                        $('.swatch-attribute-label').parent().addClass('expanded');
                        $('.swatch-attribute-label').click(function () {
                            $(this).parent().toggleClass('expanded');
                        });

                        $('.swatch-option.text').click(function () {
                            $('.swatch-option.text').removeClass('error');
                            $('.swatch-error-notice').hide();
                        });
                    }
                }, 100);
                if ($(window).width() >= 769) {
                    if ($('.tabs-1.product.info.detailed').length){
                      $(".sticky-gallery")
                           .stickOnScroll({
                               topOffset:          $(".page-header").outerHeight()+70,
                               bottomOffset:       55,
                               footerElement:      $(".product.info.detailed"),
                               setParentOnStick:   true,
                               setWidthOnStick:    true
                           });
                    }
                   else if($('.bundle-options-container').length){
                      console.log("Ending");
                      $(".sticky-gallery")
                           .stickOnScroll({
                               topOffset:          $(".page-header").outerHeight()+70,
                               bottomOffset:       18,
                               footerElement:      $(".bundle-options-container"),
                               setParentOnStick:   true,
                               setWidthOnStick:    true
                           });
                    }
                    else if($('.pdp-description-section').length){
                      $(".sticky-gallery")
                           .stickOnScroll({
                               topOffset:          $(".page-header").outerHeight()+70,
                               bottomOffset:       55,
                               footerElement:      $(".pdp-description-section"),
                               setParentOnStick:   true,
                               setWidthOnStick:    true
                           });
                    }
                    else{
                      $(".sticky-gallery")
                           .stickOnScroll({
                               topOffset:          $(".page-header").outerHeight()+70,
                               bottomOffset:       55,
                               footerElement:      $(".page-bottom"),
                               setParentOnStick:   true,
                               setWidthOnStick:    true
                           });
                    }
                   }
                $('.desc-wrap h1').click(function () {
                    $(this).parent().toggleClass('expanded');
                });
                $('.product-info-similar h2').click(function () {
                    $(this).parent().toggleClass('expanded');
                });
                var discPrice = $('.product-info-main > .discount-pdp');
                $('.product-info-main .old-price.sly-old-price').append(discPrice);
                if ($(window).width() <= 767) {
                    var wishlist = $('.product-info-main .product-addto-links').clone();
                    $('.product.info.detailed').after(wishlist);

                    $('.product.data.items .data.item.title').click(function () {
                        $(this).toggleClass('expanded');
                    });

                    var checkIntervalPhoto = setInterval(function () {
                        if ($('.fotorama__nav.fotorama__nav--thumbs').length) {
                            $('.fotorama__stage').height($('.fotorama__stage').width());
                            clearInterval(checkIntervalPhoto);
                        }
                    }, 1000);
                }
                var boxqty = $('.box-tocart .field.qty').clone();
                $('.product.attribute.sku').before(boxqty);

                var windowWidthPdp = $(window).width();
                $('#buy-now, .buynow-btn-sticky').click(function () {
                    if ($('.swatch-attribute').length) {
                        var attrId = $('.swatch-attribute').attr('attribute-id');
                        var checkInterval = setInterval(function () {
                            if ($('.super-attribute-select').hasClass('mage-error')) {
                                $(".swatch-option.text").addClass('error');
                                $('.super-attribute-select.mage-error + div').hide();
                                $('.swatch-error-notice').show();
                            } else {
                                $(".swatch-option.text").removeClass('error');
                                $('.swatch-error-notice').hide();
                            }
                            clearInterval(checkInterval);
                        }, 500);
                    }
                    if (windowWidthPdp < 768) {
                        setTimeout(function () {
                            //  $('html,body').animate({ scrollTop: $('.swatch-opt').offset().top - 100 }, 'fast');
                        }, 50)
                    } else {
                        setTimeout(function () {
                            $('html,body').animate({ scrollTop: $('.breadcrumbs').offset().top - 100 }, 'fast');
                        }, 50)
                    }
                });

                $('.product-addtocart-button-cls').click(function () {
                    if ($('.swatch-attribute').length) {
                        var attrId = $('.swatch-attribute').attr('attribute-id');
                        var checkInterval = setInterval(function () {
                            if ($('.super-attribute-select').hasClass('mage-error')) {
                                $(".swatch-option.text").addClass('error');
                                $('.super-attribute-select.mage-error + div').hide();
                                $('.swatch-error-notice').show();
                            } else {
                                $(".swatch-option.text").removeClass('error');
                                $('.swatch-error-notice').hide();
                            }
                            clearInterval(checkInterval);
                        }, 500);
                    }
                    if (windowWidthPdp < 768) {
                        setTimeout(function () {
                            //$('html,body').animate({ scrollTop: $('.swatch-opt').offset().top - 100 }, 'fast');
                        }, 50);
                    } else {
                        setTimeout(function () {
                            $('html,body').animate({ scrollTop: $('.breadcrumbs').offset().top - 100 }, 'fast');
                        }, 50);
                    }
                });

                $(document).on('mouseover', '.fotorama__nav__frame', function () {
                    // Code to display the current hovered thumbnail as main image.
                    var $fotoramaDiv = $(this).parents('.fotorama'),
                        fotoramaApi = $fotoramaDiv.data('fotorama');
                    fotoramaApi.show({
                        index: $('.fotorama__nav__frame', $fotoramaDiv).index(this)
                    });
                });

                if ($(window).width() < 769) {
                    if ($('body').hasClass('.catalog-product-view')) {
                        $(".header-top").css('display', 'none');
                    }
                }
                $(document).ready(function () {
                    if($(window).width() < 769){
                        $('[data-gallery-role=gallery-placeholder]').on('gallery:loaded', function () {
                            if ($('.amlabel-position-wrapper').length) {
                                $(".amlabel-position-wrapper").appendTo(".gallery-placeholder .fotorama__stage");
                                $('.amlabel-position-wrapper').addClass('amlabel-loaded');
                            }
                        });
                    }
                    $("#how-to-find-btn").click(function() {
                        $('.fancybox-inner').animate({
                            scrollTop: $("#how-to-find").offset().top
                        }, 1000);
                    });
                    $("#free-returns-btn").click(function() {
                        $('.fancybox-inner').animate({
                            scrollTop: $("#free-returns").offset().top
                        }, 1000);
                    });
                    //Sticky Add to cart_
                    if ($(window).width() < 769) {
                        $('.catalog-product-view .box-tocart').addClass('pdpsticky');
                    }

                    /* show social share icon on mouse over on PDP page*/
                    $('[data-action="social-sharing"]').on('mouseenter', function () {
                        $('[data-action="social-media-icons"]').removeClass('hidden');
                        $(this).addClass('hidden');
                        setTimeout(function () {
                            $('.social-icons').each(function () {
                                $(this).attr('onClick', $(this).data('click'));

                            });
                        }, 500);
                    });
                    $('[data-action="social-media-icons"]').on('mouseleave', function () {
                        $(this).addClass('hidden');
                        $('[data-action="social-sharing"]').removeClass('hidden');
                        setTimeout(function () {
                            $('.social-icons').each(function () {
                                $(this).removeAttr('onClick');
                            });
                        }, 500);
                    });

                    /* after option selected enable add to cart button */
                    $('body').on('click', '.swatch-option', function () {
                        if ($('.swatch-option.selected').length > 0 || $('select.swatch-select').children("option:selected").val() > 0) {
                            $('.product-addtocart-button-cls').removeAttr('disabled');
                            if ($('.price-range-container').length > 0) {
                                $('.price-wrapper-container, .price-range-container').removeClass('no-display');
                                $('.price-range-container').addClass('no-display');
                            }
                        } else {
                            $('.product-addtocart-button-cls').attr('disabled', true);
                            if ($('.price-range-container').length > 0) {
                                $('.price-wrapper-container, .price-range-container').removeClass('no-display');
                                $('.price-wrapper-container').addClass('no-display');
                            }
                        }
                    });
                    //sticky description
                    if ($(window).width() < 767) {
                        //$(".product-info-main").insertBefore(".product.media");
                    }

                    if ($(window).width() < 767) {
                        $(".more_button").click(function () {
                            // If More Info button is clicked then scroll to and open the Details (description) tab.
                            $("#tab-label-description").trigger("click");
                            $('html,body').animate({
                                scrollTop: $(".pdp-description-section").offset().top
                            }, 'slow');
                        });
                    } else {
                        $(".more_button").click(function () {
                            // If More Info button is clicked then scroll to and open the Details (description) tab.
                            $("#tab-label-description").trigger("click");
                            $('html,body').animate({
                                scrollTop: $(".pdp-description-section").offset().top - 250
                            }, 'slow');
                        });
                    }

                    if ($(window).width() > 767) {
                        $.fn.is_on_screen = function () {
                            var win = $(window);
                            var viewport = {
                                top: win.scrollTop(),
                                left: win.scrollLeft()
                            };
                            viewport.right = viewport.left + win.width();
                            viewport.bottom = viewport.top + win.height();

                            var bounds = this.offset();
                            bounds.right = bounds.left + this.outerWidth();
                            bounds.bottom = bounds.top + this.outerHeight();

                            return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
                        };
                    }
                });
            }
        }

    });

    return $.planetsports.initProductPage;

});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Catalog/js/gallery',[
    'jquery',
    'jquery-ui-modules/widget'
], function ($) {
    'use strict';

    $.widget('mage.gallery', {
        options: {
            minWidth: 300, // Minimum width of the gallery image.
            widthOffset: 90, // Offset added to the width of the gallery image.
            heightOffset: 210, // Offset added to the height of the gallery image.
            closeWindow: 'div.buttons-set a[role="close-window"]' // Selector for closing the gallery popup window.
        },

        /**
         * Bind click handler for closing the popup window and resize the popup based on the image size.
         * @private
         */
        _create: function () {
            $(this.options.closeWindow).on('click', function () {
                window.close();
            });
            this._resizeWindow();
        },

        /**
         * Resize the gallery image popup window based on the image's dimensions.
         * @private
         */
        _resizeWindow: function () {
            var img = this.element,
                width = img.width() < this.options.minWidth ? this.options.minWidth : img.width();

            window.resizeTo(width + this.options.widthOffset, img.height() + this.options.heightOffset);
        }
    });

    return $.mage.gallery;
});

define('Born_Bopis/js/product/fetch-sources',['jquery', 'Born_Bopis/js/product/stores-service'], function($, storesService) {
    "use strict";

    /**
     * declare widget.
     */
    $.widget('productSources.ajax', {
        /**
         * set default options.
         */
        options: {
            method: 'get',
            triggerEvent: 'click',
            ajaxData: {}
        },

        /**
         * @private
         */
        _create: function() {
            this._bind();
        },

        /**
         * @private
         */
        _bind: function() {
            var self = this;
            self.element.on(self.options.triggerEvent, function(event) {
                event.preventDefault();
                if (self.validate()) {
                    self._ajaxSubmit();
                } else {
                    $('#product-options-wrapper').scroll();
                }
            });
        },

        /**
         * ajax request
         * @private
         */
        _ajaxSubmit: function() {
            /**
             * @todo not working for urls
             * @type {availableStores.ajax}
             */
            var self = this;
            $.ajax({
                url: self.options.ajaxUrl,
                type: self.options.method,
                data: self.options.ajaxData,
                dataType: 'json',
                beforeSend: function() {
                    $('body').trigger('processStart');
                },
                success: function(result) {
                    $('body').trigger('processStop');
                    $(window).trigger('available.stores.change', {
                        data: self.refactorItems(result)
                    });
                }
            });
        },

        /**
         * validate add to cart form.
         * @returns {boolean}
         */
        validate: function() {
            let foundIds = [];
            let quantity = $('#product_addtocart_form #qty').val();
            if ($('.swatch-attribute').length) {
                foundIds = storesService.getSelectedProducts();
                if (!foundIds.length) {
                    const swatchErrorTitle = 'Choose Your Size';
                    $('.swatch-attribute .swatch-attribute-label').append('<div class="swatch-error-notice">' + swatchErrorTitle + '</div>');
                    $('.swatch-attribute .swatch-option').addClass('error');
                    return false;
                }
            } else if ($('.product-options-wrapper  .field.configurable .control .super-attribute-select').length) {
                foundIds = storesService.getSelectedProducts();
                if (!foundIds.length) {
                    const swatchErrorTitle = 'Choose Your Size';
                    $('.product-options-wrapper .field.configurable .control').append('<div class="swatch-error-notice">' + swatchErrorTitle + '</div>');
                    $('.product-options-wrapper  .field.configurable .control .super-attribute-select').addClass('mage-error');
                    return false;
                }
            } else {
                foundIds.push(this.options.product_id);
            }
            this.options.ajaxData = {product:foundIds, qty:quantity};

            return true;
        },

        /**
         * prepare items from result.
         * @param result
         * @returns {any[]}
         */
        refactorItems: function (result) {
            if (typeof(result.success) != "undefined" && result.success) {
                return result.data;
            }

            return [];
        }
    });

    return $.productSources.ajax;
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('mage/ie-class-fixer',[], function () {
    'use strict';

    if (navigator.userAgent.match(/Trident.*rv[ :]*11\./)) {
        document.documentElement.classList.add('ie11');
    }
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Catalog/product/view/validation',[
    'jquery',
    'jquery-ui-modules/widget',
    'mage/validation/validation'
], function ($) {
    'use strict';

    $.widget('mage.validation', $.mage.validation, {
        options: {
            radioCheckboxClosest: 'ul, ol',

            /**
             * @param {*} error
             * @param {HTMLElement} element
             */
            errorPlacement: function (error, element) {
                var messageBox,
                    dataValidate;

                if ($(element).hasClass('datetime-picker')) {
                    element = $(element).parent();

                    if (element.parent().find('.mage-error').length) {
                        return;
                    }
                }

                if (element.attr('data-errors-message-box')) {
                    messageBox = $(element.attr('data-errors-message-box'));
                    messageBox.html(error);

                    return;
                }

                dataValidate = element.attr('data-validate');

                if (dataValidate && dataValidate.indexOf('validate-one-checkbox-required-by-name') > 0) {
                    error.appendTo('#links-advice-container');
                } else if (element.is(':radio, :checkbox')) {
                    element.closest(this.radioCheckboxClosest).after(error);
                } else {
                    element.after(error);
                }
            },

            /**
             * @param {HTMLElement} element
             * @param {String} errorClass
             */
            highlight: function (element, errorClass) {
                var dataValidate = $(element).attr('data-validate');

                if (dataValidate && dataValidate.indexOf('validate-required-datetime') > 0) {
                    $(element).parent().find('.datetime-picker').each(function () {
                        $(this).removeClass(errorClass);

                        if ($(this).val().length === 0) {
                            $(this).addClass(errorClass);
                        }
                    });
                } else if ($(element).is(':radio, :checkbox')) {
                    $(element).closest(this.radioCheckboxClosest).addClass(errorClass);
                } else {
                    $(element).addClass(errorClass);
                }
            },

            /**
             * @param {HTMLElement} element
             * @param {String} errorClass
             */
            unhighlight: function (element, errorClass) {
                var dataValidate = $(element).attr('data-validate');

                if (dataValidate && dataValidate.indexOf('validate-required-datetime') > 0) {
                    $(element).parent().find('.datetime-picker').removeClass(errorClass);
                } else if ($(element).is(':radio, :checkbox')) {
                    $(element).closest(this.radioCheckboxClosest).removeClass(errorClass);
                } else {
                    $(element).removeClass(errorClass);
                }
            }
        }
    });

    return $.mage.validation;
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Review/js/process-reviews',[
    'jquery',
    'tabs',
    'collapsible'
], function ($) {
    'use strict';

    /**
     * @param {String} url
     * @param {*} fromPages
     */
    function processReviews(url, fromPages) {
        $.ajax({
            url: url,
            cache: true,
            dataType: 'html',
            showLoader: false,
            loaderContext: $('.product.data.items')
        }).done(function (data) {
            $('#product-review-container').html(data).trigger('contentUpdated');
            $('[data-role="product-review"] .pages a').each(function (index, element) {
                $(element).on('click', function (event) { //eslint-disable-line max-nested-callbacks
                    processReviews($(element).attr('href'), true);
                    event.preventDefault();
                });
            });
        }).always(function () {
            if (fromPages == true) { //eslint-disable-line eqeqeq
                $('html, body').animate({
                    scrollTop: $('#reviews').offset().top - 50
                }, 300);
            }
        });
    }

    return function (config) {
        var reviewTab = $(config.reviewsTabSelector),
            requiredReviewTabRole = 'tab';

        if (reviewTab.attr('role') === requiredReviewTabRole && reviewTab.hasClass('active')) {
            processReviews(config.productReviewUrl, location.hash === '#reviews');
        } else {
            reviewTab.one('beforeOpen', function () {
                processReviews(config.productReviewUrl);
            });
        }

        $(function () {
            $('.product-info-main .reviews-actions a').on('click', function (event) {
                var anchor, addReviewBlock;

                event.preventDefault();
                anchor = $(this).attr('href').replace(/^.*?(#|$)/, '');
                addReviewBlock = $('#' + anchor);

                if (addReviewBlock.length) {
                    $('.product.data.items [data-role="content"]').each(function (index) { //eslint-disable-line
                        if (this.id == 'reviews') { //eslint-disable-line eqeqeq
                            $('.product.data.items').tabs('activate', index);
                        }
                    });
                    $('html, body').animate({
                        scrollTop: addReviewBlock.offset().top - 50
                    }, 300);
                }

            });
        });
    };
});


define('text!Magento_InstantPurchase/template/confirmation.html',[],function () { return '<!--\n/**\n * Copyright © Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n-->\n<p class="message"><%- data.message %></p>\n<strong><%- data.shippingAddressTitle %>:</strong>\n<p><%- data.shippingAddress %></p>\n<strong><%- data.billingAddressTitle %>:</strong>\n<p><%- data.billingAddress %></p>\n<strong><%- data.paymentMethodTitle %>:</strong>\n<p><%- data.paymentToken %></p>\n<strong><%- data.shippingMethodTitle %>:</strong>\n<p><%- data.shippingMethod %></p>';});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
define('Magento_InstantPurchase/js/view/instant-purchase',[
    'ko',
    'jquery',
    'underscore',
    'uiComponent',
    'Magento_Ui/js/modal/confirm',
    'Magento_Customer/js/customer-data',
    'mage/url',
    'mage/template',
    'mage/translate',
    'text!Magento_InstantPurchase/template/confirmation.html',
    'mage/validation'
], function (ko, $, _, Component, confirm, customerData, urlBuilder, mageTemplate, $t, confirmationTemplate) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'Magento_InstantPurchase/instant-purchase',
            buttonText: $t('Instant Purchase'),
            purchaseUrl: urlBuilder.build('instantpurchase/button/placeOrder'),
            showButton: false,
            paymentToken: null,
            shippingAddress: null,
            billingAddress: null,
            shippingMethod: null,
            productFormSelector: '#product_addtocart_form',
            confirmationTitle: $t('Instant Purchase Confirmation'),
            confirmationData: {
                message: $t('Are you sure you want to place order and pay?'),
                shippingAddressTitle: $t('Shipping Address'),
                billingAddressTitle: $t('Billing Address'),
                paymentMethodTitle: $t('Payment Method'),
                shippingMethodTitle: $t('Shipping Method')
            }
        },

        /** @inheritdoc */
        initialize: function () {
            var instantPurchase = customerData.get('instant-purchase');

            this._super();

            this.setPurchaseData(instantPurchase());
            instantPurchase.subscribe(this.setPurchaseData, this);
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super()
                .observe('showButton paymentToken shippingAddress billingAddress shippingMethod');

            return this;
        },

        /**
         * Set data from customerData.
         *
         * @param {Object} data
         */
        setPurchaseData: function (data) {
            this.showButton(data.available);
            this.paymentToken(data.paymentToken);
            this.shippingAddress(data.shippingAddress);
            this.billingAddress(data.billingAddress);
            this.shippingMethod(data.shippingMethod);
        },

        /**
         * Confirmation method
         */
        instantPurchase: function () {
            var form = $(this.productFormSelector),
                confirmTemplate = mageTemplate(confirmationTemplate),
                confirmData = _.extend({}, this.confirmationData, {
                    paymentToken: this.paymentToken().summary,
                    shippingAddress: this.shippingAddress().summary,
                    billingAddress: this.billingAddress().summary,
                    shippingMethod: this.shippingMethod().summary
                });

            if (!(form.validation() && form.validation('isValid'))) {
                return;
            }

            confirm({
                title: this.confirmationTitle,
                content: confirmTemplate({
                    data: confirmData
                }),
                actions: {
                    /** @inheritdoc */
                    confirm: function () {
                        $.ajax({
                            url: this.purchaseUrl,
                            data: form.serialize(),
                            type: 'post',
                            dataType: 'json',

                            /** Show loader before send */
                            beforeSend: function () {
                                $('body').trigger('processStart');
                            }
                        }).always(function () {
                            $('body').trigger('processStop');
                        });
                    }.bind(this)
                }
            });
        }
    });
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Review/js/error-placement',[
    'jquery',
    'mage/mage'
], function ($) {
    'use strict';

    return function (config, element) {
        $(element).mage('validation', {
            /** @inheritdoc */
            errorPlacement: function (error, el) {

                if (el.parents('#product-review-table').length) {
                    $('#product-review-table').siblings(this.errorElement + '.' + this.errorClass).remove();
                    $('#product-review-table').after(error);
                } else {
                    el.after(error);
                }
            }
        });
    };
});

define('Fastly_Cdn/js/gallery/gallery-mixin',[
    'underscore'
], function (_) {
    'use strict';

    return function (gallery) {
        return gallery.extend({
            initialize: function (config, element) {
                if (_.isUndefined(config) || _.isEmpty(config))
                    return this._super(config, element);

                if (_.isUndefined(config.data) || _.isEmpty(config.data))
                    return this._super(config, element);

                let wdpr = window.devicePixelRatio;

                _.each(config.data, function (imageObject) {

                    if (_.isUndefined(imageObject.fastly_srcset))
                        return;

                    if (!_.has(imageObject.fastly_srcset, wdpr))
                        return;

                    imageObject.img = imageObject.fastly_srcset[wdpr];
                });

                this._super(config, element);
            }
        });
    };
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_ProductVideo/js/fotorama-add-video-events',[
    'jquery',
    'jquery-ui-modules/widget',
    'catalogGallery',
    'loadPlayer'
], function ($) {
    'use strict';

    /**
     * @private
     */
    var allowBase = true; //global var is needed because fotorama always fully reloads events in case of fullscreen

    /**
     * @private
     */
    function parseHref(href) {
        var a = document.createElement('a');

        a.href = href;

        return a;
    }

    /**
     * @private
     */
    function parseURL(href, forceVideo) {
        var id,
            type,
            ampersandPosition,
            vimeoRegex,
            useYoutubeNocookie = false;

        /**
         * Get youtube ID
         * @param {String} srcid
         * @returns {{}}
         */
        function _getYoutubeId(srcid) {
            if (srcid) {
                ampersandPosition = srcid.indexOf('&');

                if (ampersandPosition === -1) {
                    return srcid;
                }

                srcid = srcid.substring(0, ampersandPosition);
            }

            return srcid;
        }

        if (typeof href !== 'string') {
            return href;
        }

        href = parseHref(href);

        if (href.host.match(/youtube\.com/) && href.search) {
            id = href.search.split('v=')[1];

            if (id) {
                id = _getYoutubeId(id);
                type = 'youtube';
            }
        } else if (href.host.match(/youtube\.com|youtu\.be|youtube-nocookie.com/)) {
            id = href.pathname.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, '');
            type = 'youtube';

            if (href.host.match(/youtube-nocookie.com/)) {
                useYoutubeNocookie = true;
            }
        } else if (href.host.match(/vimeo\.com/)) {
            type = 'vimeo';
            vimeoRegex = new RegExp(['https?:\\/\\/(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)',
                '?|groups\\/([^\\/]*)\\/videos\\/|album\\/(\\d+)\\/video\\/|video\\/|)(\\d+)(?:$|\\/|\\?)'
            ].join(''));
            id = href.href.match(vimeoRegex)[3];
        }

        if ((!id || !type) && forceVideo) {
            id = href.href;
            type = 'custom';
        }

        return id ? {
            id: id, type: type, s: href.search.replace(/^\?/, ''), useYoutubeNocookie: useYoutubeNocookie
        } : false;
    }

    //create AddFotoramaVideoEvents widget
    $.widget('mage.AddFotoramaVideoEvents', {
        options: {
            videoData: '',
            videoSettings: '',
            optionsVideoData: '',
            dataMergeStrategy: 'replace',
            vimeoJSFrameworkLoaded: false
        },

        /**
         * @private
         */
        onVimeoJSFramework: function () {},
        defaultVideoData: [],
        PV: 'product-video', // [CONST]
        VU: 'video-unplayed',
        PVLOADED: 'fotorama__product-video--loaded', // [CONST]
        PVLOADING: 'fotorama__product-video--loading', // [CONST]
        VID: 'video', // [CONST]
        VI: 'vimeo', // [CONST]
        FTVC: 'fotorama__video-close',
        FTAR: 'fotorama__arr',
        fotoramaSpinner: 'fotorama__spinner',
        fotoramaSpinnerShow: 'fotorama__spinner--show',
        TI: 'video-thumb-icon',
        isFullscreen: false,
        FTCF: '[data-gallery-role="fotorama__fullscreen-icon"]',
        Base: 0, //on check for video is base this setting become true if there is any video with base role
        MobileMaxWidth: 767,
        GP: 'gallery-placeholder', //gallery placeholder class is needed to find and erase <script> tag
        videoData: null,
        videoDataPlaceholder: [{
            id: '',
            isBase: true,
            mediaType: 'image',
            provider: ''
        }],

        /**
         * Creates widget
         * @private
         */
        _create: function () {
            $(this.element).on('gallery:loaded',  $.proxy(function () {
                this.fotoramaItem = $(this.element).find('.fotorama-item');
                this._initialize();
            }, this));
        },

        /**
         *
         * @private
         */
        _initialize: function () {
            if (!this.defaultVideoData.length) {
                this.defaultVideoData = this.options.videoData;
            }

            // If product does not have images, no video data generated,
            // but for configurable product we still need a video data, in case of 'prepend' gallery strategy.
            if (!this.defaultVideoData.length && !this.options.videoData.length) {
                this.defaultVideoData = this.options.videoData = this.videoDataPlaceholder;
            }

            this.clearEvents();

            if (this._checkForVideoExist()) {
                this._checkFullscreen();
                this._listenForFullscreen();
                this._checkForVimeo();
                this._isVideoBase();
                this._initFotoramaVideo();
                this._attachFotoramaEvents();
            }
        },

        /**
         * Clear gallery events to prevent duplicated calls.
         *
         * @private
         */
        clearEvents: function () {
            if (this.fotoramaItem !== undefined) {
                this.fotoramaItem.off(
                    'fotorama:show.' + this.PV +
                    ' fotorama:showend.' + this.PV +
                    ' fotorama:fullscreenenter.' + this.PV +
                    ' fotorama:fullscreenexit.' + this.PV
                );
            }
        },

        /**
         *
         * @param {Object} options
         * @private
         */
        _setOptions: function (options) {
            if (options.videoData && options.videoData.length) {
                this.options.videoData = options.videoData;
            }

            this._loadVideoData(options);
            this._initialize();
        },

        /**
         * Set video data for configurable product.
         *
         * @param {Object} options
         * @private
         */
        _loadVideoData: function (options) {
            if (options.selectedOption) {
                if (options.dataMergeStrategy === 'prepend') {
                    this.options.videoData = [].concat(
                        this.options.optionsVideoData[options.selectedOption],
                        this.defaultVideoData
                    );
                } else {
                    this.options.videoData = this.options.optionsVideoData[options.selectedOption];
                }
            } else {
                this.options.videoData = this.defaultVideoData;
            }
        },

        /**
         *
         * @private
         */
        _checkFullscreen: function () {
            if (this.fotoramaItem.data('fotorama').fullScreen || false) {
                this.isFullscreen = true;
            }
        },

        /**
         *
         * @private
         */
        _listenForFullscreen: function () {
            this.fotoramaItem.on('fotorama:fullscreenenter.' + this.PV, $.proxy(function () {
                this.isFullscreen = true;
            }, this));

            this.fotoramaItem.on('fotorama:fullscreenexit.' + this.PV, $.proxy(function () {
                this.isFullscreen = false;
                this._hideVideoArrows();
            }, this));
        },

        /**
         *
         * @param {Object} inputData
         * @param {bool} isJSON
         * @returns {{}}
         * @private
         */
        _createVideoData: function (inputData, isJSON) {
            var videoData = [],
                dataUrl,
                tmpVideoData,
                tmpInputData,
                i;

            if (isJSON) {
                inputData = $.parseJSON(inputData);
            }

            for (i = 0; i < inputData.length; i++) {
                tmpInputData = inputData[i];
                dataUrl = '';
                tmpVideoData = {
                    mediaType: '',
                    isBase: '',
                    id: '',
                    provider: ''
                };
                tmpVideoData.mediaType = this.VID;

                if (tmpInputData.mediaType !== 'external-video') {
                    tmpVideoData.mediaType = tmpInputData.mediaType;
                }

                tmpVideoData.isBase = tmpInputData.isBase;

                if (tmpInputData.videoUrl && tmpInputData.videoUrl !== null) {
                    dataUrl = tmpInputData.videoUrl;
                    dataUrl = parseURL(dataUrl);
                    tmpVideoData.id = dataUrl.id;
                    tmpVideoData.provider = dataUrl.type;
                    tmpVideoData.videoUrl = tmpInputData.videoUrl;
                    tmpVideoData.useYoutubeNocookie = dataUrl.useYoutubeNocookie;
                }

                videoData.push(tmpVideoData);
            }

            return videoData;
        },

        /**
         *
         * @param {Object} fotorama
         * @param {bool} isBase
         * @private
         */
        _createCloseVideo: function (fotorama, isBase) {
            var closeVideo;

            this.fotoramaItem.find('.' + this.FTVC).remove();
            this.fotoramaItem.append('<div class="' + this.FTVC + '"></div>');
            this.fotoramaItem.css('position', 'relative');
            closeVideo = this.fotoramaItem.find('.' + this.FTVC);
            this._closeVideoSetEvents(closeVideo, fotorama);

            if (
                isBase &&
                this.options.videoData[fotorama.activeIndex].isBase &&
                $(window).width() > this.MobileMaxWidth) {
                this._showCloseVideo();
            }
        },

        /**
         *
         * @private
         */
        _hideCloseVideo: function () {
            this.fotoramaItem
                .find('.' + this.FTVC)
                .removeClass('fotorama-show-control');
        },

        /**
         *
         * @private
         */
        _showCloseVideo: function () {
            this.fotoramaItem
                .find('.' + this.FTVC)
                .addClass('fotorama-show-control');
        },

        /**
         *
         * @param {jQuery} $closeVideo
         * @param {jQuery} fotorama
         * @private
         */
        _closeVideoSetEvents: function ($closeVideo, fotorama) {
            $closeVideo.on('click', $.proxy(function () {
                this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, true);
                this._hideCloseVideo();
            }, this));
        },

        /**
         *
         * @returns {Boolean}
         * @private
         */
        _checkForVideoExist: function () {
            var key, result, checker, videoSettings;

            if (!this.options.videoData) {
                return false;
            }

            if (!this.options.videoSettings) {
                return false;
            }

            result = this._createVideoData(this.options.videoData, false);
            checker = false;
            videoSettings = this.options.videoSettings[0];
            videoSettings.playIfBase = parseInt(videoSettings.playIfBase, 10);
            videoSettings.showRelated = parseInt(videoSettings.showRelated, 10);
            videoSettings.videoAutoRestart = parseInt(videoSettings.videoAutoRestart, 10);

            for (key in result) {
                if (result[key].mediaType === this.VID) {
                    checker = true;
                }
            }

            if (checker) {
                this.options.videoData = result;
            }

            return checker;
        },

        /**
         *
         * @private
         */
        _checkForVimeo: function () {
            var allVideoData = this.options.videoData,
                videoItem;

            if (window.Froogaloop) { // prevent duplicated initialization
                return;
            }

            for (videoItem in allVideoData) {
                if (allVideoData[videoItem].provider === this.VI) {
                    this._loadVimeoJSFramework();

                    return;
                }
            }
        },

        /**
         *
         * @private
         */
        _isVideoBase: function () {
            var allVideoData = this.options.videoData,
                videoItem,
                allVideoDataKeys,
                key,
                i;

            allVideoDataKeys = Object.keys(allVideoData);

            for (i = 0; i < allVideoDataKeys.length; i++) {
                key = allVideoDataKeys[i];
                videoItem = allVideoData[key];

                if (
                    videoItem.mediaType === this.VID && videoItem.isBase &&
                    this.options.videoSettings[0].playIfBase && allowBase
                ) {
                    this.Base = true;
                    allowBase = false;
                }
            }

            if (!this.isFullscreen) {
                this._createCloseVideo(this.fotoramaItem.data('fotorama'), this.Base);
            }
        },

        /**
         *
         * @private
         */
        _loadVimeoJSFramework: function () {
            var element = document.createElement('script'),
                scriptTag = document.getElementsByTagName('script')[0];

            element.async = true;
            element.src = 'https://f.vimeocdn.com/js/froogaloop2.min.js';

            /**
             * Vimeo js framework on load callback.
             */
            element.onload = function () {
                this.onVimeoJSFramework();
                this.vimeoJSFrameworkLoaded = true;
            }.bind(this);
            scriptTag.parentNode.insertBefore(element, scriptTag);
        },

        /**
         *
         * @param {Event} e
         * @private
         */
        _initFotoramaVideo: function (e) {
            var fotorama = this.fotoramaItem.data('fotorama'),
                thumbsParent,
                thumbs,
                t;

            if (!fotorama.activeFrame.$navThumbFrame) {
                this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (evt, fotoramaData) {
                    $(fotoramaData.activeFrame.$stageFrame).removeAttr('href');
                }, this));

                this._startPrepareForPlayer(e, fotorama);

                return null;
            }

            fotorama.data.map($.proxy(this._setItemType, this));
            thumbsParent = fotorama.activeFrame.$navThumbFrame.parent();
            thumbs = thumbsParent.find('.fotorama__nav__frame:visible');

            for (t = 0; t < thumbs.length; t++) {
                this._setThumbsIcon(thumbs.eq(t), t);
                this._checkForVideo(e, fotorama, t + 1);
            }

            this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (evt, fotoramaData) {
                $(fotoramaData.activeFrame.$stageFrame).removeAttr('href');
            }, this));
        },

        /**
         *
         * @param {Object} elem
         * @param {Number} i
         * @private
         */
        _setThumbsIcon: function (elem, i) {
            var fotorama = this.fotoramaItem.data('fotorama');

            if (fotorama.options.nav === 'dots' && elem.hasClass(this.TI)) {
                elem.removeClass(this.TI);
            }

            if (this.options.videoData[i].mediaType === this.VID &&
                fotorama.data[i].type ===  this.VID &&
                fotorama.options.nav === 'thumbs') {
                elem.addClass(this.TI);
            }
        },

        /**
         * Temporary solution with adding types for configurable product items
         *
         * @param {Object} item
         * @param {Number} i
         * @private
         */
        _setItemType: function (item, i) {
            !item.type && (item.type = this.options.videoData[i].mediaType);
        },

        /**
         * Attach
         *
         * @private
         */
        _attachFotoramaEvents: function () {
            this.fotoramaItem.on('fotorama:showend.' + this.PV, $.proxy(function (e, fotorama) {
                this._startPrepareForPlayer(e, fotorama);
            }, this));

            this.fotoramaItem.on('fotorama:show.' + this.PV, $.proxy(function (e, fotorama) {
                this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, true);
            }, this));

            this.fotoramaItem.on('fotorama:fullscreenexit.' + this.PV, $.proxy(function (e, fotorama) {
                // fotorama.activeFrame.$stageFrame.find('.' + this.PV).remove();
                // this._startPrepareForPlayer(e, fotorama);
            }, this));
        },

        /**
         * Start prepare for player
         *
         * @param {Event} e
         * @param {jQuery} fotorama
         * @private
         */
        _startPrepareForPlayer: function (e, fotorama) {
            this._unloadVideoPlayer(fotorama.activeFrame.$stageFrame.parent(), fotorama, false);
            this._checkForVideo(e, fotorama, fotorama.activeFrame.i);
            this._checkForVideo(e, fotorama, fotorama.activeFrame.i - 1);
            this._checkForVideo(e, fotorama, fotorama.activeFrame.i + 1);
        },

        /**
         * Check for video
         *
         * @param {Event} e
         * @param {jQuery} fotorama
         * @param {Number} number
         * @private
         */
        _checkForVideo: function (e, fotorama, number) {
            var videoData = this.options.videoData[number - 1],
                $image = fotorama.data[number - 1];

            if ($image) {
                !$image.type && this._setItemType($image, number - 1);

                if ($image.type === 'image') {
                    $image.$navThumbFrame && $image.$navThumbFrame.removeClass(this.TI);
                    this._hideCloseVideo();

                    return;
                } else if ($image.$navThumbFrame && $image.type === 'video') {
                    !$image.$navThumbFrame.hasClass(this.TI) && $image.$navThumbFrame.addClass(this.TI);
                }

                $image = $image.$stageFrame;
            }

            if ($image && videoData && videoData.mediaType === this.VID) {
                $(fotorama.activeFrame.$stageFrame).removeAttr('href');
                this._prepareForVideoContainer($image, videoData, fotorama, number);
            }

            if (this.isFullscreen && this.fotoramaItem.data('fotorama').activeFrame.i === number) {
                this.fotoramaItem.data('fotorama').activeFrame.$stageFrame[0].click();
            }
        },

        /**
         * Prepare for video container
         *
         * @param {jQuery} $image
         * @param {Object} videoData
         * @param {Object} fotorama
         * @param {Number} number
         * @private
         */
        _prepareForVideoContainer: function ($image, videoData, fotorama, number) {
            $image.addClass('fotorama-video-container').addClass(this.VU);
            this._createVideoContainer(videoData, $image);
            this._setVideoEvent($image, this.PV, fotorama, number);
        },

        /**
         * Create video container
         *
         * @param {Object} videoData
         * @param {jQuery} $image
         * @private
         */
        _createVideoContainer: function (videoData, $image) {
            var videoSettings;
            videoSettings = this.options.videoSettings[0];
            $image.find('.' + this.PV).remove();
            $image.append(
                '<div class="' +
                this.PV +
                '" data-related="' +
                videoSettings.showRelated +
                '" data-loop="' +
                videoSettings.videoAutoRestart +
                '" data-type="' +
                videoData.provider +
                '" data-code="' +
                videoData.id +
                '"  data-youtubenocookie="' +
                videoData.useYoutubeNocookie +
                '" data-width="100%" data-height="100%"></div>'
            );
        },

        /**
         *
         * @param {Object} $image
         * @param {Object} PV
         * @param {Object} fotorama
         * @param {Number} number
         * @private
         */
        _setVideoEvent: function ($image, PV, fotorama, number) {
            $image.find('.magnify-lens').remove();
            $image
                .off('click tap', $.proxy(this._clickHandler, this))
                .on('click tap', $.proxy(this._clickHandler, this));
            this._handleBaseVideo(fotorama, number); //check for video is it base and handle it if it's base
        },

        /**
         * Hides preview arrows above video player.
         * @private
         */
        _hideVideoArrows: function () {
            var arrows = $('.' + this.FTAR);

            arrows.removeClass('fotorama__arr--shown');
            arrows.removeClass('fotorama__arr--hidden');
        },

        /**
         * @private
         */
        _showLoader: function () {
            var spinner = this.fotoramaItem.find('.' + this.fotoramaSpinner);

            spinner.addClass(this.fotoramaSpinnerShow);
            this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.addClass(this.PVLOADING);
        },

        /**
         * @private
         */
        _hideLoader: function () {
            var spinner = this.fotoramaItem.find('.' + this.fotoramaSpinner);

            spinner.removeClass(this.fotoramaSpinnerShow);
            this.fotoramaItem.data('fotorama').activeFrame.$stageFrame.removeClass(this.PVLOADING);
        },

        /**
         * @param {Event} event
         * @private
         */
        _clickHandler: function (event) {
            var type;

            if ($(event.target).hasClass(this.VU) && $(event.target).find('iframe').length === 0) {
                $(event.target).removeClass(this.VU);
                type = $(event.target).find('.' + this.PV).data('type');

                if (this.vimeoJSFrameworkLoaded && type === this.VI) {
                    $(event.target).find('.' + this.PV).productVideoLoader();
                } else if (type === this.VI) {
                    this._showLoader();
                    this.onVimeoJSFramework = function () {
                        $(event.target).find('.' + this.PV).productVideoLoader();
                        this._hideLoader();
                    }.bind(this);
                } else {
                    $(event.target).find('.' + this.PV).productVideoLoader();
                }

                $('.' + this.FTAR).addClass(this.isFullscreen ? 'fotorama__arr--shown' : 'fotorama__arr--hidden');
            }
        },

        /**
         * Handle base video
         * @param {Object} fotorama
         * @param {Number} srcNumber
         * @private
         */
        _handleBaseVideo: function (fotorama, srcNumber) {
            var waitForFroogaloop,
                videoData = this.options.videoData,
                activeIndex = fotorama.activeIndex,
                number = parseInt(srcNumber, 10),
                activeIndexIsBase = videoData[activeIndex];

            if (!this.Base) {
                return;
            }

            if (activeIndexIsBase && number === 1 && $(window).width() > this.MobileMaxWidth) {
                if (this.options.videoData[fotorama.activeIndex].provider === this.VI) {
                    waitForFroogaloop = setInterval($.proxy(function () {
                        if (window.Froogaloop) {
                            clearInterval(waitForFroogaloop);
                            fotorama.requestFullScreen();
                            this.fotoramaItem.data('fotorama').activeFrame.$stageFrame[0].click();
                            this.Base = false;
                        }
                    }, this), 50);
                } else { //if not a vimeo - play it immediately with a little lag in case for fotorama fullscreen
                    setTimeout($.proxy(function () {
                        fotorama.requestFullScreen();
                        this.fotoramaItem.data('fotorama').activeFrame.$stageFrame[0].click();
                        this.Base = false;
                    }, this), 50);
                }
            }
        },

        /**
         * Destroy video player
         * @param {jQuery} $wrapper
         * @param {jQuery} current
         * @param {bool} close
         * @private
         */
        _unloadVideoPlayer: function ($wrapper, current, close) {
            var self = this;

            if (!$wrapper) {
                return;
            }

            $wrapper.find('.' + this.PVLOADED).removeClass(this.PVLOADED);
            this._hideLoader();

            $wrapper.find('.' + this.PV).each(function () {
                var $item = $(this).parent(),
                    cloneVideoDiv,
                    iframeElement = $(this).find('iframe'),
                    currentIndex,
                    itemIndex;

                if (iframeElement.length === 0) {
                    return;
                }

                currentIndex = current.activeFrame.$stageFrame.index();
                itemIndex = $item.index();

                if (currentIndex === itemIndex && !close) {
                    return;
                }

                if (currentIndex !== itemIndex && close) {
                    return;
                }

                iframeElement.remove();
                cloneVideoDiv = $(this).clone();
                $(this).remove();
                $item.append(cloneVideoDiv);
                $item.addClass(self.VU);

                self._hideCloseVideo();
                self._hideVideoArrows();

                if (self.isFullscreen && !self.fotoramaItem.data('fotorama').options.fullscreen.arrows) {
                    if ($('.' + self.FTAR + '--prev').is(':focus') || $('.' + self.FTAR + '--next').is(':focus')) {
                        $(self.FTCF).focus();
                    }
                }
            });
        }
    });

    return $.mage.AddFotoramaVideoEvents;
});

/**
 * Copyright (c) 2010 Conrad Irwin <conrad@rapportive.com> MIT license.
 * Based loosely on original: Copyright (c) 2008 mkmanning MIT license.
 *
 * Parses CGI query strings into javascript objects.
 *
 * See the README for details.
 **/
define('jquery/jquery.parsequery',[
    "jquery"
], function($){
    $.parseQuery = function (options) {

        var config = {query: window.location.search || ""},
            params = {};

        if (typeof options === 'string') {
            options = {query: options};
        }
        $.extend(config, $.parseQuery, options);
        config.query = config.query.replace(/^\?/, '');

        if (config.query.length > 0) {
            $.each(config.query.split(config.separator), function (i, param) {
                var pair = param.split('='),
                    key = config.decode(pair.shift(), null).toString(),
                    value = config.decode(pair.length ? pair.join('=') : null, key);

                if (config.array_keys.test ? config.array_keys.test(key) : config.array_keys(key)) {
                    params[key] = params[key] || [];
                    params[key].push(value);
                } else {
                    params[key] = value;
                }
            });
        }
        return params;
    };
    $.parseQuery.decode = $.parseQuery.default_decode = function (string) {
        return decodeURIComponent((string || "").replace(/\+/g, ' '));
    };
    $.parseQuery.array_keys = function () {
        return false;
    };
    $.parseQuery.separator = "&";
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Mageplaza_LazyLoading/js/swatch-renderer-map',[
    'jquery',
    'underscore',
    'mage/template',
    'mage/smart-keyboard-handler',
    'mage/translate',
    'priceUtils',
    'jquery-ui-modules/widget',
    'jquery/jquery.parsequery',
    'mage/validation/validation'
], function ($, _, mageTemplate, keyboardHandler, $t, priceUtils) {
    'use strict';

    /**
     * Extend form validation to support swatch accessibility
     */
    $.widget('mage.validation', $.mage.validation, {
        /**
         * Handle form with swatches validation. Focus on first invalid swatch block.
         *
         * @param {jQuery.Event} event
         * @param {Object} validation
         */
        listenFormValidateHandler: function (event, validation) {
            var swatchWrapper, firstActive, swatches, swatch, successList, errorList, firstSwatch;

            this._superApply(arguments);

            swatchWrapper = '.swatch-attribute-options';
            swatches = $(event.target).find(swatchWrapper);

            if (!swatches.length) {
                return;
            }

            swatch = '.swatch-attribute';
            firstActive = $(validation.errorList[0].element || []);
            successList = validation.successList;
            errorList = validation.errorList;
            firstSwatch = $(firstActive).parent(swatch).find(swatchWrapper);

            keyboardHandler.focus(swatches);

            $.each(successList, function (index, item) {
                $(item).parent(swatch).find(swatchWrapper).attr('aria-invalid', false);
            });

            $.each(errorList, function (index, item) {
                $(item.element).parent(swatch).find(swatchWrapper).attr('aria-invalid', true);
            });

            if (firstSwatch.length) {
                $(firstSwatch).focus();
            }
        }
    });

    /**
     * Render tooltips by attributes (only to up).
     * Required element attributes:
     *  - option-type (integer, 0-3)
     *  - option-label (string)
     *  - option-tooltip-thumb
     *  - option-tooltip-value
     *  - thumb-width
     *  - thumb-height
     */
    $.widget('mage.SwatchRendererTooltip', {
        options: {
            delay: 200,                             //how much ms before tooltip to show
            tooltipClass: 'swatch-option-tooltip'  //configurable, but remember about css
        },

        /**
         * @private
         */
        _init: function () {
            var $widget = this,
                $this = this.element,
                $element = $('.' + $widget.options.tooltipClass),
                timer,
                type = parseInt($this.attr('option-type'), 10),
                label = $this.attr('option-label'),
                thumb = $this.attr('option-tooltip-thumb'),
                value = $this.attr('option-tooltip-value'),
                width = $this.attr('thumb-width'),
                height = $this.attr('thumb-height'),
                $image,
                $title,
                $corner;

            if (!$element.length) {
                $element = $('<div class="' +
                    $widget.options.tooltipClass +
                    '"><div class="image"></div><div class="title"></div><div class="corner"></div></div>');
                $('body').append($element);
            }

            $image = $element.find('.image');
            $title = $element.find('.title');
            $corner = $element.find('.corner');
            $this.parent().mouseleave(function() {
                var swatchLen = $this.parents(".swatch-attribute").find(".swatch-option.selected").length;
                if(swatchLen){
                    jQuery(".swatch-attribute").find(".swatch-option.selected").trigger('mouseenter');
                } else {
                    var src = $(this).closest('li').find(".child-image-photo").attr("src");
                    $(this).closest('li').find(".product-image-photo").attr("src", src);
                }
            });
            $this.hover(function () {
                if (!$this.hasClass('disabled')) {
                    timer = setTimeout(
                        function () {
                            var leftOpt = null,
                                leftCorner = 0,
                                left,
                                $window;

                            if (type === 2) {
                                // Image
                                $image.css({
                                    'background': 'url("' + thumb + '") no-repeat center', //Background case
                                    'background-size': 'initial',
                                    'width': width + 'px',
                                    'height': height + 'px'
                                });
                                $image.show();
                            } else if (type === 1) {
                                // Color
                                $image.css({
                                    background: value
                                });
                                $image.show();
                            } else if (type === 0 || type === 3) {
                                // Default
                                $image.hide();
                            }

                            $title.text(label);

                            leftOpt = $this.offset().left;
                            left = leftOpt + $this.width() / 2 - $element.width() / 2;
                            $window = $(window);

                            // the numbers (5 and 5) is magick constants for offset from left or right page
                            if (left < 0) {
                                left = 5;
                            } else if (left + $element.width() > $window.width()) {
                                left = $window.width() - $element.width() - 5;
                            }

                            // the numbers (6,  3 and 18) is magick constants for offset tooltip
                            leftCorner = 0;

                            if ($element.width() < $this.width()) {
                                leftCorner = $element.width() / 2 - 3;
                            } else {
                                leftCorner = (leftOpt > left ? leftOpt - left : left - leftOpt) + $this.width() / 2 - 6;
                            }

                            $corner.css({
                                left: leftCorner
                            });
                            $element.css({
                                left: left,
                                top: $this.offset().top - $element.height() - $corner.height() - 18
                            }).show();
                        },
                        $widget.options.delay
                    );
                }
            }, function () {
                $element.hide();
                clearTimeout(timer);
            });

            $(document).on('tap', function () {
                $element.hide();
                clearTimeout(timer);
            });

            $this.on('tap', function (event) {
                event.stopPropagation();
            });
        }
    });

    /**
     * Render swatch controls with options and use tooltips.
     * Required two json:
     *  - jsonConfig (magento's option config)
     *  - jsonSwatchConfig (swatch's option config)
     *
     *  Tuning:
     *  - numberToShow (show "more" button if options are more)
     *  - onlySwatches (hide selectboxes)
     *  - moreButtonText (text for "more" button)
     *  - selectorProduct (selector for product container)
     *  - selectorProductPrice (selector for change price)
     */
    $.widget('mage.SwatchRenderer', {
        options: {
            classes: {
                attributeClass: 'swatch-attribute',
                attributeLabelClass: 'swatch-attribute-label',
                attributeSelectedOptionLabelClass: 'swatch-attribute-selected-option',
                attributeOptionsWrapper: 'swatch-attribute-options',
                attributeInput: 'swatch-input',
                optionClass: 'swatch-option',
                selectClass: 'swatch-select',
                moreButton: 'swatch-more',
                loader: 'swatch-option-loading1',
                attributeHiddenClass: 'hidden'
            },
            // option's json config
            jsonConfig: {},

            // swatch's json config
            jsonSwatchConfig: {},

            // swatch's json config
            jsonSelectedSwatchConfig: {},

            // selector of parental block of prices and swatches (need to know where to seek for price block)
            selectorProduct: '.product-info-main',

            // selector of price wrapper (need to know where set price)
            selectorProductPrice: '[data-role=priceBox]',

            //selector of product images gallery wrapper
            mediaGallerySelector: '[data-gallery-role=gallery-placeholder]',

            // selector of category product tile wrapper
            selectorProductTile: '.product-item',

            // number of controls to show (false or zero = show all)
            numberToShow: false,

            // show only swatch controls
            onlySwatches: false,

            // enable label for control
            enableControlLabel: true,

            // control label id
            controlLabelId: '',

            // text for more button
            moreButtonText: $t('More'),

            // Callback url for media
            mediaCallback: '',

            // Local media cache
            mediaCache: {},

            // Cache for BaseProduct images. Needed when option unset
            mediaGalleryInitial: [{}],

            // Use ajax to get image data
            useAjax: false,

            /**
             * Defines the mechanism of how images of a gallery should be
             * updated when user switches between configurations of a product.
             *
             * As for now value of this option can be either 'replace' or 'prepend'.
             *
             * @type {String}
             */
            gallerySwitchStrategy: 'replace',

            // whether swatches are rendered in product list or on product page
            inProductList: false,

            // sly-old-price block selector
            slyOldPriceSelector: '.sly-old-price',

            // tier prise selectors start
            tierPriceTemplateSelector: '#tier-prices-template',
            tierPriceBlockSelector: '[data-role="tier-price-block"]',
            tierPriceTemplate: '',
            // tier prise selectors end

            // A price label selector
            normalPriceLabelSelector: '.normal-price .price-label'
        },

        /**
         * Get chosen product
         *
         * @returns int|null
         */
        getProduct: function () {
            var products = this._CalcProducts();

            return _.isArray(products) ? products[0] : null;
        },

        /**
         * Get chosen product id
         *
         * @returns int|null
         */
        getProductId: function () {
            var products = this._CalcProducts();

            return _.isArray(products) && products.length === 1 ? products[0] : null;
        },

        /**
         * @private
         */
        _init: function () {
            if (_.isEmpty(this.options.jsonConfig.images)) {
                this.options.useAjax = true;
                // creates debounced variant of _LoadProductMedia()
                // to use it in events handlers instead of _LoadProductMedia()
                this._debouncedLoadProductMedia = _.debounce(this._LoadProductMedia.bind(this), 500);
            }

            if (this.options.jsonConfig !== '' && this.options.jsonSwatchConfig !== '') {
                // store unsorted attributes
                this.options.jsonConfig.mappedAttributes = _.clone(this.options.jsonConfig.attributes);
                this._sortAttributes();
                this._RenderControls();

                //code for select first attribute value on PLP
                if ($('body.catalog-category-view').length > 0 || $('body.catalogsearch-result-index').length > 0) {
                    if (this.options.jsonConfig.attributes.length > 0) {
                        var that = this;
                        var selectswatch = this.element.find('.' + this.options.classes.attributeClass + ' .' + this.options.classes.attributeOptionsWrapper);
                        $.each(selectswatch, function (index, item) {
                            $('#wp_ln_shopby').find('li[data-option-label="Warna"], li[data-option-label="Color"]').find('.filter-value').each(function (i) {
                                var selectedColor = $(this).attr('data-option-id');
                                var swatchOption = $(item).find('div[option-id="' + selectedColor + '"]');
                                if (swatchOption.length) {
                                    $.each(JSON.parse(JSON.stringify(that.options.jsonSelectedSwatchConfig)), function(index, itemData) {
                                        if (index === selectedColor) {
                                            // add class "selected" to swatch option
                                            $(item).find('div.swatch-option.selected').removeClass('selected');
                                            $(item).find('div[option-id="' + selectedColor + '"]').addClass('selected');

                                            //change product image with selected color
                                            $(item).closest('li').find('.product-image-wrapper .product-image-photo').attr('src', itemData.value);
                                            $(item).closest('li').find('.product-image-wrapper .product-image-photo').attr('data-original', itemData.value);

                                            //change url with selected swatch
                                            var finalURL,
                                                url;
                                            var productURL = $(item).closest('li').find(".product.name a").attr("href");
                                            if (productURL.indexOf('?') > -1) {
                                                url = productURL.split('?');
                                                finalURL = url[0]+"?color="+selectedColor;
                                            } else {
                                                finalURL = productURL+"?color="+selectedColor;
                                            }
                                            $(item).closest('li').find(".product.name a").attr("href", finalURL);
                                            $(item).closest('li').find(".product_image a").attr("href", finalURL);

                                            $(item).closest('li').find(".product.name a").attr("href", finalURL);
                                            /* start - we need to uncomment below code if google gtm enabled on site*/
                                            var onclickstr = $(item).closest('li').find(".product.name a").attr("onclick");
                                            if(onclickstr != undefined){
                                                var newonclickstr = onclickstr.replace(productURL, finalURL);
                                                $(item).closest('li').find(".product.name a").attr("onclick", newonclickstr);
                                            }
                                            /* end - we need to uncomment above code if google gtm enabled on site*/

                                        }
                                    });
                                }
                            });
                        });
                    }
                }

                this._setPreSelectedGallery();
                $(this.element).trigger('swatch.initialized');
            } else {
                console.log('SwatchRenderer: No input data received');
            }
            this.options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html();
        },

        /**
         * @private
         */
        _sortAttributes: function () {
            this.options.jsonConfig.attributes = _.sortBy(this.options.jsonConfig.attributes, function (attribute) {
                return attribute.position;
            });
        },

        /**
         * @private
         */
        _create: function () {
            var options = this.options,
                gallery = $('[data-gallery-role=gallery-placeholder]', '.column.main'),
                productData = this._determineProductData(),
                $main = productData.isInProductView ?
                    this.element.parents('.column.main') :
                    this.element.parents('.product-item-info');

            if (productData.isInProductView) {
                gallery.data('gallery') ?
                    this._onGalleryLoaded(gallery) :
                    gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery));
            } else {
                options.mediaGalleryInitial = [{
                    'img': $main.find('.product-image-photo').attr('src')
                }];
            }

            this.productForm = this.element.parents(this.options.selectorProductTile).find('form:first');
            this.inProductList = this.productForm.length > 0;
        },

        /**
         * Determine product id and related data
         *
         * @returns {{productId: *, isInProductView: bool}}
         * @private
         */
        _determineProductData: function () {
            // Check if product is in a list of products.
            var productId,
                isInProductView = false;

            productId = this.element.parents('.product-item-details')
                .find('.price-box.price-final_price').attr('data-product-id');

            if (!productId) {
                // Check individual product.
                productId = $('[name=product]').val();
                isInProductView = productId > 0;
            }

            return {
                productId: productId,
                isInProductView: isInProductView
            };
        },

        /**
         * Render controls
         *
         * @private
         */
        _RenderControls: function () {
            var $widget = this,
                container = this.element,
                classes = this.options.classes,
                chooseText = this.options.jsonConfig.chooseText;

            // Start: Set default country drondown using store config value
            $('.swatch-opt').attr('data-country-dd-status',this.options.jsonConfig.country_size_dropdown_status);
            $('.swatch-opt').attr('data-country-selected-value',this.options.jsonConfig.default_size_type);
            // End: Set default country drondown using store config value

            $widget.optionsMap = {};

            $.each(this.options.jsonConfig.attributes, function () {
                var item = this,
                    controlLabelId = 'option-label-' + item.code + '-' + item.id,
                    options = $widget._RenderSwatchOptions(item, controlLabelId),
                    select = $widget._RenderSwatchSelect(item, chooseText),
                    input = $widget._RenderFormInput(item),
                    listLabel = '',
                    label = '';

                // Show only swatch controls
                if ($widget.options.onlySwatches && !$widget.options.jsonSwatchConfig.hasOwnProperty(item.id)) {
                    return;
                }

                if ($widget.options.enableControlLabel) {
                    label +=
                        '<span id="' + controlLabelId + '" class="' + classes.attributeLabelClass + '">' +
                        item.label +
                        '</span>' +
                        '<span class="' + classes.attributeSelectedOptionLabelClass + '"></span>';
                }

                if ($widget.inProductList) {
                    $widget.productForm.append(input);
                    input = '';
                    listLabel = 'aria-label="' + item.label + '"';
                } else {
                    listLabel = 'aria-labelledby="' + controlLabelId + '"';
                }

                if ($('body.catalog-category-view').length > 0 || $('body.catalogsearch-result-index').length > 0) {

                    var option_count = item.options.length;
                    var remaining_html = '';
                    if ($(window).width() < 1024) {
                        if (option_count > 5) {
                            var remaining = option_count - 5;
                            var product_url = container.parents('.product-item-info').find('.product-item-photo').attr('href');
                            var remaining_text = $t('%1 more color').replace('%1', remaining);
                            if (remaining > 1) {
                                remaining_text = $t('%1 more colors').replace('%1', remaining);
                            }
                            remaining_html = '<a href="' + product_url + '"><span class="more-color-link small-screen">+' + remaining + '</span><span class="more-color-link large-screen">' + remaining_text + '</span></a>';
                        }
                    } else {
                        if (option_count > 4) {
                            var remaining = option_count - 4;
                            var product_url = container.parents('.product-item-info').find('.product-item-photo').attr('href');
                            var remaining_text = $t('%1 more color').replace('%1', remaining);
                            if (remaining > 1) {
                                remaining_text = $t('%1 more colors').replace('%1', remaining);
                            }
                            remaining_html = '<a href="' + product_url + '"><span class="more-color-link small-screen">+' + remaining + '</span><span class="more-color-link large-screen">' + remaining_text + '</span></a>';
                        }
                    }
                    var available_text = $t('%1 color available').replace('%1', option_count);
                    if (option_count>1) {
                        available_text = $t('%1 colors available').replace('%1', option_count);
                    }
                    var available_html_content = '<p class="product-tile__swatches large-screen">'+available_text+'</p>';
                    var attribute_wrapper_cls = 'attribute-wrapper';
                    var small_screen_cls = 'small-screen';
                    var option_count_cls = 'opt-'+option_count;
                    if (option_count == 1) {
                        available_html_content = '';
                        attribute_wrapper_cls = '';
                        small_screen_cls = '';
                    }
                    // Create new control
                    item.code = item.code.toLowerCase();
                    container.append(
                        available_html_content +
                        '<div class="' + classes.attributeClass + ' ' + item.code +' '+ classes.attributeHiddenClass+' '+small_screen_cls +' '+attribute_wrapper_cls+' '+option_count_cls+' " ' +
                        'attribute-code="' + item.code + '" ' +
                        'attribute-id="' + item.id + '">' +
                        label +
                        '<div aria-activedescendant="" ' +
                        'tabindex="0" ' +
                        'aria-invalid="false" ' +
                        'aria-required="true" ' +
                        'role="listbox" ' + listLabel +
                        'class="' + classes.attributeOptionsWrapper + ' clearfix">' +
                        options + select +
                        '</div>'+ remaining_html + input +
                        '</div>'
                    );
                    if ($(window).width() > 992) {
                        $('.large-screen').removeClass('hidden');
                        $('.small-screen').addClass('hidden');
                    } else {
                        $('.large-screen').addClass('hidden');
                        $('.small-screen').removeClass('hidden');
                    }
                } else {
                    // Create new control
                    container.append(
                        '<div class="' + classes.attributeClass + ' ' + item.code + '" ' +
                        'attribute-code="' + item.code + '" ' +
                        'attribute-id="' + item.id + '">' +
                        label +
                        '<div aria-activedescendant="" ' +
                        'tabindex="0" ' +
                        'aria-invalid="false" ' +
                        'aria-required="true" ' +
                        'role="listbox" ' + listLabel +
                        'class="' + classes.attributeOptionsWrapper + ' clearfix swatch--">' +
                        options + select +
                        '</div>' + input +
                        '</div>'
                    );
                }

                $widget.optionsMap[item.id] = {};

                // Aggregate options array to hash (key => value)
                $.each(item.options, function () {
                    if (this.products.length > 0) {
                        $widget.optionsMap[item.id][this.id] = {
                            price: parseInt(
                                $widget.options.jsonConfig.optionPrices[this.products[0]].finalPrice.amount,
                                10
                            ),
                            products: this.products
                        };
                    }
                });
            });

            // Connect Tooltip
            container
                .find('[option-type="1"], [option-type="2"], [option-type="0"], [option-type="3"]')
                .SwatchRendererTooltip();

            // Hide all elements below more button
            $('.' + classes.moreButton).nextAll().hide();

            // Handle events like click or change
            $widget._EventListener();

            // Rewind options
            $widget._Rewind(container);

            //Emulate click on all swatches from Request
            var mediaGallerySelector = this.options.mediaGallerySelector;
            var mediaCallbacks = this.options.mediaCallback;
            $(document).ready(function () {
                if ($('body.catalog-product-view').length > 0) {
                    // var $widgets = this;
                    var swatchInterval;
                    var i = 0;
                    swatchInterval = setInterval(function () {
                        var swatchLength = $('.swatch-attribute.color').length;
                        var sizeLength = $('.swatch-attribute.size').length;
                        var fotoramaLength = $('.fotorama__loaded').length;
                        var galleryLoaded = false;
                        if (fotoramaLength && typeof $(mediaGallerySelector).data('gallery') != 'undefined') {
                            galleryLoaded = true;
                        }
                        i = i + 1;
                        if (i > 20) {
                            clearInterval(swatchInterval);
                        }
                        if (swatchLength > 0 && galleryLoaded) {

                            $widget._EmulateSelected($.parseQuery());
                            $widget._EmulateSelected($widget._getSelectedAttributes());

                            const queryString = window.location.search;
                            const urlParams = new URLSearchParams(queryString);
                            const colorValue = urlParams.get('color')
                            if (colorValue) {
                                var url = window.location.href;
                                if ($('.swatch-option[option-id='+colorValue+']').length == 0) {
                                    $('.swatch-option[option-id='+colorValue+']').trigger('click');
                                }
                            } else {
                                var defaultOptionId = $widget.options.jsonSwatchDefaultId;
                                if(defaultOptionId){
                                    $('.swatch-option[option-id='+defaultOptionId+']').trigger('click');
                                }else{
                                    $('.swatch-option').first().trigger('click');
                                }
                            }
                            clearInterval(swatchInterval);
                        }

                        return false;
                    },100);
                }
            });
        },

        /**
         * Render swatch options by part of config
         *
         * @param {Object} config
         * @param {String} controlId
         * @returns {String}
         * @private
         */
        _RenderSwatchOptions: function (config, controlId) {
            var optionConfig = this.options.jsonSwatchConfig[config.id],
                optionClass = this.options.classes.optionClass,
                sizeConfig = this.options.jsonSwatchImageSizeConfig,
                moreLimit = parseInt(this.options.numberToShow, 10),
                moreClass = this.options.classes.moreButton,
                moreText = this.options.moreButtonText,
                countAttributes = 0,
                html = '';

                //....Start: To add new drop-down for size type...//
                var defaultSelectedValue = $('.swatch-opt').attr('data-country-dd-status');
                if(defaultSelectedValue == 1) {
                    html += this.renderSizeDropDown(config, optionConfig);
                }

                //....End: To add new drop-down for size type...//

            if (!this.options.jsonSwatchConfig.hasOwnProperty(config.id)) {
                return '';
            }

            $.each(config.options, function (index) {
                var id,
                    type,
                    value,
                    thumb,
                    label,
                    width,
                    height,
                    attr,
                    swatchImageWidth,
                    swatchImageHeight;

                if (!optionConfig.hasOwnProperty(this.id)) {
                    // Display OOS options
                    html += '<div class="' + optionClass + ' text disabled out-of-stock" id="' + this.id + '" id="' + this.id + '" option-label="' + this.label + '" option-tooltip-value="'+this.label+'">' + this.label +
                        '</div>';
                    return '';
                }

                // Add more button
                if (moreLimit === countAttributes++) {
                    html += '<a href="#" class="' + moreClass + '"><span>' + moreText + '</span></a>';
                }

                id = this.id;
                type = parseInt(optionConfig[id].type, 10);
                value = optionConfig[id].hasOwnProperty('value') ? optionConfig[id].value : '';
                thumb = optionConfig[id].hasOwnProperty('thumb') ? optionConfig[id].thumb : '';
                width = _.has(sizeConfig, 'swatchThumb') ? sizeConfig.swatchThumb.width : 110;
                height = _.has(sizeConfig, 'swatchThumb') ? sizeConfig.swatchThumb.height : 90;
                label = this.label ? this.label : '';
                attr =
                    ' id="' + controlId + '-item-' + id + '"' +
                    ' index="' + index + '"' +
                    ' aria-checked="false"' +
                    ' aria-describedby="' + controlId + '"' +
                    ' tabindex="0"' +
                    ' option-type="' + type + '"' +
                    ' option-id="' + id + '"' +
                    ' option-label="' + label + '"' +
                    ' aria-label="' + label + '"' +
                    ' option-tooltip-thumb="' + thumb + '"' +
                    ' option-tooltip-value="' + value + '"' +
                    ' role="option"' +
                    ' thumb-width="' + width + '"' +
                    ' thumb-height="' + height + '"'+
                    ' eu_label="' + optionConfig[id].eu_label + '"' +
                    ' uk_label="' + optionConfig[id].uk_label + '"' +
                    ' us_label="' + optionConfig[id].us_label + '"';

                swatchImageWidth = _.has(sizeConfig, 'swatchImage') ? sizeConfig.swatchImage.width : 30;
                swatchImageHeight = _.has(sizeConfig, 'swatchImage') ? sizeConfig.swatchImage.height : 20;

                if (!this.hasOwnProperty('products') || this.products.length <= 0) {
                    attr += ' option-empty="true"';
                }

                if (type === 0) {
                    // Text
                    html += '<div class="' + optionClass + ' text" ' + attr + '>' + (value ? value : label) +
                        '</div>';
                } else if (type === 1) {
                    // Color
                    html += '<div class="' + optionClass + ' color" ' + attr +
                        ' style="background: ' + value +
                        ' no-repeat center; background-size: initial;">' + '' +
                        '</div>';
                } else if (type === 2) {
                    // Image
                    html += '<div class="' + optionClass + ' image" ' + attr +
                        ' style="background: url(' + value + ') no-repeat center; background-size: initial;width:' +
                        swatchImageWidth + 'px; height:' + swatchImageHeight + 'px">' + '' +
                        '</div>';
                } else if (type === 3) {
                    // Clear
                    html += '<div class="' + optionClass + '" ' + attr + '></div>';
                } else {
                    // Default
                    html += '<div class="' + optionClass + '" ' + attr + '>' + label + '</div>';
                }
            });

            return html;
        },

        /**
         * Render select by part of config
         *
         * @param {Object} config
         * @param {String} chooseText
         * @returns {String}
         * @private
         */
        _RenderSwatchSelect: function (config, chooseText) {
            var html;

            if (this.options.jsonSwatchConfig.hasOwnProperty(config.id)) {
                return '';
            }

            html =
                '<select class="' + this.options.classes.selectClass + ' ' + config.code + '">' +
                '<option value="0" option-id="0">' + chooseText + '</option>';

            $.each(config.options, function () {
                var label = this.label,
                    attr = ' value="' + this.id + '" option-id="' + this.id + '"';

                if (!this.hasOwnProperty('products') || this.products.length <= 0) {
                    attr += ' option-empty="true"';
                }

                html += '<option ' + attr + '>' + label + '</option>';
            });

            html += '</select>';

            return html;
        },

        /**
         * Input for submit form.
         * This control shouldn't have "type=hidden", "display: none" for validation work :(
         *
         * @param {Object} config
         * @private
         */
        _RenderFormInput: function (config) {
            return '<input class="' + this.options.classes.attributeInput + ' super-attribute-select" ' +
                'name="super_attribute[' + config.id + ']" ' +
                'type="text" ' +
                'value="" ' +
                'data-selector="super_attribute[' + config.id + ']" ' +
                'data-validate="{required: true}" ' +
                'aria-required="true" ' +
                'aria-invalid="false">';
        },

        /**
         * Event listener
         *
         * @private
         */
        _EventListener: function () {
            var $widget = this,
                options = this.options.classes,
                target;

            $widget.element.on('click', '.' + options.optionClass, function () {
                return $widget._OnClick($(this), $widget);
            });

            if ($('body.catalog-category-view').length > 0 || $('body.catalogsearch-result-index').length > 0) {
                $widget.element.on('mouseenter', '.' + options.optionClass, function () {
                    return $widget._OnMouseOver($(this), $widget);
                });
            }

            $widget.element.on('change', '.' + options.selectClass, function () {
                return $widget._OnChange($(this), $widget);
            });

            $widget.element.on('click', '.' + options.moreButton, function (e) {
                e.preventDefault();

                return $widget._OnMoreClick($(this));
            });

            $widget.element.on('keydown', function (e) {
                if (e.which === 13) {
                    target = $(e.target);

                    if (target.is('.' + options.optionClass)) {
                        return $widget._OnClick(target, $widget);
                    } else if (target.is('.' + options.selectClass)) {
                        return $widget._OnChange(target, $widget);
                    } else if (target.is('.' + options.moreButton)) {
                        e.preventDefault();

                        return $widget._OnMoreClick(target);
                    }
                }
            });
        },

        /**
         * Load media gallery using ajax or json config.
         *
         * @private
         */
        _loadMedia: function () {
            var $main = this.inProductList ?
                    this.element.parents('.product-item-info') :
                    this.element.parents('.column.main'),
                images;

            if (this.options.useAjax) {
                this._debouncedLoadProductMedia();
            } else {
                images = this.options.jsonConfig.images[this.getProduct()];

                if (!images) {
                    images = this.options.mediaGalleryInitial;
                }
                this.updateBaseImage(images, $main, !this.inProductList);
            }
        },

        /**
         * Sorting images array
         *
         * @private
         */
        _sortImages: function (images) {
            return _.sortBy(images, function (image) {
                return parseInt(image.position, 10);
            });
        },

        /**
         * Event for swatch options
         *
         * @param {Object} $this
         * @param {Object} $widget
         * @private
         */
        _OnClick: function ($this, $widget) {
            var $parent = $this.parents('.' + $widget.options.classes.attributeClass),
                $wrapper = $this.parents('.' + $widget.options.classes.attributeOptionsWrapper),
                $label = $parent.find('.' + $widget.options.classes.attributeSelectedOptionLabelClass),
                attributeId = $parent.attr('attribute-id'),
                $input = $parent.find('.' + $widget.options.classes.attributeInput),
                checkAdditionalData = JSON.parse(this.options.jsonSwatchConfig[attributeId]['additional_data']);

            if ($widget.inProductList) {
                $input = $widget.productForm.find(
                    '.' + $widget.options.classes.attributeInput + '[name="super_attribute[' + attributeId + ']"]'
                );
            }

            if ($this.hasClass('disabled')) {
                return;
            }

            if ($this.hasClass('selected')) {
                return;
            } else {
                $parent.attr('option-selected', $this.attr('option-id')).find('.selected').removeClass('selected');
                $label.text($this.attr('option-label'));
                $input.val($this.attr('option-id'));
                $input.attr('data-attr-name', this._getAttributeCodeById(attributeId));
                $this.addClass('selected');
                $widget._toggleCheckedAttributes($this, $wrapper);
            }

            $widget._Rebuild();

            if ($widget.element.parents($widget.options.selectorProduct)
                .find(this.options.selectorProductPrice).is(':data(mage-priceBox)')
            ) {
                $widget._UpdatePrice();
            }
            if (!$('body').hasClass('checkout-cart-configure')) {
                $(document).trigger(
                    'updateMsrpPriceBlock',
                    [
                        parseInt($this.attr('index'), 10) + 1,
                        $widget.options.jsonConfig.optionPrices
                    ]
                );
            }
            if (checkAdditionalData['update_product_preview_image'] === '1') {
                $widget._loadMedia();
            }

            $input.trigger('change');
            let productSku = this.options.jsonConfig.skus[this.getProduct()];
            this._setChildProductInFacebookPixel(productSku);

            if (typeof this.options.jsonConfig.certJson[productSku] !== 'undefined' && this.options.jsonConfig.certJson[productSku]) {
                $('.certificateNo').show();
                $('.certificateNo .value').text(this.options.jsonConfig.certJson[productSku]);
            } else {
                $('.certificateNo').hide();
                $('.certificateNo .value').text('');
            }
        },

        _setChildProductInFacebookPixel(productSku) {
            $.ajax({
                url: "/linkedproducts/product/displaysku",
                cache: false,
                type: 'GET',
                dataType: 'json',
                data: {sku: productSku}
            }).done(function (response) {
                window.mfFbPixelChildProduct = response && response.result && response.result.data ? response.result.data : undefined;
                if (!window.fbq || !window.mfFbPixelChildProduct) {
                    return;
                }
                let data = window.mfFbPixelChildProduct;
                if (data) {
                    var eventName = 'ViewContentChild';
                    fbq('track', eventName, data, {'eventID': eventName + '.' + Math.floor(Math.random() * 1000000) + '.' + Date.now()});

                }
            });
        },

        /**
         * Get selected option price index
         *
         * @return {String|undefined}
         * @private
         */
        _getSelectedOptionPriceIndex: function () {
            var allowedProduct = this._getAllowedProductWithMinPrice(this._CalcProducts());

            if (_.isEmpty(allowedProduct)) {
                return undefined;
            }

            return allowedProduct;
        },

        /**
         * Event for swatch options on mouse over
         *
         * @param {Object} $this
         * @param {Object} $widget
         * @private
         */
        _OnMouseOver: function ($this, $widget) {
            var $parent = $this.parents('.' + $widget.options.classes.attributeClass),
                $wrapper = $this.parents('.' + $widget.options.classes.attributeOptionsWrapper),
                $label = $parent.find('.' + $widget.options.classes.attributeSelectedOptionLabelClass),
                attributeId = $parent.attr('attribute-id'),
                $input = $parent.find('.' + $widget.options.classes.attributeInput),
                checkAdditionalData = JSON.parse(this.options.jsonSwatchConfig[attributeId]['additional_data']);

            if ($widget.inProductList) {
                $input = $widget.productForm.find(
                    '.' + $widget.options.classes.attributeInput + '[name="super_attribute[' + attributeId + ']"]'
                );
            }

            $parent.attr('option-selected', $this.attr('option-id')).find('.hover-selected').removeClass('hover-selected');
            $label.text($this.attr('option-label'));
            $input.val($this.attr('option-id'));
            $input.attr('data-attr-name', this._getAttributeCodeById(attributeId));
            $this.addClass('hover-selected');
            var imgHeight=$('.product-image-photo').height();
            $('.lazy').css('height',imgHeight);
            $widget._toggleCheckedAttributes($this, $wrapper);

            $widget._Rebuild();

            if ($widget.element.parents($widget.options.selectorProduct)
                .find(this.options.selectorProductPrice).is(':data(mage-priceBox)')
            ) {
                $widget._UpdatePrice();
            }

            $(document).trigger(
                'updateMsrpPriceBlock',
                [
                    parseInt($this.attr('index'), 10) + 1,
                    $widget.options.jsonConfig.optionPrices
                ]
            );

            if (checkAdditionalData['update_product_preview_image'] === '1') {
                $widget._loadMedia();
            }

            $input.trigger('change');
        },

        /**
         * Get human readable attribute code (eg. size, color) by it ID from configuration
         *
         * @param {Number} attributeId
         * @returns {*}
         * @private
         */
        _getAttributeCodeById: function (attributeId) {
            var attribute = this.options.jsonConfig.mappedAttributes[attributeId];

            return attribute ? attribute.code : attributeId;
        },

        /**
         * Toggle accessibility attributes
         *
         * @param {Object} $this
         * @param {Object} $wrapper
         * @private
         */
        _toggleCheckedAttributes: function ($this, $wrapper) {
            $wrapper.attr('aria-activedescendant', $this.attr('id'))
                .find('.' + this.options.classes.optionClass).attr('aria-checked', false);
            $this.attr('aria-checked', true);
        },

        /**
         * Event for select
         *
         * @param {Object} $this
         * @param {Object} $widget
         * @private
         */
        _OnChange: function ($this, $widget) {
            var $parent = $this.parents('.' + $widget.options.classes.attributeClass),
                attributeId = $parent.attr('attribute-id'),
                $input = $parent.find('.' + $widget.options.classes.attributeInput);

            if ($widget.productForm.length > 0) {
                $input = $widget.productForm.find(
                    '.' + $widget.options.classes.attributeInput + '[name="super_attribute[' + attributeId + ']"]'
                );
            }

            if ($this.val() > 0) {
                $parent.attr('option-selected', $this.val());
                $input.val($this.val());
            } else {
                $parent.removeAttr('option-selected');
                $input.val('');
            }

            $widget._Rebuild();
            $widget._UpdatePrice();
            $widget._loadMedia();
            $input.trigger('change');
        },

        /**
         * Event for more switcher
         *
         * @param {Object} $this
         * @private
         */
        _OnMoreClick: function ($this) {
            $this.nextAll().show();
            $this.blur().remove();
        },

        /**
         * Rewind options for controls
         *
         * @private
         */
        _Rewind: function (controls) {
            controls.find('div[option-id], option[option-id]').each(function () {
                var text = '';
                text = $(this).text();
                $(this).text(text.replace(' - Sold Out', ''));
            });
            controls.find('div[option-id], option[option-id]').removeClass('disabled').removeAttr('disabled');
            controls.find('div[option-empty], option[option-empty]').attr('disabled', true).addClass('disabled');

            controls.find('option[option-empty]').each(function () {
                var text = '';
                if ($(this).attr('disabled')) {
                    var eleType = $(this).prop('nodeName');
                    text = $(this).text();
                    if (eleType === 'OPTION') {
                        $(this).text(text + $t(' - Sold Out'));
                    }
                }
            });
        },

        /**
         * Rebuild container
         *
         * @private
         */
        _Rebuild: function () {
            var $widget = this,
                controls = $widget.element.find('.' + $widget.options.classes.attributeClass + '[attribute-id]'),
                selected = controls.filter('[option-selected]');

            // Enable all options
            $widget._Rewind(controls);

            // done if nothing selected
            if (selected.length <= 0) {
                return;
            }

            // Disable not available options
            controls.each(function () {
                var $this = $(this),
                    id = $this.attr('attribute-id'),
                    products = $widget._CalcProducts(id);

                if (selected.length === 1 && selected.first().attr('attribute-id') === id) {
                    return;
                }

                $this.find('[option-id]').each(function () {
                    var $element = $(this),
                        option = $element.attr('option-id'),
                        text;

                    if (!$widget.optionsMap.hasOwnProperty(id) || !$widget.optionsMap[id].hasOwnProperty(option) ||
                        $element.hasClass('selected') ||
                        $element.is(':selected')) {
                        return;
                    }

                    if (_.intersection(products, $widget.optionsMap[id][option].products).length <= 0) {
                        $element.attr('disabled', true).addClass('disabled');
                        if ($element.attr('disabled')) {
                            text = $element.text();
                            var eleType = $(this).prop('nodeName');
                            if (eleType === 'OPTION') {
                                $element.text(text + $t(' - Sold Out'));
                            }
                        }
                    }
                });
            });
        },

        /**
         * Get selected product list
         *
         * @returns {Array}
         * @private
         */
        _CalcProducts: function ($skipAttributeId) {
            var $widget = this,
                products = [];

            // Generate intersection of products
            $widget.element.find('.' + $widget.options.classes.attributeClass + '[option-selected]').each(function () {
                var id = $(this).attr('attribute-id'),
                    option = $(this).attr('option-selected');

                if ($skipAttributeId !== undefined && $skipAttributeId === id) {
                    return;
                }

                if (!$widget.optionsMap.hasOwnProperty(id) || !$widget.optionsMap[id].hasOwnProperty(option)) {
                    return;
                }

                if (products.length === 0) {
                    products = $widget.optionsMap[id][option].products;
                } else {
                    products = _.intersection(products, $widget.optionsMap[id][option].products);
                }
            });

            return products;
        },

        /**
         * Update total price
         *
         * @private
         */
        _UpdatePrice: function () {
            var $widget = this,
                $product = $widget.element.parents($widget.options.selectorProduct),
                $productPrice = $product.find(this.options.selectorProductPrice),
                options = _.object(_.keys($widget.optionsMap), {}),
                result,
                tierPriceHtml,
                isShow;

            $widget.element.find('.' + $widget.options.classes.attributeClass + '[option-selected]').each(function () {
                var attributeId = $(this).attr('attribute-id');
                options[attributeId] = $(this).attr('option-selected');
            });

            // Check if global SKU is present
            var hasGlobalSku = $('div.product-info-main .custom_global_sku[data-has-global-sku="true"]').length > 0 ||
                               $('div.product-info-main .sku[data-has-global-sku="true"]').length > 0;

            // Only update SKU if global SKU is not present
            if (!hasGlobalSku) {
                if  (this.options.jsonConfig.skus != undefined) {
                    var child_sku = this.options.jsonConfig.skus[_.findKey($widget.options.jsonConfig.index, options)];
                }
                
                if (child_sku == undefined) {
                    $('div.product-info-main .sku').addClass('hidden');
                    $('div.product-info-main .custom_global_sku[data-has-global-sku="false"]').hide();
                } else {
                    $('div.product-info-main .sku').removeClass('hidden');
                    $('div.product-info-main .sku .value').html(child_sku);
                    // Also update custom_global_sku if it's being used for variant SKU
                    $('div.product-info-main .custom_global_sku[data-has-global-sku="false"]').show();
                    $('div.product-info-main .custom_global_sku[data-has-global-sku="false"] .value').html(child_sku);

                    // Product Return Block
                    if (this.options.jsonConfig.pdp_product_return && this.options.jsonConfig.pdp_product_return[child_sku]
                        && '' != this.options.jsonConfig.pdp_product_return[child_sku]) {
                        $('#pdp_product_return').html(this.options.jsonConfig.pdp_product_return[child_sku]).show();
                    } else {
                        $('#pdp_product_return').html('').hide();
                    }

                    // Free Shipping Product Block
                    if (this.options.jsonConfig.pdp_free_shipping && this.options.jsonConfig.pdp_free_shipping[child_sku]
                        && '' != this.options.jsonConfig.pdp_free_shipping[child_sku]) {
                        $('#pdp_free_shipping').html(this.options.jsonConfig.pdp_free_shipping[child_sku]).show();
                    } else {
                        $('#pdp_free_shipping').html('').show();
                    }

                    // Surprise Drop Block
                    if (this.options.jsonConfig.pdp_surprise_drop && this.options.jsonConfig.pdp_surprise_drop[child_sku]
                        && '' != this.options.jsonConfig.pdp_surprise_drop[child_sku]) {
                        $('#pdp_surprise_drop').html(this.options.jsonConfig.pdp_surprise_drop[child_sku]).show();
                    } else {
                        $('#pdp_surprise_drop').html('').show();
                    }
                }
            }

            result = $widget.options.jsonConfig.optionPrices[_.findKey($widget.options.jsonConfig.index, options)];

            $productPrice.trigger(
                'updatePrice',
                {
                    'prices': $widget._getPrices(result, $productPrice.priceBox('option').prices)
                }
            );

            isShow = typeof result != 'undefined' && result.oldPrice.amount !== result.finalPrice.amount;

            $product.find(this.options.slyOldPriceSelector)[isShow ? 'show' : 'hide']();

            if (typeof result != 'undefined' && result.tierPrices.length) {
                if (this.options.tierPriceTemplate) {
                    tierPriceHtml = mageTemplate(
                        this.options.tierPriceTemplate,
                        {
                            'tierPrices': result.tierPrices,
                            '$t': $t,
                            'currencyFormat': this.options.jsonConfig.currencyFormat,
                            'priceUtils': priceUtils
                        }
                    );
                    $(this.options.tierPriceBlockSelector).html(tierPriceHtml).show();
                }
            } else {
                $(this.options.tierPriceBlockSelector).hide();
            }

            // Update Payment EMI and Sticky Cart price on change.
            if (result && result.finalPrice) {
                if ($('.payment_emi').length) {
                    var paymentEmiText = $('.payment_emi').html();
                    var tmpPaymentEmiText = paymentEmiText.split('<strong>');
                    var paymentEmiCount = tmpPaymentEmiText[0].replace(/[^1-9]/g, '');
                    $('.payment_emi .price').html(priceUtils.formatPrice(result.finalPrice.amount / paymentEmiCount));
                }
                $('.stickycart .price').html(priceUtils.formatPrice(result.finalPrice.amount));
            }
        },

        /**
         * Get new prices for selected options
         *
         * @returns {*}
         * @private
         */
        _getNewPrices: function () {
            var $widget = this,
                newPrices = $widget.options.jsonConfig.prices,
                allowedProduct = this._getAllowedProductWithMinPrice(this._CalcProducts());

            if (!_.isEmpty(allowedProduct)) {
                newPrices = this.options.jsonConfig.optionPrices[allowedProduct];
            }

            return newPrices;
        },

        /**
         * Get prices
         *
         * @param {Object} newPrices
         * @param {Object} displayPrices
         * @returns {*}
         * @private
         */
        _getPrices: function (newPrices, displayPrices) {
            var $widget = this;

            if (_.isEmpty(newPrices)) {
                newPrices = $widget.options.jsonConfig.prices;
            }

            _.each(displayPrices, function (price, code) {

                if (newPrices[code]) {
                    displayPrices[code].amount = newPrices[code].amount - displayPrices[code].amount;
                }
            });

            return displayPrices;
        },

        /**
         * Get product with minimum price from selected options.
         *
         * @param {Array} allowedProducts
         * @returns {String}
         * @private
         */
        _getAllowedProductWithMinPrice: function (allowedProducts) {
            var optionPrices = this.options.jsonConfig.optionPrices,
                product = {},
                optionFinalPrice, optionMinPrice;

            _.each(allowedProducts, function (allowedProduct) {
                optionFinalPrice = parseFloat(optionPrices[allowedProduct].finalPrice.amount);

                if (_.isEmpty(product) || optionFinalPrice < optionMinPrice) {
                    optionMinPrice = optionFinalPrice;
                    product = allowedProduct;
                }
            }, this);

            return product;
        },

        /**
         * Gets all product media and change current to the needed one
         *
         * @private
         */
        _LoadProductMedia: function () {
            var $widget = this,
                $this = $widget.element,
                productData = this._determineProductData(),
                mediaCallData,
                mediaCacheKey,

                /**
                 * Processes product media data
                 *
                 * @param {Object} data
                 * @returns void
                 */
                mediaSuccessCallback = function (data) {
                    if (!(mediaCacheKey in $widget.options.mediaCache)) {
                        $widget.options.mediaCache[mediaCacheKey] = data;
                    }
                    $widget._ProductMediaCallback($this, data, productData.isInProductView);
                    setTimeout(function () {
                        $widget._DisableProductMediaLoader($this);
                    }, 300);
                };

            if (!$widget.options.mediaCallback) {
                return;
            }

            mediaCallData = {
                'product_id': this.getProduct()
            };

            mediaCacheKey = JSON.stringify(mediaCallData);

            if (mediaCacheKey in $widget.options.mediaCache) {
                $widget._XhrKiller();
                $widget._EnableProductMediaLoader($this);
                mediaSuccessCallback($widget.options.mediaCache[mediaCacheKey]);
            } else {
                var formKey = $('input[name="form_key"]').val();
                mediaCallData.isAjax = true;
                mediaCallData.formKey = formKey;
                $widget._XhrKiller();
                $widget._EnableProductMediaLoader($this);
                $widget.xhr = $.ajax({
                    url: $widget.options.mediaCallback,
                    cache: false,
                    type: 'GET',
                    dataType: 'json',
                    data: mediaCallData,
                    success: mediaSuccessCallback
                }).done(function () {
                    $widget._XhrKiller();
                });
            }
        },

        /**
         * Enable loader
         *
         * @param {Object} $this
         * @private
         */
        _EnableProductMediaLoader: function ($this) {
            var $widget = this;

            if ($('body.catalog-product-view').length > 0) {
                $this.parents('.column.main').find('.photo.image')
                    .addClass($widget.options.classes.loader);
            } else {
                //Category View
                $this.parents('.product-item-info').find('.product-image-photo')
                    .addClass($widget.options.classes.loader);
            }
        },

        /**
         * Disable loader
         *
         * @param {Object} $this
         * @private
         */
        _DisableProductMediaLoader: function ($this) {
            var $widget = this;

            if ($('body.catalog-product-view').length > 0) {
                $this.parents('.column.main').find('.photo.image')
                    .removeClass($widget.options.classes.loader);
            } else {
                //Category View
                $this.parents('.product-item-info').find('.product-image-photo')
                    .removeClass($widget.options.classes.loader);
            }
        },

        /**
         * Callback for product media
         *
         * @param {Object} $this
         * @param {String} response
         * @param {Boolean} isInProductView
         * @private
         */
        _ProductMediaCallback: function ($this, response, isInProductView) {
            var $main = isInProductView ? $this.parents('.column.main') : $this.parents('.product-item-info'),
                $widget = this,
                images = [],

                /**
                 * Check whether object supported or not
                 *
                 * @param {Object} e
                 * @returns {*|Boolean}
                 */
                support = function (e) {
                    return e.hasOwnProperty('large') && e.hasOwnProperty('medium') && e.hasOwnProperty('small');
                };

            if (_.size($widget) < 1 || !support(response)) {
                this.updateBaseImage(this.options.mediaGalleryInitial, $main, isInProductView);

                return;
            }

            images.push({
                full: response.large,
                img: response.medium,
                thumb: response.small,
                isMain: true
            });

            if (response.hasOwnProperty('gallery')) {
                $.each(response.gallery, function () {
                    if (!support(this) || response.large === this.large) {
                        return;
                    }
                    images.push({
                        full: this.large,
                        img: this.medium,
                        thumb: this.small
                    });
                });
            }

            this.updateBaseImage(images, $main, isInProductView);
        },

        /**
         * Check if images to update are initial and set their type
         * @param {Array} images
         */
        _setImageType: function (images) {
            var initial = this.options.mediaGalleryInitial[0].img;

            if (images[0].img === initial) {
                images = $.extend(true, [], this.options.mediaGalleryInitial);
            } else {
                images.map(function (img) {
                    if (!img.type) {
                        img.type = 'image';
                    }
                });
            }

            return images;
        },

        /**
         * Update [gallery-placeholder] or [product-image-photo]
         * @param {Array} images
         * @param {jQuery} context
         * @param {Boolean} isInProductView
         */
        updateBaseImage: function (images, context, isInProductView) {
            var justAnImage = images[0],
                initialImages = this.options.mediaGalleryInitial,
                gallery = context.find(this.options.mediaGallerySelector).data('gallery'),
                imagesToUpdate,
                isInitial;

            if (isInProductView) {
                imagesToUpdate = images.length ? this._setImageType($.extend(true, [], images)) : [];
                isInitial = _.isEqual(imagesToUpdate, initialImages);

                if (this.options.gallerySwitchStrategy === 'prepend' && !isInitial) {
                    imagesToUpdate = imagesToUpdate.concat(initialImages);
                }

                imagesToUpdate = this._setImageIndex(imagesToUpdate);
                if (typeof gallery == 'undefined') {
                    var mediaEle = $(this.options.mediaGallerySelector);
                    if (mediaEle.length) {
                        gallery = $(this.options.mediaGallerySelector).data('gallery');
                    }
                }
                window.imagesToUpdate = images;
                this._addFotoramaVideoEvents(isInitial);
                gallery.updateData(images); //NOSONAR
                $(window.imagesToUpdate).each(function(i, imageItem) {
                    if (imageItem.isMain) {
                        gallery.seek(i+1);
                        return false;
                    }
                });
            } else if (justAnImage && justAnImage.img) {
                context.find('.product-image-photo').attr('src', justAnImage.img);
            }
        },

        /**
         * Add video events
         *
         * @param {Boolean} isInitial
         * @private
         */
        _addFotoramaVideoEvents: function (isInitial) {
            if (_.isUndefined($.mage.AddFotoramaVideoEvents)) {
                return;
            }

            if (isInitial) {
                $(this.options.mediaGallerySelector).AddFotoramaVideoEvents();

                return;
            }

            $(this.options.mediaGallerySelector).AddFotoramaVideoEvents({
                selectedOption: this.getProduct(),
                dataMergeStrategy: this.options.gallerySwitchStrategy
            });
        },

        /**
         * Set correct indexes for image set.
         *
         * @param {Array} images
         * @private
         */
        _setImageIndex: function (images) {
            var length = images.length,
                i;

            for (i = 0; length > i; i++) {
                images[i].i = i + 1;
            }

            return images;
        },

        /**
         * Kill doubled AJAX requests
         *
         * @private
         */
        _XhrKiller: function () {
            var $widget = this;

            if ($widget.xhr !== undefined && $widget.xhr !== null) {
                $widget.xhr.abort();
                $widget.xhr = null;
            }
        },

        /**
         * Emulate mouse click on all swatches that should be selected
         * @param {Object} [selectedAttributes]
         * @private
         */
        _EmulateSelected: function (selectedAttributes) {
            $.each(selectedAttributes, $.proxy(function (attributeCode, optionId) {
                this.element.find('.' + this.options.classes.attributeClass +
                    '[attribute-code="' + attributeCode + '"] [option-id="' + optionId + '"]').trigger('click');
            }, this));
        },

        /**
         * Emulate mouse click or selection change on all swatches that should be selected
         * @param {Object} [selectedAttributes]
         * @private
         */
        _EmulateSelectedByAttributeId: function (selectedAttributes) {
            $.each(selectedAttributes, $.proxy(function (attributeId, optionId) {
                var elem = this.element.find('.' + this.options.classes.attributeClass +
                        '[attribute-id="' + attributeId + '"] [option-id="' + optionId + '"]'),
                    parentInput = elem.parent();

                /*if (elem.hasClass('selected')) {
                    return;
                }*/

                if (parentInput.hasClass(this.options.classes.selectClass)) {
                    parentInput.val(optionId);
                    parentInput.trigger('change');
                } else {
                    elem.trigger('click');
                }
            }, this));
        },

        /**
         * Get default options values settings with either URL query parameters
         * @private
         */
        _getSelectedAttributes: function () {
            var hashIndex = window.location.href.indexOf('#'),
                selectedAttributes = {},
                params;

            if (hashIndex !== -1) {
                params = $.parseQuery(window.location.href.substr(hashIndex + 1));

                selectedAttributes = _.invert(_.mapObject(_.invert(params), function (attributeId) {
                    var attribute = this.options.jsonConfig.mappedAttributes[attributeId];

                    return attribute ? attribute.code : attributeId;
                }.bind(this)));
            }

            return selectedAttributes;
        },

        /**
         * Callback which fired after gallery gets initialized.
         *
         * @param {HTMLElement} element - DOM element associated with a gallery.
         */
        _onGalleryLoaded: function (element) {
            var galleryObject = element.data('gallery');

            this.options.mediaGalleryInitial = galleryObject.returnCurrentImages();
        },

        /**
         * Sets mediaCache for cases when jsonConfig contains preSelectedGallery on layered navigation result pages
         *
         * @private
         */
        _setPreSelectedGallery: function () {
            var mediaCallData;

            if (this.options.jsonConfig.preSelectedGallery) {
                mediaCallData = {
                    'product_id': this.getProduct()
                };

                this.options.mediaCache[JSON.stringify(mediaCallData)] = this.options.jsonConfig.preSelectedGallery;
            }
        },

        renderSizeDropDown: function(config, optionConfig, html) {
            var noCountrySizes = true;
            var html = '';
            if (config.code == "size") {
                html +='<select name ="sizeChart" id="size_type">';
                var flagEuCheck = false;
                var flagUkCheck = false;
                var flagUsCheck = false;
                $.each(config.options, function (index) {
                    var customId = this.id;
                    if(customId != null)
                    {
                        if(typeof optionConfig[customId] != 'undefined' && optionConfig[customId].eu_label != null && flagEuCheck == false) {
                            html += '<option value="eu">' + $t('EU') + '</option>';
                            noCountrySizes = false;
                            flagEuCheck = true;
                        }
                        if(typeof optionConfig[customId] != 'undefined'  && optionConfig[customId].uk_label != null && flagUkCheck == false) {
                            html += '<option value="uk">' + $t('UK') + '</option>';
                            noCountrySizes = false;
                            flagUkCheck = true;
                        }
                        if(typeof optionConfig[customId] != 'undefined' && optionConfig[customId].us_label != null && flagUsCheck == false) {
                            html += '<option value="us">' + $t('US') + '</option>';
                            noCountrySizes = false;
                            flagUsCheck = true;
                        }
                    }
                });
                html += '</select>';

                $( window ).on("load", function() {
                    //alert("loaded!!!!!!!!!!");
                    $('#size_type').change(function ($e){
                        var currentType = $('select[name=sizeChart]').val();
                        $('.swatch-option.text').each(function( index ) {
                            $(this).show();
                            if(currentType == "eu") {
                                if ($(this).attr("eu_label") == "" || $(this).attr("eu_label") == "null" || $(this).attr("uk_label") == null) {
                                    $(this).hide();
                                } else {
                                    $(this).html($(this).attr("eu_label"));
                                }
                            } else if(currentType == "uk") {
                                if ($(this).attr("uk_label") == "" || $(this).attr("uk_label") == "null" || $(this).attr("uk_label") == null) {
                                    $(this).hide();
                                } else {
                                    $(this).html($(this).attr("uk_label"));
                                }
                            } else if(currentType == "us") {
                                if ($(this).attr("us_label") == "" || $(this).attr("us_label") == "null" || $(this).attr("uk_label") == null) {
                                    $(this).hide();
                                } else {
                                    $(this).html($(this).attr("us_label"));
                                }
                            }
                        });
                    });
                    var defaultSelectedValue = $('.swatch-opt').attr('data-country-selected-value');
                    $('#size_type').val(defaultSelectedValue).trigger('change');
                });
            }
            if (noCountrySizes) {
                html = "";
            }
            return html;
         }
    });
     if (($('body.catalog-category-view').length > 0 || $('body.catalogsearch-result-index').length > 0) && ($(window).width() > 767)) {
         $('body').on('mouseenter','.product-items .product-item', function () {
            if (!$(this).find('.swatch-attribute').hasClass('opt-1')) {
                $(this).find('.swatch-attribute').removeClass('hidden');
                $(this).find('.product-tile__swatches').addClass('hidden');
            }
        });

        $('body').on('mouseleave','.product-items .product-item', function () {
            if (!$(this).find('.swatch-attribute').hasClass('opt-1')) {
                $(this).find('.swatch-attribute').addClass('hidden');
                $(this).find('.product-tile__swatches').removeClass('hidden');
            }
        });

        $('body').on('mouseleave', '.attribute-wrapper', function () {
            var role_id = $(this).parent().attr('data-role');
            $('[data-role="'+role_id+'"] > .swatch-attribute.color > .swatch-attribute-options > .swatch-option.color.selected').trigger('mouseover');
            $('[data-role="'+role_id+'"] > .swatch-attribute.color > .swatch-attribute-options > .swatch-option.color').removeClass('hover-selected');
        });

        $(window).on('resize', function () {
            if ($(this).width() > 767) {
                $('.large-screen').removeClass('hidden');
                $('.small-screen').addClass('hidden');
            } else {
                $('.large-screen').addClass('hidden');
                $('.small-screen').removeClass('hidden');
            }
        });
    }

    if ($('body.catalog-category-view').length > 0 || $('body.catalogsearch-result-index').length > 0) {
        $('body').on('click', '.attribute-wrapper .swatch-attribute-options .swatch-option', function () {
            var finalURL,
                url;
            var optionId = $(this).attr('option-id');
            var productURL = $(this).closest('li').find(".product.name a").attr("href");

            if (productURL.indexOf('?') > -1) {
                url = productURL.split('?');
                finalURL = url[0] + "?color=" + optionId;
            } else {
                finalURL = productURL + "?color=" + optionId;
            }

            $(this).closest('li').find(".product.name a").attr("href", finalURL);
            $(this).closest('li').find(".product_image a").attr("href", finalURL);
            /* start - we need to uncomment below code if google gtm enabled on site*/
            var onclickstr = $(this).closest('li').find(".product.name a").attr("onclick");
            if(onclickstr != undefined){
                var newonclickstr = onclickstr.replace(productURL, finalURL);
                $(this).closest('li').find(".product.name a").attr("onclick", newonclickstr);
                var onclickimagestr = $(this).closest('li').find(".product_image a").attr("onclick");
                var newonclickimagestr = onclickimagestr.replace(productURL, finalURL);
                $(this).closest('li').find(".product_image a").attr("onclick", newonclickimagestr);
            }
            /* end - we need to uncomment above code if google gtm enabled on site*/

        });
    }

    return $.mage.SwatchRenderer;
});

define('Born_StockInfo/js/stock-status-label',[
    'jquery',
    'Magento_Swatches/js/swatch-renderer',
    'mage/translate'
], function ($) {

    var selectedOptions = {};
    var childsConfig = {};

    var _getSelectedChild = function () {
    var allOptionsSelected = true;
    $('.super-attribute-select').each(function () {
            var str = $(this).attr("name");
            var re = /super_attribute\[(\d+)\]/g;
            var matches = re.exec(str);
            var attributeId = matches[1];

        if (Object.keys(selectedOptions).indexOf(attributeId) == '-1' ) {
            allOptionsSelected = false;
        }
    });

        if (!allOptionsSelected) {
            return false;
        } else {
            var selectedChild,
            obj1,
            obj2;
            for (var property in childsConfig) {
                obj1 = JSON.stringify(childsConfig[property]);
                obj2 = JSON.stringify(selectedOptions)
                if (obj1 === obj2) {
                    var selectedChildId = property;
                    return selectedChildId;
                }
            }
        }
    }

    var stockStatusLabelComponent = function (options) {
        if (options.productData.type == 'configurable' ) {
            childsConfig = options.productOptions.index;
            var childsStatus = options.productData.childs;
            var childsStock = options.productData.stock_status;
            var childsThresholdValue = options.productData.threshold_stock;
            var storeThresholdvalue  = options.productData.store_threshold_qty;

            $('.super-attribute-select').on('change', function () {
                var str = $(this).attr("name");
                var re = /super_attribute\[(\d+)\]/g;
                var matches = re.exec(str);
                var attributeId = matches[1];

                if ( $(this).val() == "" ) {
                    delete selectedOptions[attributeId];
                    $('#stock_status_label').removeClass();
                    $('#stock_status_label').html("");
                    $('.cart-stock-status').removeClass();

                } else {
                    $('.cart-stock-status').removeClass('configurable');
                    var optionId = $(this).val();
                    selectedOptions[attributeId] = optionId;
                    var selectedChild = _getSelectedChild();
                    var stockInfo = $.mage.__('In stock');
                    var labelClass = 'instock';

                    if (selectedChild) {

                        var childSelectedStock  = childsStock[selectedChild];
                        var selectedChildsThresholdValue = childsThresholdValue[selectedChild];

                        if(selectedChildsThresholdValue == null || selectedChildsThresholdValue ==0){
                            if(childSelectedStock < storeThresholdvalue){
                                var stockInfo = $.mage.__('Less than') +' '+ childSelectedStock +' '+ $.mage.__('items left');
                                var labelClass = 'configurable';
                            }
                        }else{
                             if(childSelectedStock < selectedChildsThresholdValue){
                                var stockInfo = $.mage.__('Less than') +' '+ childSelectedStock +' '+ $.mage.__('items left');
                                var labelClass = 'configurable';
                            }
                        }

                        $('#stock_status_label').removeClass();
                        $('#stock_status_label').html(stockInfo);
                        $('.cart-stock-status').addClass(labelClass);
                    }

                }
            });

        } else if (options.productData.type == 'simple' ) {
            var sku = options.productData.sku;
                $('#stock_status_label').html('In Stock');
        }
    }
    return stockStatusLabelComponent;
});

define('WeltPixel_ProductPage/js/productPage',[
	'jquery',
	'mage/mage',
	'mage/ie-class-fixer',
	'mage/gallery/gallery'
], function (jQuery) {
	"use strict";


	var productPage = {
		init: function () {
			jQuery('.togglet').bind('click', function() {
				setTimeout(function() {jQuery(window).trigger('resize')}, 300);
			});
		},

		load: function () {
			this.action();
			this.mageSticky();
			this.addMinHeight();
		},

		ajaxComplete: function () {
			this.mageSticky();
			this.adjustHeight();
		},

		resize: function () {
			this.action();
			this.adjustHeight();
			this.mageSticky();
		},

		adjustHeight: function() {
			// adjust left media height as well, in case it is smallers
			var media = jQuery('.product.media'),
				mediaGallery = jQuery('.product.media .gallery'),
				infoMain = jQuery('.product-info-main');

			if ( jQuery('body').hasClass('wp-device-xs') ||
				jQuery('body').hasClass('wp-device-s') ||
				jQuery('body').hasClass('wp-device-m')
			) {
				media.height('auto');
			} else {
				if ( ( mediaGallery.height() > 0 ) && ( mediaGallery.height() < infoMain.height())) {
					media.height(infoMain.height());
				}
			}
		},

		mageSticky: function () {
			var positionProductInfo = window.positionProductInfo;

			if (positionProductInfo == 1) {
				if (jQuery('body').hasClass('product-page-v2')) {
					jQuery('.product-info-main.product_v2.cart-summary').mage('sticky', {
						container: '.product-top-main.product_v2',
						spacingTop: 100
					});
				}
				if (jQuery('body').hasClass('product-page-v4')) {
					jQuery('.product-info-main.product_v4.cart-summary').mage('sticky', {
						container: '.product-top-main.product_v4',
						spacingTop: 25
					});
				}

			} else {
				if (jQuery('body').hasClass('product-page-v2') || jQuery('body').hasClass('product-page-v4')) {
					jQuery('.product-info-main.product_v2.cart-summary, .product-info-main.product_v4.cart-summary').addClass("no-sticky-product-page");
				}
			}

		},

		action: function () {
			var media = jQuery('.product.media.product_v2'),
				media_v4 = jQuery('.product.media.product_v4'),
				swipeOff = jQuery('.swipe_desktop_off #swipeOff');

			if(jQuery(window).width() > 768) {
				media.addClass('v2');
				media_v4.addClass('v4');
			} else {
				media.removeClass('v2');
				media_v4.removeClass('v4');
			}

			if(jQuery(window).width() > 1024) {
				swipeOff.addClass('active');
			} else {
				swipeOff.removeClass('active');
			}
		},

		addMinHeight: function() {
			var media_v4 = jQuery('.product.media.product_v4');
			if (media_v4.length) {
				var mediaContainer = media_v4.find('.gallery-placeholder'),
					selector = '.fotorama__loaded--img';
				this.waitForEl(function() {
					return jQuery(selector).length;
				}, function() {
					var prodImg = mediaContainer.find(selector).first();
					mediaContainer.css('min-height', prodImg.outerHeight());
				}, function() {
					// do nothing
				});
			}
		},

		waitForEl: function (isReady, success, error, count, interval) {
			if (count === undefined) count = 10;
			if (interval === undefined) interval = 200;

			if (isReady()) {
				success();
				return;
			}
			var that = this;
			setTimeout(function(){
				if (!count) {
					if (error !== undefined) {
						error();
					}
				} else {
					that.waitForEl(isReady, success, error, count -1, interval);
				}
			}, interval);
		},

		bindStickyScroll: function() {
			var productInfoMain = jQuery('.product-info-main'),
				productInfoMainLeft = parseInt(productInfoMain.offset().left),
				productInfoMainWidth = parseInt(productInfoMain.width()),
				bottomCorrection = '27px',
				leftCorrection = productInfoMainLeft + 'px',
				topOffset = parseInt(jQuery('header.page-header').height()),
				lastScrollTop = -50,
				fixedPos = 0;

			var that = this;
			if(that.isMobileCheck()){
				return true;
			}
			if(jQuery('body').hasClass('product-page-v4')) {
				productInfoMain.removeAttr('style');
				productInfoMainLeft = parseInt(productInfoMain.offset().left);
				productInfoMainWidth = parseInt(productInfoMain.width());
				leftCorrection = productInfoMainLeft + 'px';
				productInfoMain.removeClass('pp-fixed').addClass('pp-floating-v4').css({
					'left': productInfoMainLeft+'px',
					'width': productInfoMainWidth+'px'});
			}

			jQuery(window).on('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(e) {
				if(that.isMobileCheck()){
					return true;
				}
				var autoScroll = false;
				if(e.which == 1 && e.type == 'mousedown') {
					autoScroll = true;
				}

				var scrollTopPos = parseInt(jQuery(window).scrollTop()),
					scrollPos = parseInt(jQuery(window).scrollTop()) + parseInt(jQuery(window).outerHeight()),
					productInfoMainBottom = parseInt(productInfoMain.offset().top) + parseInt(productInfoMain.outerHeight()),
					topPos = scrollTopPos + parseInt(productInfoMain.outerHeight()) + 95,
					productInfoMainTop = parseInt(productInfoMain.offset().top) - parseInt(productInfoMain.css('top')),
					v2MediaBlock = jQuery('.product.media.product_v2.v2'),
					v4MediaBlock = jQuery('.product.media.product_v4.v4'),
					footerEl = v2MediaBlock.length > 0 ? v2MediaBlock : v4MediaBlock,
					footerOffset = footerEl.length ? parseInt(footerEl.offset().top) + parseInt(footerEl.outerHeight() - 20) : 0,
					galleryHeight = parseInt(jQuery('.gallery-placeholder').outerHeight()),
					scrollDir = 'dwn';

				jQuery('.gallery-placeholder').css('height', 'auto');
				if(scrollTopPos >  lastScrollTop){
					scrollDir = 'dwn';
				} else {
					scrollDir = 'up';
				}

				if(footerEl.hasClass('product_v4')) {
					footerEl.addClass('pp-floating-v4')
				}

				if(jQuery('body').hasClass('product-page-v2')) {
                    jQuery('.product_v2.media').css('height', galleryHeight+"px");
					if(scrollTopPos >= 0 && scrollTopPos <= topOffset){
						productInfoMain.removeClass('pp-fixed').removeAttr('style');
					} else if(scrollTopPos >= topOffset && productInfoMainBottom <= footerOffset) {
						productInfoMain.addClass('pp-fixed').css({
							'left': productInfoMainLeft+'px',
							'width': productInfoMainWidth+'px'});
					} else if(productInfoMainTop > topOffset && scrollDir==='up' && productInfoMainBottom <= footerOffset && topPos <= footerOffset) {
						productInfoMain.addClass('pp-fixed').removeAttr('style').css({
							'left': productInfoMainLeft+'px',
							'width': productInfoMainWidth+'px'});
					} else if(productInfoMainBottom >= footerOffset && topPos >= footerOffset && scrollTopPos >= fixedPos) {
						if(fixedPos == 0) fixedPos = scrollTopPos;
						if(autoScroll || scrollDir === 'dwn'){
							productInfoMain.removeClass('pp-fixed').removeAttr('style').css({
								'margin':'0 !important',
								'padding':'0 !important',
								'bottom': bottomCorrection,
								'right' : '0',
								'position' : 'absolute',
								'width': productInfoMainWidth+'px'});

						} else if(!autoScroll && scrollDir === 'up') {
							productInfoMain.addClass('pp-fixed').removeAttr('style').css({
								'left': productInfoMainLeft+'px',
								'width': productInfoMainWidth+'px'});
						}

					} else if(scrollTopPos <= fixedPos && scrollDir == 'up') {
						fixedPos = 0;
						productInfoMain.addClass('pp-fixed').removeAttr('style').css({
							'left': productInfoMainLeft+'px',
							'width': productInfoMainWidth+'px'});
					} else {
						productInfoMain.removeAttr('style').css({'left': productInfoMainLeft+'px', 'width': productInfoMainWidth+'px'});
					}
				}

				if(jQuery('body').hasClass('product-page-v4')) {
                    jQuery('.product_v4.media').css('height', galleryHeight+"px");
					if(scrollTopPos >= 0 && scrollTopPos <= topOffset){
						productInfoMain.removeClass('pp-fixed').addClass('pp-floating-v4').removeAttr('style').css({
							'left': productInfoMainLeft+'px',
							'width': productInfoMainWidth+'px'});
					} else if(scrollTopPos >= topOffset && productInfoMainBottom <= footerOffset ) {
						productInfoMain.addClass('pp-fixed').removeClass('pp-floating-v4').removeAttr('style').css({
							'width': productInfoMainWidth+'px'});
					} else if(productInfoMainTop > topOffset && scrollDir==='up' && productInfoMainBottom <= footerOffset && topPos <= footerOffset) {
						productInfoMain.addClass('pp-fixed').removeClass('pp-floating-v4').removeAttr('style').css({
							'width': productInfoMainWidth+'px'});
					} else if(productInfoMainBottom >= footerOffset && topPos >= footerOffset && scrollTopPos >= fixedPos) {
						if(fixedPos == 0) fixedPos = scrollTopPos;
						productInfoMain.addClass('pp-floating-v4').removeClass('pp-fixed').css({
							'margin':'0 !important',
							'padding':'0 !important',
							'bottom': bottomCorrection,
							'left': leftCorrection,
							'width': productInfoMainWidth+'px'});
					} else if(scrollTopPos <= fixedPos && scrollDir === 'up') {
						fixedPos = 0;
						productInfoMain.addClass('pp-fixed').removeClass('pp-floating-v4').removeAttr('style').css({'left': productInfoMainLeft+'px', 'width': productInfoMainWidth+'px'});
					} else {
						productInfoMain.addClass('pp-fixed').removeClass('pp-floating-v4').removeAttr('style').css({
							'width': productInfoMainWidth+'px'});
					}
				}

				lastScrollTop = scrollTopPos - 50;
			})
		},

		isMobileCheck: function() {
            var screenWidth = jQuery(window).width();
            if(screenWidth < window.wpMobileBreakpoint){
                return true;
            }
            return false;
		},

		scrollToUrlHash: function(url) {
			this.scrollTo(url.indexOf('#') !== -1 ? url.substring(url.indexOf('#') + 1) : null);
		},

		scrollTo: function(targetHash) {
			if ((targetHash !== null) && (targetHash.length)) {
				var that = this;
				that.preLoadProductReviews(function() {
					var selector = jQuery('a[href^="#' + targetHash + '"]');
					that.waitForEl(function() {
						return jQuery(selector).length;
					}, function() {
						var target = jQuery('#' + targetHash);
						target.show();
						setTimeout(function() {
							jQuery('html, body').animate({
								scrollTop: target.offset().top - jQuery('header.page-header').outerHeight()
							}, {
								duration: 600,
								easing: 'easeOutExpo'
							}).promise().then(function() {
								if (!target.parent().hasClass('active')) {
									target.trigger('click');
								}
								selector.parent().addClass('active').attr({'aria-selected': true, 'aria-expanded': true});
								target.attr('aria-hidden', false);
							});
						}, 300);
					}, function() {
						// do nothing
					});
				});
			}
		},

		reviewIsLoaded: function() {
			var reviewsContainer = jQuery('#product-review-container').html();
			return !!reviewsContainer.length;
		},

		preLoadProductReviews: function(callback) {
			var that = this;
			setTimeout(function () {
				if (!that.reviewIsLoaded()) {
					jQuery("#tab-label-reviews-title").click().promise().then(function() {
						callback();
					});
				} else {
					callback();
				}
			}, 1000);
		}
	};

	return productPage;
});

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define('Magento_Catalog/js/catalog-add-to-cart',[
    'jquery',
    'mage/translate',
    'underscore',
    'Magento_Catalog/js/product/view/product-ids-resolver',
    'jquery-ui-modules/widget'
], function ($, $t, _, idsResolver) {
    'use strict';

    $.widget('mage.catalogAddToCart', {
        options: {
            processStart: null,
            processStop: null,
            bindSubmit: true,
            minicartSelector: '[data-block="minicart"]',
            messagesSelector: '[data-placeholder="messages"]',
            productStatusSelector: '.stock.available',
            addToCartButtonSelector: '.action.tocart',
            addToCartButtonDisabledClass: 'disabled',
            addToCartButtonAddedClass: 'added',
            addToCartButtonTextWhileAdding: '',
            addToCartButtonTextAdded: '',
            addToCartButtonTextDefault: ''
        },

        /** @inheritdoc */
        _create: function () {
            if (this.options.bindSubmit) {
                this._bindSubmit();
            }
        },

        /**
         * @private
         */
        _bindSubmit: function () {
            var self = this;

            if (this.element.data('catalog-addtocart-initialized')) {
                return;
            }

            this.element.data('catalog-addtocart-initialized', 1);
            this.element.on('submit', function (e) {
                e.preventDefault();
                self.submitForm($(this));
            });
        },

        /**
         * @private
         */
        _redirect: function (url) {
            var urlParts, locationParts, forceReload;

            urlParts = url.split('#');
            locationParts = window.location.href.split('#');
            forceReload = urlParts[0] === locationParts[0];

            window.location.assign(url);

            if (forceReload) {
                window.location.reload();
            }
        },

        /**
         * @return {Boolean}
         */
        isLoaderEnabled: function () {
            return this.options.processStart && this.options.processStop;
        },

        /**
         * Handler for the form 'submit' event
         *
         * @param {jQuery} form
         */
        submitForm: function (form) {
            var addToCartButton, self = this;
            if (form.has('input[type="file"]').length && form.find('input[type="file"]').val() !== '') {
                self.element.off('submit');
                // disable 'Add to Cart' button
                addToCartButton = $(form).find(this.options.addToCartButtonSelector);
                addToCartButton.prop('disabled', true);
                addToCartButton.addClass(this.options.addToCartButtonDisabledClass);
                form.submit();
            } else {
                self.ajaxSubmit(form);
            }
        },

        /**
         * @param {jQuery} form
         */
        ajaxSubmit: function (form) {
            var self = this,
                productIds = idsResolver(form),
                formData;

            $(self.options.minicartSelector).trigger('contentLoading');
            self.disableAddToCartButton(form);
            formData = new FormData(form[0]);

            $.ajax({
                url: form.attr('action'),
                data: formData,
                type: 'post',
                dataType: 'json',
                cache: false,
                contentType: false,
                processData: false,

                /** @inheritdoc */
                beforeSend: function () {
                    if (self.isLoaderEnabled()) {
                        $('body').trigger(self.options.processStart);
                    }
                },

                /** @inheritdoc */
                success: function (res) {
                    //console.log("success", res);
                    var eventData, parameters;

                    $(document).trigger('ajax:addToCart', {
                        'sku': form.data().productSku,
                        'productIds': productIds,
                        'form': form,
                        'response': res
                    });

                    if (self.isLoaderEnabled()) {
                        $('body').trigger(self.options.processStop);
                    }
                    // expand mini cart on product added successfully
                    var ajdustedFlag = true, successJs = true;
                    if (res.errorFlag || res.adjusted) {
                        self.options.addToCartButtonTextAdded = $t('Add to Cart');
                        ajdustedFlag = false;
                        successJs = false;
                    }

                    $('[data-block="minicart"]').on('contentUpdated', function () {

                        if ((ajdustedFlag || successJs) && $(window).width() < 767) {
                            $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog("open");
                        }

                        if (res.adjusted && ajdustedFlag) {
                            ajdustedFlag = false;
                            $('#minicart-success-message').show();
                            $('#minicart-success-message').addClass("qty_adjusted_error");
                            $('#minicart-success-message').html('<i class="fa fa-check-circle" aria-hidden="true"></i>' + res.adjusted[1]);
                            setTimeout(function () {
                                $('#minicart-success-message').empty();
                                $('#minicart-success-message').removeClass("qty_adjusted_error");
                            }, 5500);
                        }
                        if ((ajdustedFlag || successJs) && $(window).width() > 767) {
                              setTimeout(function () {
                                $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog("open");
                                //  $('.minicart-transition').slideDown(1500);
                              }, 500);
                        }

                        if(successJs) {
                            $('#minicart-success-message').html('<i class="fa fa-check-circle" aria-hidden="true"></i>' + $t('SUCCESSFULLY ADDED'));
                            setTimeout(function () {
                                $('#minicart-success-message').empty();
                            }, 4000);

                            $('#minicart-success-message-mobile').html('<i class="fa fa-check-circle" aria-hidden="true"></i>' + $t('SUCCESSFULLY ADDED'));
                            setTimeout(function () {
                                $('#minicart-success-message-mobile').empty();
                            }, 4000);

                              if ($(window).width() > 767) {
                                    setTimeout(function() {
                                        $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog("close");
                                        // $('#minicart-content-wrapper').removeClass('minicart-transition');
                                        // $('.minicart-wrapper').removeClass('active');
                                        // $('#stOverlay').hide();
                                    }, 5000);
                                    setTimeout(function() {
                                        // $('.minicart-transition').slideUp(3000);
                                    },4700);
                             }

                            successJs = false;
                        }

                        // ----toogle dark overlay when clicked----
                        $('#stOverlay').click(function () {
                            $('#stOverlay').hide();
                        });
                        // ----toogle dark overlay when clicked----
                    });

                    if (res.backUrl) {
                        eventData = {
                            'form': form,
                            'redirectParameters': []
                        };
                        // trigger global event, so other modules will be able add parameters to redirect url
                        $('body').trigger('catalogCategoryAddToCartRedirect', eventData);

                        if (eventData.redirectParameters.length > 0) {
                            parameters = res.backUrl.split('#');
                            parameters.push(eventData.redirectParameters.join('&'));
                            res.backUrl = parameters.join('#');
                        }

                        self._redirect(res.backUrl);

                        return;
                    }

                    if (res.messages) {
                        $(self.options.messagesSelector).html(res.messages);
                    }

                    if (res.minicart) {
                        $(self.options.minicartSelector).replaceWith(res.minicart);
                        $(self.options.minicartSelector).trigger('contentUpdated');
                    }

                    if (res.product && res.product.statusText) {
                        $(self.options.productStatusSelector)
                            .removeClass('available')
                            .addClass('unavailable')
                            .find('span')
                            .html(res.product.statusText);
                    }
                    self.enableAddToCartButton(form);

                },

                /** @inheritdoc */
                error: function (res) {
                    //console.log("error", res);
                    $(document).trigger('ajax:addToCart:error', {
                        'sku': form.data().productSku,
                        'productIds': productIds,
                        'form': form,
                        'response': res
                    });
                },

                /** @inheritdoc */
                complete: function (res) {
                    //console.log("complete", res);
                    if (res.state() === 'rejected') {
                        location.reload();
                    }
                }
            });
        },

        /**
         * @param {String} form
         */
        disableAddToCartButton: function (form) {
            var addToCartButtonTextWhileAdding = this.options.addToCartButtonTextWhileAdding || $t('Adding...'),
                addToCartButton = $(form).find(this.options.addToCartButtonSelector);

            addToCartButton.addClass(this.options.addToCartButtonDisabledClass);
            addToCartButton.find('span').text(addToCartButtonTextWhileAdding);
            addToCartButton.attr('title', addToCartButtonTextWhileAdding);
        },

        /**
         * @param {String} form
         */
        enableAddToCartButton: function (form) {
            var addToCartButtonTextAdded = this.options.addToCartButtonTextAdded || $t('SUCCESSFULLY ADDED');
            var self = this,
                addToCartButton = $(form).find(this.options.addToCartButtonSelector);

            addToCartButton.removeClass(self.options.addToCartButtonDisabledClass).addClass(this.options.addToCartButtonAddedClass);
            addToCartButton.find('span').text(addToCartButtonTextAdded);
            addToCartButton.attr('title', addToCartButtonTextAdded);

            setTimeout(function () {
                var addToCartButtonTextDefault = self.options.addToCartButtonTextDefault || $t('Add to Cart');

                addToCartButton.removeClass(self.options.addToCartButtonDisabledClass).removeClass(self.options.addToCartButtonAddedClass);
                addToCartButton.find('span').text(addToCartButtonTextDefault);
                addToCartButton.attr('title', addToCartButtonTextDefault);
                self.options.addToCartButtonTextAdded = '';
            }, 3000);

          //  $("html, body").animate({ scrollTop: 0 }, "slow");
        }
    });

    return $.mage.catalogAddToCart;
});


define("bundles/product", function(){});

//# sourceMappingURL=product.js.map