From ced0f0093097127c73aef3357685de2948435b6d Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Wed, 9 Sep 2015 13:19:40 +0300 Subject: [PATCH 001/116] MAGETWO-32170: [Vanilla] Gallery Widget on Configurable Product --- .../Catalog/Block/Product/View/Gallery.php | 39 +- app/code/Magento/Catalog/Model/Product.php | 1 + .../Magento/Catalog/Model/Product/Image.php | 3 + .../templates/product/view/gallery.phtml | 35 +- .../Block/Product/View/Type/Configurable.php | 1 + .../ConfigurableProduct/Helper/Data.php | 55 ++- .../Model/Product/Type/Configurable.php | 6 +- .../view/frontend/web/js/configurable.js | 237 +++++++----- .../frontend/Magento/blank/etc/view.xml | 55 ++- app/design/frontend/Magento/luma/etc/view.xml | 55 ++- .../Magento/Framework/Config/View.php | 37 +- .../Magento/Framework/Config/etc/view.xsd | 17 +- lib/web/mage/gallery/gallery.js | 352 ++++++++---------- 13 files changed, 525 insertions(+), 368 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/View/Gallery.php b/app/code/Magento/Catalog/Block/Product/View/Gallery.php index f8b77d46d3ca7..4be631e618245 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Gallery.php +++ b/app/code/Magento/Catalog/Block/Product/View/Gallery.php @@ -12,6 +12,7 @@ namespace Magento\Catalog\Block\Product\View; use Magento\Framework\Data\Collection; +use Magento\Framework\Json\EncoderInterface; class Gallery extends \Magento\Catalog\Block\Product\View\AbstractView { @@ -20,6 +21,22 @@ class Gallery extends \Magento\Catalog\Block\Product\View\AbstractView */ protected $configView; + /** + * @var \Magento\Framework\Json\EncoderInterface + */ + protected $jsonEncoder; + + public function __construct( + \Magento\Catalog\Block\Product\Context $context, + \Magento\Framework\Stdlib\ArrayUtils $arrayUtils, + EncoderInterface $jsonEncoder, + array $data = [] + ) + { + $this->jsonEncoder = $jsonEncoder; + parent::__construct($context, $arrayUtils, $data); + } + /** * Retrieve collection of gallery images * @@ -56,6 +73,26 @@ public function getGalleryImages() return $images; } + /** + * Return magnifier options + * + * @return string + */ + public function getMagnifier() + { + return $this->jsonEncoder->encode($this->getVar('magnifier')); + } + + /** + * Return breakpoints options + * + * @return string + */ + public function getBreakpoints() + { + return $this->jsonEncoder->encode($this->getVar('breakpoints')); + } + /** * Retrieve product images in JSON format * @@ -128,4 +165,4 @@ private function getConfigView() } return $this->configView; } -} +} \ No newline at end of file diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index dd0f5ec4ead4f..d83299c1cdd56 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -18,6 +18,7 @@ * Catalog product model * * @method Product setHasError(bool $value) + * @method \Magento\Catalog\Model\Resource\Product getResource() * @method null|bool getHasError() * @method Product setAssociatedProductIds(array $productIds) * @method array getAssociatedProductIds() diff --git a/app/code/Magento/Catalog/Model/Product/Image.php b/app/code/Magento/Catalog/Model/Product/Image.php index f669b73ca51ff..87af2b3c815da 100644 --- a/app/code/Magento/Catalog/Model/Product/Image.php +++ b/app/code/Magento/Catalog/Model/Product/Image.php @@ -19,6 +19,9 @@ * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @method string getFile() + * @method string getLabel() + * @method string getPosition() */ class Image extends \Magento\Framework\Model\AbstractModel { diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 3089c2cf50f6f..9ab7c65ab91f0 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -16,21 +16,14 @@ ".gallery-placeholder": { "mage/gallery/gallery": { "mixins":["magnifier/magnify"], - "magnifierOpts": { - "enabled": getVar("magnifier:enabled"); ?>, - "eventType": "getVar("magnifier:action"); ?>", - "width": "getVar("magnifier:width"); ?>", - "height": "getVar("magnifier:height"); ?>", - "top": "getVar("magnifier:top"); ?>", - "left": "getVar("magnifier:left"); ?>" - }, + "magnifierOpts": getMagnifier(); ?>, "data": getGalleryImagesJson(); ?>, "options": { - "nav": "getVar("gallery:navigation"); ?>", - "loop": getVar("gallery:loop"); ?>, - "keyboard": getVar("gallery:keyboard"); ?>, - "arrows": getVar("gallery:arrows"); ?>, - "showCaption": getVar("gallery:show_caption"); ?>, + "nav": "getVar("gallery/navigation"); ?>", + "loop": getVar("gallery/loop"); ?>, + "keyboard": getVar("gallery/keyboard"); ?>, + "arrows": getVar("gallery/arrows"); ?>, + "showCaption": getVar("gallery/show_caption"); ?>, "width": getImageAttribute('product_page_image_medium', 'width'); ?>, "thumbwidth": getImageAttribute('product_page_image_small', 'width'); ?>, "thumbheight": getImageAttribute('product_page_image_small', 'height') @@ -38,21 +31,7 @@ "height": getImageAttribute('product_page_image_medium', 'height') ?: $block->getImageAttribute('product_page_image_medium', 'width'); ?> }, - "breakpoints": { - "mobile": { - "conditions": { - "max-width": "767px" - }, - "options": { - "options": { - "nav": "dots" - }, - "magnifierOpts": { - "enabled": false - } - } - } - } + "breakpoints": getBreakpoints(); ?> } } } diff --git a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php index b67361c4fcc8a..14973a48c1135 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php @@ -198,6 +198,7 @@ public function getJsonConfig() 'productId' => $currentProduct->getId(), 'chooseText' => __('Choose an Option...'), 'images' => isset($options['images']) ? $options['images'] : [], + 'index' => isset($options['index']) ? $options['index'] : [], ]; if ($currentProduct->hasPreconfiguredValues() && !empty($attributesData['defaultValues'])) { diff --git a/app/code/Magento/ConfigurableProduct/Helper/Data.php b/app/code/Magento/ConfigurableProduct/Helper/Data.php index bfd993d75414c..45302ad89f8c6 100644 --- a/app/code/Magento/ConfigurableProduct/Helper/Data.php +++ b/app/code/Magento/ConfigurableProduct/Helper/Data.php @@ -30,6 +30,42 @@ public function __construct(\Magento\Catalog\Helper\Image $imageHelper) $this->imageHelper = $imageHelper; } + /** + * Retrieve collection of gallery images + * + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return \Magento\Catalog\Model\Product\Image[]|null + */ + public function getGalleryImages(\Magento\Catalog\Api\Data\ProductInterface $product) + { + $images = $product->getMediaGalleryImages(); + if ($images instanceof \Magento\Framework\Data\Collection) { + foreach ($images as &$image) { + /** @var $image \Magento\Catalog\Model\Product\Image */ + $image->setData( + 'small_image_url', + $this->imageHelper->init($product, 'product_page_image_small') + ->setImageFile($image->getFile()) + ->getUrl() + ); + $image->setData( + 'medium_image_url', + $this->imageHelper->init($product, 'product_page_image_medium') + ->setImageFile($image->getFile()) + ->getUrl() + ); + $image->setData( + 'large_image_url', + $this->imageHelper->init($product, 'product_page_image_large') + ->setImageFile($image->getFile()) + ->getUrl() + ); + } + } + + return $images; + } + /** * Get Options for Configurable Product Options * @@ -42,16 +78,27 @@ public function getOptions($currentProduct, $allowedProducts) $options = []; foreach ($allowedProducts as $product) { $productId = $product->getId(); + $images = $this->getGalleryImages($product); + if ($images) { + foreach ($images as $image) { + $options['images'][$productId][] = + [ + 'thumb' => $image->getData('small_image_url'), + 'img' => $image->getData('medium_image_url'), + 'original' => $image->getData('large_image_url'), + 'caption' => $image->getLabel(), + 'position' => $image->getPosition(), + 'isMain' => $image->getFile() == $product->getImage(), + ]; + } + } foreach ($this->getAllowAttributes($currentProduct) as $attribute) { $productAttribute = $attribute->getProductAttribute(); $productAttributeId = $productAttribute->getId(); $attributeValue = $product->getData($productAttribute->getAttributeCode()); $options[$productAttributeId][$attributeValue][] = $productId; - $imageUrl = (!$product->getImage() || $product->getImage() === 'no_selection') - ? $this->imageHelper->init($currentProduct, 'product_page_image_large')->getUrl() - : $this->imageHelper->init($product, 'product_page_image_large')->getUrl(); - $options['images'][$productAttributeId][$attributeValue][$productId] = $imageUrl; + $options['index'][$productId][$productAttributeId] = $attributeValue; } } return $options; diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index 4c8c10f01476e..d6c5da4b6e734 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -440,7 +440,9 @@ public function getUsedProducts($product, $requiredAttributeIds = null) } $usedProducts = []; - $collection = $this->getUsedProductCollection($product)->addAttributeToSelect('*') + $collection = $this->getUsedProductCollection($product) + ->addAttributeToSelect('*') + ->addAttributeToSelect('media_gallery') ->addFilterByRequiredOptions() ->setStoreId($product->getStoreId()); @@ -454,6 +456,8 @@ public function getUsedProducts($product, $requiredAttributeIds = null) } foreach ($collection as $item) { + /** @var \Magento\Catalog\Model\Product $item */ + $item->getResource()->getAttribute('media_gallery')->getBackend()->afterLoad($item); $usedProducts[] = $item; } diff --git a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js index b793612a5ebc0..f4dc170bbb33f 100644 --- a/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js @@ -4,14 +4,14 @@ */ /*jshint browser:true jquery:true*/ define([ - "jquery", - "underscore", - "mage/template", - "priceUtils", - "priceBox", - "jquery/ui", - "jquery/jquery.parsequery" -], function($, _, mageTemplate, utils){ + 'jquery', + 'underscore', + 'mage/template', + 'priceUtils', + 'priceBox', + 'jquery/ui', + 'jquery/jquery.parsequery' +], function ($, _, mageTemplate) { $.widget('mage.configurable', { options: { @@ -21,13 +21,16 @@ define([ state: {}, priceFormat: {}, optionTemplate: '<%- data.label %>' + - '<% if (data.finalPrice.value) { %>' + - ' <%- data.finalPrice.formatted %>' + - '<% } %>', - mediaGallerySelector: '[data-role=media-gallery]' + '<% if (data.finalPrice.value) { %>' + + ' <%- data.finalPrice.formatted %>' + + '<% } %>', + mediaGallerySelector: '[data-gallery-role=gallery]' }, - - _create: function() { + /** + * Creates widget + * @private + */ + _create: function () { // Initial setting of various option values this._initializeOptions(); @@ -51,14 +54,14 @@ define([ * Initialize tax configuration, initial settings, and options values. * @private */ - _initializeOptions: function() { + _initializeOptions: function () { var priceBoxOptions = $(this.options.priceHolderSelector).priceBox('option'); - if(priceBoxOptions.priceConfig && priceBoxOptions.priceConfig.optionTemplate) { + if (priceBoxOptions.priceConfig && priceBoxOptions.priceConfig.optionTemplate) { this.options.optionTemplate = priceBoxOptions.priceConfig.optionTemplate; } - if(priceBoxOptions.priceConfig && priceBoxOptions.priceConfig.priceFormat) { + if (priceBoxOptions.priceConfig && priceBoxOptions.priceConfig.priceFormat) { this.options.priceFormat = priceBoxOptions.priceConfig.priceFormat; } this.options.optionTemplate = mageTemplate(this.options.optionTemplate); @@ -70,8 +73,8 @@ define([ this.options.values = this.options.spConfig.defaultValues || {}; this.options.parentImage = $('[data-role=base-image-container] img').attr('src'); - this.initialGalleryImages = $(this.options.mediaGallerySelector).data('mageGallery') - ? $(this.options.mediaGallerySelector).gallery('option', 'images') + this.initialGalleryImages = $(this.options.mediaGallerySelector).data('mageGallery') ? + $(this.options.mediaGallerySelector).gallery('option', 'images') : []; this.inputSimpleProduct = this.element.find(this.options.selectSimpleProduct); }, @@ -81,11 +84,13 @@ define([ * initialized inputs values. * @private */ - _overrideDefaults: function() { + _overrideDefaults: function () { var hashIndex = window.location.href.indexOf('#'); + if (hashIndex !== -1) { this._parseQueryParams(window.location.href.substr(hashIndex + 1)); } + if (this.options.spConfig.inputsInitialized) { this._setValuesByAttribute(); } @@ -94,12 +99,15 @@ define([ /** * Parse query parameters from a query string and set options values based on the * key value pairs of the parameters. - * @param queryString URL query string containing query parameters. + * @param {*} queryString - URL query string containing query parameters. * @private */ - _parseQueryParams: function(queryString) { - var queryParams = $.parseQuery({query: queryString}); - $.each(queryParams, $.proxy(function(key, value) { + _parseQueryParams: function (queryString) { + var queryParams = $.parseQuery({ + query: queryString + }); + + $.each(queryParams, $.proxy(function (key, value) { this.options.values[key] = value; }, this)); }, @@ -109,9 +117,9 @@ define([ * identifier. * @private */ - _setValuesByAttribute: function() { + _setValuesByAttribute: function () { this.options.values = {}; - $.each(this.options.settings, $.proxy(function(index, element) { + $.each(this.options.settings, $.proxy(function (index, element) { if (element.value) { var attributeId = element.id.replace(/[a-z]*/, ''); this.options.values[attributeId] = element.value; @@ -123,8 +131,8 @@ define([ * Set up .on('change') events for each option element to configure the option. * @private */ - _setupChangeEvents: function() { - $.each(this.options.settings, $.proxy(function(index, element) { + _setupChangeEvents: function () { + $.each(this.options.settings, $.proxy(function (index, element) { $(element).on('change', this, this._configure); }, this)); }, @@ -134,9 +142,10 @@ define([ * attribute identifier. Set the state based on the attribute identifier. * @private */ - _fillState: function() { - $.each(this.options.settings, $.proxy(function(index, element) { + _fillState: function () { + $.each(this.options.settings, $.proxy(function (index, element) { var attributeId = element.id.replace(/[a-z]*/, ''); + if (attributeId && this.options.spConfig.attributes[attributeId]) { element.config = this.options.spConfig.attributes[attributeId]; element.attributeId = attributeId; @@ -150,10 +159,10 @@ define([ * an option's list of selections as needed or disable an option's setting. * @private */ - _setChildSettings: function() { - var childSettings = [], - settings = this.options.settings, - index = settings.length, + _setChildSettings: function () { + var childSettings = [], + settings = this.options.settings, + index = settings.length, option; while (index--) { @@ -164,9 +173,9 @@ define([ (option.disabled = true); _.extend(option, { - childSettings: childSettings.slice(), - prevSetting: settings[index - 1], - nextSetting: settings[index + 1] + childSettings: childSettings.slice(), + prevSetting: settings[index - 1], + nextSetting: settings[index + 1] }); childSettings.push(option); @@ -178,11 +187,11 @@ define([ * the option, which sets its state, and initializes the option's choices, etc. * @private */ - _configureForValues: function() { + _configureForValues: function () { if (this.options.values) { - this.options.settings.each($.proxy(function(index, element) { + this.options.settings.each($.proxy(function (index, element) { var attributeId = element.attributeId; - element.value = (typeof(this.options.values[attributeId]) === 'undefined') ? + element.value = (typeof (this.options.values[attributeId]) === 'undefined') ? '' : this.options.values[attributeId]; this._configureElement(element); @@ -193,9 +202,9 @@ define([ /** * Event handler for configuring an option. * @private - * @param event Event triggered to configure an option. + * @param {Object} event - Event triggered to configure an option. */ - _configure: function(event) { + _configure: function (event) { event.data._configureElement(this); }, @@ -203,11 +212,12 @@ define([ * Configure an option, initializing it's state and enabling related options, which * populates the related option's selection and resets child option selections. * @private - * @param element The element associated with a configurable option. + * @param {*} element - The element associated with a configurable option. */ - _configureElement: function(element) { + _configureElement: function (element) { if (element.value) { this.options.state[element.config.id] = element.value; + if (element.nextSetting) { element.nextSetting.disabled = false; this._fillSelect(element.nextSetting); @@ -215,8 +225,7 @@ define([ } else { this.inputSimpleProduct.val(element.selectedOptions[0].config.allowedProducts[0]); } - } - else { + } else { this._resetChildren(element); } this._reloadPrice(); @@ -228,38 +237,41 @@ define([ * @private */ _changeProductImage: function () { - var images = this.options.spConfig.images, - imagesArray = null, - galleryElement = $(this.options.mediaGallerySelector); - $.each(this.options.settings, function (k, v) { - var selectValue = parseInt(v.value, 10), - attributeId = v.id.replace(/[a-z]*/, ''); - if (selectValue > 0 && attributeId) { - if (!imagesArray) { - imagesArray = images[attributeId][selectValue]; - } else { - var intersectedArray = {}; - $.each(imagesArray, function (productId) { - if (images[attributeId][selectValue][productId]) { - intersectedArray[productId] = images[attributeId][selectValue][productId]; - } - }); - imagesArray = intersectedArray; + var state = (function () { + var p, + state = JSON.stringify(this.options.state); + + for (p in this.options.spConfig.index) { + + if (JSON.stringify(this.options.spConfig.index[p]) === state) { + return p; + } } - } - }); - var result = []; - $.each(imagesArray || {}, function (k, v) { - result.push({ - small: v, - medium: v, - large: v - }); - }); + return false; + }.bind(this)()), + option = (function () { + return this.options.state[state] ? this.options.state[state] : false; + }.bind(this)()), + images, + galleryObject = $(this.options.mediaGallerySelector).data('gallery'); + + if (state && state !== this.options.previousState) { + this.options.previousState = state; + images = this.options.spConfig.images[state]; + } - if (galleryElement.length && galleryElement.data('mageGallery')) { - galleryElement.gallery('option', 'images', result.length > 0 ? result : this.initialGalleryImages); + if (galleryObject) { + + if (!this.options.initialState) { + this.options.initialState = galleryObject.returnCurrentImages(); + } + + if (images) { + galleryObject.updateData(images); + } else if (!option) { + galleryObject.updateData(this.options.initialState); + } } }, @@ -267,13 +279,14 @@ define([ * For a given option element, reset all of its selectable options. Clear any selected * index, disable the option choice, and reset the option's state if necessary. * @private - * @param element The element associated with a configurable option. + * @param {*} element - The element associated with a configurable option. */ - _resetChildren: function(element) { + _resetChildren: function (element) { if (element.childSettings) { for (var i = 0; i < element.childSettings.length; i++) { element.childSettings[i].selectedIndex = 0; element.childSettings[i].disabled = true; + if (element.config) { this.options.state[element.config.id] = false; } @@ -284,25 +297,32 @@ define([ /** * Populates an option's selectable choices. * @private - * @param element Element associated with a configurable option. + * @param {*} element - Element associated with a configurable option. */ - _fillSelect: function(element) { + _fillSelect: function (element) { var attributeId = element.id.replace(/[a-z]*/, ''), - options = this._getAttributeOptions(attributeId); + options = this._getAttributeOptions(attributeId), + prevConfig, + index = 1, + allowedProducts, + i, + j; + this._clearSelect(element); element.options[0] = new Option('', ''); element.options[0].innerHTML = this.options.spConfig.chooseText; + prevConfig = false; - var prevConfig = false; if (element.prevSetting) { prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex]; } + if (options) { - var index = 1; - for (var i = 0; i < options.length; i++) { - var allowedProducts = []; + for (i = 0; i < options.length; i++) { + allowedProducts = []; + if (prevConfig) { - for (var j = 0; j < options[i].products.length; j++) { + for (j = 0; j < options[i].products.length; j++) { // prevConfig.config can be undefined if (prevConfig.config && prevConfig.config.allowedProducts && @@ -313,12 +333,15 @@ define([ } else { allowedProducts = options[i].products.slice(0); } + if (allowedProducts.length > 0) { options[i].allowedProducts = allowedProducts; element.options[index] = new Option(this._getOptionLabel(options[i]), options[i].id); + if (typeof options[i].price !== 'undefined') { element.options[index].setAttribute('price', options[i].prices); } + element.options[index].config = options[i]; index++; } @@ -330,20 +353,19 @@ define([ * Generate the label associated with a configurable option. This includes the option's * label or value and the option's price. * @private - * @param option A single choice among a group of choices for a configurable option. - * @param selOption Current selected option. + * @param {*} option - A single choice among a group of choices for a configurable option. * @return {String} The option label with option value and price (e.g. Black +1.99) */ - _getOptionLabel: function(option, selOption) { + _getOptionLabel: function (option) { return option.label; }, /** * Removes an option's selections. * @private - * @param element The element associated with a configurable option. + * @param {*} element - The element associated with a configurable option. */ - _clearSelect: function(element) { + _clearSelect: function (element) { for (var i = element.options.length - 1; i >= 0; i--) { element.remove(i); } @@ -352,10 +374,10 @@ define([ /** * Retrieve the attribute options associated with a specific attribute Id. * @private - * @param attributeId The id of the attribute whose configurable options are sought. + * @param {Number} attributeId - The id of the attribute whose configurable options are sought. * @return {Object} Object containing the attribute options. */ - _getAttributeOptions: function(attributeId) { + _getAttributeOptions: function (attributeId) { if (this.options.spConfig.attributes[attributeId]) { return this.options.spConfig.attributes[attributeId].options; } @@ -364,38 +386,47 @@ define([ /** * Reload the price of the configurable product incorporating the prices of all of the * configurable product's option selections. - * @private - * @return {Number} The price of the configurable product including selected options. */ - _reloadPrice: function() { + _reloadPrice: function () { $(this.options.priceHolderSelector).trigger('updatePrice', this._getPrices()); }, - + /** + * Get product various prices + * @returns {{}} + * @private + */ _getPrices: function () { var prices = {}, elements = _.toArray(this.options.settings); - _.each(elements, function(element) { + _.each(elements, function (element) { var selected = element.options[element.selectedIndex], config = selected && selected.config; - prices[element.attributeId] = config && config.allowedProducts.length === 1 - ? this._calculatePrice(config) + prices[element.attributeId] = config && config.allowedProducts.length === 1 ? + this._calculatePrice(config) : {}; }, this); return prices; }, - + /** + * Returns pracies for configured products + * + * @param {*} config - Products configuration + * @returns {*} + * @private + */ _calculatePrice: function (config) { - var displayPrices = $(this.options.priceHolderSelector).priceBox('option').prices; - var newPrices = this.options.spConfig.optionPrices[_.first(config.allowedProducts)]; + var displayPrices = $(this.options.priceHolderSelector).priceBox('option').prices, + newPrices = this.options.spConfig.optionPrices[_.first(config.allowedProducts)]; _.each(displayPrices, function (price, code) { if (newPrices[code]) { - displayPrices[code].amount = newPrices[code].amount - displayPrices[code].amount + displayPrices[code].amount = newPrices[code].amount - displayPrices[code].amount } }); + return displayPrices; } diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml index 897a3c54b3b27..5069307421894 100644 --- a/app/design/frontend/Magento/blank/etc/view.xml +++ b/app/design/frontend/Magento/blank/etc/view.xml @@ -180,18 +180,51 @@ - thumbs - true - true - true - false + + thumbs + true + true + true + false + - - - - - hover - true + + + + + + hover + true + + + + + + 767px + + + + dots + + + false + + + + + + 768px + + + + thumbs + + + true + + + + 100 diff --git a/app/design/frontend/Magento/luma/etc/view.xml b/app/design/frontend/Magento/luma/etc/view.xml index 573f628d52629..ed9439f338114 100644 --- a/app/design/frontend/Magento/luma/etc/view.xml +++ b/app/design/frontend/Magento/luma/etc/view.xml @@ -184,18 +184,51 @@ - dots - false - true - true - true + + thumbs + true + true + true + false + - - - - - click - true + + + + + + hover + true + + + + + + 767px + + + + dots + + + false + + + + + + 768px + + + + thumbs + + + true + + + + 100 diff --git a/lib/internal/Magento/Framework/Config/View.php b/lib/internal/Magento/Framework/Config/View.php index 3221b201c9953..fb294bbbd0e4f 100644 --- a/lib/internal/Magento/Framework/Config/View.php +++ b/lib/internal/Magento/Framework/Config/View.php @@ -36,12 +36,7 @@ protected function _extractData(\DOMDocument $dom) switch ($childNode->tagName) { case 'vars': $moduleName = $childNode->getAttribute('module'); - /** @var $varNode \DOMElement */ - foreach ($childNode->getElementsByTagName('var') as $varNode) { - $varName = $varNode->getAttribute('name'); - $varValue = $varNode->nodeValue; - $result[$childNode->tagName][$moduleName][$varName] = $varValue; - } + $result[$childNode->tagName][$moduleName] = $this->parseVarElement($childNode); break; case 'images': $moduleName = $childNode->getAttribute('module'); @@ -70,6 +65,24 @@ protected function _extractData(\DOMDocument $dom) return $result; } + /** + * @param \DOMElement $node + * @return string|[] + */ + protected function parseVarElement(\DOMElement $node) + { + if ($node->getElementsByTagName('var')->length) { + $result = []; + foreach ($node->getElementsByTagName('var') as $varNode) { + $varName = $varNode->getAttribute('name'); + $result[$varName] = $this->parseVarElement($varNode); + } + } else { + $result = $node->nodeValue; + } + return $result; + } + /** * Get a list of variables in scope of specified module * @@ -88,11 +101,19 @@ public function getVars($module) * * @param string $module * @param string $var - * @return string|false + * @return string|false|array */ public function getVarValue($module, $var) { - return isset($this->_data['vars'][$module][$var]) ? $this->_data['vars'][$module][$var] : false; + $value = $this->_data['vars'][$module]; + foreach (explode('/', $var) as $node) { + if (is_array($value) && isset($value[$node])) { + $value = $value[$node]; + } else { + return false; + } + } + return $value; } /** diff --git a/lib/internal/Magento/Framework/Config/etc/view.xsd b/lib/internal/Magento/Framework/Config/etc/view.xsd index a9fb9593b2531..0f6c53c1cc3b4 100644 --- a/lib/internal/Magento/Framework/Config/etc/view.xsd +++ b/lib/internal/Magento/Framework/Config/etc/view.xsd @@ -12,15 +12,7 @@ - - - - - - - - - + @@ -38,6 +30,13 @@ + + + + + + + diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index 9f81daba85bcc..e81d584239e41 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -7,93 +7,47 @@ define([ 'fotorama/fotorama', 'underscore', 'matchMedia', - 'text!mage/gallery/gallery.html', - 'Magento_Ui/js/lib/class' -], function ($, fotorama, _, mediaCheck, template, Class) { + 'text!mage/gallery/gallery.html' +], function ($, fotorama, _, mediaCheck, template) { 'use strict'; - return Class.extend({ + return function (config, element) { - defaults: { - settings: {}, - config: {}, - startConfig: {} - }, + var triggeredBreakpoints = 0, + settings = {}, + isTouchEnabled, + initGallery, + setupBreakpoints, + initApi, + initConfig = {}; - /** - * 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) { - this._super(); - - this.config = config; - - this.settings = { - $element: $(element), - currentConfig: config, - defaultConfig: _.clone(config), - fullscreenConfig: _.clone(config.fullscreen), - breakpoints: config.breakpoints, - activeBreakpoint: {}, - fotoramaApi: null, - isFullscreen: false, - api: null - }; + config.options.ratio = config.options.width / config.options.height; + config.options.height = null; - config.options.ratio = config.options.width / config.options.height; - config.options.height = null; - config.options.allowfullscreen = false; + settings = { + $element: $(element), + currentConfig: config.options, + defaultConfig: config.options, + breakpoints: config.breakpoints, + fotoramaApi: null, + api: null + }; - $.extend(true, this.startConfig, config); - - this.initGallery(); - this.initApi(); - this.setupBreakpoints(); - this.initFullscreenSettings(); - }, + $.extend(true, initConfig, config); /** - * Gallery fullscreen settings. + * Checks if device has touch interface. + * @return {Boolean} The result of searching touch events on device. */ - initFullscreenSettings: function () { - var settings = this.settings; - settings.$element.on('fotorama:fullscreenenter', function () { - settings.api.updateOptions(settings.defaultConfig.options, true); - settings.api.updateOptions(settings.fullscreenConfig, true); - - if (!_.isEqual(settings.activeBreakpoint, {})) { - settings.api.updateOptions(settings.activeBreakpoint.options, true); - } - settings.isFullscreen = true; - }); - - settings.$element.on('fotorama:fullscreenexit', function () { - settings.api.updateOptions(settings.defaultConfig.options, true); - - if (!_.isEqual(settings.activeBreakpoint, {})) { - settings.api.updateOptions(settings.activeBreakpoint.options, true); - } - settings.isFullscreen = false; - }); - }, + isTouchEnabled = (function () { + return 'ontouchstart' in document.documentElement; + })(); /** * Initializes gallery with configuration options. */ - initGallery: function () { + initGallery = function () { var breakpoints = {}, - settings = this.settings, - config = this.config, mainImage; if (settings.breakpoints) { @@ -111,7 +65,7 @@ define([ _.extend(config, config.options); config.options = undefined; - if (this.isTouchEnabled) { + if (isTouchEnabled) { config.arrows = false; } @@ -126,26 +80,25 @@ define([ config.breakpoints = null; config.startindex = mainImage; settings.currentConfig = config; + $.extend(true, settings.defaultConfig, config); settings.$element.html(template); settings.$element = $(settings.$element.children()[0]); settings.$element.fotorama(config); settings.fotoramaApi = settings.$element.data('fotorama'); - $.extend(true, config, this.startConfig); - }, + $.extend(true, config, initConfig); + }; /** * Creates breakpoints for gallery. + * @param {Object} breakpoints - Object with keys as media queries and values as configurations. */ - setupBreakpoints: function () { - var pairs, - settings = this.settings, - config = this.config, - startConfig = this.startConfig, - triggeredBreakpoints = 0; - - if (_.isObject(settings.breakpoints)) { - pairs = _.pairs(settings.breakpoints); + setupBreakpoints = function (breakpoints) { + var pairs; + + if (_.isObject(breakpoints)) { + pairs = _.pairs(breakpoints); _.each(pairs, function (pair) { + var initialized = 0; mediaCheck({ media: pair[0], @@ -154,139 +107,154 @@ define([ */ entry: function () { triggeredBreakpoints++; - $.extend(true, config, _.clone(startConfig)); + initialized = initialized < pairs.length ? initialized++ : initialized; + settings.api.updateOptions(settings.defaultConfig, true); + $.extend(true, config, initConfig); settings.api.updateOptions(settings.defaultConfig.options, true); + settings.currentConfig = settings.breakpoints[pair[0]]; + settings.api.updateOptions(settings.currentConfig.options, true); - if (settings.isFullscreen) { - settings.api.updateOptions(settings.fullscreenConfig, true); - } - settings.api.updateOptions(settings.breakpoints[pair[0]].options, true); - $.extend(true, config, settings.breakpoints[pair[0]]); - settings.activeBreakpoint = settings.breakpoints[pair[0]]; + $.extend(true, config, settings.currentConfig); + settings.$element.trigger('gallery:updated', $('.fotorama-item').data('fotorama')); }, /** * Is triggered when breakpoint exits. */ exit: function () { - if (triggeredBreakpoints < 1) { - $.extend(true, config, _.clone(startConfig)); - settings.api.updateOptions(settings.defaultConfig.options, true); - - if (settings.isFullscreen) { - settings.api.updateOptions(settings.fullscreenConfig, true); - } - settings.activeBreakpoint = {}; + triggeredBreakpoints = triggeredBreakpoints > 0 ? triggeredBreakpoints-- : 0; + initialized = initialized < pairs.length ? initialized++ : initialized; + + if (!triggeredBreakpoints && initialized === pairs.length) { + settings.currentConfig = settings.defaultConfig; + settings.api.updateOptions(settings.currentConfig.options, true); + $.extend(true, config, initConfig); + settings.$element.trigger('gallery:updated', settings.fotoramaApi); } - triggeredBreakpoints--; } }); }); } - }, + }; /** * 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 () { - this.fotorama.show('>>'); - }, - - /** - * Displays the first image on preview. - */ - first: function () { - this.fotorama.show('<<'); - }, - - /** - * Displays previous element on preview. - */ - prev: function () { - this.fotorama.show('<'); - }, - - /** - * Displays next element on preview. - */ - next: function () { - this.fotorama.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; - } - this.fotorama.show(index); + initApi = function () { + var api = { + + /** + * Contains fotorama's API methods. + */ + fotorama: settings.fotoramaApi, + + /** + * Displays the last image on preview. + */ + last: function () { + this.fotorama.show('>>'); + }, + + /** + * Displays the first image on preview. + */ + first: function () { + this.fotorama.show('<<'); + }, + + /** + * Displays previous element on preview. + */ + prev: function () { + this.fotorama.show('<'); + }, + + /** + * Displays next element on preview. + */ + next: function () { + this.fotorama.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; } - }, - - /** - * 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) { - if (_.isObject(configuration)) { - if (this.isTouchEnabled) { - configuration.arrows = false; - } - configuration.click = false; - configuration.breakpoints = null; + this.fotorama.show(index); + } + }, - if (!isInternal) { - !_.isEqual(settings.activeBreakpoint, {}) ? - $.extend(true, settings.activeBreakpoint.options, configuration) : + /** + * 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) { - settings.isFullscreen ? - $.extend(true, settings.fullscreenConfig, configuration) : - $.extend(true, settings.defaultConfig.options, configuration); + if (_.isObject(configuration)) { - } - $.extend(true, settings.currentConfig.options, configuration); - this.fotorama.setOptions(settings.currentConfig.options); + if (isTouchEnabled) { + configuration.arrows = false; } - }, - - /** - * Updates gallery with specific set of items. - * @param {Array.} data - Set of gallery items to update. - */ - updateData: function (data) { - if (_.isArray(data)) { - this.fotorama.load(data); - $.extend(false, settings.defaultConfig, { - data: data - }); - $.extend(false, config, { - data: data - }); + configuration.click = false; + setupBreakpoints(configuration.breakpoints); + configuration.breakpoints = null; + + if (!isInternal) { + $.extend(true, settings.currentConfig.options, configuration); } + this.fotorama.setOptions(settings.currentConfig.options); } - }; + }, + + /** + * Updates gallery with specific set of items. + * @param {Array.} data - Set of gallery items to update. + */ + updateData: function (data) { + + if (_.isArray(data)) { + this.fotorama.load(data); + $.extend(false, settings.defaultConfig, { + data: data + }); + $.extend(false, config, { + data: data + }); + } + }, + + /**Returns current images list + * + * @returns {*} + */ + returnCurrentImages: function () { + var images = []; + + _.forEach(this.fotorama.data, function (item) { + images.push({ + 'img': item.img + }) + }); + + return images; + } + }; settings.$element.data('gallery', api); settings.api = settings.$element.data('gallery'); settings.$element.trigger('gallery:loaded'); - } - }); + }; + + initGallery(); + initApi(); + setupBreakpoints(settings.breakpoints); + }; }); From 78a54c8c79e27b4e866230ab202feb5f843f6a85 Mon Sep 17 00:00:00 2001 From: Ihor Melnychenko Date: Thu, 10 Sep 2015 10:23:24 +0300 Subject: [PATCH 002/116] MAGETWO-32170: [Vanilla] Gallery Widget on Configurable Product --- lib/web/mage/gallery/gallery.js | 366 ++++++++++++++++++-------------- 1 file changed, 206 insertions(+), 160 deletions(-) diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index e81d584239e41..9f7aa62bec7b7 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -7,47 +7,93 @@ define([ 'fotorama/fotorama', 'underscore', 'matchMedia', - 'text!mage/gallery/gallery.html' -], function ($, fotorama, _, mediaCheck, template) { + 'text!mage/gallery/gallery.html', + 'Magento_Ui/js/lib/class' +], function ($, fotorama, _, mediaCheck, template, Class) { 'use strict'; - return function (config, element) { + return Class.extend({ - var triggeredBreakpoints = 0, - settings = {}, - isTouchEnabled, - initGallery, - setupBreakpoints, - initApi, - initConfig = {}; - - config.options.ratio = config.options.width / config.options.height; - config.options.height = null; - - settings = { - $element: $(element), - currentConfig: config.options, - defaultConfig: config.options, - breakpoints: config.breakpoints, - fotoramaApi: null, - api: null - }; - - $.extend(true, initConfig, config); + defaults: { + settings: {}, + config: {}, + startConfig: {} + }, /** * Checks if device has touch interface. * @return {Boolean} The result of searching touch events on device. */ - isTouchEnabled = (function () { + 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) { + this._super(); + + this.config = config; + + this.settings = { + $element: $(element), + currentConfig: config, + defaultConfig: _.clone(config), + fullscreenConfig: _.clone(config.fullscreen), + breakpoints: config.breakpoints, + activeBreakpoint: {}, + fotoramaApi: null, + isFullscreen: false, + api: null + }; + + config.options.ratio = config.options.width / config.options.height; + config.options.height = null; + config.options.allowfullscreen = false; + + $.extend(true, this.startConfig, config); + + this.initGallery(); + this.initApi(); + this.setupBreakpoints(); + this.initFullscreenSettings(); + }, + + /** + * Gallery fullscreen settings. + */ + initFullscreenSettings: function () { + var settings = this.settings; + settings.$element.on('fotorama:fullscreenenter', function () { + settings.api.updateOptions(settings.defaultConfig.options, true); + settings.api.updateOptions(settings.fullscreenConfig, true); + + if (!_.isEqual(settings.activeBreakpoint, {})) { + settings.api.updateOptions(settings.activeBreakpoint.options, true); + } + settings.isFullscreen = true; + }); + + settings.$element.on('fotorama:fullscreenexit', function () { + settings.api.updateOptions(settings.defaultConfig.options, true); + + if (!_.isEqual(settings.activeBreakpoint, {})) { + settings.api.updateOptions(settings.activeBreakpoint.options, true); + } + settings.isFullscreen = false; + }); + }, /** * Initializes gallery with configuration options. */ - initGallery = function () { + initGallery: function () { var breakpoints = {}, + settings = this.settings, + config = this.config, mainImage; if (settings.breakpoints) { @@ -55,7 +101,7 @@ define([ var conditions; _.each(_.pairs(breakpoint.conditions), function (pair) { conditions = conditions ? conditions + ' and (' + pair[0] + ': ' + pair[1] + ')' : - '(' + pair[0] + ': ' + pair[1] + ')'; + '(' + pair[0] + ': ' + pair[1] + ')'; }); breakpoints[conditions] = breakpoint.options; }); @@ -65,7 +111,7 @@ define([ _.extend(config, config.options); config.options = undefined; - if (isTouchEnabled) { + if (this.isTouchEnabled) { config.arrows = false; } @@ -80,25 +126,26 @@ define([ config.breakpoints = null; config.startindex = mainImage; settings.currentConfig = config; - $.extend(true, settings.defaultConfig, config); settings.$element.html(template); settings.$element = $(settings.$element.children()[0]); settings.$element.fotorama(config); settings.fotoramaApi = settings.$element.data('fotorama'); - $.extend(true, config, initConfig); - }; + $.extend(true, config, this.startConfig); + }, /** * Creates breakpoints for gallery. - * @param {Object} breakpoints - Object with keys as media queries and values as configurations. */ - setupBreakpoints = function (breakpoints) { - var pairs; - - if (_.isObject(breakpoints)) { - pairs = _.pairs(breakpoints); + setupBreakpoints: function () { + var pairs, + settings = this.settings, + config = this.config, + startConfig = this.startConfig, + triggeredBreakpoints = 0; + + if (_.isObject(settings.breakpoints)) { + pairs = _.pairs(settings.breakpoints); _.each(pairs, function (pair) { - var initialized = 0; mediaCheck({ media: pair[0], @@ -107,154 +154,153 @@ define([ */ entry: function () { triggeredBreakpoints++; - initialized = initialized < pairs.length ? initialized++ : initialized; - settings.api.updateOptions(settings.defaultConfig, true); - $.extend(true, config, initConfig); + $.extend(true, config, _.clone(startConfig)); settings.api.updateOptions(settings.defaultConfig.options, true); - settings.currentConfig = settings.breakpoints[pair[0]]; - settings.api.updateOptions(settings.currentConfig.options, true); - $.extend(true, config, settings.currentConfig); - settings.$element.trigger('gallery:updated', $('.fotorama-item').data('fotorama')); + if (settings.isFullscreen) { + settings.api.updateOptions(settings.fullscreenConfig, true); + } + 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 () { - triggeredBreakpoints = triggeredBreakpoints > 0 ? triggeredBreakpoints-- : 0; - initialized = initialized < pairs.length ? initialized++ : initialized; - - if (!triggeredBreakpoints && initialized === pairs.length) { - settings.currentConfig = settings.defaultConfig; - settings.api.updateOptions(settings.currentConfig.options, true); - $.extend(true, config, initConfig); - settings.$element.trigger('gallery:updated', settings.fotoramaApi); + if (triggeredBreakpoints < 1) { + $.extend(true, config, _.clone(startConfig)); + settings.api.updateOptions(settings.defaultConfig.options, true); + + if (settings.isFullscreen) { + settings.api.updateOptions(settings.fullscreenConfig, true); + } + settings.activeBreakpoint = {}; } + triggeredBreakpoints--; } }); }); } - }; + }, /** * Creates gallery's API. */ - initApi = function () { - var api = { - - /** - * Contains fotorama's API methods. - */ - fotorama: settings.fotoramaApi, - - /** - * Displays the last image on preview. - */ - last: function () { - this.fotorama.show('>>'); - }, - - /** - * Displays the first image on preview. - */ - first: function () { - this.fotorama.show('<<'); - }, - - /** - * Displays previous element on preview. - */ - prev: function () { - this.fotorama.show('<'); - }, - - /** - * Displays next element on preview. - */ - next: function () { - this.fotorama.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; + 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 () { + this.fotorama.show('>>'); + }, + + /** + * Displays the first image on preview. + */ + first: function () { + this.fotorama.show('<<'); + }, + + /** + * Displays previous element on preview. + */ + prev: function () { + this.fotorama.show('<'); + }, + + /** + * Displays next element on preview. + */ + next: function () { + this.fotorama.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; + } + this.fotorama.show(index); } - this.fotorama.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) { + }, + + /** + * 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) { + if (_.isObject(configuration)) { + if (this.isTouchEnabled) { + configuration.arrows = false; + } + configuration.click = false; + configuration.breakpoints = null; - if (_.isObject(configuration)) { + if (!isInternal) { + !_.isEqual(settings.activeBreakpoint, {}) ? + $.extend(true, settings.activeBreakpoint.options, configuration) : - if (isTouchEnabled) { - configuration.arrows = false; - } - configuration.click = false; - setupBreakpoints(configuration.breakpoints); - configuration.breakpoints = null; + settings.isFullscreen ? + $.extend(true, settings.fullscreenConfig, configuration) : + $.extend(true, settings.defaultConfig.options, configuration); - if (!isInternal) { + } $.extend(true, settings.currentConfig.options, configuration); + this.fotorama.setOptions(settings.currentConfig.options); } - this.fotorama.setOptions(settings.currentConfig.options); - } - }, - - /** - * Updates gallery with specific set of items. - * @param {Array.} data - Set of gallery items to update. - */ - updateData: function (data) { - - if (_.isArray(data)) { - this.fotorama.load(data); - $.extend(false, settings.defaultConfig, { - data: data - }); - $.extend(false, config, { - data: data + }, + + /** + * Updates gallery with specific set of items. + * @param {Array.} data - Set of gallery items to update. + */ + updateData: function (data) { + if (_.isArray(data)) { + this.fotorama.load(data); + $.extend(false, settings.defaultConfig, { + data: data + }); + $.extend(false, config, { + data: data + }); + } + }, + + /**Returns curent images list + * + * @return {Array} + */ + returnCurrentImages: function () { + var images = []; + + _.forEach(this.fotorama.data, function (item) { + images.push({ + 'img': item.img + }) }); } - }, - - /**Returns current images list - * - * @returns {*} - */ - returnCurrentImages: function () { - var images = []; - - _.forEach(this.fotorama.data, function (item) { - images.push({ - 'img': item.img - }) - }); - - return images; - } - }; + }; settings.$element.data('gallery', api); settings.api = settings.$element.data('gallery'); settings.$element.trigger('gallery:loaded'); - }; - - initGallery(); - initApi(); - setupBreakpoints(settings.breakpoints); - }; + } + }); }); From 1030911cb760df1182618423a2cabc0f57c0e531 Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Mon, 7 Sep 2015 16:04:54 +0300 Subject: [PATCH 003/116] JS-153: Magnifier preview must be hidden, while start swiping or dragging --- lib/web/mage/gallery/gallery.html | 4 ++-- lib/web/magnifier/magnify.js | 40 +++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/web/mage/gallery/gallery.html b/lib/web/mage/gallery/gallery.html index 6a9a3cfbe3c3c..69a196d86c6df 100644 --- a/lib/web/mage/gallery/gallery.html +++ b/lib/web/mage/gallery/gallery.html @@ -8,13 +8,13 @@
-
+
-
+
diff --git a/lib/web/magnifier/magnify.js b/lib/web/magnifier/magnify.js index a30a827aabdd3..146c014b444d2 100644 --- a/lib/web/magnifier/magnify.js +++ b/lib/web/magnifier/magnify.js @@ -13,7 +13,9 @@ define([ var isTouchEnabled = 'ontouchstart' in document.documentElement, gallerySelector = '[data-gallery-role="gallery"]', magnifierSelector = '[data-gallery-role="magnifier"]', - magnifierZoomSelector = '[data-gallery-role="magnifier-zoom"]'; + magnifierZoomSelector = '[data-gallery-role="magnifier-zoom"]', + hideMagnifier, + behaveOnHover; if (isTouchEnabled) { $(element).on('fotorama:showend fotorama:load', function () { @@ -23,8 +25,38 @@ define([ return config; } + /** + * Hides magnifier preview and zoom blocks. + */ + hideMagnifier = function () { + $(magnifierSelector).empty().hide(); + $(magnifierZoomSelector).remove(); + }; + + /** + * Hides magnifier on drag and while arrow click. + */ + behaveOnHover = function (e, initPos) { + var pos = [e.pageX, e.pageY], + isArrow = $(e.target).data('gallery-role') === 'arrow', + isClick = initPos[0] === pos[0] && initPos[1] === pos[1]; + if (isArrow || !isClick) { + hideMagnifier(); + } + }; + if (config.magnifierOpts.eventType === 'click') { config.options.swipe = false; + } else if (config.magnifierOpts.eventType === 'hover') { + $(element).on('pointerdown mousedown MSPointerDown', function (e) { + var pos = [e.pageX, e.pageY]; + $(element).on('mousemove pointermove MSPointerMove', function (ev) { + navigator.msPointerEnabled ? hideMagnifier() : behaveOnHover(ev, pos); + }); + $(document).on('mouseup pointerup MSPointerUp', function () { + $(element).off('mousemove pointermove MSPointerMove'); + }); + }); } $.extend(config.magnifierOpts, { @@ -48,15 +80,13 @@ define([ }); $(element).on('fotorama:showend fotorama:load', function (e, fotorama) { - $(magnifierSelector).empty().hide(); - $(magnifierZoomSelector).remove(); + hideMagnifier(); config.magnifierOpts.large = $(gallerySelector).data('fotorama').activeFrame.img; config.magnifierOpts.original = fotorama.data[fotorama.activeIndex].original; $($(gallerySelector).data('fotorama').activeFrame.$stageFrame).magnify(config.magnifierOpts); }); $(element).on('fotorama:show', function () { - $(magnifierSelector).empty().hide(); - $(magnifierZoomSelector).remove(); + hideMagnifier(); }); return config; From fc20660d3b079106c31e14ee8c8d56f0e642b0b7 Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Mon, 7 Sep 2015 16:13:45 +0300 Subject: [PATCH 004/116] JS-182: Magnifier doesn't appear on gallery arrows hover --- lib/web/magnifier/magnifier.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/web/magnifier/magnifier.js b/lib/web/magnifier/magnifier.js index 3a31236832e68..6e5a05cfd68e7 100644 --- a/lib/web/magnifier/magnifier.js +++ b/lib/web/magnifier/magnifier.js @@ -394,7 +394,7 @@ onThumbLeave(); } handleEvents(e); - isOverThumb = true; + isOverThumb = inBounds; } }).trigger('mouseover'); } @@ -564,6 +564,10 @@ getMousePos(); + if (gEventType === 'hover') { + isOverThumb = inBounds; + } + if (inBounds && isOverThumb) { $largeWrapper.removeClass(MagnifyCls.magnifyHidden); move(); From 1f1e43b79c77185e8117bf0e1119ea7762d8f5cd Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Mon, 7 Sep 2015 16:23:41 +0300 Subject: [PATCH 005/116] JS-160: Erratic behaviour when changing slides --- lib/web/fotorama/fotorama.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 592f9d4cff047..7ae347e8dd7bf 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -1573,17 +1573,9 @@ fotoramaVersion = '4.6.4'; if (typeof options.overPos !== 'undefined' && options.overPos !== options.pos) { elPos = options.overPos; - onEndFn = function () { - slide($el, $.extend({}, options, { - overPos: options.pos, - time: Math.max(TRANSITION_DURATION, options.time / 2) - })); - }; } - ////////console.time('var translate = $.extend'); var translate = $.extend(getTranslate(elPos/*, options._001*/), options.width && {width: options.width}); - ////////console.timeEnd('var translate = $.extend'); if (elData && elData.sliding) { elData.sliding = true; } @@ -1591,9 +1583,7 @@ fotoramaVersion = '4.6.4'; if (CSS3) { $el.css($.extend(getDuration(options.time), translate)); if (options.time > 10) { - ////////console.time('afterTransition'); afterTransition($el, 'transform', onEndFn, options.time); - ////////console.timeEnd('afterTransition'); } else { onEndFn(); } From 8885c3ea99c1106d09b82ecc381111c5c41429f0 Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Mon, 7 Sep 2015 16:49:16 +0300 Subject: [PATCH 006/116] JS-171: Implement enabling/disabling of full-screen mode --- .../templates/product/view/gallery.phtml | 1 + .../frontend/Magento/blank/etc/view.xml | 1 + app/design/frontend/Magento/luma/etc/view.xml | 3 +- lib/web/mage/gallery/gallery.js | 2 +- lib/web/mage/gallery/gallery.less | 32 ++++++++----------- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 3089c2cf50f6f..5c81ceb62097e 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -30,6 +30,7 @@ "loop": getVar("gallery:loop"); ?>, "keyboard": getVar("gallery:keyboard"); ?>, "arrows": getVar("gallery:arrows"); ?>, + "allowfullscreen": getVar("gallery:allowfullscreen"); ?>, "showCaption": getVar("gallery:show_caption"); ?>, "width": getImageAttribute('product_page_image_medium', 'width'); ?>, "thumbwidth": getImageAttribute('product_page_image_small', 'width'); ?>, diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml index 897a3c54b3b27..4c3a737ee7ed3 100644 --- a/app/design/frontend/Magento/blank/etc/view.xml +++ b/app/design/frontend/Magento/blank/etc/view.xml @@ -185,6 +185,7 @@ true true false + true diff --git a/app/design/frontend/Magento/luma/etc/view.xml b/app/design/frontend/Magento/luma/etc/view.xml index 2795d84c168a1..4b3777ba944f7 100644 --- a/app/design/frontend/Magento/luma/etc/view.xml +++ b/app/design/frontend/Magento/luma/etc/view.xml @@ -188,7 +188,8 @@ false true true - true + true + true diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index 9f81daba85bcc..7eeed339a862a 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -42,7 +42,7 @@ define([ $element: $(element), currentConfig: config, defaultConfig: _.clone(config), - fullscreenConfig: _.clone(config.fullscreen), + fullscreenConfig: _.clone(config.allowfullscreen), breakpoints: config.breakpoints, activeBreakpoint: {}, fotoramaApi: null, diff --git a/lib/web/mage/gallery/gallery.less b/lib/web/mage/gallery/gallery.less index 9fd58e8b302ef..0e5d52ae073b5 100644 --- a/lib/web/mage/gallery/gallery.less +++ b/lib/web/mage/gallery/gallery.less @@ -58,16 +58,6 @@ width: 100%; } -.fotorama-image-reset { - border-radius: 0 !important; - box-shadow: none !important; - max-height: 99999px !important; - max-width: 99999px !important; - min-height: 0 !important; - min-width: 0 !important; - padding: 0 !important; -} - .fotorama-grab-cursor { cursor: move; cursor: -webkit-grab; @@ -202,8 +192,7 @@ } .fotorama--fullscreen { - &:extend(.fotorama-image-reset); - background: @color-black; + background: @color-white; bottom: 0 !important; float: none !important; height: 100% !important; @@ -214,9 +203,8 @@ top: 0 !important; width: 100% !important; z-index: @z-index-10 !important; - .fotorama__stage, - .fotorama__nav { - background: @color-black; + .fotorama__wrap { + max-width: 100% !important; } } @@ -583,6 +571,14 @@ &:extend(.fotorama-no-tap); cursor: pointer; position: absolute; +} + +.fotorama__arr { + z-index: @z-index-9; + +} +.fotorama__fullscreen-icon, +.fotorama__video-close { z-index: @z-index-10; } @@ -629,7 +625,7 @@ right: 2px; top: 2px; width: @size-fotorama-block; - z-index: 20; + z-index: @z-index-10; } .fotorama__fullscreen-icon { @@ -642,7 +638,7 @@ .fotorama--fullscreen { .fotorama__fullscreen-icon { - background-position: (-@fotorama_fullscreen_button) (-@fotorama_fullscreen_button); + background-position: (-@size-fotorama-block) 0; } } @@ -859,7 +855,7 @@ overflow: hidden; position: absolute; top: 0; - z-index: @z-index-10; + z-index: @z-index-9; } .magnify-lens { From 634c32d50db5ceee61ccf90e122774f942c90c9a Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Wed, 9 Sep 2015 16:49:25 +0300 Subject: [PATCH 007/116] JS-175: Implement transition options support from theme level --- .../templates/product/view/gallery.phtml | 6 +++ .../frontend/Magento/blank/etc/view.xml | 2 + app/design/frontend/Magento/luma/etc/view.xml | 2 + .../js/jasmine/assets/gallery/config.json | 9 ++++- .../js/jasmine/tests/lib/mage/gallery.test.js | 37 ++++++++++++++++++- 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 5c81ceb62097e..a36f9bccf2029 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -38,6 +38,12 @@ ?: $block->getImageAttribute('product_page_image_small', 'width'); ?>, "height": getImageAttribute('product_page_image_medium', 'height') ?: $block->getImageAttribute('product_page_image_medium', 'width'); ?> + "transitionduration": getVar("gallery:transition:duration"); ?>, + "transition": "getVar("gallery:transition:effect"); ?>" + }, + "fullscreen": { + "nav": "thumbs", + "swipe": false }, "breakpoints": { "mobile": { diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml index 4c3a737ee7ed3..de5711efd7e9b 100644 --- a/app/design/frontend/Magento/blank/etc/view.xml +++ b/app/design/frontend/Magento/blank/etc/view.xml @@ -186,6 +186,8 @@ true false true + dissolve + 500 diff --git a/app/design/frontend/Magento/luma/etc/view.xml b/app/design/frontend/Magento/luma/etc/view.xml index 4b3777ba944f7..518193199c5ce 100644 --- a/app/design/frontend/Magento/luma/etc/view.xml +++ b/app/design/frontend/Magento/luma/etc/view.xml @@ -190,6 +190,8 @@ true true true + slide + 500 diff --git a/dev/tests/js/jasmine/assets/gallery/config.json b/dev/tests/js/jasmine/assets/gallery/config.json index b3c8b8bc0b38d..d1d8e94d7f220 100644 --- a/dev/tests/js/jasmine/assets/gallery/config.json +++ b/dev/tests/js/jasmine/assets/gallery/config.json @@ -59,12 +59,17 @@ "arrows": "false", "thumbwidth": "90", "thumbheight": "90", - "ratio": "1" + "ratio": "1", + "allowfullscreen": true + }, + "fullscreen": { + "nav": false }, "breakpoints": { "alias": { "conditions": { - "min-width": "0px" + "min-width": "0px", + "max-width": "1px" }, "options": { "options": { diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js index 3f076659b4923..dd29ec79a64ec 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js @@ -19,6 +19,7 @@ define([ stageSelector = '[data-gallery-role="stage-shaft"]', navSelector = '[data-gallery-role="nav-frame"]', dotSelector = '[data-nav-type="dot"]', + navWrap = '[data-gallery-role="nav-wrap"]', dataToUpdate = [ { img: 'data:image/png;base64,' + @@ -33,7 +34,16 @@ define([ img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAw' + 'CAAAAC0lEQVR42mP4Xw8AAoABf5/NhYYAAAAASUVORK5CYII=' } - ]; + ], + waitsFor = function (test, fn) { + if (test()) { + fn(); + } else { + setTimeout(function () { + waitsFor(test, fn); + }, 10); + } + }; gallery(magnifier(conf, body), body); @@ -115,5 +125,30 @@ define([ it('breakpoints override configs', function () { expect($('.fotorama__arr').css('display')).toBe('none'); }); + + it('fullscreen enter', function (done) { + expect($(navWrap).css('display') === 'block').toBeTruthy(); + galleryAPI.fotorama.requestFullScreen(); + + waitsFor(function () { + return $(navWrap).css('display') !== 'block'; + }, function () { + expect($(navWrap).css('display') === 'none').toBeTruthy(); + done(); + }); + }); + + + it('fullscreen exit', function (done) { + expect($(navWrap).css('display') === 'none').toBeTruthy(); + galleryAPI.fotorama.cancelFullScreen(); + + waitsFor(function () { + return $(navWrap).css('display') !== 'none'; + }, function () { + expect($(navWrap).css('display') === 'block').toBeTruthy(); + done(); + }); + }); }); }); From 6b15356040a3a9d4150060732ad35929c4e7b24a Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Wed, 9 Sep 2015 17:34:32 +0300 Subject: [PATCH 008/116] JS-157: Implement drag for image on desktops --- .../templates/product/view/gallery.phtml | 8 +- .../frontend/Magento/blank/etc/view.xml | 9 +- app/design/frontend/Magento/luma/etc/view.xml | 8 ++ lib/web/fotorama/fotorama.js | 2 +- lib/web/mage/gallery/gallery.js | 5 +- lib/web/mage/gallery/gallery.less | 15 ++ lib/web/magnifier/magnifier.js | 131 ++++++++++++++++++ lib/web/magnifier/magnify.js | 5 +- 8 files changed, 175 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index a36f9bccf2029..024df1446a5b2 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -42,8 +42,12 @@ "transition": "getVar("gallery:transition:effect"); ?>" }, "fullscreen": { - "nav": "thumbs", - "swipe": false + "nav": "getVar("gallery:fullscreen:navigation"); ?>", + "loop": getVar("gallery:fullscreen:loop"); ?>, + "arrows": getVar("gallery:fullscreen:arrows"); ?>, + "showCaption": getVar("gallery:fullscreen:show_caption"); ?>, + "transitionduration": getVar("gallery:fullscreen:transition:duration"); ?>, + "transition": "getVar("gallery:fullscreen:transition:effect"); ?>" }, "breakpoints": { "mobile": { diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml index de5711efd7e9b..15a8191641ff0 100644 --- a/app/design/frontend/Magento/blank/etc/view.xml +++ b/app/design/frontend/Magento/blank/etc/view.xml @@ -186,9 +186,16 @@ true false true - dissolve + slide 500 + thumbs + false + null + null + crossfade + 500 + diff --git a/app/design/frontend/Magento/luma/etc/view.xml b/app/design/frontend/Magento/luma/etc/view.xml index 518193199c5ce..df358d1629bda 100644 --- a/app/design/frontend/Magento/luma/etc/view.xml +++ b/app/design/frontend/Magento/luma/etc/view.xml @@ -193,6 +193,14 @@ slide 500 + thumbs + true + true + false + false + dissolve + 500 + diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 7ae347e8dd7bf..5f34cd9820e89 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -977,7 +977,7 @@ fotoramaVersion = '4.6.4'; arrows: true, click: true, - swipe: true, + swipe: false, trackpad: false, shuffle: false, diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index 7eeed339a862a..ed4e12dde1f29 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -36,6 +36,7 @@ define([ initialize: function (config, element) { this._super(); + config.options.swipe = true; this.config = config; this.settings = { @@ -52,7 +53,6 @@ define([ config.options.ratio = config.options.width / config.options.height; config.options.height = null; - config.options.allowfullscreen = false; $.extend(true, this.startConfig, config); @@ -67,6 +67,9 @@ define([ */ initFullscreenSettings: function () { var settings = this.settings; + + settings.fullscreenConfig.swipe = false; + settings.$element.on('fotorama:fullscreenenter', function () { settings.api.updateOptions(settings.defaultConfig.options, true); settings.api.updateOptions(settings.fullscreenConfig, true); diff --git a/lib/web/mage/gallery/gallery.less b/lib/web/mage/gallery/gallery.less index 0e5d52ae073b5..1f7eac04d2d53 100644 --- a/lib/web/mage/gallery/gallery.less +++ b/lib/web/mage/gallery/gallery.less @@ -897,6 +897,21 @@ } } +.fotorama--fullscreen { + .fotorama__stage__frame { + .fotorama__img { + position: absolute; + max-width: inherit; + max-height: inherit; + margin: auto; + top: 0px; + bottom: 0px; + left: 0px; + right: 0px; + } + } +} + .fotorama__stage__frame { text-align: center; .fotorama__img { diff --git a/lib/web/magnifier/magnifier.js b/lib/web/magnifier/magnifier.js index 6e5a05cfd68e7..acfd548bccadd 100644 --- a/lib/web/magnifier/magnifier.js +++ b/lib/web/magnifier/magnifier.js @@ -578,6 +578,99 @@ } } + function magnifierFullscreen () { + var isDragActive = false, + startX, + startY, + imagePosX, + imagePosY, + touch, + isTouchEnabled = 'ontouchstart' in document.documentElement; + + $('[data-gallery-role="gallery"]').on('fotorama:fullscreenenter fotorama:showend fotorama:load', function () { + + var $image = $('[data-gallery-role="stage-shaft"] [data-active="true"] img'), + $imageContainer = $image.parent(), + gallery = $('[data-gallery-role="gallery"]'); + + gallery.on('fotorama:fullscreenexit', function () { + $thumb.css({ + 'top': '', + 'left': '' + }); + }); + + $image.on(isTouchEnabled ? 'touchstart' : 'mousedown', function (e) { + if (gallery.data('fotorama').fullScreen) { + e.preventDefault(); + + $image.css('cursor', 'move'); + imagePosY = $image.offset().top; + 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; + startY = e.clientY; + isDragActive = true; + } + }); + + $image.on(isTouchEnabled ? 'touchmove' : 'mousemove', function (e) { + if (gallery.data('fotorama').fullScreen && isDragActive) { + + var top, + left, + startOffset = $image.offset(); + + e.preventDefault(); + + if (isTouchEnabled) { + touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; + e.clientX = touch.pageX; + e.clientY = touch.pageY; + } + top = +imagePosY + (e.clientY - startY); + left = +imagePosX + (e.clientX - startX); + + if ($image.height() > $imageContainer.height()) { + + if (($imageContainer.offset().top + $imageContainer.height()) > (top + $image.height())) { + top = $imageContainer.offset().top + $imageContainer.height() - $image.height(); + } else { + top = ($imageContainer.offset().top < top) ? 0 : top; + } + $image.offset({ + 'top': top + }); + } + + 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) ? 0 : left; + } + $image.offset({ + 'left': left + }); + } + } + }); + + $image.on(isTouchEnabled ? 'touchend' : 'mouseup', function (e) { + if (gallery.data('fotorama').fullScreen) { + isDragActive = false; + $image.css('cursor', 'pointer'); + } + }); + }); + }; + function onScroll() { if (curThumb !== null) { @@ -587,9 +680,47 @@ $(window).on('scroll', onScroll); $(window).resize(function() { + + if ($('[data-gallery-role="gallery"]').data('fotorama').fullScreen) { + + var $image = $('[data-gallery-role="stage-shaft"] > [data-active="true"] > img'), + $imageContainer = $image.parent(), + top, left; + + if (($imageContainer.offset().top + $imageContainer.height()) > ($image.offset().top + $image.height())) { + top = $imageContainer.offset().top + $imageContainer.height() - $image.height(); + } else { + top = ($imageContainer.offset().top < $image.offset().top) ? 0 : top; + } + + if (top !== undefined) { + $image.css('top', top); + } + + if (($imageContainer.offset().left + $imageContainer.width()) > ($image.offset().left + $image.width())) { + left = $imageContainer.offset().left + $imageContainer.width() - $image.width(); + } else { + left = ($imageContainer.offset().left < $image.offset().left) ? 0 : left; + } + + if (left !== undefined) { + $image.css('left', left); + } + + if ($image.width() < $imageContainer.width()) { + $image.css('left', ''); + } + + if ($image.height() < $imageContainer.height()) { + $image.css('top', ''); + } + } + _init($box, gOptions); + }); $(document).on('mousemove', onMousemove); _init($box, gOptions); + magnifierFullscreen(); } }(jQuery)); diff --git a/lib/web/magnifier/magnify.js b/lib/web/magnifier/magnify.js index 146c014b444d2..d6f7c9931f374 100644 --- a/lib/web/magnifier/magnify.js +++ b/lib/web/magnifier/magnify.js @@ -20,9 +20,8 @@ define([ if (isTouchEnabled) { $(element).on('fotorama:showend fotorama:load', function () { $(magnifierSelector).remove(); + $(magnifierZoomSelector).remove(); }); - - return config; } /** @@ -79,7 +78,7 @@ define([ } }); - $(element).on('fotorama:showend fotorama:load', function (e, fotorama) { + $(element).on('fotorama:showend fotorama:load fotorama:fullscreenexit', function (e, fotorama) { hideMagnifier(); config.magnifierOpts.large = $(gallerySelector).data('fotorama').activeFrame.img; config.magnifierOpts.original = fotorama.data[fotorama.activeIndex].original; From 31c7fdbb22e2cd1cc8f2c841780c59246724a268 Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Tue, 15 Sep 2015 01:27:22 +0300 Subject: [PATCH 009/116] JS-50: Different configurations for Page and Full Screen Gallery Widget modes --- .../templates/product/view/gallery.phtml | 13 +- .../frontend/Magento/blank/etc/view.xml | 5 +- app/design/frontend/Magento/luma/etc/view.xml | 3 +- .../js/jasmine/tests/lib/mage/gallery.test.js | 2 +- lib/web/fotorama/fotorama.js | 239 +++++++++---- lib/web/mage/gallery/gallery.html | 4 +- lib/web/mage/gallery/gallery.js | 22 +- lib/web/mage/gallery/gallery.less | 324 +++++++++++++++--- lib/web/magnifier/magnifier.js | 54 +++ lib/web/magnifier/magnify.js | 3 +- 10 files changed, 548 insertions(+), 121 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 024df1446a5b2..7bf679228f998 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -29,15 +29,14 @@ "nav": "getVar("gallery:navigation"); ?>", "loop": getVar("gallery:loop"); ?>, "keyboard": getVar("gallery:keyboard"); ?>, - "arrows": getVar("gallery:arrows"); ?>, + "navdir": "getVar("gallery:navdir"); ?>", "allowfullscreen": getVar("gallery:allowfullscreen"); ?>, - "showCaption": getVar("gallery:show_caption"); ?>, + "showCaption": getVar("gallery:caption"); ?>, "width": getImageAttribute('product_page_image_medium', 'width'); ?>, - "thumbwidth": getImageAttribute('product_page_image_small', 'width'); ?>, - "thumbheight": getImageAttribute('product_page_image_small', 'height') - ?: $block->getImageAttribute('product_page_image_small', 'width'); ?>, + "thumbwidth": 120, + "thumbheight": 90, "height": getImageAttribute('product_page_image_medium', 'height') - ?: $block->getImageAttribute('product_page_image_medium', 'width'); ?> + ?: $block->getImageAttribute('product_page_image_medium', 'width'); ?>, "transitionduration": getVar("gallery:transition:duration"); ?>, "transition": "getVar("gallery:transition:effect"); ?>" }, @@ -45,7 +44,7 @@ "nav": "getVar("gallery:fullscreen:navigation"); ?>", "loop": getVar("gallery:fullscreen:loop"); ?>, "arrows": getVar("gallery:fullscreen:arrows"); ?>, - "showCaption": getVar("gallery:fullscreen:show_caption"); ?>, + "showCaption": getVar("gallery:fullscreen:caption"); ?>, "transitionduration": getVar("gallery:fullscreen:transition:duration"); ?>, "transition": "getVar("gallery:fullscreen:transition:effect"); ?>" }, diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml index 15a8191641ff0..93815d880aad0 100644 --- a/app/design/frontend/Magento/blank/etc/view.xml +++ b/app/design/frontend/Magento/blank/etc/view.xml @@ -184,15 +184,16 @@ true true true - false + false true + vertical slide 500 thumbs false null - null + null crossfade 500 diff --git a/app/design/frontend/Magento/luma/etc/view.xml b/app/design/frontend/Magento/luma/etc/view.xml index df358d1629bda..b5f49bfde17f3 100644 --- a/app/design/frontend/Magento/luma/etc/view.xml +++ b/app/design/frontend/Magento/luma/etc/view.xml @@ -190,6 +190,7 @@ true true true + horizontal slide 500 @@ -197,7 +198,7 @@ true true false - false + false dissolve 500 diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js index dd29ec79a64ec..d762ca5fe9f25 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js @@ -138,7 +138,6 @@ define([ }); }); - it('fullscreen exit', function (done) { expect($(navWrap).css('display') === 'none').toBeTruthy(); galleryAPI.fotorama.cancelFullScreen(); @@ -150,5 +149,6 @@ define([ done(); }); }); + }); }); diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 5f34cd9820e89..d7f64c62bc116 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -5,7 +5,7 @@ fotoramaVersion = '4.6.4'; (function (window, document, location, $, undefined) { "use strict"; var _fotoramaClass = 'fotorama', - _fullscreenClass = 'fullscreen', + _fullscreenClass = 'fotorama__fullscreen', wrapClass = _fotoramaClass + '__wrap', wrapCss2Class = wrapClass + '--css2', @@ -37,6 +37,9 @@ fotoramaVersion = '4.6.4'; navClass = _fotoramaClass + '__nav', navWrapClass = navClass + '-wrap', navShaftClass = navClass + '__shaft', + navShaftVerticalClass = navWrapClass + '--vertical', + navShaftListClass = navWrapClass + '--list', + navShaftHorisontalClass = navWrapClass + '--horisontal', navDotsClass = navClass + '--dots', navThumbsClass = navClass + '--thumbs', navFrameClass = navClass + '__frame', @@ -49,6 +52,8 @@ fotoramaVersion = '4.6.4'; shadowsClass = shadowClass + 's', shadowsLeftClass = shadowsClass + '--left', shadowsRightClass = shadowsClass + '--right', + shadowsTopClass = shadowsClass + '--top', + shadowsBottomClass = shadowsClass + '--bottom', activeClass = _fotoramaClass + '__active', selectClass = _fotoramaClass + '__select', @@ -482,7 +487,7 @@ fotoramaVersion = '4.6.4'; , n for (n in prop) el[n] = prop[n] - return el; + return el } /** @@ -986,7 +991,8 @@ fotoramaVersion = '4.6.4'; shadows: true, spinner: null, - showcaption: true + showcaption: true, + navdir: 'horisontal' }, KEYBOARD_OPTIONS = { @@ -1005,24 +1011,40 @@ fotoramaVersion = '4.6.4'; return Math.max(isNaN(min) ? -Infinity : min, Math.min(isNaN(max) ? Infinity : max, value)); } - function readTransform(css) { - return css.match(/ma/) && css.match(/-?\d+(?!d)/g)[css.match(/3d/) ? 12 : 4]; + 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) { + function readPosition($el, dir) { if (CSS3) { - return +readTransform($el.css('transform')); + return +readTransform($el.css('transform'), dir); } else { - return +$el.css('left').replace('px', ''); + return +$el.css(dir === 'vertical' ? 'top': 'left').replace('px', ''); } } - function getTranslate(pos/*, _001*/) { + function getTranslate(pos, direction) { var obj = {}; + if (CSS3) { - obj.transform = 'translate3d(' + (pos/* + (_001 ? 0.001 : 0)*/) + 'px,0,0)'; // 0.001 to remove Retina artifacts + + switch (direction){ + case 'vertical': + obj.transform = 'translate3d(0, ' + (pos) + 'px,0)'; + break; + case 'list': + //console.warn("transition not implemented"); + break; + default : + obj.transform = 'translate3d(' + (pos) + 'px,0,0)'; + break; + } } else { - obj.left = pos; + direction === 'vertical' ? + obj.top = pos : + obj.left = pos; } return obj; } @@ -1103,7 +1125,8 @@ fotoramaVersion = '4.6.4'; } - function stop($el, left/*, _001*/) { + function stop($el, pos/*, _001*/) { + var dir = $el.navdir || 'horizontal'; if ($el.length) { var elData = $el.data(); if (CSS3) { @@ -1113,12 +1136,12 @@ fotoramaVersion = '4.6.4'; } else { $el.stop(); } - var lockedLeft = getNumber(left, function () { - return readPosition($el); + var lockedPos = getNumber(pos, function () { + return readPosition($el, dir); }); - $el.css(getTranslate(lockedLeft/*, _001*/));//.width(); // `.width()` for reflow - return lockedLeft; + $el.css(getTranslate(lockedPos, dir/*, _001*/));//.width(); // `.width()` for reflow + return lockedPos; } } @@ -1353,8 +1376,11 @@ fotoramaVersion = '4.6.4'; } } - function findShadowEdge(pos, min, max) { - return min === max ? false : pos <= min ? 'left' : pos >= max ? 'right' : 'left right'; + 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) { @@ -1377,7 +1403,6 @@ fotoramaVersion = '4.6.4'; onMove: _options.onMove || noop, onTouchEnd: _options.onTouchEnd || noop, onEnd: function (result) { - ////console.log('smartClick → result.moved', result.moved); if (result.moved) return; fn.call(this, startEvent); } @@ -1575,7 +1600,7 @@ fotoramaVersion = '4.6.4'; elPos = options.overPos; } - var translate = $.extend(getTranslate(elPos/*, options._001*/), options.width && {width: options.width}); + var translate = $.extend(getTranslate(elPos, options.direction), options.width && {width: options.width}, options.height && {height: options.height}); if (elData && elData.sliding) { elData.sliding = true; } @@ -1635,7 +1660,8 @@ fotoramaVersion = '4.6.4'; var lastEvent, moveEventType, preventEvent, - preventEventTimeout; + preventEventTimeout, + dragDomEl; function extendEvent(e) { var touch = (e.touches || [])[0] || e; @@ -1709,7 +1735,6 @@ fotoramaVersion = '4.6.4'; stopEvent(e); } } else { - ////console.log('onMove e.preventDefault'); stopEvent(e); (options.onMove || noop).call(el, e, {touch: touchFLAG}); } @@ -1786,11 +1811,12 @@ fotoramaVersion = '4.6.4'; .on('mousemove', onMove) .on('mouseup', onEnd); } - - $el.on('click', 'a', function (e) { - if (!Modernizr.touch) { - e.preventDefault(); - } + if (Modernizr.touch) { + dragDomEl = 'a'; + } else { + dragDomEl = 'div'; + } + $el.on('click', dragDomEl, function (e) { tail.checked && stopEvent(e); }); @@ -1812,6 +1838,7 @@ fotoramaVersion = '4.6.4'; min, max, snap, + dir = options.direction || 'horizontal', slowFLAG, controlFLAG, moved, @@ -1819,9 +1846,10 @@ fotoramaVersion = '4.6.4'; function startTracking(e, noStop) { tracked = true; - startCoo = coo = e._x; + startCoo = coo = (dir === 'vertical') ? e._y : e._x; startTime = e._now; + moveTrack = [ [startTime, startCoo] ]; @@ -1834,7 +1862,9 @@ fotoramaVersion = '4.6.4'; function onStart(e, result) { min = tail.min; max = tail.max; - snap = tail.snap; + snap = tail.snap, + dir = tail.direction||'horizontal', + $el.navdir = dir; slowFLAG = e.altKey; tracked = moved = false; @@ -1851,14 +1881,13 @@ fotoramaVersion = '4.6.4'; if (!tracked) { startTracking(e); } - - coo = e._x; + coo = (dir === 'vertical') ? e._y : e._x; moveTrack.push([e._now, coo]); moveElPos = startElPos - (startCoo - coo); - edge = findShadowEdge(moveElPos, min, max); + edge = findShadowEdge(moveElPos, min, max, dir); if (moveElPos <= min) { moveElPos = edgeResistance(moveElPos, min); @@ -1867,7 +1896,7 @@ fotoramaVersion = '4.6.4'; } if (!tail.noMove) { - $el.css(getTranslate(moveElPos/*, options._001*/)); + $el.css(getTranslate(moveElPos, dir)); if (!moved) { moved = true; // only for mouse @@ -1959,7 +1988,8 @@ fotoramaVersion = '4.6.4'; pos: moveElPos, newPos: newPos, overPos: overPos, - time: time + time: time, + dir:dir })); } @@ -2118,7 +2148,11 @@ fotoramaVersion = '4.6.4'; stageLeft = 0, fadeStack = []; - $wrap[STAGE_FRAME_KEY] = $(''); + if (Modernizr.touch) { + $wrap[STAGE_FRAME_KEY] = $(''); + } else { + $wrap[STAGE_FRAME_KEY] = $('
'); + } $wrap[NAV_THUMB_FRAME_KEY] = $($.Fotorama.jst.thumb()); @@ -2160,6 +2194,25 @@ fotoramaVersion = '4.6.4'; return o_keyboard[key] || that.fullScreen; } + function setStagePosition() { + if ($stage !== undefined) { + + if (opts.navdir == 'vertical') { + var padding = opts.thumbwidth + opts.thumbmargin; + + $stage.css('left', padding); + $arrNext.css('right', padding); + $wrap.css('width', $wrap.css('width') + padding); + $stageShaft.css('max-width', $wrap.width() - padding); + } else { + $stage.css('left', ''); + $arrNext.css('right', ''); + $wrap.css('width', $wrap.css('width') + padding); + $stageShaft.css('max-width', ''); + } + } + } + function bindGlobalEvents(FLAG) { var keydownCommon = 'keydown.' + _fotoramaClass, localStamp = _fotoramaClass + stamp, @@ -2266,6 +2319,10 @@ fotoramaVersion = '4.6.4'; * Options on the fly * */ function setOptions() { + if (opts.nav === 'dots') { + opts.navdir = 'horizontal' + } + that.options = opts = optionsToLowerCase(opts); o_fade = (opts.transition === 'crossfade' || opts.transition === 'dissolve'); @@ -2386,6 +2443,7 @@ fotoramaVersion = '4.6.4'; .removeClass(classes.remove.join(' ')); lastOptions = $.extend({}, opts); + setStagePosition(); } function normalizeIndex(index) { @@ -2415,8 +2473,13 @@ fotoramaVersion = '4.6.4'; } function setNavShaftMinMax() { - navShaftTouchTail.min = Math.min(0, measures.nw - $navShaft.width()); + + 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)); } @@ -2724,6 +2787,10 @@ fotoramaVersion = '4.6.4'; } function thumbsDraw(pos, loadFLAG) { + if (opts.navdir === 'vertical') { + pos = pos - opts.thumbheight; + } + if (o_nav !== 'thumbs' || isNaN(pos)) return; var leftLimit = -pos, @@ -2739,8 +2806,7 @@ fotoramaVersion = '4.6.4'; w: thisData.w } }, - specialMeasures = getSpecialMeasures(), - dataFrame = data[eq] || {}; + specialMeasures = getSpecialMeasures(); specialMeasures.w = thisData.w; @@ -2756,7 +2822,8 @@ fotoramaVersion = '4.6.4'; if (!frameAppend[type]) { var thumbsFLAG = type === 'nav' && o_navThumbs, - left = 0; + left = 0, + top = 0; $shaft.append( $frames @@ -2787,13 +2854,16 @@ fotoramaVersion = '4.6.4'; var $this = $(this), frameData = $this.data(), - thumbwidth = Math.round(o_thumbSide2 * frameData.data.thumbratio) || o_thumbSide; - + 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; }) ); @@ -2830,29 +2900,43 @@ fotoramaVersion = '4.6.4'; function getNavFrameBounds($navFrame) { var navFrameData = $navFrame.data(), left, - width; + 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(); } - return { + 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: navFrameData.l, - width: navFrameData.w + pos: (opts.navdir === 'vertical' ? navFrameData.t : navFrameData.l), + width: navFrameData.w, + height: navFrameData.h, + direction: opts.navdir }); } @@ -2861,19 +2945,22 @@ fotoramaVersion = '4.6.4'; if ($guessNavFrame) { var overflowFLAG = navShaftTouchTail.min !== navShaftTouchTail.max, minMax = options.minMax || overflowFLAG && getNavFrameBounds(activeFrame[navFrameKey]), - l = overflowFLAG && (options.keep && slideNavShaft.l ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max)), + 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), time = options.time * 1.1; slide($navShaft, { time: time, pos: pos || 0, + direction: opts.navdir, onEnd: function () { thumbsDraw(pos, true); } }); - setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max)); + setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max, opts.navdir)); slideNavShaft.l = l; } } @@ -3120,8 +3207,7 @@ fotoramaVersion = '4.6.4'; pos: -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex), overPos: overPos, time: time, - onEnd: onEnd/*, - _001: true*/ + onEnd: onEnd }); } else { var $activeFrame = activeFrame[STAGE_FRAME_KEY], @@ -3264,11 +3350,11 @@ fotoramaVersion = '4.6.4'; if (measureIsValid(width)) { $stage.css({width: ''}); $stage.css({height: ''}); + $stage.css({'line-height': ''}); $stageShaft.css({width: ''}); $stageShaft.css({height: ''}); $nav.css({width: ''}); $nav.css({height: ''}); - $stage.css({'line-height': ''}); $wrap.css({minWidth: measures.minwidth || 0, maxWidth: measures.maxwidth || MAX_WIDTH}); width = measures.W = measures.w = $wrap.width(); @@ -3283,16 +3369,35 @@ fotoramaVersion = '4.6.4'; 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, 'line-height': height + 'px'}); - stageShaftReposition(); - if (o_nav) { - $nav - .stop() - .animate({width: measures.nw}, time); + switch (opts.navdir) { + case 'vertical': + $navWrap.removeClass(navShaftHorisontalClass); + $navWrap.removeClass(navShaftListClass); + $navWrap.addClass(navShaftVerticalClass); + $nav + .stop() + .animate({height: measures.h, width: opts.thumbwidth}, time); + break; + case 'list': + $navWrap.removeClass(navShaftVerticalClass); + $navWrap.removeClass(navShaftHorisontalClass); + $navWrap.addClass(navShaftListClass); + //console.warn("List not implemented"); + break; + default: + $navWrap.removeClass(navShaftVerticalClass); + $navWrap.removeClass(navShaftListClass); + $navWrap.addClass(navShaftHorisontalClass); + $nav + .stop() + .animate({width: measures.nw}, time); + break; + } + stageShaftReposition(); slideNavShaft({guessIndex: activeIndex, time: time, keep: true}); if (o_navThumbs && frameAppend.nav) slideThumbBorder(time); } @@ -3304,6 +3409,7 @@ fotoramaVersion = '4.6.4'; } stageLeft = $stage.offset().left; + setStagePosition(); return this; }; @@ -3322,6 +3428,7 @@ fotoramaVersion = '4.6.4'; function setShadow($el, edge) { if (o_shadows) { $el.removeClass(shadowsLeftClass + ' ' + shadowsRightClass); + $el.removeClass(shadowsTopClass + ' ' + shadowsBottomClass); edge && !$videoPlaying && $el.addClass(edge.replace(/^|\s/g, ' ' + shadowsClass + '--')); } } @@ -3492,7 +3599,9 @@ fotoramaVersion = '4.6.4'; timeHigh: 1, friction: 2, select: '.' + selectClass + ', .' + selectClass + ' *', - $wrap: $stage + $wrap: $stage, + direction: 'horizontal' + }); navShaftTouchTail = moveOnTouch($navShaft, { @@ -3519,10 +3628,11 @@ fotoramaVersion = '4.6.4'; 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)); + o_shadows && setShadow($nav, findShadowEdge(result.newPos, navShaftTouchTail.min, navShaftTouchTail.max, result.dir)); } else { onEnd(); } @@ -3530,7 +3640,8 @@ fotoramaVersion = '4.6.4'; timeLow: .5, timeHigh: 2, friction: 5, - $wrap: $nav + $wrap: $nav, + direction: opts.navdir }); stageWheelTail = wheel($stage, { @@ -3547,8 +3658,8 @@ fotoramaVersion = '4.6.4'; onTouchStart(); onTouchEnd(); var newPos = stop($navShaft) + direction * .25; - $navShaft.css(getTranslate(minMaxLimit(newPos, navShaftTouchTail.min, navShaftTouchTail.max))); - o_shadows && setShadow($nav, findShadowEdge(newPos, navShaftTouchTail.min, navShaftTouchTail.max)); + $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 () { @@ -3567,7 +3678,7 @@ fotoramaVersion = '4.6.4'; }, 0); }, function () { - //console.log("click"); + ////console.log("click"); if (!hoverFLAG) return; toggleControlsClass(!(hoverFLAG = false)); } @@ -3676,8 +3787,6 @@ fotoramaVersion = '4.6.4'; reset(); }; - - $.fn.fotorama = function (opts) { return this.each(function () { var that = this, @@ -3730,7 +3839,7 @@ fotoramaVersion = '4.6.4'; $.Fotorama.jst.dots = function(v) { var __t, __p = '', __e = _.escape; - __p += '
\r\n
\r\n
'; + __p += '
\r\n
\r\n
'; return __p }; diff --git a/lib/web/mage/gallery/gallery.html b/lib/web/mage/gallery/gallery.html index 69a196d86c6df..473d784d22c05 100644 --- a/lib/web/mage/gallery/gallery.html +++ b/lib/web/mage/gallery/gallery.html @@ -17,6 +17,8 @@
+
+
@@ -28,4 +30,4 @@
-
+
diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index ed4e12dde1f29..b66c45363e4fd 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -34,6 +34,8 @@ define([ * @param {String} element - String selector of gallery DOM element. */ initialize: function (config, element) { + var fullscreenData = []; + this._super(); config.options.swipe = true; @@ -43,14 +45,24 @@ define([ $element: $(element), currentConfig: config, defaultConfig: _.clone(config), - fullscreenConfig: _.clone(config.allowfullscreen), + fullscreenConfig: _.clone(config.fullscreen), breakpoints: config.breakpoints, activeBreakpoint: {}, fotoramaApi: null, isFullscreen: false, - api: null + api: null, + data: _.clone(config.data), + fullscreenData: [] }; + _.each(_.clone(this.settings.data), function (item) { + fullscreenData.push({ + img: item.original, + thumb: item.thumb + }); + }); + this.settings.fullscreenData = fullscreenData; + config.options.ratio = config.options.width / config.options.height; config.options.height = null; @@ -66,17 +78,20 @@ define([ * Gallery fullscreen settings. */ initFullscreenSettings: function () { - var settings = this.settings; + var settings = this.settings, + items = []; settings.fullscreenConfig.swipe = false; settings.$element.on('fotorama:fullscreenenter', function () { + settings.api.updateOptions(settings.defaultConfig.options, true); settings.api.updateOptions(settings.fullscreenConfig, true); if (!_.isEqual(settings.activeBreakpoint, {})) { settings.api.updateOptions(settings.activeBreakpoint.options, true); } + settings.api.updateData(_.clone(settings.fullscreenData)); settings.isFullscreen = true; }); @@ -86,6 +101,7 @@ define([ if (!_.isEqual(settings.activeBreakpoint, {})) { settings.api.updateOptions(settings.activeBreakpoint.options, true); } + settings.api.updateData(_.clone(settings.data)); settings.isFullscreen = false; }); }, diff --git a/lib/web/mage/gallery/gallery.less b/lib/web/mage/gallery/gallery.less index 1f7eac04d2d53..195dd5dec43b9 100644 --- a/lib/web/mage/gallery/gallery.less +++ b/lib/web/mage/gallery/gallery.less @@ -6,7 +6,6 @@ @fotorama-duration-time: 0.3s; @fotorama-arw-size: 95px; @fotorama_close_size: 30px; -@fotorama_fullscreen_button: 32px; @size-fotorama-block: 50px; @import '../../css/source/lib/_lib.less'; // Global lib @@ -21,22 +20,21 @@ } .translateX(@value) { + -webkit-transform: translateX(@value); -ms-transform: translateX(@value); -o-transform: translateX(@value); - -webkit-transform: translateX(@value); transform: translateX(@value); } .translateY(@value) { + -webkit-transform: translateY(@value); -ms-transform: translateY(@value); -o-transform: translateY(@value); - -webkit-transform: translateY(@value); transform: translateY(@value); } -.translate3d(@x, @y, @z) { - -webkit-transform: translate3d(@x, @y, @z); - transform: translate3d(@x, @y, @z); +.fotorama-shadow-gradient(@x, @y) { + background-image: linear-gradient(transparent, rgba(0, 0, 0, 0.2) 25%, rgba(0, 0, 0, 0.3) 75%, transparent), radial-gradient(farthest-side at @x @y, rgba(0, 0, 0, 0.4), transparent); } .fotorama-inline-block(@va: middle) { @@ -48,6 +46,86 @@ vertical-align: @va; } +.fotorama__zoom-in, +.fotorama__zoom-out { + display: none; +} +.fotorama__fullscreen { + .fotorama__zoom-in, + .fotorama__zoom-out { + position: absolute; + width: 50px; + height: 50px; + display: block; + margin-left: 20px; + } + .fotorama__zoom-out { + top: 51px; + &:extend(.fotorama-sprite); + background-position: 0 (-@size-fotorama-block) !important; + } + + .fotorama__zoom-in { + top: 0; + &:extend(.fotorama-sprite); + background-position: 0 0 !important; + } +} + +.fotorama__zoom-in, +.fotorama__zoom-out { + display: none; +} +.fotorama__fullscreen { + .fotorama__zoom-in, + .fotorama__zoom-out { + position: absolute; + width: 50px; + height: 50px; + display: block; + margin-left: 20px; + cursor: pointer; + } + .fotorama__zoom-out { + top: 51px; + &:extend(.fotorama-sprite); + background-position: 0 (-@size-fotorama-block) !important; + } + + .fotorama__zoom-in { + top: 0; + &:extend(.fotorama-sprite); + background-position: 0 0 !important; + } +} + +.fotorama__zoom-in, +.fotorama__zoom-out { + display: none; +} +.fotorama__fullscreen { + .fotorama__zoom-in, + .fotorama__zoom-out { + position: absolute; + width: 50px; + height: 50px; + display: block; + margin-left: 20px; + cursor: pointer; + } + .fotorama__zoom-out { + top: 51px; + &:extend(.fotorama-sprite); + background-position: 0 (-@size-fotorama-block) !important; + } + + .fotorama__zoom-in { + top: 0; + &:extend(.fotorama-sprite); + background-position: 0 0 !important; + } +} + .fotorama-stretch { bottom: 0; height: 100%; @@ -682,7 +760,7 @@ } .fotorama__wrap--css3 & { - .translate3d(@fotorama-arw-size, -@fotorama-arw-size, 0); + .fotorama-translate3d(@fotorama-arw-size, -@fotorama-arw-size, 0); } .fotorama__wrap--video & { @@ -707,6 +785,60 @@ } } +.fotorama__wrap--toggle-arrows { + &:not(.fotorama__wrap--video) { + .fotorama__video-close { + display: none; + } + } +} + +.fotorama__wrap--toggle-arrows { + &.fotorama__wrap--video { + .fotorama__video-close { + top: 97px; + right: 93px; + opacity: 1; + } + } +} + +.fotorama__wrap--toggle-arrows { + &:not(.fotorama__wrap--video) { + .fotorama__video-close { + display: none; + } + } +} + +.fotorama__wrap--toggle-arrows { + &.fotorama__wrap--video { + .fotorama__video-close { + top: 97px; + right: 93px; + opacity: 1; + } + } +} + +.fotorama__wrap--toggle-arrows { + &:not(.fotorama__wrap--video) { + .fotorama__video-close { + display: none; + } + } +} + +.fotorama__wrap--toggle-arrows { + &.fotorama__wrap--video { + .fotorama__video-close { + top: 97px; + right: 93px; + opacity: 1; + } + } +} + .fotorama__wrap--video { .fotorama__arr, .fotorama__fullscreen-icon { @@ -735,24 +867,24 @@ .fotorama__wrap--css3 { &.fotorama__wrap--no-controls.fotorama__wrap--slide.fotorama__wrap--toggle-arrows { .fotorama__fullscreen-icon:not(:focus) { - .translate3d(@fotorama-arw-size, -@fotorama-arw-size, 0); + .fotorama-translate3d(@fotorama-arw-size, -@fotorama-arw-size, 0); } .fotorama__arr--prev:not(:focus) { - .translate3d(-@fotorama-arw-size * 1.5, 0, 0); + .fotorama-translate3d(-@fotorama-arw-size * 1.5, 0, 0); } .fotorama__arr--next:not(:focus) { - .translate3d(@fotorama-arw-size * 1.5, 0, 0); + .fotorama-translate3d(@fotorama-arw-size * 1.5, 0, 0); } } &.fotorama__wrap--video { .fotorama__fullscreen-icon { - .translate3d(@fotorama-arw-size, -@fotorama-arw-size, 0) !important; + .fotorama-translate3d(@fotorama-arw-size, -@fotorama-arw-size, 0) !important; } .fotorama__arr--prev { - .translate3d(-@fotorama-arw-size * 1.5, 0, 0) !important; + .fotorama-translate3d(-@fotorama-arw-size * 1.5, 0, 0) !important; } .fotorama__arr--next { - .translate3d(@fotorama-arw-size * 1.5, 0, 0) !important; + .fotorama-translate3d(@fotorama-arw-size * 1.5, 0, 0) !important; } } } @@ -773,34 +905,59 @@ &:after { &:extend(.fotorama-gpu); background-repeat: no-repeat; - background-size: 1px 100%, 5px 100%; - bottom: 0; content: ''; display: block; - height: auto; pointer-events: none; position: absolute; text-decoration: none; - top: 0; - width: 10px; z-index: 10; } &:before { - background-image: linear-gradient(transparent, rgba(0, 0, 0, 0.2) 25%, rgba(0, 0, 0, 0.3) 75%, transparent), radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, 0.4), transparent); - background-position: 0 0, 0 0; left: -10px; - } - &.fotorama__shadows--left:before { - left: 0; + top: -10px; } &:after { - background-image: linear-gradient(transparent, rgba(0, 0, 0, 0.2) 25%, rgba(0, 0, 0, 0.3) 75%, transparent), radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.4), transparent); - background-position: 100% 0, 100% 0; right: -10px; + bottom: -10px; } + &.fotorama__shadows--left:before, &.fotorama__shadows--right:after { + top: 0; + bottom: 0; + background-size: 1px 100%, 5px 100%; + height: auto; + width: 10px; + } + &.fotorama__shadows--top:before, + &.fotorama__shadows--bottom:after { + left: 0; + right:0; + background-size: 100% 1px, 100% 5px ; + height:10px; + width:auto; + } + &.fotorama__shadows--left:before { + .fotorama-shadow-gradient(0, 50%); + background-position: 0 0, 0 0; + left: 0; + } + + &.fotorama__shadows--right:after { + .fotorama-shadow-gradient(100%, 50%); + background-position: 100% 0, 100% 0; right: 0; } + &.fotorama__shadows--top:before { + .fotorama-shadow-gradient(50%, 0); + background-position: 0 0, 0 0; + top:0; + + } + &.fotorama__shadows--bottom:after { + .fotorama-shadow-gradient(50%, 100%); + background-position: 0 100%, 0 100%; + bottom:0; + } } .fotorama--fullscreen .fotorama__stage, @@ -897,21 +1054,6 @@ } } -.fotorama--fullscreen { - .fotorama__stage__frame { - .fotorama__img { - position: absolute; - max-width: inherit; - max-height: inherit; - margin: auto; - top: 0px; - bottom: 0px; - left: 0px; - right: 0px; - } - } -} - .fotorama__stage__frame { text-align: center; .fotorama__img { @@ -930,3 +1072,105 @@ .magnify-hidden { display: none; } + +.fotorama__nav-wrap--vertical { + &.fotorama__nav-wrap { + display: inline-block; + position: absolute; + top: 0; + left: 0; + } + + .fotorama__nav__shaft { + width: 100%; + background-color: white; + .fotorama__nav__frame--thumb { + display: block; + padding-bottom: inherit !important; + } + } +} + +.fotorama--fullscreen { + .fotorama__stage__frame { + .fotorama__img { + position: absolute; + max-width: inherit; + max-height: inherit; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + } +} + + +.fotorama__nav-wrap--vertical { + &.fotorama__nav-wrap { + display: inline-block; + position: absolute; + top: 0; + left: 0; + } + + .fotorama__nav__shaft { + width: 100%; + background-color: white; + .fotorama__nav__frame--thumb { + display: block; + padding-bottom: inherit !important; + } + } +} + +.fotorama--fullscreen { + .fotorama__stage__frame { + .fotorama__img { + position: absolute; + max-width: inherit; + max-height: inherit; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + } +} + + +.fotorama__nav-wrap--vertical { + &.fotorama__nav-wrap { + display: inline-block; + position: absolute; + top: 0; + left: 0; + } + + .fotorama__nav__shaft { + width: 100%; + background-color: white; + .fotorama__nav__frame--thumb { + display: block; + padding-bottom: inherit !important; + } + } +} + +.fotorama--fullscreen { + .fotorama__stage__frame { + .fotorama__img { + position: absolute; + max-width: inherit; + max-height: inherit; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + } +} + diff --git a/lib/web/magnifier/magnifier.js b/lib/web/magnifier/magnifier.js index acfd548bccadd..6a9f279d9e5af 100644 --- a/lib/web/magnifier/magnifier.js +++ b/lib/web/magnifier/magnifier.js @@ -719,8 +719,62 @@ _init($box, gOptions); }); + function zoomIn(e) { + var $image = $('[data-gallery-role="stage-shaft"] [data-active="true"] img'), + gallery = $('[data-gallery-role="gallery"]'), + imgOriginalSize = getImageSize($image[0].src), + setedResult = Math.round($image.width() + 10); + e.preventDefault(); + + if (setedResult >imgOriginalSize.rw) { + setedResult = imgOriginalSize.rw; + } + $image.css('width', setedResult); + } + + function zoomOut(e) { + var $image = $('[data-gallery-role="stage-shaft"] [data-active="true"] img'), + gallery = $('[data-gallery-role="gallery"]'), + imgOriginalSize = getImageSize($image[0].src), + setedResult = Math.round($image.width() - 10); + e.preventDefault(); + + if (setedResult < imgOriginalSize.rw/2) { + setedResult = imgOriginalSize.rw/2; + } + $image.css('width', setedResult); + } + + /** + * Return width and height of original image + * @param src path for original image + * @returns {{rw: number, rh: number}} + */ + function getImageSize(src) { + var img = new Image(), + imgSize = { + rw: 0, + rh: 0 + }; + img.src = src; + imgSize.rw = img.width; + imgSize.rh = img.height; + return imgSize; + } + + + function setEventOnce() { + $('.fotorama__zoom-in') + .off('click', zoomIn) + .on('click', zoomIn); + $('.fotorama__zoom-out') + .off('click', zoomOut) + .on('click', zoomOut); + } + $(document).on('mousemove', onMousemove); _init($box, gOptions); magnifierFullscreen(); + setEventOnce(); } }(jQuery)); diff --git a/lib/web/magnifier/magnify.js b/lib/web/magnifier/magnify.js index d6f7c9931f374..3544ad6b6c316 100644 --- a/lib/web/magnifier/magnify.js +++ b/lib/web/magnifier/magnify.js @@ -84,7 +84,8 @@ define([ config.magnifierOpts.original = fotorama.data[fotorama.activeIndex].original; $($(gallerySelector).data('fotorama').activeFrame.$stageFrame).magnify(config.magnifierOpts); }); - $(element).on('fotorama:show', function () { + $(element).on('fotorama:show fotorama:fullscreenenter ', function () { + console.log('AAAAAA') hideMagnifier(); }); From 5ef22a8584e22279258a59cbc534c0370b207608 Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Tue, 15 Sep 2015 18:41:22 +0300 Subject: [PATCH 010/116] JS-52: Zoom on Full Screen Mode --- .../templates/product/view/gallery.phtml | 10 +- .../frontend/Magento/blank/etc/view.xml | 5 +- app/design/frontend/Magento/luma/etc/view.xml | 2 + lib/web/fotorama/fotorama.js | 51 ++++++-- lib/web/mage/gallery/gallery.js | 16 +-- lib/web/mage/gallery/gallery.less | 68 +--------- lib/web/magnifier/magnifier.js | 116 +++++++++++++++--- lib/web/magnifier/magnify.js | 3 +- 8 files changed, 158 insertions(+), 113 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 7bf679228f998..2c598b2f5e49b 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -22,7 +22,8 @@ "width": "getVar("magnifier:width"); ?>", "height": "getVar("magnifier:height"); ?>", "top": "getVar("magnifier:top"); ?>", - "left": "getVar("magnifier:left"); ?>" + "left": "getVar("magnifier:left"); ?>", + "inc": "getVar("magnifier:fullscreenzoom"); ?>" }, "data": getGalleryImagesJson(); ?>, "options": { @@ -30,11 +31,13 @@ "loop": getVar("gallery:loop"); ?>, "keyboard": getVar("gallery:keyboard"); ?>, "navdir": "getVar("gallery:navdir"); ?>", + "arrows": getVar("gallery:arrows"); ?>, "allowfullscreen": getVar("gallery:allowfullscreen"); ?>, "showCaption": getVar("gallery:caption"); ?>, "width": getImageAttribute('product_page_image_medium', 'width'); ?>, - "thumbwidth": 120, - "thumbheight": 90, + "thumbwidth": getImageAttribute('product_page_image_small', 'width'); ?>, + "thumbheight": getImageAttribute('product_page_image_small', 'height') + ?: $block->getImageAttribute('product_page_image_small', 'width'); ?>, "height": getImageAttribute('product_page_image_medium', 'height') ?: $block->getImageAttribute('product_page_image_medium', 'width'); ?>, "transitionduration": getVar("gallery:transition:duration"); ?>, @@ -43,6 +46,7 @@ "fullscreen": { "nav": "getVar("gallery:fullscreen:navigation"); ?>", "loop": getVar("gallery:fullscreen:loop"); ?>, + "navdir": "getVar("gallery:fullscreen:navdir"); ?>", "arrows": getVar("gallery:fullscreen:arrows"); ?>, "showCaption": getVar("gallery:fullscreen:caption"); ?>, "transitionduration": getVar("gallery:fullscreen:transition:duration"); ?>, diff --git a/app/design/frontend/Magento/blank/etc/view.xml b/app/design/frontend/Magento/blank/etc/view.xml index 93815d880aad0..14f7695e7b3d5 100644 --- a/app/design/frontend/Magento/blank/etc/view.xml +++ b/app/design/frontend/Magento/blank/etc/view.xml @@ -181,7 +181,7 @@ thumbs - true + false true true false @@ -192,11 +192,14 @@ thumbs false + true null null + horizontal crossfade 500 + 20 diff --git a/app/design/frontend/Magento/luma/etc/view.xml b/app/design/frontend/Magento/luma/etc/view.xml index b5f49bfde17f3..b2d2d21ad4dc9 100644 --- a/app/design/frontend/Magento/luma/etc/view.xml +++ b/app/design/frontend/Magento/luma/etc/view.xml @@ -199,9 +199,11 @@ true false false + horizontal dissolve 500 + 5 diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index d7f64c62bc116..453597325f4ab 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -2202,11 +2202,13 @@ fotoramaVersion = '4.6.4'; $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', ''); } @@ -2319,7 +2321,7 @@ fotoramaVersion = '4.6.4'; * Options on the fly * */ function setOptions() { - if (opts.nav === 'dots') { + if (!opts.nav || opts.nav === 'dots') { opts.navdir = 'horizontal' } @@ -2787,14 +2789,20 @@ fotoramaVersion = '4.6.4'; } function thumbsDraw(pos, loadFLAG) { - if (opts.navdir === 'vertical') { - pos = pos - opts.thumbheight; - } + var leftLimit, + rightLimit, + exceedLimit; + if (o_nav !== 'thumbs' || isNaN(pos)) return; - var leftLimit = -pos, - rightLimit = -pos + measures.nw; + leftLimit = -pos; + rightLimit = -pos + measures.nw; + + if (opts.navdir === 'vertical') { + pos = pos - opts.thumbheight; + rightLimit = -pos + measures.h; + } $navThumbFrame.each(function () { var $this = $(this), @@ -2806,12 +2814,13 @@ fotoramaVersion = '4.6.4'; w: thisData.w } }, - specialMeasures = getSpecialMeasures(); - - specialMeasures.w = thisData.w; + specialMeasures = getSpecialMeasures(), + exceedLimit = opts.navdir === 'vertical' ? + thisData.t > rightLimit : thisData.l > rightLimit; + specialMeasures.w = thisData.w; if (thisData.l + thisData.w < leftLimit - || thisData.l > rightLimit + || exceedLimit || callFit(thisData.$img, specialMeasures)) return; loadFLAG && loadImg([eq], 'navThumb', getSpecialMeasures); @@ -3334,10 +3343,10 @@ fotoramaVersion = '4.6.4'; setFLAG = arguments[2]; extendMeasures(!that.fullScreen ? optionsToLowerCase(options) : { - width: '100%', + width: $(window).width(), maxwidth: null, minwidth: null, - height: '100%', + height: $(window).height(), maxheight: null, minheight: null }, [measures, setFLAG || that.fullScreen || opts]); @@ -3348,6 +3357,8 @@ fotoramaVersion = '4.6.4'; windowHeight = $WINDOW.height() - (o_nav ? $nav.height() : 0); if (measureIsValid(width)) { + $wrap.css({width: ''}); + $wrap.css({height: ''}); $stage.css({width: ''}); $stage.css({height: ''}); $stage.css({'line-height': ''}); @@ -3371,6 +3382,22 @@ fotoramaVersion = '4.6.4'; height = measures.h = Math.round(minMaxLimit(height, numberFromWhatever(measures.minheight, windowHeight), numberFromWhatever(measures.maxheight, windowHeight))); $stage.css({'width': width, 'height': height, 'line-height': height + 'px'}); + 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 (opts.navdir === 'vertical' && that.fullScreen) { + $stage.css('height', $(window).height()); + } + + if (opts.navdir === 'horizontal' && that.fullScreen) { + $stage.css('height', $(window).height() - (opts.thumbheight + opts.thumbmargin * 2)); + } + if (o_nav) { switch (opts.navdir) { case 'vertical': diff --git a/lib/web/mage/gallery/gallery.js b/lib/web/mage/gallery/gallery.js index b66c45363e4fd..78c5b4b91a8d0 100644 --- a/lib/web/mage/gallery/gallery.js +++ b/lib/web/mage/gallery/gallery.js @@ -172,7 +172,6 @@ define([ * Is triggered when breakpoint enties. */ entry: function () { - triggeredBreakpoints++; $.extend(true, config, _.clone(startConfig)); settings.api.updateOptions(settings.defaultConfig.options, true); @@ -189,16 +188,13 @@ define([ * Is triggered when breakpoint exits. */ exit: function () { - if (triggeredBreakpoints < 1) { - $.extend(true, config, _.clone(startConfig)); - settings.api.updateOptions(settings.defaultConfig.options, true); - - if (settings.isFullscreen) { - settings.api.updateOptions(settings.fullscreenConfig, true); - } - settings.activeBreakpoint = {}; + $.extend(true, config, _.clone(startConfig)); + settings.api.updateOptions(settings.defaultConfig.options, true); + + if (settings.isFullscreen) { + settings.api.updateOptions(settings.fullscreenConfig, true); } - triggeredBreakpoints--; + settings.activeBreakpoint = {}; } }); }); diff --git a/lib/web/mage/gallery/gallery.less b/lib/web/mage/gallery/gallery.less index 195dd5dec43b9..05fb94cd6aae1 100644 --- a/lib/web/mage/gallery/gallery.less +++ b/lib/web/mage/gallery/gallery.less @@ -1058,6 +1058,7 @@ text-align: center; .fotorama__img { height: auto; + width: auto; max-height: 100%; max-width: 100%; vertical-align: middle; @@ -1102,75 +1103,12 @@ bottom: 0; left: 0; right: 0; - } - } -} - -.fotorama__nav-wrap--vertical { - &.fotorama__nav-wrap { - display: inline-block; - position: absolute; - top: 0; - left: 0; - } - - .fotorama__nav__shaft { - width: 100%; - background-color: white; - .fotorama__nav__frame--thumb { - display: block; - padding-bottom: inherit !important; - } - } -} - -.fotorama--fullscreen { - .fotorama__stage__frame { - .fotorama__img { - position: absolute; - max-width: inherit; - max-height: inherit; - margin: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; } - } -} - -.fotorama__nav-wrap--vertical { - &.fotorama__nav-wrap { - display: inline-block; - position: absolute; - top: 0; - left: 0; - } - - .fotorama__nav__shaft { - width: 100%; - background-color: white; - .fotorama__nav__frame--thumb { - display: block; - padding-bottom: inherit !important; - } } } -.fotorama--fullscreen { - .fotorama__stage__frame { - .fotorama__img { - position: absolute; - max-width: inherit; - max-height: inherit; - margin: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - } - } +body.fotorama__fullscreen { + overflow-y: hidden; } - diff --git a/lib/web/magnifier/magnifier.js b/lib/web/magnifier/magnifier.js index 6a9f279d9e5af..294d1b4c65113 100644 --- a/lib/web/magnifier/magnifier.js +++ b/lib/web/magnifier/magnifier.js @@ -187,7 +187,7 @@ data[idx].lensH = data[idx].lensH > $thumb.height() ? $thumb.height() : data[idx].lensH; lens.css({ width: data[idx].lensW + 1 + 'px', - height: data[idx].lensH + 'px' + height: data[idx].lensH + 0.5 + 'px' }); } @@ -301,8 +301,8 @@ pos.l = pos.l <= 0 ? 0 : pos.l; //pos.l = pos.l > 0 ? pos.l : pos.l; curLens.css({ - left: pos.l + paddingX + 'px', - top: pos.t + paddingY + 'px' + left: pos.l + paddingX +'px', + top: pos.t + paddingY + 1.75 + 'px' }); if (lensbg) { @@ -587,7 +587,7 @@ touch, isTouchEnabled = 'ontouchstart' in document.documentElement; - $('[data-gallery-role="gallery"]').on('fotorama:fullscreenenter fotorama:showend fotorama:load', function () { + $('[data-gallery-role="gallery"]').on('fotorama:fullscreenenter fotorama:showend fotorama:load fotorama:ready', function () { var $image = $('[data-gallery-role="stage-shaft"] [data-active="true"] img'), $imageContainer = $image.parent(), @@ -600,7 +600,32 @@ }); }); - $image.on(isTouchEnabled ? 'touchstart' : 'mousedown', function (e) { + if (gallery.data('fotorama').fullScreen) { + + $('.fotorama__stage__frame .fotorama__img').each(function () { + var image = new Image(); + image.src = $(this).attr("src"); + + if ( (image.height > $(this).parent().height()) || (image.width > $(this).parent().width()) ) { + + if (image.height / image.width < $(this).parent().height() / $(this).parent().width()) { + $(this).width($(this).parent().width()); + $(this).height('auto'); + } else { + $(this).height($(this).parent().height()); + $(this).width('auto'); + } + + $(this).css({ + 'top': '', + 'left': '' + }); + } + + }); + } + + $image.on(isTouchEnabled ? 'touchstart' : 'pointerdown mousedown MSPointerDow', function (e) { if (gallery.data('fotorama').fullScreen) { e.preventDefault(); @@ -613,18 +638,23 @@ e.clientX = touch.pageX; e.clientY = touch.pageY; } - startX = e.clientX; - startY = e.clientY; + startX = e.clientX || e.originalEvent.clientX; + startY = e.clientY || e.originalEvent.clientY; isDragActive = true; } }); - $image.on(isTouchEnabled ? 'touchmove' : 'mousemove', function (e) { + + + $image.on(isTouchEnabled ? 'touchmove' : 'mousemove pointermove MSPointerMove', function (e) { if (gallery.data('fotorama').fullScreen && isDragActive) { var top, left, - startOffset = $image.offset(); + startOffset = $image.offset(), + clientX = e.clientX || e.originalEvent.clientX, + clientY = e.clientY || e.originalEvent.clientY; + e.preventDefault(); @@ -633,8 +663,8 @@ e.clientX = touch.pageX; e.clientY = touch.pageY; } - top = +imagePosY + (e.clientY - startY); - left = +imagePosX + (e.clientX - startX); + top = +imagePosY + (clientY - startY); + left = +imagePosX + (clientX - startX); if ($image.height() > $imageContainer.height()) { @@ -653,7 +683,7 @@ if (($imageContainer.offset().left + $imageContainer.width()) > (left + $image.width())) { left = $imageContainer.offset().left + $imageContainer.width() - $image.width(); } else { - left = ($imageContainer.offset().left < left) ? 0 : left; + left = ($imageContainer.offset().left < left) ? $imageContainer.offset().left : left; } $image.offset({ 'left': left @@ -662,7 +692,7 @@ } }); - $image.on(isTouchEnabled ? 'touchend' : 'mouseup', function (e) { + $image.on(isTouchEnabled ? 'touchend' : 'mouseup pointerup MSPointerUp', function (e) { if (gallery.data('fotorama').fullScreen) { isDragActive = false; $image.css('cursor', 'pointer'); @@ -678,9 +708,51 @@ } } + if ($('.fotorama-item').data('fotorama').fullScreen) { + $('.fotorama__stage__frame .fotorama__img').each(function () { + var image = new Image(); + image.src = $(this).attr("src"); + + if ( (image.height > $(this).parent().height()) || (image.width > $(this).parent().width()) ) { + + if (image.height / image.width < $(this).parent().height() / $(this).parent().width()) { + $(this).width($(this).parent().width()); + $(this).height(''); + } else { + $(this).height($(this).parent().height()); + $(this).width(''); + } + } + }); + } + $(window).on('scroll', onScroll); $(window).resize(function() { + if ($('.fotorama-item').data('fotorama').fullScreen) { + $('.fotorama__stage__frame .fotorama__img').each(function () { + var image = new Image(); + image.src = $(this).attr("src"); + + if ( (image.height > $(this).parent().height()) || (image.width > $(this).parent().width()) ) { + + if (image.height / image.width < $(this).parent().height() / $(this).parent().width()) { + $(this).width($(this).parent().width()); + $(this).height(''); + } else { + $(this).height($(this).parent().height()); + $(this).width(''); + } + } + }); + } + + + _init($box, gOptions); + + }); + + function checkFullscreenImagePosition() { if ($('[data-gallery-role="gallery"]').data('fotorama').fullScreen) { var $image = $('[data-gallery-role="stage-shaft"] > [data-active="true"] > img'), @@ -715,10 +787,8 @@ $image.css('top', ''); } } + } - _init($box, gOptions); - - }); function zoomIn(e) { var $image = $('[data-gallery-role="stage-shaft"] [data-active="true"] img'), gallery = $('[data-gallery-role="gallery"]'), @@ -729,7 +799,8 @@ if (setedResult >imgOriginalSize.rw) { setedResult = imgOriginalSize.rw; } - $image.css('width', setedResult); + $image.css({'width': setedResult, height: 'auto'}); + checkFullscreenImagePosition(); } function zoomOut(e) { @@ -737,12 +808,15 @@ gallery = $('[data-gallery-role="gallery"]'), imgOriginalSize = getImageSize($image[0].src), setedResult = Math.round($image.width() - 10); - e.preventDefault(); + if(e) { + e.preventDefault(); + } if (setedResult < imgOriginalSize.rw/2) { setedResult = imgOriginalSize.rw/2; } - $image.css('width', setedResult); + $image.css({'width': setedResult, height: 'auto'}); + checkFullscreenImagePosition(); } /** @@ -774,7 +848,9 @@ $(document).on('mousemove', onMousemove); _init($box, gOptions); - magnifierFullscreen(); setEventOnce(); + //checkFullscreenImagePosition(); + magnifierFullscreen(); + } }(jQuery)); diff --git a/lib/web/magnifier/magnify.js b/lib/web/magnifier/magnify.js index 3544ad6b6c316..cd96c0f6328e0 100644 --- a/lib/web/magnifier/magnify.js +++ b/lib/web/magnifier/magnify.js @@ -63,7 +63,7 @@ define([ thumb: '.fotorama__img', largeWrapper: '[data-gallery-role="magnifier"]', height: config.magnifierOpts.height || function () { - return $('[data-active="true"]').width() / config.options.ratio; + return $('[data-active="true"]').height(); }, width: config.magnifierOpts.width || function () { var productMedia = $(gallerySelector).parent().parent(); @@ -85,7 +85,6 @@ define([ $($(gallerySelector).data('fotorama').activeFrame.$stageFrame).magnify(config.magnifierOpts); }); $(element).on('fotorama:show fotorama:fullscreenenter ', function () { - console.log('AAAAAA') hideMagnifier(); }); From d7bfee080c90802b348c94513af6b9d6d6d89a4e Mon Sep 17 00:00:00 2001 From: AnastasiaBuniak Date: Wed, 16 Sep 2015 15:17:27 +0300 Subject: [PATCH 011/116] JS-51: Gallery Widget Configuration and Extension on theme level --- lib/web/fotorama/fotorama.js | 13 ++---- lib/web/magnifier/magnifier.js | 74 ++++++++++++++++------------------ lib/web/magnifier/magnify.js | 2 +- 3 files changed, 40 insertions(+), 49 deletions(-) diff --git a/lib/web/fotorama/fotorama.js b/lib/web/fotorama/fotorama.js index 453597325f4ab..ef45700a3ed05 100644 --- a/lib/web/fotorama/fotorama.js +++ b/lib/web/fotorama/fotorama.js @@ -1035,7 +1035,6 @@ fotoramaVersion = '4.6.4'; obj.transform = 'translate3d(0, ' + (pos) + 'px,0)'; break; case 'list': - //console.warn("transition not implemented"); break; default : obj.transform = 'translate3d(' + (pos) + 'px,0,0)'; @@ -1909,15 +1908,12 @@ fotoramaVersion = '4.6.4'; } function onEnd(result) { - //////console.time('moveontouch.js onEnd'); if (tail.noSwipe && result.moved) return; if (!tracked) { startTracking(result.startEvent, true); } - ////console.log('onEnd'); - result.touch || MS_POINTER || $el.removeClass(grabbingClass); endTime = $.now(); @@ -2294,7 +2290,7 @@ fotoramaVersion = '4.6.4'; data = that.data = data || clone(opts.data) || getDataFromHtml($fotorama); size = that.size = data.length; - !ready.ok && opts.shuffle && shuffle(data); + ready.ok && opts.shuffle && shuffle(data); checkForVideo(); @@ -3412,7 +3408,6 @@ fotoramaVersion = '4.6.4'; $navWrap.removeClass(navShaftVerticalClass); $navWrap.removeClass(navShaftHorisontalClass); $navWrap.addClass(navShaftListClass); - //console.warn("List not implemented"); break; default: $navWrap.removeClass(navShaftVerticalClass); @@ -3431,6 +3426,7 @@ fotoramaVersion = '4.6.4'; measuresSetFLAG = setFLAG || true; + ready.ok = true; ready(); } } @@ -3705,7 +3701,6 @@ fotoramaVersion = '4.6.4'; }, 0); }, function () { - ////console.log("click"); if (!hoverFLAG) return; toggleControlsClass(!(hoverFLAG = false)); } @@ -3806,8 +3801,8 @@ fotoramaVersion = '4.6.4'; }); function ready() { - if (!ready.ok) { - ready.ok = true; + if (ready.ok) { + ready.ok = false; triggerEvent('ready'); } } diff --git a/lib/web/magnifier/magnifier.js b/lib/web/magnifier/magnifier.js index 294d1b4c65113..355321a00f531 100644 --- a/lib/web/magnifier/magnifier.js +++ b/lib/web/magnifier/magnifier.js @@ -116,42 +116,6 @@ _init($box, options); }; - /** - * Delete events and created block for magnify - * - */ - that.destroy = function () { - console.warn("API not implemented."); - }; - - /** - * @todo - */ - that.zoomIn = function () { - console.warn("API not implemented."); - }; - - /** - * @todo - */ - that.zoomOut = function () { - console.warn("API not implemented."); - }; - - /** - * @todo - */ - that.show = function () { - console.warn("API not implemented."); - }; - - /** - * @todo - */ - that.hide = function () { - console.warn("API not implemented."); - }; - function createLens(thumb) { if ($(thumb).siblings('.magnify-lens').length) { return false; @@ -587,8 +551,7 @@ touch, isTouchEnabled = 'ontouchstart' in document.documentElement; - $('[data-gallery-role="gallery"]').on('fotorama:fullscreenenter fotorama:showend fotorama:load fotorama:ready', function () { - + $('[data-gallery-role="gallery"]').on('fotorama:fullscreenenter fotorama:showend fotorama:load', function () { var $image = $('[data-gallery-role="stage-shaft"] [data-active="true"] img'), $imageContainer = $image.parent(), gallery = $('[data-gallery-role="gallery"]'); @@ -849,8 +812,41 @@ $(document).on('mousemove', onMousemove); _init($box, gOptions); setEventOnce(); - //checkFullscreenImagePosition(); magnifierFullscreen(); + $('.fotorama-item').on('fotorama:load', function () { + if (document.querySelector('.fotorama__stage').addEventListener) { + if ('onwheel' in document) { + // IE9+, FF17+, Ch31+ + document.querySelector('.fotorama__stage').addEventListener("wheel", onWheel); + } else if ('onmousewheel' in document) { + + document.querySelector('.fotorama__stage').addEventListener("mousewheel", onWheel); + } else { + // Firefox < 17 + document.querySelector('.fotorama__stage').addEventListener("MozMousePixelScroll", onWheel); + } + } else { // IE8- + document.querySelector('.fotorama__stage').attachEvent("onmousewheel", onWheel); + } + + function onWheel(e) { + if ($('[data-gallery-role="gallery"]').data('fotorama').fullScreen) { + e = e || window.event; + + + var delta = e.deltaY || e.detail || e.wheelDelta; + + if (delta > 0) { + zoomOut(e) + } else { + zoomIn(e) + } + + e.preventDefault ? e.preventDefault() : (e.returnValue = false); + } + } + }) + } }(jQuery)); diff --git a/lib/web/magnifier/magnify.js b/lib/web/magnifier/magnify.js index cd96c0f6328e0..c78f1705517ee 100644 --- a/lib/web/magnifier/magnify.js +++ b/lib/web/magnifier/magnify.js @@ -78,7 +78,7 @@ define([ } }); - $(element).on('fotorama:showend fotorama:load fotorama:fullscreenexit', function (e, fotorama) { + $(element).on('fotorama:showend fotorama:load fotorama:fullscreenexit fotorama:ready', function (e, fotorama) { hideMagnifier(); config.magnifierOpts.large = $(gallerySelector).data('fotorama').activeFrame.img; config.magnifierOpts.original = fotorama.data[fotorama.activeIndex].original; From aefc2f5c952bf679e663f3ef2ab62dfca29ade36 Mon Sep 17 00:00:00 2001 From: Anton Guz Date: Wed, 16 Sep 2015 16:04:33 +0300 Subject: [PATCH 012/116] MAGETWO-42478: Stabialize - --- .../templates/product/view/gallery.phtml | 4 +- .../view/frontend/web/js/configurable.js | 106 +++++++++++------- lib/web/mage/gallery/gallery.js | 34 +++--- 3 files changed, 83 insertions(+), 61 deletions(-) diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml index 9ab7c65ab91f0..e0708dceabb5d 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml @@ -10,10 +10,10 @@ * @var $block \Magento\Catalog\Block\Product\View\Gallery */ ?> - +