123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- (function ($) {
- $.fn.magnify = function (options) {
- 'use strict';
- var magnify = new Magnify($(this), options);
- /* events must be tracked here */
- /**
- * Return that from _init function
- *
- */
- return magnify;
- };
- function Magnify(element, options) {
- var customUserOptions = options || {},
- $box = $(element),
- $thumb,
- that = this,
- largeWrapper = options.largeWrapper || '.magnifier-preview',
- $magnifierPreview = $(largeWrapper);
- curThumb = null,
- magnifierOptions = {
- x: 0,
- y: 0,
- w: 0,
- h: 0,
- lensW: 0,
- lensH: 0,
- lensBgX: 0,
- lensBgY: 0,
- largeW: 0,
- largeH: 0,
- largeL: 0,
- largeT: 0,
- zoom: 2,
- zoomMin: 1.1,
- zoomMax: 5,
- mode: 'outside',
- eventType: 'click',
- status: 0,
- zoomAttached: false,
- zoomable: customUserOptions.zoomable !== undefined ?
- customUserOptions.zoomable
- : false,
- onthumbenter: customUserOptions.onthumbenter !== undefined ?
- customUserOptions.onthumbenter
- : null,
- onthumbmove: customUserOptions.onthumbmove !== undefined ?
- customUserOptions.onthumbmove
- : null,
- onthumbleave: customUserOptions.onthumbleave !== undefined ?
- customUserOptions.onthumbleave
- : null,
- onzoom: customUserOptions.onzoom !== undefined ?
- customUserOptions.onzoom
- : null
- },
- pos = {
- t: 0,
- l: 0,
- x: 0,
- y: 0
- },
- gId = 0,
- status = 0,
- curIdx = '',
- curLens = null,
- curLarge = null,
- lensbg = customUserOptions.bg !== undefined ?
- customUserOptions.lensbg
- : true,
- gZoom = customUserOptions.zoom !== undefined ?
- customUserOptions.zoom
- : magnifierOptions.zoom,
- gZoomMin = customUserOptions.zoomMin !== undefined ?
- customUserOptions.zoomMin
- : magnifierOptions.zoomMin,
- gZoomMax = customUserOptions.zoomMax !== undefined ?
- customUserOptions.zoomMax
- : magnifierOptions.zoomMax,
- gMode = customUserOptions.mode || magnifierOptions.mode,
- gEventType = customUserOptions.eventType || magnifierOptions.eventType,
- data = {},
- inBounds = false,
- isOverThumb = false,
- rate = 1,
- paddingX = 0,
- paddingY = 0,
- enabled = true,
- showWrapper = true;
- var MagnifyCls = {
- magnifyHidden: 'magnify-hidden',
- magnifyOpaque: 'magnify-opaque',
- magnifyFull: 'magnify-fullimage'
- };
- /**
- * Update Lens positon on.
- *
- */
- that.update = function () {
- updateLensOnLoad();
- };
- /**
- * Init new Magnifier
- *
- */
- that.init = function () {
- _init($box, options);
- };
- function _toBoolean(str) {
- if (typeof str === 'string') {
- if (str === 'true') {
- return true;
- } else if (str === 'false' || '') {
- return false;
- }
- console.warn('Wrong type: can\'t be transformed to Boolean');
- } else if (typeof str === 'boolean') {
- return str;
- }
- }
- function createLens(thumb) {
- if ($(thumb).siblings('.magnify-lens').length) {
- return false;
- }
- var lens = $('<div class="magnify-lens magnify-hidden" data-gallery-role="magnifier-zoom"></div>');
- $(thumb).parent().append(lens);
- }
- function updateLensOnLoad(idSelectorMainImg, thumb, largeImgInMagnifyLens, largeWrapper) {
- var magnifyLensElement= $box.find('.magnify-lens'),
- textWrapper;
- if (data[idSelectorMainImg].status === 1) {
- textWrapper = $('<div class="magnifier-loader-text"></div>');
- magnifyLensElement.className = 'magnifier-loader magnify-hidden';
- textWrapper.html('Loading...');
- magnifyLensElement.html('').append(textWrapper);
- } else if (data[idSelectorMainImg].status === 2) {
- magnifyLensElement.addClass(MagnifyCls.magnifyHidden);
- magnifyLensElement.html('');
- largeImgInMagnifyLens.id = idSelectorMainImg + '-large';
- largeImgInMagnifyLens.style.width = data[idSelectorMainImg].largeImgInMagnifyLensWidth + 'px';
- largeImgInMagnifyLens.style.height = data[idSelectorMainImg].largeImgInMagnifyLensHeight + 'px';
- largeImgInMagnifyLens.className = 'magnifier-large magnify-hidden';
- if (data[idSelectorMainImg].mode === 'inside') {
- magnifyLensElement.append(largeImgInMagnifyLens);
- } else {
- largeWrapper.html('').append(largeImgInMagnifyLens);
- }
- }
- data[idSelectorMainImg].lensH = data[idSelectorMainImg].lensH > $thumb.height() ? $thumb.height() : data[idSelectorMainImg].lensH;
- if (Math.round(data[idSelectorMainImg].lensW) === 0) {
- magnifyLensElement.css('display', 'none');
- } else {
- magnifyLensElement.css({
- width: Math.round(data[idSelectorMainImg].lensW) + 'px',
- height: Math.round(data[idSelectorMainImg].lensH) + 'px',
- display: ''
- });
- }
- }
- function getMousePos() {
- var xPos = pos.x - magnifierOptions.x,
- yPos = pos.y - magnifierOptions.y,
- t,
- l;
- inBounds = xPos < 0 || yPos < 0 || xPos > magnifierOptions.w || yPos > magnifierOptions.h ? false : true;
- l = xPos - magnifierOptions.lensW / 2;
- t = yPos - magnifierOptions.lensH / 2;
- if (xPos < magnifierOptions.lensW / 2) {
- l = 0;
- }
- if (yPos < magnifierOptions.lensH / 2) {
- t = 0;
- }
- if (xPos - magnifierOptions.w + Math.ceil(magnifierOptions.lensW / 2) > 0) {
- l = magnifierOptions.w - Math.ceil(magnifierOptions.lensW + 2);
- }
- if (yPos - magnifierOptions.h + Math.ceil(magnifierOptions.lensH / 2) > 0) {
- t = magnifierOptions.h - Math.ceil(magnifierOptions.lensH);
- }
- pos.l = l;
- pos.t = t;
- magnifierOptions.lensBgX = pos.l;
- magnifierOptions.lensBgY = pos.t;
- if (magnifierOptions.mode === 'inside') {
- magnifierOptions.largeL = Math.round(xPos * (magnifierOptions.zoom - magnifierOptions.lensW / magnifierOptions.w));
- magnifierOptions.largeT = Math.round(yPos * (magnifierOptions.zoom - magnifierOptions.lensH / magnifierOptions.h));
- } else {
- magnifierOptions.largeL = Math.round(magnifierOptions.lensBgX * magnifierOptions.zoom * (magnifierOptions.largeWrapperW / magnifierOptions.w));
- magnifierOptions.largeT = Math.round(magnifierOptions.lensBgY * magnifierOptions.zoom * (magnifierOptions.largeWrapperH / magnifierOptions.h));
- }
- }
- function onThumbEnter() {
- if (_toBoolean(enabled)) {
- magnifierOptions = data[curIdx];
- curLens = $box.find('.magnify-lens');
- if (magnifierOptions.status === 2) {
- curLens.removeClass(MagnifyCls.magnifyOpaque);
- curLarge = $('#' + curIdx + '-large');
- curLarge.removeClass(MagnifyCls.magnifyHidden);
- } else if (magnifierOptions.status === 1) {
- curLens.className = 'magnifier-loader';
- }
- }
- }
- function onThumbLeave() {
- if (magnifierOptions.status > 0) {
- var handler = magnifierOptions.onthumbleave;
- if (handler !== null) {
- handler({
- thumb: curThumb,
- lens: curLens,
- large: curLarge,
- x: pos.x,
- y: pos.y
- });
- }
- if (!curLens.hasClass(MagnifyCls.magnifyHidden)) {
- curLens.addClass(MagnifyCls.magnifyHidden);
- //$curThumb.removeClass(MagnifyCls.magnifyOpaque);
- if (curLarge !== null) {
- curLarge.addClass(MagnifyCls.magnifyHidden);
- }
- }
- }
- }
- function move() {
- if (_toBoolean(enabled)) {
- if (status !== magnifierOptions.status) {
- onThumbEnter();
- }
- if (magnifierOptions.status > 0) {
- curThumb.className = magnifierOptions.thumbCssClass + ' magnify-opaque';
- if (magnifierOptions.status === 1) {
- curLens.className = 'magnifier-loader';
- } else if (magnifierOptions.status === 2) {
- curLens.removeClass(MagnifyCls.magnifyHidden);
- curLarge.removeClass(MagnifyCls.magnifyHidden);
- curLarge.css({
- left: '-' + magnifierOptions.largeL + 'px',
- top: '-' + magnifierOptions.largeT + 'px'
- });
- }
- var borderOffset = 2; // Offset for magnify-lens border
- pos.t = pos.t <= 0 ? 0 : pos.t - borderOffset;
- curLens.css({
- left: pos.l + paddingX + 'px',
- top: pos.t + paddingY + 'px'
- });
- if (lensbg) {
- curLens.css({
- 'background-color': 'rgba(f,f,f,.5)'
- });
- } else {
- curLens.get(0).style.backgroundPosition = '-' +
- magnifierOptions.lensBgX + 'px -' +
- magnifierOptions.lensBgY + 'px';
- }
- var handler = magnifierOptions.onthumbmove;
- if (handler !== null) {
- handler({
- thumb: curThumb,
- lens: curLens,
- large: curLarge,
- x: pos.x,
- y: pos.y
- });
- }
- }
- status = magnifierOptions.status;
- }
- }
- function setThumbData(mainImage, mainImageData) {
- var thumbBounds = mainImage.getBoundingClientRect(),
- w = 0,
- h = 0;
- mainImageData.x = Math.round(thumbBounds.left);
- mainImageData.y = Math.round(thumbBounds.top);
- mainImageData.w = Math.round(thumbBounds.right - mainImageData.x);
- mainImageData.h = Math.round(thumbBounds.bottom - mainImageData.y);
- if (mainImageData.mode === 'inside') {
- w = mainImageData.w;
- h = mainImageData.h;
- } else {
- w = mainImageData.largeWrapperW;
- h = mainImageData.largeWrapperH;
- }
- mainImageData.largeImgInMagnifyLensWidth = Math.round(mainImageData.zoom * w);
- mainImageData.largeImgInMagnifyLensHeight = Math.round(mainImageData.zoom * h);
- mainImageData.lensW = Math.round(mainImageData.w / mainImageData.zoom);
- mainImageData.lensH = Math.round(mainImageData.h / mainImageData.zoom);
- }
- function _init($box, options) {
- var opts = {};
- if (options.thumb === undefined) {
- return false;
- }
- $thumb = $box.find(options.thumb);
- if ($thumb.length) {
- for (var key in options) {
- opts[key] = options[key];
- }
- opts.thumb = $thumb;
- enabled = opts.enabled;
- if (_toBoolean(enabled)) {
- $magnifierPreview.show().css('display', '');
- $magnifierPreview.addClass(MagnifyCls.magnifyHidden);
- set(opts);
- } else {
- $magnifierPreview.empty().hide();
- }
- }
- return that;
- }
- function hoverEvents(thumb) {
- $(thumb).on('mouseover', function (e) {
- if (showWrapper) {
- if (magnifierOptions.status !== 0) {
- onThumbLeave();
- }
- handleEvents(e);
- isOverThumb = inBounds;
- }
- }).trigger('mouseover');
- }
- function clickEvents(thumb) {
- $(thumb).on('click', function (e) {
- if (showWrapper) {
- if (!isOverThumb) {
- if (magnifierOptions.status !== 0) {
- onThumbLeave();
- }
- handleEvents(e);
- isOverThumb = true;
- }
- }
- });
- }
- function bindEvents(eType, thumb) {
- switch (eType) {
- case 'hover':
- hoverEvents(thumb);
- break;
- case 'click':
- clickEvents(thumb);
- break;
- }
- }
- function handleEvents(e) {
- var src = e.target;
- curIdx = src.id;
- curThumb = src;
- onThumbEnter(src);
- setThumbData(curThumb, magnifierOptions);
- pos.x = e.clientX;
- pos.y = e.clientY;
- getMousePos();
- move();
- var handler = magnifierOptions.onthumbenter;
- if (handler !== null) {
- handler({
- thumb: curThumb,
- lens: curLens,
- large: curLarge,
- x: pos.x,
- y: pos.y
- });
- }
- }
- function set(options) {
- if (data[options.thumb.id] !== undefined) {
- curThumb = options.thumb;
- return false;
- }
- var thumbObj = new Image(),
- largeObj = new Image(),
- $thumb = options.thumb,
- thumb = $thumb.get(0),
- idx = thumb.id,
- largeUrl,
- largeWrapper = $(options.largeWrapper),
- zoom = options.zoom || thumb.getAttribute('data-zoom') || gZoom,
- zoomMin = options.zoomMin || gZoomMin,
- zoomMax = options.zoomMax || gZoomMax,
- mode = options.mode || thumb.getAttribute('data-mode') || gMode,
- eventType = options.eventType || thumb.getAttribute('data-eventType') || gEventType,
- onthumbenter = options.onthumbenter !== undefined ?
- options.onthumbenter
- : magnifierOptions.onthumbenter,
- onthumbleave = options.onthumbleave !== undefined ?
- options.onthumbleave
- : magnifierOptions.onthumbleave,
- onthumbmove = options.onthumbmove !== undefined ?
- options.onthumbmove
- : magnifierOptions.onthumbmove;
- largeUrl = $thumb.data('original') || customUserOptions.full || $thumb.attr('src');
- if (thumb.id === '') {
- idx = thumb.id = 'magnifier-item-' + gId;
- gId += 1;
- }
- createLens(thumb, idx);
- if (options.width) {
- largeWrapper.width(options.width);
- }
- if (options.height) {
- largeWrapper.height(options.height);
- }
- if (options.top) {
- if (typeof options.top == 'function') {
- var top = options.top() + 'px';
- } else {
- var top = options.top + 'px';
- }
- if (largeWrapper.length) {
- largeWrapper[0].style.top = top.replace('%px', '%');
- }
- }
- if (options.left) {
- if (typeof options.left == 'function') {
- var left = options.left() + 'px';
- } else {
- var left = options.left + 'px';
- }
- if (largeWrapper.length) {
- largeWrapper[0].style.left = left.replace('%px', '%');
- }
- }
- data[idx] = {
- zoom: zoom,
- zoomMin: zoomMin,
- zoomMax: zoomMax,
- mode: mode,
- eventType: eventType,
- thumbCssClass: thumb.className,
- zoomAttached: false,
- status: 0,
- largeUrl: largeUrl,
- largeWrapperId: mode === 'outside' ? largeWrapper.attr('id') : null,
- largeWrapperW: mode === 'outside' ? largeWrapper.width() : null,
- largeWrapperH: mode === 'outside' ? largeWrapper.height() : null,
- onthumbenter: onthumbenter,
- onthumbleave: onthumbleave,
- onthumbmove: onthumbmove
- };
- paddingX = ($thumb.parent().width() - $thumb.width()) / 2;
- paddingY = ($thumb.parent().height() - $thumb.height()) / 2;
- showWrapper = false;
- $(thumbObj).on('load', function () {
- data[idx].status = 1;
- $(largeObj).on('load', function () {
- if (largeObj.width > largeWrapper.width() || largeObj.height > largeWrapper.height()) {
- showWrapper = true;
- bindEvents(eventType, thumb);
- data[idx].status = 2;
- if (largeObj.width > largeObj.height) {
- data[idx].zoom = largeObj.width / largeWrapper.width();
- } else {
- data[idx].zoom = largeObj.height / largeWrapper.height();
- }
- setThumbData(thumb, data[idx]);
- updateLensOnLoad(idx, thumb, largeObj, largeWrapper);
- }
- });
- largeObj.src = data[idx].largeUrl;
- });
- thumbObj.src = thumb.src;
- }
- /**
- * Hide magnifier when mouse exceeds image bounds.
- */
- function onMouseLeave() {
- onThumbLeave();
- isOverThumb = false;
- $magnifierPreview.addClass(MagnifyCls.magnifyHidden);
- }
- function onMousemove(e) {
- pos.x = e.clientX;
- pos.y = e.clientY;
- getMousePos();
- if (gEventType === 'hover') {
- isOverThumb = inBounds;
- }
- if (inBounds && isOverThumb && gMode === 'outside') {
- $magnifierPreview.removeClass(MagnifyCls.magnifyHidden);
- move();
- }
- }
- function onScroll() {
- if (curThumb !== null) {
- setThumbData(curThumb, magnifierOptions);
- }
- }
- $(window).on('scroll', onScroll);
- $(window).resize(function () {
- _init($box, customUserOptions);
- });
- $box.on('mousemove', onMousemove);
- $box.on('mouseleave', onMouseLeave);
- _init($box, customUserOptions);
- }
- }(jQuery));
|