JAVASCRIPT   46

zoom.js

Guest on 22nd July 2021 02:12:10 AM

  1. /**
  2.  * Copyright آ© Magento, Inc. All rights reserved.
  3.  * See COPYING.txt for license details.
  4.  */*//**
  5.  * @deprecated since version 2.2.0
  6.  */*/
  7. (function (root, factory) {
  8.     'use strict';
  9.  
  10.     if (typeof define === 'function' && define.amd) {
  11.         define([
  12.             'jquery',
  13.             'mage/template',
  14.             'jquery/ui'
  15.         ], factory);
  16.     } else {
  17.         factory(root.jQuery, root.mageTemplate);
  18.     }
  19. }(this, function ($, mageTemplate) {
  20.     'use strict';
  21.  
  22.     $.widget('mage.zoom', {
  23.         options: {
  24.             largeImage: null,
  25.             startZoomEvent: 'click',
  26.             stopZoomEvent: 'mouseleave',
  27.             hideDelay: '100',
  28.             effects: {
  29.                 show: {
  30.                     effect: 'fade',
  31.                     duration: 100
  32.                 },
  33.                 hide: {
  34.                     effect: 'fade',
  35.                     duration: 100
  36.                 }
  37.             },
  38.             controls: {
  39.                 lens: {
  40.                     template: '[data-template=zoom-lens]',
  41.                     opacity: 0.7,
  42.                     background: '#ffffff'
  43.                 },
  44.                 track: {
  45.                     template: '[data-template=zoom-track]'
  46.                 },
  47.                 display: {
  48.                     template: '[data-template=zoom-display]',
  49.                     width: 400,
  50.                     height: 400,
  51.                     left: 0,
  52.                     top: 0
  53.                 },
  54.                 notice: {
  55.                     template: '[data-template=notice]',
  56.                     text: null,
  57.                     container: '[data-role=gallery-notice-container]'
  58.                 }
  59.             },
  60.             selectors: {
  61.                 image: '[data-role=zoom-image]',
  62.                 imageContainer: '[data-role=gallery-base-image-container]',
  63.                 zoomInner: '[data-role=zoom-inner]',
  64.                 track: '[data-role=zoom-track]',
  65.                 notice: '[data-role=notice]'
  66.             }
  67.         },
  68.         noticeOriginal: '',
  69.  
  70.       /**
  71.          * Widget constructor.
  72.          * @protected
  73.          */*/
  74.         _create: function () {
  75.             this._setZoomData();
  76.             this._render();
  77.             this._bind();
  78.  
  79.             if (this.largeImage[0].complete) {
  80.                 this._largeImageLoaded();
  81.             }
  82.             this._hide(this.display);
  83.             this._hide(this.track);
  84.         },
  85.  
  86.       /**
  87.          * Render zoom controls.
  88.          * @protected
  89.          */*/
  90.         _render: function () {
  91.             var noticeContainer;
  92.  
  93.             this.element.append(this._renderControl('track').append(this._renderControl('lens')));
  94.             this.element.append(this._renderControl('display'))
  95.                 .find(this.options.selectors.zoomInner)
  96.                 .append(this._renderLargeImage());
  97.             noticeContainer = this.element.find(this.options.controls.notice.container);
  98.             noticeContainer = noticeContainer.length ?
  99.                 noticeContainer :
  100.                 this.element;
  101.             noticeContainer.append(this._renderControl('notice'));
  102.         },
  103.  
  104.       /**
  105.          * Toggle zoom notice.
  106.          * @protected
  107.          */*/
  108.         _toggleNotice: function () {
  109.             this.noticeOriginal = this.notice.text() !== this.options.controls.notice.text ?
  110.                 this.notice.text() :
  111.                 this.noticeOriginal;
  112.  
  113.             if (this.getZoomRatio() > 1 && this.largeImageSrc && !this.activated) {
  114.                 this.notice.text(this.options.controls.notice.text);
  115.             } else {
  116.                 this.notice.text(this.noticeOriginal);
  117.             }
  118.         },
  119.  
  120.       /**
  121.          * Render zoom control.
  122.          *
  123.          * @param {String} control - name of the control
  124.          * @return {Element} DOM-element
  125.          * @protected
  126.          */*/
  127.         _renderControl: function (control) {
  128.             var controlData = this.options.controls[control],
  129.                 templateData = {},
  130.                 css = {},
  131.                 controlElement;
  132.  
  133.             switch (control) {
  134.                 case 'display':
  135.                     templateData = {
  136.                         img: this.largeImageSrc
  137.                     };
  138.                     css = {
  139.                         width: controlData.width,
  140.                         height: controlData.height
  141.                     };
  142.                     break;
  143.  
  144.                 case 'notice':
  145.                     templateData = {
  146.                         text: controlData.text || ''
  147.                     };
  148.                     break;
  149.             }
  150.             controlElement = this.element.find(this.options.selectors[control]);
  151.             controlElement = controlElement.length ?
  152.                 controlElement :
  153.                 $(mageTemplate(controlData.template, {
  154.                     data: templateData
  155.                 }));
  156.             this[control] = controlElement.css(css);
  157.  
  158.             return this[control];
  159.         },
  160.  
  161.       /**
  162.          * Refresh zoom controls.
  163.          * @protected
  164.          */*/
  165.         _refresh: function () {
  166.             this._refreshControl('display');
  167.             this._refreshControl('track');
  168.             this._refreshControl('lens');
  169.         },
  170.  
  171.       /**
  172.          * Refresh zoom control position and css.
  173.          *
  174.          * @param {String} control - name of the control
  175.          * @protected
  176.          */*/
  177.         _refreshControl: function (control) {
  178.             var controlData = this.options.controls[control],
  179.                 position,
  180.                 css = {
  181.                     position: 'absolute'
  182.                 };
  183.  
  184.             switch (control) {
  185.                 case 'display':
  186.                     position = {
  187.                         my: 'left+' + this.options.controls.display.left + ' top+' +
  188.                             this.options.controls.display.top + '',
  189.                         at: 'left+' + $(this.image).outerWidth() + ' top',
  190.                         of: $(this.image)
  191.                     };
  192.                     break;
  193.  
  194.                 case 'track':
  195.                     $.extend(css, {
  196.                         height: $(this.image).height(),
  197.                         width: $(this.image).width()
  198.                     });
  199.                     position = {
  200.                         my: 'left top',
  201.                         at: 'left top',
  202.                         of: $(this.image)
  203.                     };
  204.                     break;
  205.  
  206.                 case 'lens':
  207.                     $.extend(css, this._calculateLensSize(), {
  208.                         background: controlData.background,
  209.                         opacity: controlData.opacity,
  210.                         left: 0,
  211.                         top: 0
  212.                     });
  213.                     break;
  214.             }
  215.             this[control].css(css);
  216.  
  217.             if (position) {
  218.                 this[control].position(position);
  219.             }
  220.         },
  221.  
  222.       /**
  223.          * Bind zoom event handlers.
  224.          * @protected
  225.          */*/
  226.         _bind: function () {
  227.           /* Events delegated to this.element, which means that all zoom controls can be changed any time
  228.              *  and not required to re-bind events
  229.              */*/
  230.             var events = {};
  231.  
  232.             events[this.options.startZoomEvent + ' + this.options.selectors.image] = ' 'show';
  233.  
  234.           /** Handler */*/
  235.             events[this.options.stopZoomEvent + ' + this.options.selectors.track] = function () {
  236.                this._delay(this.hide, this.options.hideDelay || 0);
  237.            };
  238.            events['['mousemove ' + this.options.selectors.track] = '_move';
  239.             events.imageupdated = '_onImageUpdated';
  240.             this._on(events);
  241.             this._on(this.largeImage, {
  242.                 load: '_largeImageLoaded'
  243.             });
  244.         },
  245.  
  246.       /**
  247.          * Store initial zoom data.
  248.          * @protected
  249.          */*/
  250.         _setZoomData: function () {
  251.             this.image = this.element.find(this.options.selectors.image);
  252.             this.largeImageSrc = this.options.largeImage ||
  253.                 this.element.find(this.image).data('large');
  254.         },
  255.  
  256.       /**
  257.          * Update zoom when called enable method.
  258.          * @override
  259.          */*/
  260.         enable: function () {
  261.             this._super();
  262.             this._onImageUpdated();
  263.         },
  264.  
  265.       /**
  266.          * Toggle notice when called disable method.
  267.          * @override
  268.          */*/
  269.         disable: function () {
  270.             this.notice.text(this.noticeOriginal || '');
  271.             this._super();
  272.         },
  273.  
  274.       /**
  275.          * Show zoom controls.
  276.          *
  277.          * @param {Object} e - event object
  278.          */*/
  279.         show: function (e) {
  280.             e.preventDefault();
  281.  
  282.             if (this.getZoomRatio() > 1 && this.largeImageSrc) {
  283.                 e.stopImmediatePropagation();
  284.                 this.activated = true;
  285.                 this._show(this.display, this.options.effects.show);
  286.                 this._show(this.track, this.options.effects.show);
  287.                 this._refresh();
  288.                 this.lens.position({
  289.                     my: 'center',
  290.                     at: 'center',
  291.                     of: e,
  292.                     using: $.proxy(this._refreshZoom, this)
  293.                 });
  294.                 this._toggleNotice();
  295.                 this._trigger('show');
  296.             }
  297.         },
  298.  
  299.       /** Hide zoom controls */*/
  300.         hide: function () {
  301.             this.activated = false;
  302.             this._hide(this.display, this.options.effects.hide);
  303.             this._hide(this.track, this.options.effects.hide);
  304.             this._toggleNotice();
  305.             this._trigger('hide');
  306.         },
  307.  
  308.       /**
  309.          * Refresh zoom when image is updated
  310.          * @protected
  311.          */*/
  312.         _onImageUpdated: function () {
  313.           // Stop loader in case previous active image has not been loaded yet
  314. t
  315.             $(this.options.selectors.image).trigger('processStop');
  316.  
  317.             if (!this.image.is($(this.options.selectors.image))) {
  318.                 this._setZoomData();
  319.  
  320.                 if (this.largeImageSrc) {
  321.                     this._refreshLargeImage();
  322.                     this._refresh();
  323.                 } else {
  324.                     this.hide();
  325.                 }
  326.             }
  327.         },
  328.  
  329.       /**
  330.          * Reset this.ratio when large image is loaded
  331.          * @protected
  332.          */*/
  333.         _largeImageLoaded: function () {
  334.             this.largeImage.css({
  335.                 width: 'auto',
  336.                 height: 'auto'
  337.             });
  338.             this.largeImageSize = {
  339.                 width: this.largeImage.width() || this.largeImage.get(0).naturalWidth,
  340.                 height: this.largeImage.height() || this.largeImage.get(0).naturalHeight
  341.             };
  342.             this.ratio = null;
  343.             this._toggleNotice();
  344.             $(this.options.selectors.image).trigger('processStop');
  345.         },
  346.  
  347.       /**
  348.          * Refresh large image (refresh "src" and initial position)
  349.          * @protected
  350.          */*/
  351.         _refreshLargeImage: function () {
  352.             var oldSrc;
  353.  
  354.             if (this.largeImage) {
  355.                 oldSrc = this.largeImage.attr('src');
  356.  
  357.                 if (oldSrc !== this.largeImageSrc) {
  358.                     $(this.options.selectors.image).trigger('processStart');
  359.                     this.largeImage.attr('src', this.largeImageSrc);
  360.                 }
  361.  
  362.                 this.largeImage.css({
  363.                     top: 0,
  364.                     left: 0
  365.                 });
  366.             }
  367.         },
  368.  
  369.       /**
  370.          * @return {Element} DOM-element
  371.          * @protected
  372.          */*/
  373.         _renderLargeImage: function () {
  374.             var image = $(this.options.selectors.image);
  375.  
  376.           // Start loader if 'load' event of image is expected to trigger later
  377. r
  378.             if (this.largeImageSrc) {
  379.                 image.trigger('processStart');
  380.             }
  381.  
  382.           // No need to create template just for img tag
  383. g
  384.             this.largeImage = $('<img />', {
  385.                 src: this.largeImageSrc
  386.             });
  387.  
  388.             return this.largeImage;
  389.         },
  390.  
  391.       /**
  392.          * Calculate zoom ratio.
  393.          *
  394.          * @return {Number}
  395.          * @protected
  396.          */*/
  397.         getZoomRatio: function () {
  398.             var imageWidth;
  399.  
  400.             if (this.ratio === null || typeof this.ratio === 'undefined') {
  401.                 imageWidth = $(this.image).width() || $(this.image).prop('width');
  402.  
  403.                 return this.largeImageSize ? this.largeImageSize.width / imageWidth : 1;
  404.             }
  405.  
  406.             return this.ratio;
  407.         },
  408.  
  409.       /**
  410.          * Calculate lens size, depending on zoom ratio.
  411.          *
  412.          * @return {Object} object contain width and height fields
  413.          * @protected
  414.          */*/
  415.         _calculateLensSize: function () {
  416.             var displayData = this.options.controls.display,
  417.                 ratio = this.getZoomRatio();
  418.  
  419.             return {
  420.                 width: Math.ceil(displayData.width / ratio),
  421.                 height: Math.ceil(displayData.height / ratio)
  422.             };
  423.         },
  424.  
  425.       /**
  426.          * Refresh position of large image depending of position of zoom lens.
  427.          *
  428.          * @param {Object} position
  429.          * @param {Object} ui
  430.          * @protected
  431.          */*/
  432.         _refreshZoom: function (position, ui) {
  433.             $(ui.element.element).css(position);
  434.             this.largeImage.css(this._getLargeImageOffset(position));
  435.         },
  436.  
  437.       /**
  438.          * @param {Object} position
  439.          * @return {Object}
  440.          * @private
  441.          */*/
  442.         _getLargeImageOffset: function (position) {
  443.             var ratio = this.getZoomRatio();
  444.  
  445.             return {
  446.                 top: -(position.top * ratio),
  447.                 left: -(position.left * ratio)
  448.             };
  449.         },
  450.  
  451.       /**
  452.          * Mouse move handler.
  453.          *
  454.          * @param {Object} e - event object
  455.          * @protected
  456.          */*/
  457.         _move: function (e) {
  458.             this.lens.position({
  459.                 my: 'center',
  460.                 at: 'left top',
  461.                 of: e,
  462.                 collision: 'fit',
  463.                 within: this.image,
  464.                 using: $.proxy(this._refreshZoom, this)
  465.             });
  466.         }
  467.     });
  468.  
  469.   /** Extension for zoom widget - white borders detection */*/
  470.     $.widget('mage.zoom', $.mage.zoom, {
  471.       /**
  472.          * Get aspect ratio of the element.
  473.          *
  474.          * @param {Object} element - jQuery collection
  475.          * @return {*}
  476.          * @protected
  477.          */*/
  478.         _getAspectRatio: function (element) {
  479.             var width, height, aspectRatio;
  480.  
  481.             if (!element || !element.length) {
  482.                 return null;
  483.             }
  484.             width = element.width() || element.prop('width');
  485.             height = element.height() || element.prop('height');
  486.             aspectRatio = width / height;
  487.  
  488.             return Math.round(aspectRatio * 100) / 100;
  489.         },
  490.  
  491.       /**
  492.          * Calculate large image offset depending on enabled "white borders" functionality.
  493.          *
  494.          * @return {Object}
  495.          * @protected
  496.          */*/
  497.         _getWhiteBordersOffset: function () {
  498.             var ratio = this.getZoomRatio(),
  499.                 largeWidth = this.largeImageSize.width / ratio,
  500.                 largeHeight = this.largeImageSize.height / ratio,
  501.                 width = this.image.width() || this.image.prop('width'),
  502.                 height = this.image.height() || this.image.prop('height'),
  503.                 offsetLeft = width - largeWidth > 0 ?
  504.                 Math.ceil((width - largeWidth) / 2) :
  505.                 0,
  506.                 offsetTop = height - largeHeight > 0 ?
  507.                 Math.ceil((height - largeHeight) / 2) :
  508.                 0;
  509.  
  510.             return {
  511.                 top: offsetTop,
  512.                 left: offsetLeft
  513.             };
  514.         },
  515.  
  516.       /**
  517.          * @override
  518.          */*/
  519.         _largeImageLoaded: function () {
  520.             this._super();
  521.             this.whiteBordersOffset = null;
  522.  
  523.             if (this._getAspectRatio(this.image) !== this._getAspectRatio(this.largeImage)) {
  524.                 this.whiteBordersOffset = this._getWhiteBordersOffset();
  525.             }
  526.         },
  527.  
  528.       /**
  529.          * @override
  530.          */*/
  531.         _getLargeImageOffset: function (position) {
  532.             if (this.whiteBordersOffset) {
  533.                 position.top -= this.whiteBordersOffset.top;
  534.                 position.left -= this.whiteBordersOffset.left;
  535.             }
  536.  
  537.             return this._superApply([position]);
  538.         }
  539.     });
  540.  
  541.     return $.mage.zoom;
  542. })

Raw Paste


Login or Register to edit or fork this paste. It's free.