title: Need help implementing EasyZoom jquery plugin
body: <p>I'm not too familiar with jquery and javascript in general, so bear with me here. But, I'm trying to create an image gallery with zoom on hover using EasyZoom:<a href="https://i-like-robots.github.io/EasyZoom/" rel="nofollow noreferrer">https://i-like-robots.github.io/EasyZoom/</a>. I want to achieve something like what is under the &quot;with thumbnail images&quot; in the link.</p>
  <p>So far, I've created the divs with images in them, copied the CSS and javascript files from GitHub, and linked my HTML page to them, see specific code below.</p>
  <p>But, I'm obviously missing something here. In the JS file, I found a spot where it said <code>@param {Object} target</code> am I supposed to specify the objects in the HTML where there needs to be Easyzoom? If so, how? I'm also confused as to how i can specify that I want an image gallery with Easyzoom. So, if anyone could help me with this, it would be great.</p>
  <p><strong>HTML code</strong>
  (I have a list of image links that I got from a Django model under 'images')</p>
  <pre><code>       {% for image in images %}
             &lt;div class=&quot;slides&quot;&gt;
                 &lt;div class=&quot;easyzoom&quot;&gt;
                     &lt;a href=&quot;{{image}}&quot;&gt;
                         &lt;img src=&quot;{{image}}&quot;&gt;
                     &lt;/a&gt;
                 &lt;/div&gt;
             &lt;/div&gt;
         {% endfor %}
  </code></pre>
  <p><strong>Easyzoom.css</strong></p>
  <pre><code>/**
   * EasyZoom core styles
   */
   .easyzoom {
      position: relative;
  
      /* 'Shrink-wrap' the element */
      display: inline-block;
      *display: inline;
      *zoom: 1;
  }
  
  .easyzoom img {
      vertical-align: bottom;
  }
  
  .easyzoom.is-loading img {
      cursor: progress;
  }
  
  .easyzoom.is-ready img {
      cursor: crosshair;
  }
  
  .easyzoom.is-error  img {
      cursor: not-allowed;
  }
  
  .easyzoom-notice {
      position: absolute;
      top: 50%;
      left: 50%;
      z-index: 150;
      width: 10em;
      margin: -1em 0 0 -5em;
      line-height: 2em;
      text-align: center;
      background: #FFF;
      box-shadow: 0 0 10px #888;
  }
  
  .easyzoom-flyout {
      position:absolute;
      z-index: 100;
      overflow: hidden;
      background: #FFF;
  }
  </code></pre>
  <p><strong>Easyzoom.js</strong></p>
  <pre><code>(function (root, factory) {
      'use strict';
      if(typeof define === 'function' &amp;&amp; define.amd) {
          define(['jquery'], function($){
              factory($);
          });
      } else if(typeof module === 'object' &amp;&amp; module.exports) {
          module.exports = (root.EasyZoom = factory(require('jquery')));
      } else {
          root.EasyZoom = factory(root.jQuery);
      }
  }(this, function ($) {
  
      'use strict';
  
      var zoomImgOverlapX;
      var zoomImgOverlapY;
      var ratioX;
      var ratioY;
      var pointerPositionX;
      var pointerPositionY;
  
      var defaults = {
  
          // The text to display within the notice box while loading the zoom image.
          loadingNotice: 'Loading image',
  
          // The text to display within the notice box if an error occurs when loading the zoom image.
          errorNotice: 'The image could not be loaded',
  
          // The time (in milliseconds) to display the error notice.
          errorDuration: 2500,
  
          // Attribute to retrieve the zoom image URL from.
          linkAttribute: 'href',
  
          // Prevent clicks on the zoom image link.
          preventClicks: true,
  
          // Callback function to execute before the flyout is displayed.
          beforeShow: $.noop,
  
          // Callback function to execute before the flyout is removed.
          beforeHide: $.noop,
  
          // Callback function to execute when the flyout is displayed.
          onShow: $.noop,
  
          // Callback function to execute when the flyout is removed.
          onHide: $.noop,
  
          // Callback function to execute when the cursor is moved while over the image.
          onMove: $.noop
  
      };
  
      /**
       * EasyZoom
       * @constructor
       * @param {Object} target
       * @param {Object} options (Optional)
       */
      function EasyZoom(target, options) {
          this.$target = $(target);
          this.opts = $.extend({}, defaults, options, this.$target.data());
  
          this.isOpen === undefined &amp;&amp; this._init();
      }
  
      /**
       * Init
       * @private
       */
      EasyZoom.prototype._init = function() {
          this.$link   = this.$target.find('a');
          this.$image  = this.$target.find('img');
  
          this.$flyout = $('&lt;div class=&quot;easyzoom-flyout&quot; /&gt;');
          this.$notice = $('&lt;div class=&quot;easyzoom-notice&quot; /&gt;');
  
          this.$target.on({
              'mousemove.easyzoom touchmove.easyzoom': $.proxy(this._onMove, this),
              'mouseleave.easyzoom touchend.easyzoom': $.proxy(this._onLeave, this),
              'mouseenter.easyzoom touchstart.easyzoom': $.proxy(this._onEnter, this)
          });
  
          this.opts.preventClicks &amp;&amp; this.$target.on('click.easyzoom', function(e) {
              e.preventDefault();
          });
      };
  
      /**
       * Show
       * @param {MouseEvent|TouchEvent} e
       * @param {Boolean} testMouseOver (Optional)
       */
      EasyZoom.prototype.show = function(e, testMouseOver) {
          var self = this;
  
          if (this.opts.beforeShow.call(this) === false) return;
  
          if (!this.isReady) {
              return this._loadImage(this.$link.attr(this.opts.linkAttribute), function() {
                  if (self.isMouseOver || !testMouseOver) {
                      self.show(e);
                  }
              });
          }
  
          this.$target.append(this.$flyout);
  
          var targetWidth = this.$target.outerWidth();
          var targetHeight = this.$target.outerHeight();
  
          var flyoutInnerWidth = this.$flyout.width();
          var flyoutInnerHeight = this.$flyout.height();
  
          var zoomImgWidth = this.$zoom.width();
          var zoomImgHeight = this.$zoom.height();
  
          zoomImgOverlapX = Math.ceil(zoomImgWidth - flyoutInnerWidth);
          zoomImgOverlapY = Math.ceil(zoomImgHeight - flyoutInnerHeight);
  
          // For when the zoom image is smaller than the flyout element.
          if (zoomImgOverlapX &lt; 0) zoomImgOverlapX = 0;
          if (zoomImgOverlapY &lt; 0) zoomImgOverlapY = 0;
  
          ratioX = zoomImgOverlapX / targetWidth;
          ratioY = zoomImgOverlapY / targetHeight;
  
          this.isOpen = true;
  
          this.opts.onShow.call(this);
  
          e &amp;&amp; this._move(e);
      };
  
      /**
       * On enter
       * @private
       * @param {Event} e
       */
      EasyZoom.prototype._onEnter = function(e) {
          var touches = e.originalEvent.touches;
  
          this.isMouseOver = true;
  
          if (!touches || touches.length == 1) {
              e.preventDefault();
              this.show(e, true);
          }
      };
  
      /**
       * On move
       * @private
       * @param {Event} e
       */
      EasyZoom.prototype._onMove = function(e) {
          if (!this.isOpen) return;
  
          e.preventDefault();
          this._move(e);
      };
  
      /**
       * On leave
       * @private
       */
      EasyZoom.prototype._onLeave = function() {
          this.isMouseOver = false;
          this.isOpen &amp;&amp; this.hide();
      };
  
      /**
       * On load
       * @private
       * @param {Event} e
       */
      EasyZoom.prototype._onLoad = function(e) {
          // IE may fire a load event even on error so test the image dimensions
          if (!e.currentTarget.width) return;
  
          this.isReady = true;
  
          this.$notice.detach();
          this.$flyout.html(this.$zoom);
          this.$target.removeClass('is-loading').addClass('is-ready');
  
          e.data.call &amp;&amp; e.data();
      };
  
      /**
       * On error
       * @private
       */
      EasyZoom.prototype._onError = function() {
          var self = this;
  
          this.$notice.text(this.opts.errorNotice);
          this.$target.removeClass('is-loading').addClass('is-error');
  
          this.detachNotice = setTimeout(function() {
              self.$notice.detach();
              self.detachNotice = null;
          }, this.opts.errorDuration);
      };
  
      /**
       * Load image
       * @private
       * @param {String} href
       * @param {Function} callback
       */
      EasyZoom.prototype._loadImage = function(href, callback) {
          var zoom = new Image();
  
          this.$target
              .addClass('is-loading')
              .append(this.$notice.text(this.opts.loadingNotice));
  
          this.$zoom = $(zoom)
              .on('error', $.proxy(this._onError, this))
              .on('load', callback, $.proxy(this._onLoad, this));
  
          zoom.style.position = 'absolute';
          zoom.src = href;
      };
  
      /**
       * Move
       * @private
       * @param {Event} e
       */
      EasyZoom.prototype._move = function(e) {
  
          if (e.type.indexOf('touch') === 0) {
              var touchlist = e.touches || e.originalEvent.touches;
              pointerPositionX = touchlist[0].pageX;
              pointerPositionY = touchlist[0].pageY;
          } else {
              pointerPositionX = e.pageX || pointerPositionX;
              pointerPositionY = e.pageY || pointerPositionY;
          }
  
          var targetOffset  = this.$target.offset();
          var relativePositionX = pointerPositionX - targetOffset.left;
          var relativePositionY = pointerPositionY - targetOffset.top;
          var moveX = Math.ceil(relativePositionX * ratioX);
          var moveY = Math.ceil(relativePositionY * ratioY);
  
          // Close if outside
          if (moveX &lt; 0 || moveY &lt; 0 || moveX &gt; zoomImgOverlapX || moveY &gt; zoomImgOverlapY) {
              this.hide();
          } else {
              var top = moveY * -1;
              var left = moveX * -1;
  
              this.$zoom.css({
                  top: top,
                  left: left
              });
  
              this.opts.onMove.call(this, top, left);
          }
  
      };
  
      /**
       * Hide
       */
      EasyZoom.prototype.hide = function() {
          if (!this.isOpen) return;
          if (this.opts.beforeHide.call(this) === false) return;
  
          this.$flyout.detach();
          this.isOpen = false;
  
          this.opts.onHide.call(this);
      };
  
      /**
       * Swap
       * @param {String} standardSrc
       * @param {String} zoomHref
       * @param {String|Array} srcset (Optional)
       */
      EasyZoom.prototype.swap = function(standardSrc, zoomHref, srcset) {
          this.hide();
          this.isReady = false;
  
          this.detachNotice &amp;&amp; clearTimeout(this.detachNotice);
  
          this.$notice.parent().length &amp;&amp; this.$notice.detach();
  
          this.$target.removeClass('is-loading is-ready is-error');
  
          this.$image.attr({
              src: standardSrc,
              srcset: $.isArray(srcset) ? srcset.join() : srcset
          });
  
          this.$link.attr(this.opts.linkAttribute, zoomHref);
      };
  
      /**
       * Teardown
       */
      EasyZoom.prototype.teardown = function() {
          this.hide();
  
          this.$target
              .off('.easyzoom')
              .removeClass('is-loading is-ready is-error');
  
          this.detachNotice &amp;&amp; clearTimeout(this.detachNotice);
  
          delete this.$link;
          delete this.$zoom;
          delete this.$image;
          delete this.$notice;
          delete this.$flyout;
  
          delete this.isOpen;
          delete this.isReady;
      };
  
      // jQuery plugin wrapper
      $.fn.easyZoom = function(options) {
          return this.each(function() {
              var api = $.data(this, 'easyZoom');
  
              if (!api) {
                  $.data(this, 'easyZoom', new EasyZoom(this, options));
              } else if (api.isOpen === undefined) {
                  api._init();
              }
          });
      };
  
      return EasyZoom;
  }));
  </code></pre>
  <p>The js and CSS files are basically exact copies of what is on Github here: <a href="https://github.com/i-like-robots/EasyZoom" rel="nofollow noreferrer">https://github.com/i-like-robots/EasyZoom</a></p>