T.D
T.D

Reputation: 113

Mouseleave delay

I'd like to delay the zoomed image disappearing by a X seconds so I can fade out the image rather than it simply disappearing.

Can I simply add .delay(1000) somewhere to the mouseleave / hide lines of code?

I've tried that but unfortunately doesn't seem to work. I've also tried to wrap a setTimeout( ... , 1000); around various parts of the code, but couldn't make that work either.

Any help much appreciated!

Here is the Jsfiddle https://jsfiddle.net/mr_antlers/nh5jw5tb/2/

This is the original 'EasyZoom' .js code.

        /*!
 * @name        EasyZoom
 * @author      Matt Hinchliffe <>
 * @modified    Tuesday, September 6th, 2016
 * @version     2.4.0
 */

! function (a) {
    "use strict";
function b(b, c) {
    this.$target = a(b), this.opts = a.extend({}, i, c, this.$target.data()), void 0 === this.isOpen && this._init()
}
var c, d, e, f, g, h, i = {
    loadingNotice: "Loading image",
    errorNotice: "The image could not be loaded",
    errorDuration: 2500,
    linkAttribute: "href",
    preventClicks: !0,
    beforeShow: a.noop,
    beforeHide: a.noop,
    onShow: a.noop,
    onHide: a.noop,
    onMove: a.noop
};
b.prototype._init = function () {
    this.$link = this.$target.find("a"), this.$image = this.$target.find("img"), this.$flyout = a('<div class="easyzoom-flyout" />'), this.$notice = a('<div class="easyzoom-notice" />'), this.$target.on({
        "mousemove.easyzoom touchmove.easyzoom": a.proxy(this._onMove, this),
        "mouseleave.easyzoom touchend.easyzoom": a.proxy(this._onLeave, this),
        "mouseenter.easyzoom touchstart.easyzoom": a.proxy(this._onEnter, this)
    }), this.opts.preventClicks && this.$target.on("click.easyzoom", function (a) {
        a.preventDefault()
    })
}, b.prototype.show = function (a, b) {
    var g, h, i, j, k = this;
    if (this.opts.beforeShow.call(this) !== !1) {
        if (!this.isReady) return this._loadImage(this.$link.attr(this.opts.linkAttribute), function () {
            (k.isMouseOver || !b) && k.show(a)
        });
        this.$target.append(this.$flyout), g = this.$target.width(), h = this.$target.height(), i = this.$flyout.width(), j = this.$flyout.height(), c = this.$zoom.width() - i, d = this.$zoom.height() - j, 0 > c && (c = 0), 0 > d && (d = 0), e = c / g, f = d / h, this.isOpen = !0, this.opts.onShow.call(this), a && this._move(a)
    }
}, b.prototype._onEnter = function (a) {
    var b = a.originalEvent.touches;
    this.isMouseOver = !0, b && 1 != b.length || (a.preventDefault(), this.show(a, !0))
}, b.prototype._onMove = function (a) {
    this.isOpen && (a.preventDefault(), this._move(a))
}, b.prototype._onLeave = function () {
    this.isMouseOver = !1, this.isOpen && this.hide()
}, b.prototype._onLoad = function (a) {
    a.currentTarget.width && (this.isReady = !0, this.$notice.detach(), this.$flyout.html(this.$zoom), this.$target.removeClass("is-loading").addClass("is-ready"), a.data.call && a.data())
}, b.prototype._onError = function () {
    var a = this;
    this.$notice.text(this.opts.errorNotice), this.$target.removeClass("is-loading").addClass("is-error"), this.detachNotice = setTimeout(function () {
        a.$notice.detach(), a.detachNotice = null
    }, this.opts.errorDuration)
}, b.prototype._loadImage = function (b, c) {
    var d = new Image;
    this.$target.addClass("is-loading").append(this.$notice.text(this.opts.loadingNotice)), this.$zoom = a(d).on("error", a.proxy(this._onError, this)).on("load", c, a.proxy(this._onLoad, this)), d.style.position = "absolute", d.src = b
}, b.prototype._move = function (a) {
    if (0 === a.type.indexOf("touch")) {
        var b = a.touches || a.originalEvent.touches;
        g = b[0].pageX, h = b[0].pageY
    } else g = a.pageX || g, h = a.pageY || h;
    var i = this.$target.offset(),
        j = h - i.top,
        k = g - i.left,
        l = Math.ceil(j * f),
        m = Math.ceil(k * e);
    if (0 > m || 0 > l || m > c || l > d) this.hide();
    else {
        var n = -1 * l,
            o = -1 * m;
        this.$zoom.css({
            top: n,
            left: o
        }), this.opts.onMove.call(this, n, o)
    }
}, b.prototype.hide = function () {
    this.isOpen && this.opts.beforeHide.call(this) !== !1 && (this.$flyout.detach(), this.isOpen = !1, this.opts.onHide.call(this))
}, b.prototype.swap = function (b, c, d) {
    this.hide(), this.isReady = !1, this.detachNotice && clearTimeout(this.detachNotice), this.$notice.parent().length && this.$notice.detach(), this.$target.removeClass("is-loading is-ready is-error"), this.$image.attr({
        src: b,
        srcset: a.isArray(d) ? d.join() : d
    }), this.$link.attr(this.opts.linkAttribute, c)
}, b.prototype.teardown = function () {
    this.hide(), this.$target.off(".easyzoom").removeClass("is-loading is-ready is-error"), this.detachNotice && clearTimeout(this.detachNotice), delete this.$link, delete this.$zoom, delete this.$image, delete this.$notice, delete this.$flyout, delete this.isOpen, delete this.isReady
}, a.fn.easyZoom = function (c) {
    return this.each(function () {
        var d = a.data(this, "easyZoom");
        d ? void 0 === d.isOpen && d._init() : a.data(this, "easyZoom", new b(this, c))
    })
}, "function" == typeof define && define.amd ? define(function () {
    return b
}) : "undefined" != typeof module && module.exports && (module.exports = b)
}(jQuery);



    // Instantiate EasyZoom instances
    var $easyzoom = $('.easyzoom').easyZoom();

    // Setup thumbnails example
    var api1 = $easyzoom.filter('.easyzoom--with-thumbnails').data('easyZoom');

    $('.thumbnails').on('click', 'a', function(e) {
        var $this = $(this);

        e.preventDefault();

        // Use EasyZoom's `swap` method
        api1.swap($this.data('standard'), $this.attr('href'));
    });

    // Setup toggles example
    var api2 = $easyzoom.filter('.easyzoom--with-toggle').data('easyZoom');

    $('.toggle').on('click', function() {
        var $this = $(this);

        if ($this.data("active") === true) {
            $this.text("Switch on").data("active", false);
            api2.teardown();
        } else {
            $this.text("Switch off").data("active", true);
            api2._init();
        }
    });

Upvotes: 4

Views: 562

Answers (2)

josephting
josephting

Reputation: 2665

You can pass in beforeShow and beforeHide argument into easyZoom when you instantiate them.

var $easyzoom = $('.easyzoom').easyZoom({
    beforeHide: function() {
        this.$flyout.fadeOut();
        return false;
    },
    beforeShow: function() {
        this.$flyout.show();
    }
});

    /*!
     * @name        EasyZoom
     * @author      Matt Hinchliffe <>
     * @modified    Tuesday, September 6th, 2016
     * @version     2.4.0
     */
    ! function(a) {
      "use strict";

      function b(b, c) {
        this.$target = a(b), this.opts = a.extend({}, i, c, this.$target.data()), void 0 === this.isOpen && this._init()
      }
      var c, d, e, f, g, h, i = {
        loadingNotice: "Loading image",
        errorNotice: "The image could not be loaded",
        errorDuration: 2500,
        linkAttribute: "href",
        preventClicks: !0,
        beforeShow: a.noop,
        beforeHide: a.noop,
        onShow: a.noop,
        onHide: a.noop,
        onMove: a.noop
      };
      b.prototype._init = function() {
        this.$link = this.$target.find("a"), this.$image = this.$target.find("img"), this.$flyout = a('<div class="easyzoom-flyout" />'), this.$notice = a('<div class="easyzoom-notice" />'), this.$target.on({
          "mousemove.easyzoom touchmove.easyzoom": a.proxy(this._onMove, this),
          "mouseleave.easyzoom touchend.easyzoom": a.proxy(this._onLeave, this),
          "mouseenter.easyzoom touchstart.easyzoom": a.proxy(this._onEnter, this)
        }), this.opts.preventClicks && this.$target.on("click.easyzoom", function(a) {
          a.preventDefault()
        })
      }, b.prototype.show = function(a, b) {
        var g, h, i, j, k = this;
        if (this.opts.beforeShow.call(this) !== !1) {
          if (!this.isReady) return this._loadImage(this.$link.attr(this.opts.linkAttribute), function() {
            (k.isMouseOver || !b) && k.show(a)
          });
          this.$target.append(this.$flyout), g = this.$target.width(), h = this.$target.height(), i = this.$flyout.width(), j = this.$flyout.height(), c = this.$zoom.width() - i, d = this.$zoom.height() - j, 0 > c && (c = 0), 0 > d && (d = 0), e = c / g, f = d / h, this.isOpen = !0, this.opts.onShow.call(this), a && this._move(a)
        }
      }, b.prototype._onEnter = function(a) {
        var b = a.originalEvent.touches;
        this.isMouseOver = !0, b && 1 != b.length || (a.preventDefault(), this.show(a, !0))
      }, b.prototype._onMove = function(a) {
        this.isOpen && (a.preventDefault(), this._move(a))
      }, b.prototype._onLeave = function() {
        this.isMouseOver = !1, this.isOpen && this.hide()
      }, b.prototype._onLoad = function(a) {
        a.currentTarget.width && (this.isReady = !0, this.$notice.detach(), this.$flyout.html(this.$zoom), this.$target.removeClass("is-loading").addClass("is-ready"), a.data.call && a.data())
      }, b.prototype._onError = function() {
        var a = this;
        this.$notice.text(this.opts.errorNotice), this.$target.removeClass("is-loading").addClass("is-error"), this.detachNotice = setTimeout(function() {
          a.$notice.detach(), a.detachNotice = null
        }, this.opts.errorDuration)
      }, b.prototype._loadImage = function(b, c) {
        var d = new Image;
        this.$target.addClass("is-loading").append(this.$notice.text(this.opts.loadingNotice)), this.$zoom = a(d).on("error", a.proxy(this._onError, this)).on("load", c, a.proxy(this._onLoad, this)), d.style.position = "absolute", d.src = b
      }, b.prototype._move = function(a) {
        if (0 === a.type.indexOf("touch")) {
          var b = a.touches || a.originalEvent.touches;
          g = b[0].pageX, h = b[0].pageY
        } else g = a.pageX || g, h = a.pageY || h;
        var i = this.$target.offset(),
          j = h - i.top,
          k = g - i.left,
          l = Math.ceil(j * f),
          m = Math.ceil(k * e);
        if (0 > m || 0 > l || m > c || l > d) this.hide();
        else {
          var n = -1 * l,
            o = -1 * m;
          this.$zoom.css({
            top: n,
            left: o
          }), this.opts.onMove.call(this, n, o)
        }
      }, b.prototype.hide = function() {
        this.isOpen && this.opts.beforeHide.call(this) !== !1 && (this.$flyout.detach(), this.isOpen = !1, this.opts.onHide.call(this))
      }, b.prototype.swap = function(b, c, d) {
        this.hide(), this.isReady = !1, this.detachNotice && clearTimeout(this.detachNotice), this.$notice.parent().length && this.$notice.detach(), this.$target.removeClass("is-loading is-ready is-error"), this.$image.attr({
          src: b,
          srcset: a.isArray(d) ? d.join() : d
        }), this.$link.attr(this.opts.linkAttribute, c)
      }, b.prototype.teardown = function() {
        this.hide(), this.$target.off(".easyzoom").removeClass("is-loading is-ready is-error"), this.detachNotice && clearTimeout(this.detachNotice), delete this.$link, delete this.$zoom, delete this.$image, delete this.$notice, delete this.$flyout, delete this.isOpen, delete this.isReady
      }, a.fn.easyZoom = function(c) {
        return this.each(function() {
          var d = a.data(this, "easyZoom");
          d ? void 0 === d.isOpen && d._init() : a.data(this, "easyZoom", new b(this, c))
        })
      }, "function" == typeof define && define.amd ? define(function() {
        return b
      }) : "undefined" != typeof module && module.exports && (module.exports = b)
    }(jQuery);



     // Instantiate EasyZoom instances
    var $easyzoom = $('.easyzoom').easyZoom({
      beforeHide: function() {
        this.$flyout.fadeOut();
        return false;
      },
      beforeShow: function() {
        this.$flyout.show();
      }
    });

     // Setup thumbnails example
    var api1 = $easyzoom.filter('.easyzoom--with-thumbnails').data('easyZoom');

    $('.thumbnails').on('click', 'a', function(e) {
      var $this = $(this);

      e.preventDefault();

      // Use EasyZoom's `swap` method
      api1.swap($this.data('standard'), $this.attr('href'));
    });

     // Setup toggles example
    var api2 = $easyzoom.filter('.easyzoom--with-toggle').data('easyZoom');

    $('.toggle').on('click', function() {
      var $this = $(this);

      if ($this.data("active") === true) {
        $this.text("Switch on").data("active", false);
        api2.teardown();
      } else {
        $this.text("Switch off").data("active", true);
        api2._init();
      }
    });
.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: default;
}
.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;
  opacity: 0;
  transition: 0.2s;
}
.easyzoom-flyout:hover {
  position: absolute;
  z-index: 100;
  overflow: hidden;
  background: #FFF;
  opacity: 1;
  transition: 0.8s;
}
.easyzoom--overlay .easyzoom-flyout {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.easyzoom--adjacent .easyzoom-flyout {
  top: 0;
  left: 100%;
  width: 100%;
  height: 100%;
  margin-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="easyzoom easyzoom--overlay">
  <a href="http://radarmidcentury.com.au/wp-content/uploads/2016/12/z-danish-sideboard-hans-wegner-president-in-oak-1a.jpg">
    <img src="http://radarmidcentury.com.au/wp-content/uploads/2016/12/z-danish-sideboard-hans-wegner-president-in-oak-1a.jpg" alt="" width="608.917" height="405.833" />
  </a>
</div>

You can refer the flyout zoomed image using this.$flyout in the functions.

Return false if you want to stop the default hide or show function. Just remember to add the default behavior into your function if you are doing that.

In the example I did above, I do a fadeOut on the zoomed image and stop the flyout from detaching (default behavior is detach() the zoomed image element). Then, as the flyout element was faded out, I have to use $.show() or the element will be stuck at display: none and nothing will be shown on mouseover.

Hope this helps.

Upvotes: 2

Paweł
Paweł

Reputation: 4516

'mouseleave' trigger _onLeave() which fire hide() which cause the zoomed div with image is removed from the DOM so any CSS transition or $().fadeOut() does not work. I removed hide() firing when mouseleave and change opacity in CSS and it seems to work now and anything else seems to be broken. Change opacity time as you wish.

fiddle

 /*!
 * @name        EasyZoom
 * @author      Matt Hinchliffe <>
 * @modified    Tuesday, September 6th, 2016
 * @version     2.4.0
 */
! function (a) {
	"use strict";

	function b(b, c) {
		this.$target = a(b), this.opts = a.extend({}, i, c, this.$target.data()), void 0 === this.isOpen && this._init()
	}
	var c, d, e, f, g, h, i = {
		loadingNotice: "Loading image",
		errorNotice: "The image could not be loaded",
		errorDuration: 2500,
		linkAttribute: "href",
		preventClicks: !0,
		beforeShow: a.noop,
		beforeHide: a.noop,
		onShow: a.noop,
		onHide: a.noop,
		onMove: a.noop
	};
	b.prototype._init = function () {
		this.$link = this.$target.find("a"), this.$image = this.$target.find("img"), this.$flyout = a('<div class="easyzoom-flyout" />'), this.$notice = a('<div class="easyzoom-notice" />'), this.$target.on({
			"mousemove.easyzoom touchmove.easyzoom": a.proxy(this._onMove, this),
			"mouseleave.easyzoom touchend.easyzoom": a.proxy(this._onLeave, this),
			"mouseenter.easyzoom touchstart.easyzoom": a.proxy(this._onEnter, this)
		}), this.opts.preventClicks && this.$target.on("click.easyzoom", function (a) {
			a.preventDefault()
		})
	}, b.prototype.show = function (a, b) {
		var g, h, i, j, k = this;
		if (this.opts.beforeShow.call(this) !== !1) {
			if (!this.isReady) return this._loadImage(this.$link.attr(this.opts.linkAttribute), function () {
				(k.isMouseOver || !b) && k.show(a)
			});
			this.$target.append(this.$flyout), g = this.$target.width(), h = this.$target.height(), i = this.$flyout.width(), j = this.$flyout.height(), c = this.$zoom.width() - i, d = this.$zoom.height() - j, 0 > c && (c = 0), 0 > d && (d = 0), e = c / g, f = d / h, this.isOpen = !0, this.opts.onShow.call(this), a && this._move(a)
		}
	}, b.prototype._onEnter = function (a) {
		var b = a.originalEvent.touches;
		this.isMouseOver = !0, b && 1 != b.length || (a.preventDefault(), this.show(a, !0))
	}, b.prototype._onMove = function (a) {
		this.isOpen && (a.preventDefault(), this._move(a))
	}, b.prototype._onLeave = function () {
  
		this.isMouseOver = !1, this.isOpen
	}, b.prototype._onLoad = function (a) {
		a.currentTarget.width && (this.isReady = !0, this.$notice.detach(), this.$flyout.html(this.$zoom), this.$target.removeClass("is-loading").addClass("is-ready"), a.data.call && a.data())
	}, b.prototype._onError = function () {
		var a = this;
		this.$notice.text(this.opts.errorNotice), this.$target.removeClass("is-loading").addClass("is-error"), this.detachNotice = setTimeout(function () {
			a.$notice.detach(), a.detachNotice = null
		}, this.opts.errorDuration)
	}, b.prototype._loadImage = function (b, c) {
		var d = new Image;
		this.$target.addClass("is-loading").append(this.$notice.text(this.opts.loadingNotice)), this.$zoom = a(d).on("error", a.proxy(this._onError, this)).on("load", c, a.proxy(this._onLoad, this)), d.style.position = "absolute", d.src = b
	}, b.prototype._move = function (a) {
		if (0 === a.type.indexOf("touch")) {
			var b = a.touches || a.originalEvent.touches;
			g = b[0].pageX, h = b[0].pageY
		} else g = a.pageX || g, h = a.pageY || h;
		var i = this.$target.offset(),
			j = h - i.top,
			k = g - i.left,
			l = Math.ceil(j * f),
			m = Math.ceil(k * e);
		if (0 > m || 0 > l || m > c || l > d) this.hide();
		else {
			var n = -1 * l,
				o = -1 * m;
			this.$zoom.css({
				top: n,
				left: o
			}), this.opts.onMove.call(this, n, o)
		}
	}, b.prototype.hide = function () {
  		
		this.isOpen && this.opts.beforeHide.call(this) !== !1 && (this.$flyout.detach(), this.isOpen = !1, this.opts.onHide.call(this))
	}, b.prototype.swap = function (b, c, d) {
		this.hide(), this.isReady = !1, this.detachNotice && clearTimeout(this.detachNotice), this.$notice.parent().length && this.$notice.detach(), this.$target.removeClass("is-loading is-ready is-error"), this.$image.attr({
			src: b,
			srcset: a.isArray(d) ? d.join() : d
		}), this.$link.attr(this.opts.linkAttribute, c)
	}, b.prototype.teardown = function () {
		this.hide(), this.$target.off(".easyzoom").removeClass("is-loading is-ready is-error"), this.detachNotice && clearTimeout(this.detachNotice), delete this.$link, delete this.$zoom, delete this.$image, delete this.$notice, delete this.$flyout, delete this.isOpen, delete this.isReady
	}, a.fn.easyZoom = function (c) {
		return this.each(function () {
			var d = a.data(this, "easyZoom");
			d ? void 0 === d.isOpen && d._init() : a.data(this, "easyZoom", new b(this, c))
		})
	}, "function" == typeof define && define.amd ? define(function () {
		return b
	}) : "undefined" != typeof module && module.exports && (module.exports = b)
}(jQuery);



		// Instantiate EasyZoom instances
		var $easyzoom = $('.easyzoom').easyZoom();

		// Setup thumbnails example
		var api1 = $easyzoom.filter('.easyzoom--with-thumbnails').data('easyZoom');

		$('.thumbnails').on('click', 'a', function(e) {
			var $this = $(this);

			e.preventDefault();

			// Use EasyZoom's `swap` method
			api1.swap($this.data('standard'), $this.attr('href'));
		});

		// Setup toggles example
		var api2 = $easyzoom.filter('.easyzoom--with-toggle').data('easyZoom');

		$('.toggle').on('click', function() {
			var $this = $(this);

			if ($this.data("active") === true) {
				$this.text("Switch on").data("active", false);
				api2.teardown();
			} else {
				$this.text("Switch off").data("active", true);
				api2._init();
			}
		});
    
.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: default;}
.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;
  opacity:0;
  transition: opacity 1s ease-in-out;
}
.easyzoom-flyout:hover {
	position:absolute;
	z-index: 100;
	overflow: hidden;
	background: #FFF;
  opacity:1;

}
.easyzoom--overlay .easyzoom-flyout {
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}
.easyzoom--adjacent .easyzoom-flyout {
	top: 0;
	left: 100%;
	width: 100%;
	height: 100%;
	margin-left: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="easyzoom easyzoom--overlay">
				<a href="http://radarmidcentury.com.au/wp-content/uploads/2016/12/z-danish-sideboard-hans-wegner-president-in-oak-1a.jpg">
					<img src="http://radarmidcentury.com.au/wp-content/uploads/2016/12/z-danish-sideboard-hans-wegner-president-in-oak-1a.jpg" alt="" width="608.917" height="405.833" />
				</a>
			</div>

Upvotes: 0

Related Questions