text: /**
   * 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 gOptions = options || {},
              $box = $(element),
              $thumb,
              that = this,
              largeWrapper = options.largeWrapper ||  '.magnifier-preview',
              $largeWrapper = $(largeWrapper);
  
          curThumb = null,
              currentOpts = {
                  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: gOptions.zoomable !== undefined ?
                      gOptions.zoomable
                      : false,
                  onthumbenter: gOptions.onthumbenter !== undefined ?
                      gOptions.onthumbenter
                      : null,
                  onthumbmove: gOptions.onthumbmove !== undefined ?
                      gOptions.onthumbmove
                      : null,
                  onthumbleave: gOptions.onthumbleave !== undefined ?
                      gOptions.onthumbleave
                      : null,
                  onzoom: gOptions.onzoom !== undefined ?
                      gOptions.onzoom
                      : null
              },
              pos = {
                  t: 0,
                  l: 0,
                  x: 0,
                  y: 0
              },
              gId = 0,
              status = 0,
              curIdx = '',
              curLens = null,
              curLarge = null,
              lensbg = gOptions.bg !== undefined ? gOptions.lensbg : true,
              gZoom = gOptions.zoom !== undefined ?
                  gOptions.zoom
                  : currentOpts.zoom,
              gZoomMin = gOptions.zoomMin !== undefined ?
                  gOptions.zoomMin
                  : currentOpts.zoomMin,
              gZoomMax = gOptions.zoomMax !== undefined ?
                  gOptions.zoomMax
                  : currentOpts.zoomMax,
              gMode = gOptions.mode || currentOpts.mode,
              gEventType = gOptions.eventType || currentOpts.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(idx, thumb, large, largeWrapper) {
              var lens = $box.find('.magnify-lens'),
                  textWrapper;
  
              if (data[idx].status === 1) {
                  textWrapper = $('<div class="magnifier-loader-text"></div>');
                  lens.className = 'magnifier-loader magnify-hidden';
                  textWrapper.html('Loading...');
                  lens.html('').append(textWrapper);
              } else if (data[idx].status === 2) {
                  lens.addClass(MagnifyCls.magnifyHidden);
                  lens.html('');
                  large.id = idx + '-large';
                  large.style.width = data[idx].largeW * rate + 'px';
                  large.style.height = data[idx].largeH + 'px';
                  large.className = 'magnifier-large magnify-hidden';
  
                  if (data[idx].mode === 'inside') {
                      lens.append(large);
                  } else {
                      largeWrapper.html('').append(large);
                  }
              }
  
              data[idx].lensH = data[idx].lensH > $thumb.height() ? $thumb.height() : data[idx].lensH;
  
              if (Math.round(data[idx].lensW) === 0) {
                  lens.css('display', 'none');
              } else {
                  lens.css({
                      width: data[idx].lensW + 1 + 'px',
                      height: data[idx].lensH - 1 + 'px',
                      display: ''
                  });
              }
          }
  
          function getMousePos() {
              var xPos = pos.x - currentOpts.x,
                  yPos = pos.y - currentOpts.y,
                  t,
                  l;
  
              inBounds =  xPos < 0 || yPos < 0 || xPos > currentOpts.w || yPos > currentOpts.h  ? false : true;
  
              l = xPos - currentOpts.lensW / 2;
              t = yPos - currentOpts.lensH / 2;
  
              if (currentOpts.mode !== 'inside') {
                  if (xPos < currentOpts.lensW / 2) {
                      l = 0;
                  }
  
                  if (yPos < currentOpts.lensH / 2) {
                      t = 0;
                  }
  
                  if (xPos - currentOpts.w + Math.ceil(currentOpts.lensW / 2) > 0) {
                      l = currentOpts.w - Math.ceil(currentOpts.lensW + 2);
                  }
  
                  if (yPos - currentOpts.h + Math.ceil(currentOpts.lensH / 2) > 0) {
                      t = currentOpts.h - Math.ceil(currentOpts.lensH);
                  }
  
                  pos.l = l;
                  pos.t = t;
  
                  currentOpts.lensBgX = pos.l;
                  currentOpts.lensBgY = pos.t;
  
                  if (currentOpts.mode === 'inside') {
                      currentOpts.largeL = xPos * (currentOpts.zoom - currentOpts.lensW / currentOpts.w);
                      currentOpts.largeT = yPos * (currentOpts.zoom - currentOpts.lensH / currentOpts.h);
                  } else {
                      currentOpts.largeL = currentOpts.lensBgX * currentOpts.zoom * (currentOpts.largeWrapperW / currentOpts.w) * rate;
                      currentOpts.largeT = currentOpts.lensBgY * currentOpts.zoom * (currentOpts.largeWrapperH / currentOpts.h);
                  }
              }
          }
  
          function onThumbEnter() {
              if (_toBoolean(enabled)) {
                  currentOpts = data[curIdx];
                  curLens = $box.find('.magnify-lens');
  
                  if (currentOpts.status === 2) {
                      curLens.removeClass(MagnifyCls.magnifyOpaque);
                      curLarge = $('#' + curIdx + '-large');
                      curLarge.removeClass(MagnifyCls.magnifyHidden);
                  } else if (currentOpts.status === 1) {
                      curLens.className = 'magnifier-loader';
                  }
              }
          }
  
          function onThumbLeave() {
              if (currentOpts.status > 0) {
                  var handler = currentOpts.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 !== currentOpts.status) {
                      onThumbEnter();
                  }
  
                  if (currentOpts.status > 0) {
                      curThumb.className = currentOpts.thumbCssClass + ' magnify-opaque';
  
                      if (currentOpts.status === 1) {
                          curLens.className = 'magnifier-loader';
                      } else if (currentOpts.status === 2) {
                          curLens.removeClass(MagnifyCls.magnifyHidden);
                          curLarge.removeClass(MagnifyCls.magnifyHidden);
                          curLarge.css({
                              left: '-' + currentOpts.largeL + 'px',
                              top: '-' + currentOpts.largeT + 'px'
                          });
                      }
  
                      pos.t = pos.t <= 0 ? 0 : pos.t;
                      curLens.css({
                          left: pos.l + paddingX + 'px',
                          top: pos.t + 1 + paddingY + 'px'
                      });
  
                      if (lensbg) {
                          curLens.css({
                              'background-color': 'rgba(f,f,f,.5)'
                          });
                      } else {
                          curLens.get(0).style.backgroundPosition = '-' +
                          currentOpts.lensBgX + 'px -' +
                          currentOpts.lensBgY + 'px';
                      }
                      var handler = currentOpts.onthumbmove;
  
                      if (handler !== null) {
                          handler({
                              thumb: curThumb,
                              lens: curLens,
                              large: curLarge,
                              x: pos.x,
                              y: pos.y
                          });
                      }
                  }
  
                  status = currentOpts.status;
              }
          }
  
          function setThumbData(thumb, thumbData) {
              var thumbBounds = thumb.getBoundingClientRect(),
                  w = 0,
                  h = 0;
  
              thumbData.x = thumbBounds.left;
              thumbData.y = thumbBounds.top;
              thumbData.w = thumbBounds.right - thumbData.x;
              thumbData.h = thumbBounds.bottom - thumbData.y;
  
              if (thumbData.mode === 'inside') {
                  w = thumbData.w;
                  h = thumbData.h;
              } else {
                  w = thumbData.largeWrapperW;
                  h = thumbData.largeWrapperH;
              }
  
              thumbData.largeW = thumbData.zoom * w;
              thumbData.largeH = thumbData.zoom * h;
  
              thumbData.lensW = thumbData.w / thumbData.zoom / rate;
              thumbData.lensH = thumbData.h / thumbData.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)) {
  
                      $largeWrapper.show().css('display', '');
                      $largeWrapper.addClass(MagnifyCls.magnifyHidden);
                      set(opts);
                  } else {
                      $largeWrapper.empty().hide();
                  }
              }
  
              return that;
          }
  
          function hoverEvents(thumb) {
              $(thumb).on('mouseover', function (e) {
  
                  if (showWrapper) {
  
                      if (currentOpts.status !== 0) {
                          onThumbLeave();
                      }
                      handleEvents(e);
                      isOverThumb = inBounds;
                  }
              }).trigger('mouseover');
          }
  
          function clickEvents(thumb) {
              $(thumb).on('click', function (e) {
  
                  if (showWrapper) {
                      if (!isOverThumb) {
                          if (currentOpts.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, currentOpts);
  
              pos.x = e.clientX;
              pos.y = e.clientY;
  
              getMousePos();
              move();
  
              var handler = currentOpts.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
                      : currentOpts.onthumbenter,
                  onthumbleave = options.onthumbleave !== undefined ?
                      options.onthumbleave
                      : currentOpts.onthumbleave,
                  onthumbmove = options.onthumbmove !== undefined ?
                      options.onthumbmove
                      : currentOpts.onthumbmove;
  
              largeUrl = $thumb.data('original') || gOptions.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
              };
  
              rate = $thumb.width() / $thumb.height() / (data[idx].largeWrapperW / data[idx].largeWrapperH);
              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;
                          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;
          }
  
          function onMousemove(e) {
  
              pos.x = e.clientX;
              pos.y = e.clientY;
  
              getMousePos();
  
              if (gEventType === 'hover') {
                  isOverThumb = inBounds;
              }
  
              if (inBounds && isOverThumb) {
                  $largeWrapper.removeClass(MagnifyCls.magnifyHidden);
                  move();
              } else {
                  onThumbLeave();
                  isOverThumb = false;
                  $largeWrapper.addClass(MagnifyCls.magnifyHidden);
              }
          }
  
          function onScroll() {
  
              if (curThumb !== null) {
                  setThumbData(curThumb, currentOpts);
              }
          }
  
          $(window).on('scroll', onScroll);
          $(window).resize(function () {
              _init($box, gOptions);
          });
  
          $box.on('mousemove', onMousemove);
          _init($box, gOptions);
  
      }
  }(jQuery));
  