/*! lightgallery - v1.2.0 - 2015-08-26
* http://sachinchoolur.github.io/lightgallery/
* copyright (c) 2015 sachin n; licensed apache 2.0 */
/**
* zoom plugin
* @version 1.2.0
* @author sachin n - @sachinchoolur
* @license mit license (mit)
*/
(function($, window, document, undefined) {
'use strict';
var defaults = {
scale: 1,
zoom: true,
enablezoomafter: 300
};
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();
this.zoomabletimeout = false;
}
return this;
};
zoom.prototype.init = function() {
var _this = this;
var zoomicons = '';
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 one time
_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
* @param {boolean} db - true if zoom called via doubleclick
* @todo currently zoom origin is center it should work from all the directions
*/
var zoom = function(scaleval, db, pagex, pagey) {
var $image = _this.core.$outer.find('.lg-current .lg-image');
var _x;
var _y;
if (db) {
_x = pagex - $image.offset().left;
_y = pagey - $image.offset().top;
} else {
_x = $image.width() / 2;
_y = $image.height() / 2;
}
var x = (scaleval - 1) * (_x);
var y = (scaleval - 1) * (_y);
$image.css('transform', 'scale3d(' + scaleval + ', ' + scaleval + ', 1)').attr('data-scale', scaleval);
$image.parent().css('transform', 'translate3d(-' + x + 'px, -' + y + 'px, 0)').attr('data-x', x).attr('data-y', y);
};
var callscale = function(db, pagex, pagey) {
if (scale > 1) {
_this.core.$outer.addclass('lg-zoomed');
} else {
_this.core.$outer.removeclass('lg-zoomed');
}
if (scale < 1) {
scale = 1;
}
zoom(scale, db, pagex, pagey);
};
// 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.dblclick(function(event) {
var w = $image.width();
var 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;
}
}
callscale(true, event.pagex, event.pagey);
settimeout(function() {
_this.core.$outer.removeclass('lg-grabbing').addclass('lg-grab');
}, 10);
});
});
// update zoom on resize and orientationchange
$(window).on('resize.lg.zoom orientationchange.lg.zoom', function() {
settimeout(function() {
if (_this.core.$outer.hasclass('lg-zoomed')) {
zoom(scale);
}
}, 10);
});
$('#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();
}
});
// reset zoom on slide change
_this.core.$el.on('onbeforeslide.lg.tm', function() {
_this.resetzoom();
});
// drag option after zoom
if (!_this.core.istouch) {
_this.zoomdrag();
}
if (_this.core.istouch) {
_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');
};
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.outerheight() * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
allowx = $image.outerwidth() * $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 = e.originalevent.targettouches[0].pagex;
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'));
}
_$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.outerheight() * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
allowx = $image.outerwidth() * $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'));
}
_$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.outerheight()) / 2;
var maxy = math.abs(($image.outerheight() * math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').height() + miny);
var minx = (_this.core.$outer.find('.lg').width() - $image.outerwidth()) / 2;
var maxx = math.abs(($image.outerwidth() * math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').width() + minx);
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'));
}
_$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;
})(jquery, window, document);