|
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
-
- define([
- 'jquery',
- 'fotorama/fotorama',
- 'underscore',
- 'matchMedia',
- 'mage/template',
- 'text!mage/gallery/gallery.html',
- 'uiClass',
- 'mage/translate'
- ], function ($, fotorama, _, mediaCheck, template, galleryTpl, Class, $t) {
- 'use strict';
-
- /**
- * 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.on('focusin', self._focusSwitcher);
- settings.focusableEnd.on('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 () {
- settings.closeIcon.hide();
- settings.focusableStart.attr('tabindex', '-1');
- settings.focusableEnd.attr('tabindex', '-1');
- settings.api.updateOptions(settings.defaultConfig.options, true);
- settings.focusableStart.off('focusin', this._focusSwitcher);
- settings.focusableEnd.off('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).trigger('focus');
- } else if (position === 'start') {
- infelicity = 3; //Constant for find last focusable element
- focusableElements = settings.$gallery.find(':focusable');
- focusableElements.eq(focusableElements.length - infelicity).trigger('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,
- $element = settings.$element,
- $fotoramaElement,
- $fotoramaStage;
-
- 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,
- {
- options: undefined,
- click: false,
- breakpoints: null
- }
- );
- settings.currentConfig = config;
-
- $element
- .css('min-height', settings.$element.height())
- .append(tpl);
-
- $fotoramaElement = $element.find('[data-gallery-role="gallery"]');
-
- $fotoramaStage = $fotoramaElement.find('.fotorama__stage');
- $fotoramaStage.css('position', 'absolute');
-
- $fotoramaElement.fotorama(config);
- $fotoramaElement.find('.fotorama__stage__frame.fotorama__active')
- .one('f:load', function () {
- // Remove placeholder when main gallery image loads.
- $element.find('.gallery-placeholder__image').remove();
- $element
- .removeClass('_block-content-loading')
- .css('min-height', '');
-
- $fotoramaStage.css('position', '');
- });
- settings.$elementF = $fotoramaElement;
- settings.fotoramaApi = $fotoramaElement.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,
- isInitialized = {},
- isTouchEnabled = this.isTouchEnabled;
-
- if (_.isObject(settings.breakpoints)) {
- pairs = _.pairs(settings.breakpoints);
- _.each(pairs, function (pair) {
- var mediaQuery = pair[0];
-
- isInitialized[mediaQuery] = false;
- mediaCheck({
- media: mediaQuery,
-
- /**
- * 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[mediaQuery].options.arrows = false;
-
- if (settings.breakpoints[mediaQuery].options.fullscreen) {
- settings.breakpoints[mediaQuery].options.fullscreen.arrows = false;
- }
- }
-
- settings.api.updateOptions(settings.breakpoints[mediaQuery].options, true);
- $.extend(true, config, settings.breakpoints[mediaQuery]);
- settings.activeBreakpoint = settings.breakpoints[mediaQuery];
-
- isInitialized[mediaQuery] = true;
- },
-
- /**
- * Is triggered when breakpoint exits.
- */
- exit: function () {
- if (isInitialized[mediaQuery]) {
- $.extend(true, config, _.clone(startConfig));
- settings.api.updateOptions(settings.defaultConfig.options, true);
-
- if (settings.isFullscreen) {
- settings.api.updateOptions(settings.fullscreenConfig, true);
- }
- settings.activeBreakpoint = {};
- } else {
- isInitialized[mediaQuery] = true;
- }
- }
- });
- });
- }
- },
-
- /**
- * 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.breakpoints) ?
- $.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).trigger('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 (settings.fotoramaApi.activeIndex !== 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');
- }
- });
- });
|