/*! lg-zoom - v1.1.0 - 2017-08-08
* http://sachinchoolur.github.io/lightgallery
* copyright (c) 2017 sachin n; licensed gplv3 */
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// amd. register as an anonymous module unless amdmoduleid is set
define(['jquery'], function (a0) {
return (factory(a0));
});
} else if (typeof exports === 'object') {
// node. does not work with strict commonjs, but
// only commonjs-like environments that support module.exports,
// like node.
module.exports = factory(require('jquery'));
} else {
factory(jquery);
}
}(this, function ($) {
(function() {
'use strict';
var getuseleft = function() {
var useleft = false;
var ischrome = navigator.useragent.match(/chrom(e|ium)\/([0-9]+)\./);
if (ischrome && parseint(ischrome[2], 10) < 54) {
useleft = true;
}
return useleft;
};
var defaults = {
scale: 1,
zoom: true,
actualsize: true,
enablezoomafter: 300,
useleftforzoom: getuseleft()
};
var zoom = function(element) {
this.core = $(element).data('lightgallery');
this.core.s = $.extend({}, defaults, this.core.s);
if (this.core.s.zoom && this.core.docss()) {
this.init();
// store the zoomable timeout value just to clear it while closing
this.zoomabletimeout = false;
// set the initial value center
this.pagex = $(window).width() / 2;
this.pagey = ($(window).height() / 2) + $(window).scrolltop();
}
return this;
};
zoom.prototype.init = function() {
var _this = this;
var zoomicons = '';
if (_this.core.s.actualsize) {
zoomicons += '';
}
if (_this.core.s.useleftforzoom) {
_this.core.$outer.addclass('lg-use-left-for-zoom');
} else {
_this.core.$outer.addclass('lg-use-transition-for-zoom');
}
this.core.$outer.find('.lg-toolbar').append(zoomicons);
// add zoomable class
_this.core.$el.on('onslideitemload.lg.tm.zoom', function(event, index, delay) {
// delay will be 0 except first time
var _speed = _this.core.s.enablezoomafter + delay;
// set _speed value 0 if gallery opened from direct url and if it is first slide
if ($('body').hasclass('lg-from-hash') && delay) {
// will execute only once
_speed = 0;
} else {
// remove lg-from-hash to enable starting animation.
$('body').removeclass('lg-from-hash');
}
_this.zoomabletimeout = settimeout(function() {
_this.core.$slide.eq(index).addclass('lg-zoomable');
}, _speed + 30);
});
var scale = 1;
/**
* @desc image zoom
* translate the wrap and scale the image to get better user experience
*
* @param {string} scaleval - zoom decrement/increment value
*/
var zoom = function(scaleval) {
var $image = _this.core.$outer.find('.lg-current .lg-image');
var _x;
var _y;
// find offset manually to avoid issue after zoom
var offsetx = ($(window).width() - $image.prop('offsetwidth')) / 2;
var offsety = (($(window).height() - $image.prop('offsetheight')) / 2) + $(window).scrolltop();
_x = _this.pagex - offsetx;
_y = _this.pagey - offsety;
var x = (scaleval - 1) * (_x);
var y = (scaleval - 1) * (_y);
$image.css('transform', 'scale3d(' + scaleval + ', ' + scaleval + ', 1)').attr('data-scale', scaleval);
if (_this.core.s.useleftforzoom) {
$image.parent().css({
left: -x + 'px',
top: -y + 'px'
}).attr('data-x', x).attr('data-y', y);
} else {
$image.parent().css('transform', 'translate3d(-' + x + 'px, -' + y + 'px, 0)').attr('data-x', x).attr('data-y', y);
}
};
var callscale = function() {
if (scale > 1) {
_this.core.$outer.addclass('lg-zoomed');
} else {
_this.resetzoom();
}
if (scale < 1) {
scale = 1;
}
zoom(scale);
};
var actualsize = function(event, $image, index, fromicon) {
var w = $image.prop('offsetwidth');
var nw;
if (_this.core.s.dynamic) {
nw = _this.core.s.dynamicel[index].width || $image[0].naturalwidth || w;
} else {
nw = _this.core.$items.eq(index).attr('data-width') || $image[0].naturalwidth || w;
}
var _scale;
if (_this.core.$outer.hasclass('lg-zoomed')) {
scale = 1;
} else {
if (nw > w) {
_scale = nw / w;
scale = _scale || 2;
}
}
if (fromicon) {
_this.pagex = $(window).width() / 2;
_this.pagey = ($(window).height() / 2) + $(window).scrolltop();
} else {
_this.pagex = event.pagex || event.originalevent.targettouches[0].pagex;
_this.pagey = event.pagey || event.originalevent.targettouches[0].pagey;
}
callscale();
settimeout(function() {
_this.core.$outer.removeclass('lg-grabbing').addclass('lg-grab');
}, 10);
};
var tapped = false;
// event triggered after appending slide content
_this.core.$el.on('onaferappendslide.lg.tm.zoom', function(event, index) {
// get the current element
var $image = _this.core.$slide.eq(index).find('.lg-image');
$image.on('dblclick', function(event) {
actualsize(event, $image, index);
});
$image.on('touchstart', function(event) {
if (!tapped) {
tapped = settimeout(function() {
tapped = null;
}, 300);
} else {
cleartimeout(tapped);
tapped = null;
actualsize(event, $image, index);
}
event.preventdefault();
});
});
// update zoom on resize and orientationchange
$(window).on('resize.lg.zoom scroll.lg.zoom orientationchange.lg.zoom', function() {
_this.pagex = $(window).width() / 2;
_this.pagey = ($(window).height() / 2) + $(window).scrolltop();
zoom(scale);
});
$('#lg-zoom-out').on('click.lg', function() {
if (_this.core.$outer.find('.lg-current .lg-image').length) {
scale -= _this.core.s.scale;
callscale();
}
});
$('#lg-zoom-in').on('click.lg', function() {
if (_this.core.$outer.find('.lg-current .lg-image').length) {
scale += _this.core.s.scale;
callscale();
}
});
$('#lg-actual-size').on('click.lg', function(event) {
actualsize(event, _this.core.$slide.eq(_this.core.index).find('.lg-image'), _this.core.index, true);
});
// reset zoom on slide change
_this.core.$el.on('onbeforeslide.lg.tm', function() {
scale = 1;
_this.resetzoom();
});
// drag option after zoom
_this.zoomdrag();
_this.zoomswipe();
};
// reset zoom effect
zoom.prototype.resetzoom = function() {
this.core.$outer.removeclass('lg-zoomed');
this.core.$slide.find('.lg-img-wrap').removeattr('style data-x data-y');
this.core.$slide.find('.lg-image').removeattr('style data-scale');
// reset pagx pagy values to center
this.pagex = $(window).width() / 2;
this.pagey = ($(window).height() / 2) + $(window).scrolltop();
};
zoom.prototype.zoomswipe = function() {
var _this = this;
var startcoords = {};
var endcoords = {};
var ismoved = false;
// allow x direction drag
var allowx = false;
// allow y direction drag
var allowy = false;
_this.core.$slide.on('touchstart.lg', function(e) {
if (_this.core.$outer.hasclass('lg-zoomed')) {
var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
allowy = $image.prop('offsetheight') * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
allowx = $image.prop('offsetwidth') * $image.attr('data-scale') > _this.core.$outer.find('.lg').width();
if ((allowx || allowy)) {
e.preventdefault();
startcoords = {
x: e.originalevent.targettouches[0].pagex,
y: e.originalevent.targettouches[0].pagey
};
}
}
});
_this.core.$slide.on('touchmove.lg', function(e) {
if (_this.core.$outer.hasclass('lg-zoomed')) {
var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
var distancex;
var distancey;
e.preventdefault();
ismoved = true;
endcoords = {
x: e.originalevent.targettouches[0].pagex,
y: e.originalevent.targettouches[0].pagey
};
// reset opacity and transition duration
_this.core.$outer.addclass('lg-zoom-dragging');
if (allowy) {
distancey = (-math.abs(_$el.attr('data-y'))) + (endcoords.y - startcoords.y);
} else {
distancey = -math.abs(_$el.attr('data-y'));
}
if (allowx) {
distancex = (-math.abs(_$el.attr('data-x'))) + (endcoords.x - startcoords.x);
} else {
distancex = -math.abs(_$el.attr('data-x'));
}
if ((math.abs(endcoords.x - startcoords.x) > 15) || (math.abs(endcoords.y - startcoords.y) > 15)) {
if (_this.core.s.useleftforzoom) {
_$el.css({
left: distancex + 'px',
top: distancey + 'px'
});
} else {
_$el.css('transform', 'translate3d(' + distancex + 'px, ' + distancey + 'px, 0)');
}
}
}
});
_this.core.$slide.on('touchend.lg', function() {
if (_this.core.$outer.hasclass('lg-zoomed')) {
if (ismoved) {
ismoved = false;
_this.core.$outer.removeclass('lg-zoom-dragging');
_this.touchendzoom(startcoords, endcoords, allowx, allowy);
}
}
});
};
zoom.prototype.zoomdrag = function() {
var _this = this;
var startcoords = {};
var endcoords = {};
var isdraging = false;
var ismoved = false;
// allow x direction drag
var allowx = false;
// allow y direction drag
var allowy = false;
_this.core.$slide.on('mousedown.lg.zoom', function(e) {
// execute only on .lg-object
var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
allowy = $image.prop('offsetheight') * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
allowx = $image.prop('offsetwidth') * $image.attr('data-scale') > _this.core.$outer.find('.lg').width();
if (_this.core.$outer.hasclass('lg-zoomed')) {
if ($(e.target).hasclass('lg-object') && (allowx || allowy)) {
e.preventdefault();
startcoords = {
x: e.pagex,
y: e.pagey
};
isdraging = true;
// ** fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
_this.core.$outer.scrollleft += 1;
_this.core.$outer.scrollleft -= 1;
_this.core.$outer.removeclass('lg-grab').addclass('lg-grabbing');
}
}
});
$(window).on('mousemove.lg.zoom', function(e) {
if (isdraging) {
var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
var distancex;
var distancey;
ismoved = true;
endcoords = {
x: e.pagex,
y: e.pagey
};
// reset opacity and transition duration
_this.core.$outer.addclass('lg-zoom-dragging');
if (allowy) {
distancey = (-math.abs(_$el.attr('data-y'))) + (endcoords.y - startcoords.y);
} else {
distancey = -math.abs(_$el.attr('data-y'));
}
if (allowx) {
distancex = (-math.abs(_$el.attr('data-x'))) + (endcoords.x - startcoords.x);
} else {
distancex = -math.abs(_$el.attr('data-x'));
}
if (_this.core.s.useleftforzoom) {
_$el.css({
left: distancex + 'px',
top: distancey + 'px'
});
} else {
_$el.css('transform', 'translate3d(' + distancex + 'px, ' + distancey + 'px, 0)');
}
}
});
$(window).on('mouseup.lg.zoom', function(e) {
if (isdraging) {
isdraging = false;
_this.core.$outer.removeclass('lg-zoom-dragging');
// fix for chrome mouse move on click
if (ismoved && ((startcoords.x !== endcoords.x) || (startcoords.y !== endcoords.y))) {
endcoords = {
x: e.pagex,
y: e.pagey
};
_this.touchendzoom(startcoords, endcoords, allowx, allowy);
}
ismoved = false;
}
_this.core.$outer.removeclass('lg-grabbing').addclass('lg-grab');
});
};
zoom.prototype.touchendzoom = function(startcoords, endcoords, allowx, allowy) {
var _this = this;
var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
var distancex = (-math.abs(_$el.attr('data-x'))) + (endcoords.x - startcoords.x);
var distancey = (-math.abs(_$el.attr('data-y'))) + (endcoords.y - startcoords.y);
var miny = (_this.core.$outer.find('.lg').height() - $image.prop('offsetheight')) / 2;
var maxy = math.abs(($image.prop('offsetheight') * math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').height() + miny);
var minx = (_this.core.$outer.find('.lg').width() - $image.prop('offsetwidth')) / 2;
var maxx = math.abs(($image.prop('offsetwidth') * math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').width() + minx);
if ((math.abs(endcoords.x - startcoords.x) > 15) || (math.abs(endcoords.y - startcoords.y) > 15)) {
if (allowy) {
if (distancey <= -maxy) {
distancey = -maxy;
} else if (distancey >= -miny) {
distancey = -miny;
}
}
if (allowx) {
if (distancex <= -maxx) {
distancex = -maxx;
} else if (distancex >= -minx) {
distancex = -minx;
}
}
if (allowy) {
_$el.attr('data-y', math.abs(distancey));
} else {
distancey = -math.abs(_$el.attr('data-y'));
}
if (allowx) {
_$el.attr('data-x', math.abs(distancex));
} else {
distancex = -math.abs(_$el.attr('data-x'));
}
if (_this.core.s.useleftforzoom) {
_$el.css({
left: distancex + 'px',
top: distancey + 'px'
});
} else {
_$el.css('transform', 'translate3d(' + distancex + 'px, ' + distancey + 'px, 0)');
}
}
};
zoom.prototype.destroy = function() {
var _this = this;
// unbind all events added by lightgallery zoom plugin
_this.core.$el.off('.lg.zoom');
$(window).off('.lg.zoom');
_this.core.$slide.off('.lg.zoom');
_this.core.$el.off('.lg.tm.zoom');
_this.resetzoom();
cleartimeout(_this.zoomabletimeout);
_this.zoomabletimeout = false;
};
$.fn.lightgallery.modules.zoom = zoom;
})();
}));