1(function($, window, document, undefined) { 2 3 'use strict'; 4 5 var defaults = { 6 scale: 1, 7 zoom: true, 8 actualSize: true, 9 enableZoomAfter: 300 10 }; 11 12 var Zoom = function(element) { 13 14 this.core = $(element).data('lightGallery'); 15 16 this.core.s = $.extend({}, defaults, this.core.s); 17 18 if (this.core.s.zoom && this.core.doCss()) { 19 this.init(); 20 21 // Store the zoomable timeout value just to clear it while closing 22 this.zoomabletimeout = false; 23 24 // Set the initial value center 25 this.pageX = $(window).width() / 2; 26 this.pageY = ($(window).height() / 2) + $(window).scrollTop(); 27 } 28 29 return this; 30 }; 31 32 Zoom.prototype.init = function() { 33 34 var _this = this; 35 var zoomIcons = '<span id="lg-zoom-in" class="lg-icon"></span><span id="lg-zoom-out" class="lg-icon"></span>'; 36 37 if (_this.core.s.actualSize) { 38 zoomIcons += '<span id="lg-actual-size" class="lg-icon"></span>'; 39 } 40 41 this.core.$outer.find('.lg-toolbar').append(zoomIcons); 42 43 // Add zoomable class 44 _this.core.$el.on('onSlideItemLoad.lg.tm.zoom', function(event, index, delay) { 45 46 // delay will be 0 except first time 47 var _speed = _this.core.s.enableZoomAfter + delay; 48 49 // set _speed value 0 if gallery opened from direct url and if it is first slide 50 if ($('body').hasClass('lg-from-hash') && delay) { 51 52 // will execute only once 53 _speed = 0; 54 } else { 55 56 // Remove lg-from-hash to enable starting animation. 57 $('body').removeClass('lg-from-hash'); 58 } 59 60 _this.zoomabletimeout = setTimeout(function() { 61 _this.core.$slide.eq(index).addClass('lg-zoomable'); 62 }, _speed + 30); 63 }); 64 65 var scale = 1; 66 /** 67 * @desc Image zoom 68 * Translate the wrap and scale the image to get better user experience 69 * 70 * @param {String} scaleVal - Zoom decrement/increment value 71 */ 72 var zoom = function(scaleVal) { 73 74 var $image = _this.core.$outer.find('.lg-current .lg-image'); 75 var _x; 76 var _y; 77 78 // Find offset manually to avoid issue after zoom 79 var offsetX = ($(window).width() - $image.width()) / 2; 80 var offsetY = (($(window).height() - $image.height()) / 2) + $(window).scrollTop(); 81 82 _x = _this.pageX - offsetX; 83 _y = _this.pageY - offsetY; 84 85 var x = (scaleVal - 1) * (_x); 86 var y = (scaleVal - 1) * (_y); 87 88 $image.css('transform', 'scale3d(' + scaleVal + ', ' + scaleVal + ', 1)').attr('data-scale', scaleVal); 89 90 $image.parent().css({ 91 left: -x + 'px', 92 top: -y + 'px' 93 }).attr('data-x', x).attr('data-y', y); 94 }; 95 96 var callScale = function() { 97 if (scale > 1) { 98 _this.core.$outer.addClass('lg-zoomed'); 99 } else { 100 _this.resetZoom(); 101 } 102 103 if (scale < 1) { 104 scale = 1; 105 } 106 107 zoom(scale); 108 }; 109 110 var actualSize = function(event, $image, index, fromIcon) { 111 var w = $image.width(); 112 var nw; 113 if (_this.core.s.dynamic) { 114 nw = _this.core.s.dynamicEl[index].width || $image[0].naturalWidth || w; 115 } else { 116 nw = _this.core.$items.eq(index).attr('data-width') || $image[0].naturalWidth || w; 117 } 118 119 var _scale; 120 121 if (_this.core.$outer.hasClass('lg-zoomed')) { 122 scale = 1; 123 } else { 124 if (nw > w) { 125 _scale = nw / w; 126 scale = _scale || 2; 127 } 128 } 129 130 if (fromIcon) { 131 _this.pageX = $(window).width() / 2; 132 _this.pageY = ($(window).height() / 2) + $(window).scrollTop(); 133 } else { 134 _this.pageX = event.pageX || event.originalEvent.targetTouches[0].pageX; 135 _this.pageY = event.pageY || event.originalEvent.targetTouches[0].pageY; 136 } 137 138 callScale(); 139 setTimeout(function() { 140 _this.core.$outer.removeClass('lg-grabbing').addClass('lg-grab'); 141 }, 10); 142 }; 143 144 var tapped = false;
145 146 // event triggered after appending slide content 147 _this.core.$el.on('onAferAppendSlide.lg.tm.zoom', function(event, index) { 148 149 // Get the current element 150 var $image = _this.core.$slide.eq(index).find('.lg-image'); 151 152 $image.on('dblclick', function(event) { 153 actualSize(event, $image, index); 154 }); 155 156 $image.on('touchstart', function(event) { 157 if (!tapped) { 158 tapped = setTimeout(function() { 159 tapped = null; 160 }, 300); 161 } else { 162 clearTimeout(tapped); 163 tapped = null; 164 actualSize(event, $image, index); 165 } 166 167 event.preventDefault(); 168 }); 169 170 }); 171 172 // Update zoom on resize and orientationchange 173 $(window).on('resize.lg.zoom scroll.lg.zoom orientationchange.lg.zoom', function() { 174 _this.pageX = $(window).width() / 2; 175 _this.pageY = ($(window).height() / 2) + $(window).scrollTop(); 176 zoom(scale); 177 }); 178 179 $('#lg-zoom-out').on('click.lg', function() { 180 if (_this.core.$outer.find('.lg-current .lg-image').length) { 181 scale -= _this.core.s.scale; 182 callScale(); 183 } 184 }); 185 186 $('#lg-zoom-in').on('click.lg', function() { 187 if (_this.core.$outer.find('.lg-current .lg-image').length) { 188 scale += _this.core.s.scale; 189 callScale(); 190 } 191 }); 192 193 $('#lg-actual-size').on('click.lg', function(event) { 194 actualSize(event, _this.core.$slide.eq(_this.core.index).find('.lg-image'), _this.core.index, true); 195 }); 196 197 // Reset zoom on slide change 198 _this.core.$el.on('onBeforeSlide.lg.tm', function() { 199 scale = 1; 200 _this.resetZoom(); 201 }); 202 203 // Drag option after zoom 204 if (!_this.core.isTouch) { 205 _this.zoomDrag(); 206 } 207 208 if (_this.core.isTouch) { 209 _this.zoomSwipe(); 210 } 211 212 }; 213 214 // Reset zoom effect 215 Zoom.prototype.resetZoom = function() { 216 this.core.$outer.removeClass('lg-zoomed'); 217 this.core.$slide.find('.lg-img-wrap').removeAttr('style data-x data-y'); 218 this.core.$slide.find('.lg-image').removeAttr('style data-scale'); 219 220 // Reset pagx pagy values to center 221 this.pageX = $(window).width() / 2; 222 this.pageY = ($(window).height() / 2) + $(window).scrollTop(); 223 }; 224 225 Zoom.prototype.zoomSwipe = function() { 226 var _this = this; 227 var startCoords = {}; 228 var endCoords = {}; 229 var isMoved = false; 230 231 // Allow x direction drag 232 var allowX = false; 233 234 // Allow Y direction drag 235 var allowY = false; 236 237 _this.core.$slide.on('touchstart.lg', function(e) { 238 239 if (_this.core.$outer.hasClass('lg-zoomed')) { 240 var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object'); 241 242 allowY = $image.outerHeight() * $image.attr('data-scale') > _this.core.$outer.find('.lg').height(); 243 allowX = $image.outerWidth() * $image.attr('data-scale') > _this.core.$outer.find('.lg').width(); 244 if ((allowX || allowY)) { 245 e.preventDefault(); 246 startCoords = { 247 x: e.originalEvent.targetTouches[0].pageX, 248 y: e.originalEvent.targetTouches[0].pageY 249 }; 250 } 251 } 252 253 }); 254 255 _this.core.$slide.on('touchmove.lg', function(e) { 256 257 if (_this.core.$outer.hasClass('lg-zoomed')) { 258 259 var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap'); 260 var distanceX; 261 var distanceY; 262 263 e.preventDefault(); 264 isMoved = true; 265 266 endCoords = { 267 x: e.originalEvent.targetTouches[0].pageX, 268 y: e.originalEvent.targetTouches[0].pageY 269 }; 270 271 // reset opacity and transition duration 272 _this.core.$outer.addClass('lg-zoom-dragging'); 273 274 if (allowY) { 275 distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y); 276 } else { 277 distanceY = -Math.abs(_$el.attr('data-y')); 278 } 279 280 if (allowX) { 281 distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x); 282 } else { 283 distanceX = -Math.abs(_$el.attr('data-x')); 284 } 285 286 if ((Math.abs(endCoords.x - startCoords.x) > 15) || (Math.abs(endCoords.y - startCoords.y) > 15)) { 287 _$el.css({ 288 left: distanceX + 'px', 289 top: distanceY + 'px' 290 }); 291 } 292 293 } 294 295 }); 296 297 _this.core.$slide.on('touchend.lg', function() { 298 if (_this.core.$outer.hasClass('lg-zoomed')) { 299 if (isMoved) { 300 isMoved = false;
301 _this.core.$outer.removeClass('lg-zoom-dragging'); 302 _this.touchendZoom(startCoords, endCoords, allowX, allowY); 303 304 } 305 } 306 }); 307 308 }; 309 310 Zoom.prototype.zoomDrag = function() { 311 312 var _this = this; 313 var startCoords = {}; 314 var endCoords = {}; 315 var isDraging = false; 316 var isMoved = false; 317 318 // Allow x direction drag 319 var allowX = false; 320 321 // Allow Y direction drag 322 var allowY = false; 323 324 _this.core.$slide.on('mousedown.lg.zoom', function(e) { 325 326 // execute only on .lg-object 327 var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object'); 328 329 allowY = $image.outerHeight() * $image.attr('data-scale') > _this.core.$outer.find('.lg').height(); 330 allowX = $image.outerWidth() * $image.attr('data-scale') > _this.core.$outer.find('.lg').width(); 331 332 if (_this.core.$outer.hasClass('lg-zoomed')) { 333 if ($(e.target).hasClass('lg-object') && (allowX || allowY)) { 334 e.preventDefault(); 335 startCoords = { 336 x: e.pageX, 337 y: e.pageY 338 }; 339 340 isDraging = true; 341 342 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 343 _this.core.$outer.scrollLeft += 1; 344 _this.core.$outer.scrollLeft -= 1; 345 346 _this.core.$outer.removeClass('lg-grab').addClass('lg-grabbing'); 347 } 348 } 349 }); 350 351 $(window).on('mousemove.lg.zoom', function(e) { 352 if (isDraging) { 353 var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap'); 354 var distanceX; 355 var distanceY; 356 357 isMoved = true; 358 endCoords = { 359 x: e.pageX, 360 y: e.pageY 361 }; 362 363 // reset opacity and transition duration 364 _this.core.$outer.addClass('lg-zoom-dragging'); 365 366 if (allowY) { 367 distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y); 368 } else { 369 distanceY = -Math.abs(_$el.attr('data-y')); 370 } 371 372 if (allowX) { 373 distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x); 374 } else { 375 distanceX = -Math.abs(_$el.attr('data-x')); 376 } 377 378 _$el.css({ 379 left: distanceX + 'px', 380 top: distanceY + 'px' 381 }); 382 } 383 }); 384 385 $(window).on('mouseup.lg.zoom', function(e) { 386 387 if (isDraging) { 388 isDraging = false; 389 _this.core.$outer.removeClass('lg-zoom-dragging'); 390 391 // Fix for chrome mouse move on click 392 if (isMoved && ((startCoords.x !== endCoords.x) || (startCoords.y !== endCoords.y))) { 393 endCoords = { 394 x: e.pageX, 395 y: e.pageY 396 }; 397 _this.touchendZoom(startCoords, endCoords, allowX, allowY); 398 399 } 400 401 isMoved = false; 402 } 403 404 _this.core.$outer.removeClass('lg-grabbing').addClass('lg-grab'); 405 406 }); 407 }; 408 409 Zoom.prototype.touchendZoom = function(startCoords, endCoords, allowX, allowY) { 410 411 var _this = this; 412 var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap'); 413 var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object'); 414 var distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x); 415 var distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y); 416 var minY = (_this.core.$outer.find('.lg').height() - $image.outerHeight()) / 2; 417 var maxY = Math.abs(($image.outerHeight() * Math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').height() + minY); 418 var minX = (_this.core.$outer.find('.lg').width() - $image.outerWidth()) / 2; 419 var maxX = Math.abs(($image.outerWidth() * Math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').width() + minX); 420 421 if ((Math.abs(endCoords.x - startCoords.x) > 15) || (Math.abs(endCoords.y - startCoords.y) > 15)) { 422 if (allowY) { 423 if (distanceY <= -maxY) { 424 distanceY = -maxY; 425 } else if (distanceY >= -minY) { 426 distanceY = -minY; 427 } 428 } 429 430 if (allowX) { 431 if (distanceX <= -maxX) { 432 distanceX = -maxX; 433 } else if (distanceX >= -minX) { 434 distanceX = -minX; 435 } 436 } 437 438 if (allowY) { 439 _$el.attr('data-y', Math.abs(distanceY)); 440 } else { 441 distanceY = -Math.abs(_$el.attr('data-y')); 442 } 443 444 if (allowX) { 445 _$el.attr('data-x', Math.abs(distanceX)); 446 } else { 447 distanceX = -Math.abs(_$el.attr('data-x')); 448 } 449 450 _$el.css({ 451 left: distanceX + 'px', 452 top: distanceY + 'px' 453 }); 454 455 } 456 }; 457 458 Zoom.prototype.destroy = function() { 459 460 var _this = this; 461 462 // Unbind all events added by lightGallery zoom plugin 463 _this.core.$el.off('.lg.zoom'); 464 $(window).off('.lg.zoom'); 465 _this.core.$slide.off('.lg.zoom'); 466 _this.core.$el.off('.lg.tm.zoom'); 467 _this.resetZoom(); 468 clearTimeout(_this.zoomabletimeout); 469 _this.zoomabletimeout = false;
470 }; 471 472 $.fn.lightGallery.modules.zoom = Zoom; 473 474})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.