1(function($, window, document, undefined) { 2 3 'use strict'; 4 5 var defaults = { 6 7 mode: 'lg-slide', 8 9 // Ex : 'ease' 10 cssEasing: 'ease', 11 12 //'for jquery animation' 13 easing: 'linear', 14 speed: 600, 15 height: '100%', 16 width: '100%', 17 addClass: '', 18 startClass: 'lg-start-zoom', 19 backdropDuration: 150, 20 hideBarsDelay: 6000, 21 22 useLeft: false, 23 24 closable: true, 25 loop: true, 26 escKey: true, 27 keyPress: true, 28 controls: true, 29 slideEndAnimatoin: true, 30 hideControlOnEnd: false, 31 mousewheel: true, 32 33 getCaptionFromTitleOrAlt: true, 34 35 // .lg-item || '.lg-sub-html' 36 appendSubHtmlTo: '.lg-sub-html', 37 38 /** 39 * @desc number of preload slides 40 * will exicute only after the current slide is fully loaded. 41 * 42 * @ex you clicked on 4th image and if preload = 1 then 3rd slide and 5th 43 * slide will be loaded in the background after the 4th slide is fully loaded.. 44 * if preload is 2 then 2nd 3rd 5th 6th slides will be preloaded.. ... ... 45 * 46 */ 47 preload: 1, 48 showAfterLoad: true, 49 selector: '', 50 selectWithin: '', 51 nextHtml: '', 52 prevHtml: '', 53 54 // 0, 1 55 index: false, 56 57 iframeMaxWidth: '100%', 58 59 download: false, 60 counter: true, 61 appendCounterTo: '.lg-toolbar', 62 63 swipeThreshold: 50, 64 enableSwipe: true, 65 enableDrag: true, 66 67 dynamic: false, 68 dynamicEl: [], 69 galleryId: 1 70 }; 71 72 function Plugin(element, options) { 73 74 // Current lightGallery element 75 this.el = element; 76 77 // Current jquery element 78 this.$el = $(element); 79 80 // lightGallery settings 81 this.s = $.extend({}, defaults, options); 82 83 // When using dynamic mode, ensure dynamicEl is an array 84 if (this.s.dynamic && this.s.dynamicEl !== 'undefined' && this.s.dynamicEl.constructor === Array && !this.s.dynamicEl.length) { 85 throw ('When using dynamic mode, you must also define dynamicEl as an Array.'); 86 } 87 88 // lightGallery modules 89 this.modules = {}; 90 91 // false when lightgallery complete first slide; 92 this.lGalleryOn = false; 93 94 this.lgBusy = false; 95 96 // Timeout function for hiding controls; 97 this.hideBartimeout = false; 98 99 // To determine browser supports for touch events; 100 this.isTouch = ('ontouchstart' in document.documentElement); 101 102 // Disable hideControlOnEnd if sildeEndAnimation is true 103 if (this.s.slideEndAnimatoin) { 104 this.s.hideControlOnEnd = false; 105 } 106 107 // Gallery items 108 if (this.s.dynamic) { 109 this.$items = this.s.dynamicEl; 110 } else { 111 if (this.s.selector === 'this') { 112 this.$items = this.$el; 113 } else if (this.s.selector !== '') { 114 if (this.s.selectWithin) { 115 this.$items = $(this.s.selectWithin).find(this.s.selector); 116 } else { 117 this.$items = this.$el.find($(this.s.selector)); 118 } 119 } else { 120 this.$items = this.$el.children(); 121 } 122 } 123 124 // .lg-item 125 this.$slide = ''; 126 127 // .lg-outer 128 this.$outer = ''; 129 130 this.init(); 131 132 return this; 133 } 134 135 Plugin.prototype.init = function() { 136 137 var _this = this; 138 139 // s.preload should not be more than $item.length 140 if (_this.s.preload > _this.$items.length) { 141 _this.s.preload = _this.$items.length; 142 } 143 144 // if dynamic option is enabled execute immediately 145 var _hash = window.location.hash; 146 if (_hash.indexOf('lg=' + this.s.galleryId) > 0) { 147 148 _this.index = parseInt(_hash.split('&slide=')[1], 10); 149 150 $('body').addClass('lg-from-hash'); 151 if (!$('body').hasClass('lg-on')) { 152 setTimeout(function() { 153 _this.build(_this.index); 154 $('body').addClass('lg-on'); 155 }); 156 } 157 } 158 159 if (_this.s.dynamic) { 160 161 _this.$el.trigger('onBeforeOpen.lg'); 162 163 _this.index = _this.s.index || 0; 164 165 // prevent accidental double execution 166 if (!$('body').hasClass('lg-on')) { 167 setTimeout(function() { 168 _this.build(_this.index); 169 $('body').addClass('lg-on'); 170 }); 171 } 172 } else { 173 174 // Using different namespace for click because click event should not unbind if selector is same object('this') 175 _this.$items.on('click.lgcustom', function(event) { 176 177 // For IE8 178 try { 179 event.preventDefault(); 180 event.preventDefault(); 181 } catch (er) { 182 event.returnValue = false;
183 } 184 185 _this.$el.trigger('onBeforeOpen.lg'); 186 187 _this.index = _this.s.index || _this.$items.index(this); 188 189 // prevent accidental double execution 190 if (!$('body').hasClass('lg-on')) { 191 _this.build(_this.index); 192 $('body').addClass('lg-on'); 193 } 194 }); 195 } 196 197 }; 198 199 Plugin.prototype.build = function(index) { 200 201 var _this = this; 202 203 _this.structure(); 204 205 // module constructor 206 $.each($.fn.lightGallery.modules, function(key) { 207 _this.modules[key] = new $.fn.lightGallery.modules[key](_this.el); 208 }); 209 210 // initiate slide function 211 _this.slide(index, false, false); 212 213 if (_this.s.keyPress) { 214 _this.keyPress(); 215 } 216 217 if (_this.$items.length > 1) { 218 219 _this.arrow(); 220 221 setTimeout(function() { 222 _this.enableDrag(); 223 _this.enableSwipe(); 224 }, 50); 225 226 if (_this.s.mousewheel) { 227 _this.mousewheel(); 228 } 229 } 230 231 _this.counter(); 232 233 _this.closeGallery(); 234 235 _this.$el.trigger('onAfterOpen.lg'); 236 237 // Hide controllers if mouse doesn't move for some period 238 _this.$outer.on('mousemove.lg click.lg touchstart.lg', function() { 239 240 _this.$outer.removeClass('lg-hide-items'); 241 242 clearTimeout(_this.hideBartimeout); 243 244 // Timeout will be cleared on each slide movement also 245 _this.hideBartimeout = setTimeout(function() { 246 _this.$outer.addClass('lg-hide-items'); 247 }, _this.s.hideBarsDelay); 248 249 }); 250 251 }; 252 253 Plugin.prototype.structure = function() { 254 var list = ''; 255 var controls = ''; 256 var i = 0; 257 var subHtmlCont = ''; 258 var template; 259 var _this = this; 260 261 $('body').append('<div class="lg-backdrop"></div>'); 262 $('.lg-backdrop').css('transition-duration', this.s.backdropDuration + 'ms'); 263 264 // Create gallery items 265 for (i = 0; i < this.$items.length; i++) { 266 list += '<div class="lg-item"></div>'; 267 } 268 269 // Create controlls 270 if (this.s.controls && this.$items.length > 1) { 271 controls = '<div class="lg-actions">' + 272 '<div class="lg-prev lg-icon">' + this.s.prevHtml + '</div>' + 273 '<div class="lg-next lg-icon">' + this.s.nextHtml + '</div>' + 274 '</div>'; 275 } 276 277 if (this.s.appendSubHtmlTo === '.lg-sub-html') { 278 subHtmlCont = '<div class="lg-sub-html"></div>'; 279 } 280 281 template = '<div class="lg-outer ' + this.s.addClass + ' ' + this.s.startClass + '">' + 282 '<div class="lg" style="width:' + this.s.width + '; height:' + this.s.height + '">' + 283 '<div class="lg-inner">' + list + '</div>' + 284 '<div class="lg-toolbar group">' + 285 '<span class="lg-close lg-icon"></span>' + 286 '</div>' + 287 controls + 288 subHtmlCont + 289 '</div>' + 290 '</div>'; 291 292 $('body').append(template); 293 this.$outer = $('.lg-outer'); 294 this.$slide = this.$outer.find('.lg-item'); 295 296 if (this.s.useLeft) { 297 this.$outer.addClass('lg-use-left'); 298 299 // Set mode lg-slide if use left is true; 300 this.s.mode = 'lg-slide'; 301 } else { 302 this.$outer.addClass('lg-use-css3'); 303 } 304 305 // For fixed height gallery 306 _this.setTop(); 307 $(window).on('resize.lg orientationchange.lg', function() { 308 setTimeout(function() { 309 _this.setTop(); 310 }, 100); 311 }); 312 313 // add class lg-current to remove initial transition 314 this.$slide.eq(this.index).addClass('lg-current'); 315 316 // add Class for css support and transition mode 317 if (this.doCss()) { 318 this.$outer.addClass('lg-css3'); 319 } else { 320 this.$outer.addClass('lg-css'); 321 322 // Set speed 0 because no animation will happen if browser doesn't support css3 323 this.s.speed = 0; 324 } 325 326 this.$outer.addClass(this.s.mode); 327 328 if (this.s.enableDrag && this.$items.length > 1) { 329 this.$outer.addClass('lg-grab'); 330 } 331 332 if (this.s.showAfterLoad) { 333 this.$outer.addClass('lg-show-after-load'); 334 } 335 336 if (this.doCss()) { 337 var $inner = this.$outer.find('.lg-inner'); 338 $inner.css('transition-timing-function', this.s.cssEasing); 339 $inner.css('transition-duration', this.s.speed + 'ms'); 340 } 341 342 $('.lg-backdrop').addClass('in'); 343 344 setTimeout(function() { 345 _this.$outer.addClass('lg-visible'); 346 }, this.s.backdropDuration); 347 348 if (this.s.download) { 349 this.$outer.find('.lg-toolbar').append('<a id="lg-download" target="_blank" download class="lg-download lg-icon"></a>'); 350 } 351 352 // Store the current scroll top value to scroll back after closing the gallery.. 353 this.prevScrollTop = $(window).scrollTop(); 354 355 }; 356 357 // For fixed height gallery 358 Plugin.prototype.setTop = function() { 359 if (this.s.height !== '100%') { 360 var wH = $(window).height(); 361 var top = (wH - parseInt(this.s.height, 10)) / 2; 362 var $lGallery = this.$outer.find('.lg'); 363 if (wH >= parseInt(this.s.height, 10)) { 364 $lGallery.css('top', top + 'px'); 365 } else { 366 $lGallery.css('top', '0px'); 367 } 368 } 369 }; 370 371 // Find css3 support 372 Plugin.prototype.doCss = function() { 373 // check for css animation support 374 var support = function() { 375 var transition = ['transition', 'MozTransition', 'WebkitTransition', 'OTransition', 'msTransition', 'KhtmlTransition']; 376 var root = document.documentElement; 377 var i = 0; 378 for (i = 0; i < transition.length; i++) { 379 if (transition[i] in root.style) { 380 return true; 381 } 382 } 383 }; 384 385 if (support()) { 386 return true; 387 } 388 389 return false;
390 }; 391 392 /** 393 * @desc Check the given src is video 394 * @param {String} src 395 * @return {Object} video type 396 * Ex:{ youtube : ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] } 397 */ 398 Plugin.prototype.isVideo = function(src, index) { 399 400 var html; 401 if (this.s.dynamic) { 402 html = this.s.dynamicEl[index].html; 403 } else { 404 html = this.$items.eq(index).attr('data-html'); 405 } 406 407 if (!src && html) { 408 return { 409 html5: true 410 }; 411 } 412 413 var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)/i); 414 var vimeo = src.match(/\/\/(?:www\.)?vimeo.com\/([0-9a-z\-_]+)/i); 415 var dailymotion = src.match(/\/\/(?:www\.)?dai.ly\/([0-9a-z\-_]+)/i); 416 var vk = src.match(/\/\/(?:www\.)?(?:vk\.com|vkontakte\.ru)\/(?:video_ext\.php\?)(.*)/i); 417 418 if (youtube) { 419 return { 420 youtube: youtube 421 }; 422 } else if (vimeo) { 423 return { 424 vimeo: vimeo 425 }; 426 } else if (dailymotion) { 427 return { 428 dailymotion: dailymotion 429 }; 430 } else if (vk) { 431 return { 432 vk: vk 433 }; 434 } 435 }; 436 437 /** 438 * @desc Create image counter 439 * Ex: 1/10 440 */ 441 Plugin.prototype.counter = function() { 442 if (this.s.counter) { 443 $(this.s.appendCounterTo).append('<div id="lg-counter"><span id="lg-counter-current">' + (parseInt(this.index, 10) + 1) + '</span> / <span id="lg-counter-all">' + this.$items.length + '</span></div>'); 444 } 445 }; 446 447 /** 448 * @desc add sub-html into the slide 449 * @param {Number} index - index of the slide 450 */ 451 Plugin.prototype.addHtml = function(index) { 452 var subHtml = null; 453 var subHtmlUrl; 454 if (this.s.dynamic) { 455 if (this.s.dynamicEl[index].subHtmlUrl) { 456 subHtmlUrl = this.s.dynamicEl[index].subHtmlUrl; 457 } else { 458 subHtml = this.s.dynamicEl[index].subHtml; 459 } 460 } else { 461 if (this.$items.eq(index).attr('data-sub-html-url')) { 462 subHtmlUrl = this.$items.eq(index).attr('data-sub-html-url'); 463 } else { 464 465 subHtml = this.$items.eq(index).attr('data-sub-html'); 466 if (this.s.getCaptionFromTitleOrAlt && !subHtml) { 467 subHtml = this.$items.eq(index).attr('title') || this.$items.eq(index).find('img').first().attr('alt'); 468 } 469 } 470 } 471 472 if (!subHtmlUrl) { 473 if (typeof subHtml !== 'undefined' && subHtml !== null) { 474 475 // get first letter of subhtml 476 // if first letter starts with . or # get the html form the jQuery object 477 var fL = subHtml.substring(0, 1); 478 if (fL === '.' || fL === '#') { 479 subHtml = $(subHtml).html(); 480 } 481 } else { 482 subHtml = ''; 483 } 484 } 485 486 if (this.s.appendSubHtmlTo === '.lg-sub-html') { 487 488 if (subHtmlUrl) { 489 this.$outer.find(this.s.appendSubHtmlTo).load(subHtmlUrl); 490 } else { 491 this.$outer.find(this.s.appendSubHtmlTo).html(subHtml); 492 } 493 494 } else { 495 496 if (subHtmlUrl) { 497 this.$slide.eq(index).load(subHtmlUrl); 498 } else { 499 this.$slide.eq(index).append(subHtml); 500 } 501 } 502 503 // Add lg-empty-html class if title doesn't exist 504 if (typeof subHtml !== 'undefined' && subHtml !== null) { 505 if (subHtml === '') { 506 this.$outer.find(this.s.appendSubHtmlTo).addClass('lg-empty-html'); 507 } else { 508 this.$outer.find(this.s.appendSubHtmlTo).removeClass('lg-empty-html'); 509 } 510 } 511 512 this.$el.trigger('onAfterAppendSubHtml.lg', [index]); 513 }; 514 515 /** 516 * @desc Preload slides 517 * @param {Number} index - index of the slide 518 */ 519 Plugin.prototype.preload = function(index) { 520 var i = 1; 521 var j = 1; 522 for (i = 1; i <= this.s.preload; i++) { 523 if (i >= this.$items.length - index) { 524 break; 525 } 526 527 this.loadContent(index + i, false, 0); 528 } 529 530 for (j = 1; j <= this.s.preload; j++) { 531 if (index - j < 0) { 532 break; 533 } 534 535 this.loadContent(index - j, false, 0); 536 } 537 }; 538 539 /**
540 * @desc Load slide content into slide. 541 * @param {Number} index - index of the slide. 542 * @param {Boolean} rec - if true call loadcontent() function again. 543 * @param {Boolean} delay - delay for adding complete class. it is 0 except first time. 544 */ 545 Plugin.prototype.loadContent = function(index, rec, delay) { 546 547 var _this = this; 548 var _hasPoster = false; 549 var _$img; 550 var _src; 551 var _poster; 552 var _srcset; 553 var _sizes; 554 var _html; 555 var getResponsiveSrc = function(srcItms) { 556 var rsWidth = []; 557 var rsSrc = []; 558 for (var i = 0; i < srcItms.length; i++) { 559 var __src = srcItms[i].split(' '); 560 561 // Manage empty space 562 if (__src[0] === '') { 563 __src.splice(0, 1); 564 } 565 566 rsSrc.push(__src[0]); 567 rsWidth.push(__src[1]); 568 } 569 570 var wWidth = $(window).width(); 571 for (var j = 0; j < rsWidth.length; j++) { 572 if (parseInt(rsWidth[j], 10) > wWidth) { 573 _src = rsSrc[j]; 574 break; 575 } 576 } 577 }; 578 579 if (_this.s.dynamic) { 580 581 if (_this.s.dynamicEl[index].poster) { 582 _hasPoster = true; 583 _poster = _this.s.dynamicEl[index].poster; 584 } 585 586 _html = _this.s.dynamicEl[index].html; 587 _src = _this.s.dynamicEl[index].src; 588 589 if (_this.s.dynamicEl[index].responsive) { 590 var srcDyItms = _this.s.dynamicEl[index].responsive.split(','); 591 getResponsiveSrc(srcDyItms); 592 } 593 594 _srcset = _this.s.dynamicEl[index].srcset; 595 _sizes = _this.s.dynamicEl[index].sizes; 596 597 } else { 598 599 if (_this.$items.eq(index).attr('data-poster')) { 600 _hasPoster = true; 601 _poster = _this.$items.eq(index).attr('data-poster'); 602 } 603 604 _html = _this.$items.eq(index).attr('data-html'); 605 _src = _this.$items.eq(index).attr('href') || _this.$items.eq(index).attr('data-src'); 606 607 if (_this.$items.eq(index).attr('data-responsive')) { 608 var srcItms = _this.$items.eq(index).attr('data-responsive').split(','); 609 getResponsiveSrc(srcItms); 610 } 611 612 _srcset = _this.$items.eq(index).attr('data-srcset'); 613 _sizes = _this.$items.eq(index).attr('data-sizes'); 614 615 } 616 617 //if (_src || _srcset || _sizes || _poster) { 618 619 var iframe = false; 620 if (_this.s.dynamic) { 621 if (_this.s.dynamicEl[index].iframe) { 622 iframe = true; 623 } 624 } else { 625 if (_this.$items.eq(index).attr('data-iframe') === 'true') { 626 iframe = true; 627 } 628 } 629 630 var _isVideo = _this.isVideo(_src, index); 631 if (!_this.$slide.eq(index).hasClass('lg-loaded')) { 632 if (iframe) { 633 _this.$slide.eq(index).prepend('<div class="lg-video-cont" style="max-width:' + _this.s.iframeMaxWidth + '"><div class="lg-video"><iframe class="lg-object" frameborder="0" src="' + _src + '" allowfullscreen="true"></iframe></div></div>'); 634 } else if (_hasPoster) { 635 var videoClass = ''; 636 if (_isVideo && _isVideo.youtube) { 637 videoClass = 'lg-has-youtube'; 638 } else if (_isVideo && _isVideo.vimeo) { 639 videoClass = 'lg-has-vimeo'; 640 } else { 641 videoClass = 'lg-has-html5'; 642 } 643 644 _this.$slide.eq(index).prepend('<div class="lg-video-cont ' + videoClass + ' "><div class="lg-video"><span class="lg-video-play"></span><img class="lg-object lg-has-poster" src="' + _poster + '" /></div></div>'); 645 646 } else if (_isVideo) { 647 _this.$slide.eq(index).prepend('<div class="lg-video-cont "><div class="lg-video"></div></div>'); 648 _this.$el.trigger('hasVideo.lg', [index, _src, _html]); 649 } else { 650 _this.$slide.eq(index).prepend('<div class="lg-img-wrap"><img class="lg-object lg-image" src="' + _src + '" /></div>'); 651 } 652 653 _this.$el.trigger('onAferAppendSlide.lg', [index]); 654 655 _$img = _this.$slide.eq(index).find('.lg-object'); 656 if (_sizes) { 657 _$img.attr('sizes', _sizes); 658 } 659 660 if (_srcset) { 661 _$img.attr('srcset', _srcset); 662 try { 663 picturefill({ 664 elements: [_$img[0]] 665 }); 666 } catch (e) { 667 console.error('Make sure you have included Picturefill version 2'); 668 } 669 } 670 671 if (this.s.appendSubHtmlTo !== '.lg-sub-html') { 672 _this.addHtml(index); 673 } 674 675 _this.$slide.eq(index).addClass('lg-loaded'); 676 } 677 678 _this.$slide.eq(index).find('.lg-object').on('load.lg error.lg', function() { 679 680 // For first time add some delay for displaying the start animation. 681 var _speed = 0; 682
683 // Do not change the delay value because it is required for zoom plugin. 684 // If gallery opened from direct url (hash) speed value should be 0 685 if (delay && !$('body').hasClass('lg-from-hash')) { 686 _speed = delay; 687 } 688 689 setTimeout(function() { 690 _this.$slide.eq(index).addClass('lg-complete'); 691 _this.$el.trigger('onSlideItemLoad.lg', [index, delay || 0]); 692 }, _speed); 693 694 }); 695 696 // @todo check load state for html5 videos 697 if (_isVideo && _isVideo.html5 && !_hasPoster) { 698 _this.$slide.eq(index).addClass('lg-complete'); 699 } 700 701 if (rec === true) { 702 if (!_this.$slide.eq(index).hasClass('lg-complete')) { 703 _this.$slide.eq(index).find('.lg-object').on('load.lg error.lg', function() { 704 _this.preload(index); 705 }); 706 } else { 707 _this.preload(index); 708 } 709 } 710 711 //} 712 }; 713 714 /** 715 * @desc slide function for lightgallery 716 ** Slide() gets call on start 717 ** ** Set lg.on true once slide() function gets called. 718 ** Call loadContent() on slide() function inside setTimeout 719 ** ** On first slide we do not want any animation like slide of fade 720 ** ** So on first slide( if lg.on if false that is first slide) loadContent() should start loading immediately 721 ** ** Else loadContent() should wait for the transition to complete. 722 ** ** So set timeout s.speed + 50 723 <=> ** loadContent() will load slide content in to the particular slide 724 ** ** It has recursion (rec) parameter. if rec === true loadContent() will call preload() function. 725 ** ** preload will execute only when the previous slide is fully loaded (images iframe) 726 ** ** avoid simultaneous image load 727 <=> ** Preload() will check for s.preload value and call loadContent() again accoring to preload value 728 ** loadContent() <====> Preload(); 729 730 * @param {Number} index - index of the slide 731 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag 732 * @param {Boolean} fromThumb - true if slide function called via thumbnail click 733 */ 734 Plugin.prototype.slide = function(index, fromTouch, fromThumb) { 735 736 var _prevIndex = this.$outer.find('.lg-current').index(); 737 var _this = this; 738 739 // Prevent if multiple call 740 // Required for hsh plugin 741 if (_this.lGalleryOn && (_prevIndex === index)) { 742 return; 743 } 744 745 var _length = this.$slide.length; 746 var _time = _this.lGalleryOn ? this.s.speed : 0; 747 var _next = false; 748 var _prev = false; 749 750 if (!_this.lgBusy) { 751 752 if (this.s.download) { 753 var _src; 754 if (_this.s.dynamic) { 755 _src = _this.s.dynamicEl[index].downloadUrl !== false && (_this.s.dynamicEl[index].downloadUrl || _this.s.dynamicEl[index].src); 756 } else { 757 _src = _this.$items.eq(index).attr('data-download-url') !== 'false' && (_this.$items.eq(index).attr('data-download-url') || _this.$items.eq(index).attr('href') || _this.$items.eq(index).attr('data-src')); 758 759 } 760 761 if (_src) { 762 $('#lg-download').attr('href', _src); 763 _this.$outer.removeClass('lg-hide-download'); 764 } else { 765 _this.$outer.addClass('lg-hide-download'); 766 } 767 } 768 769 this.$el.trigger('onBeforeSlide.lg', [_prevIndex, index, fromTouch, fromThumb]); 770 771 _this.lgBusy = true; 772 773 clearTimeout(_this.hideBartimeout); 774 775 // Add title if this.s.appendSubHtmlTo === lg-sub-html 776 if (this.s.appendSubHtmlTo === '.lg-sub-html') { 777 778 // wait for slide animation to complete 779 setTimeout(function() { 780 _this.addHtml(index); 781 }, _time); 782 } 783 784 this.arrowDisable(index); 785 786 if (!fromTouch) { 787 788 // remove all transitions 789 _this.$outer.addClass('lg-no-trans'); 790 791 this.$slide.removeClass('lg-prev-slide lg-next-slide'); 792 793 if (index < _prevIndex) { 794 _prev = true; 795 if ((index === 0) && (_prevIndex === _length - 1) && !fromThumb) { 796 _prev = false;
797 _next = true; 798 } 799 } else if (index > _prevIndex) { 800 _next = true; 801 if ((index === _length - 1) && (_prevIndex === 0) && !fromThumb) { 802 _prev = true; 803 _next = false; 804 } 805 } 806 807 if (_prev) { 808 809 //prevslide 810 this.$slide.eq(index).addClass('lg-prev-slide'); 811 this.$slide.eq(_prevIndex).addClass('lg-next-slide'); 812 } else if (_next) { 813 814 // next slide 815 this.$slide.eq(index).addClass('lg-next-slide'); 816 this.$slide.eq(_prevIndex).addClass('lg-prev-slide'); 817 } 818 819 // give 50 ms for browser to add/remove class 820 setTimeout(function() { 821 _this.$slide.removeClass('lg-current'); 822 823 //_this.$slide.eq(_prevIndex).removeClass('lg-current'); 824 _this.$slide.eq(index).addClass('lg-current'); 825 826 // reset all transitions 827 _this.$outer.removeClass('lg-no-trans'); 828 }, 50); 829 } else { 830 831 var touchPrev = index - 1; 832 var touchNext = index + 1; 833 834 if ((index === 0) && (_prevIndex === _length - 1)) { 835 836 // next slide 837 touchNext = 0; 838 touchPrev = _length - 1; 839 } else if ((index === _length - 1) && (_prevIndex === 0)) { 840 841 // prev slide 842 touchNext = 0; 843 touchPrev = _length - 1; 844 } 845 846 this.$slide.removeClass('lg-prev-slide lg-current lg-next-slide'); 847 _this.$slide.eq(touchPrev).addClass('lg-prev-slide'); 848 _this.$slide.eq(touchNext).addClass('lg-next-slide'); 849 _this.$slide.eq(index).addClass('lg-current'); 850 } 851 852 if (_this.lGalleryOn) { 853 setTimeout(function() { 854 _this.loadContent(index, true, 0); 855 }, this.s.speed + 50); 856 857 setTimeout(function() { 858 _this.lgBusy = false; 859 _this.$el.trigger('onAfterSlide.lg', [_prevIndex, index, fromTouch, fromThumb]); 860 }, this.s.speed); 861 862 } else { 863 _this.loadContent(index, true, _this.s.backdropDuration); 864 865 _this.lgBusy = false; 866 _this.$el.trigger('onAfterSlide.lg', [_prevIndex, index, fromTouch, fromThumb]); 867 } 868 869 _this.lGalleryOn = true; 870 871 if (this.s.counter) { 872 $('#lg-counter-current').text(index + 1); 873 } 874 875 } 876 877 }; 878 879 /** 880 * @desc Go to next slide 881 * @param {Boolean} fromTouch - true if slide function called via touch event 882 */ 883 Plugin.prototype.goToNextSlide = function(fromTouch) { 884 var _this = this; 885 if (!_this.lgBusy) { 886 if ((_this.index + 1) < _this.$slide.length) { 887 _this.index++; 888 _this.$el.trigger('onBeforeNextSlide.lg', [_this.index]); 889 _this.slide(_this.index, fromTouch, false); 890 } else { 891 if (_this.s.loop) { 892 _this.index = 0; 893 _this.$el.trigger('onBeforeNextSlide.lg', [_this.index]); 894 _this.slide(_this.index, fromTouch, false); 895 } else if (_this.s.slideEndAnimatoin) { 896 _this.$outer.addClass('lg-right-end'); 897 setTimeout(function() { 898 _this.$outer.removeClass('lg-right-end'); 899 }, 400); 900 } 901 } 902 } 903 }; 904 905 /** 906 * @desc Go to previous slide 907 * @param {Boolean} fromTouch - true if slide function called via touch event 908 */ 909 Plugin.prototype.goToPrevSlide = function(fromTouch) { 910 var _this = this; 911 if (!_this.lgBusy) { 912 if (_this.index > 0) { 913 _this.index--; 914 _this.$el.trigger('onBeforePrevSlide.lg', [_this.index, fromTouch]); 915 _this.slide(_this.index, fromTouch, false); 916 } else { 917 if (_this.s.loop) { 918 _this.index = _this.$items.length - 1; 919 _this.$el.trigger('onBeforePrevSlide.lg', [_this.index, fromTouch]); 920 _this.slide(_this.index, fromTouch, false); 921 } else if (_this.s.slideEndAnimatoin) { 922 _this.$outer.addClass('lg-left-end'); 923 setTimeout(function() { 924 _this.$outer.removeClass('lg-left-end'); 925 }, 400); 926 } 927 } 928 } 929 }; 930 931 Plugin.prototype.keyPress = function() { 932 var _this = this; 933 if (this.$items.length > 1) { 934 $(window).on('keyup.lg', function(e) { 935 if (_this.$items.length > 1) { 936 if (e.keyCode === 37) { 937 e.preventDefault(); 938 _this.goToPrevSlide(); 939 } 940 941 if (e.keyCode === 39) { 942 e.preventDefault(); 943 _this.goToNextSlide(); 944 } 945 } 946 }); 947 } 948 949 $(window).on('keydown.lg', function(e) { 950 if (_this.s.escKey === true && e.keyCode === 27) { 951 e.preventDefault(); 952 if (!_this.$outer.hasClass('lg-thumb-open')) { 953 _this.destroy(); 954 } else { 955 _this.$outer.removeClass('lg-thumb-open'); 956 } 957 } 958 }); 959 }; 960 961 Plugin.prototype.arrow = function() { 962 var _this = this; 963 this.$outer.find('.lg-prev').on('click.lg', function() { 964 _this.goToPrevSlide(); 965 }); 966 967 this.$outer.find('.lg-next').on('click.lg', function() { 968 _this.goToNextSlide(); 969 }); 970 }; 971 972 Plugin.prototype.arrowDisable = function(index) { 973 974 // Disable arrows if s.hideControlOnEnd is true 975 if (!this.s.loop && this.s.hideControlOnEnd) { 976 if ((index + 1) < this.$slide.length) { 977 this.$outer.find('.lg-next').removeAttr('disabled').removeClass('disabled'); 978 } else { 979 this.$outer.find('.lg-next').attr('disabled', 'disabled').addClass('disabled'); 980 } 981 982 if (index > 0) { 983 this.$outer.find('.lg-prev').removeAttr('disabled').removeClass('disabled'); 984 } else { 985 this.$outer.find('.lg-prev').attr('disabled', 'disabled').addClass('disabled'); 986 } 987 } 988 }; 989 990 Plugin.prototype.setTranslate = function($el, xValue, yValue) { 991 // jQuery supports Automatic CSS prefixing since jQuery 1.8.0 992 if (this.s.useLeft) { 993 $el.css('left', xValue); 994 } else { 995 $el.css({ 996 transform: 'translate3d(' + (xValue) + 'px, ' + yValue + 'px, 0px)' 997 }); 998 } 999 }; 1000 1001 Plugin.prototype.touchMove = function(startCoords, endCoords) { 1002 1003 var distance = endCoords - startCoords; 1004 1005 if (Math.abs(distance) > 15) { 1006 // reset opacity and transition duration 1007 this.$outer.addClass('lg-dragging'); 1008 1009 // move current slide 1010 this.setTranslate(this.$slide.eq(this.index), distance, 0); 1011 1012 // move next and prev slide with current slide 1013 this.setTranslate($('.lg-prev-slide'), -this.$slide.eq(this.index).width() + distance, 0); 1014 this.setTranslate($('.lg-next-slide'), this.$slide.eq(this.index).width() + distance, 0); 1015 } 1016 }; 1017 1018 Plugin.prototype.touchEnd = function(distance) { 1019 var _this = this; 1020 1021 // keep slide animation for any mode while dragg/swipe 1022 if (_this.s.mode !== 'lg-slide') { 1023 _this.$outer.addClass('lg-slide'); 1024 } 1025 1026 this.$slide.not('.lg-current, .lg-prev-slide, .lg-next-slide').css('opacity', '0'); 1027 1028 // set transition duration 1029 setTimeout(function() { 1030 _this.$outer.removeClass('lg-dragging'); 1031 if ((distance < 0) && (Math.abs(distance) > _this.s.swipeThreshold)) { 1032 _this.goToNextSlide(true); 1033 } else if ((distance > 0) && (Math.abs(distance) > _this.s.swipeThreshold)) { 1034 _this.goToPrevSlide(true); 1035 } else if (Math.abs(distance) < 5) { 1036 1037 // Trigger click if distance is less than 5 pix 1038 _this.$el.trigger('onSlideClick.lg'); 1039 } 1040 1041 _this.$slide.removeAttr('style'); 1042 }); 1043 1044 // remove slide class once drag/swipe is completed if mode is not slide 1045 setTimeout(function() { 1046 if (!_this.$outer.hasClass('lg-dragging') && _this.s.mode !== 'lg-slide') { 1047 _this.$outer.removeClass('lg-slide'); 1048 } 1049 }, _this.s.speed + 100); 1050 1051 }; 1052 1053 Plugin.prototype.enableSwipe = function() { 1054 var _this = this; 1055 var startCoords = 0; 1056 var endCoords = 0; 1057 var isMoved = false;
1058 1059 if (_this.s.enableSwipe && _this.isTouch && _this.doCss()) { 1060 1061 _this.$slide.on('touchstart.lg', function(e) { 1062 if (!_this.$outer.hasClass('lg-zoomed') && !_this.lgBusy) { 1063 e.preventDefault(); 1064 _this.manageSwipeClass(); 1065 startCoords = e.originalEvent.targetTouches[0].pageX; 1066 } 1067 }); 1068 1069 _this.$slide.on('touchmove.lg', function(e) { 1070 if (!_this.$outer.hasClass('lg-zoomed')) { 1071 e.preventDefault(); 1072 endCoords = e.originalEvent.targetTouches[0].pageX; 1073 _this.touchMove(startCoords, endCoords); 1074 isMoved = true; 1075 } 1076 }); 1077 1078 _this.$slide.on('touchend.lg', function() { 1079 if (!_this.$outer.hasClass('lg-zoomed')) { 1080 if (isMoved) { 1081 isMoved = false; 1082 _this.touchEnd(endCoords - startCoords); 1083 } else { 1084 _this.$el.trigger('onSlideClick.lg'); 1085 } 1086 } 1087 }); 1088 } 1089 1090 }; 1091 1092 Plugin.prototype.enableDrag = function() { 1093 var _this = this; 1094 var startCoords = 0; 1095 var endCoords = 0; 1096 var isDraging = false; 1097 var isMoved = false; 1098 if (_this.s.enableDrag && !_this.isTouch && _this.doCss()) { 1099 _this.$slide.on('mousedown.lg', function(e) { 1100 // execute only on .lg-object 1101 if (!_this.$outer.hasClass('lg-zoomed')) { 1102 if ($(e.target).hasClass('lg-object') || $(e.target).hasClass('lg-video-play')) { 1103 e.preventDefault(); 1104 1105 if (!_this.lgBusy) { 1106 _this.manageSwipeClass(); 1107 startCoords = e.pageX; 1108 isDraging = true; 1109 1110 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 1111 _this.$outer.scrollLeft += 1; 1112 _this.$outer.scrollLeft -= 1; 1113 1114 // * 1115 1116 _this.$outer.removeClass('lg-grab').addClass('lg-grabbing'); 1117 1118 _this.$el.trigger('onDragstart.lg'); 1119 } 1120 1121 } 1122 } 1123 }); 1124 1125 $(window).on('mousemove.lg', function(e) { 1126 if (isDraging) { 1127 isMoved = true; 1128 endCoords = e.pageX; 1129 _this.touchMove(startCoords, endCoords); 1130 _this.$el.trigger('onDragmove.lg'); 1131 } 1132 }); 1133 1134 $(window).on('mouseup.lg', function(e) { 1135 if (isMoved) { 1136 isMoved = false; 1137 _this.touchEnd(endCoords - startCoords); 1138 _this.$el.trigger('onDragend.lg'); 1139 } else if ($(e.target).hasClass('lg-object') || $(e.target).hasClass('lg-video-play')) { 1140 _this.$el.trigger('onSlideClick.lg'); 1141 } 1142 1143 // Prevent execution on click 1144 if (isDraging) { 1145 isDraging = false; 1146 _this.$outer.removeClass('lg-grabbing').addClass('lg-grab'); 1147 } 1148 }); 1149 1150 } 1151 }; 1152 1153 Plugin.prototype.manageSwipeClass = function() { 1154 var touchNext = this.index + 1; 1155 var touchPrev = this.index - 1; 1156 var length = this.$slide.length; 1157 if (this.s.loop) { 1158 if (this.index === 0) { 1159 touchPrev = length - 1; 1160 } else if (this.index === length - 1) { 1161 touchNext = 0; 1162 } 1163 } 1164 1165 this.$slide.removeClass('lg-next-slide lg-prev-slide'); 1166 if (touchPrev > -1) { 1167 this.$slide.eq(touchPrev).addClass('lg-prev-slide'); 1168 } 1169 1170 this.$slide.eq(touchNext).addClass('lg-next-slide'); 1171 }; 1172 1173 Plugin.prototype.mousewheel = function() { 1174 var _this = this; 1175 _this.$outer.on('mousewheel.lg', function(e) { 1176 1177 if (!e.deltaY) { 1178 return; 1179 } 1180 1181 if (e.deltaY > 0) { 1182 _this.goToPrevSlide(); 1183 } else { 1184 _this.goToNextSlide(); 1185 } 1186 1187 e.preventDefault(); 1188 }); 1189 1190 }; 1191 1192 Plugin.prototype.closeGallery = function() { 1193 1194 var _this = this; 1195 var mousedown = false;
1196 this.$outer.find('.lg-close').on('click.lg', function() { 1197 _this.destroy(); 1198 }); 1199 1200 if (_this.s.closable) { 1201 1202 // If you drag the slide and release outside gallery gets close on chrome 1203 // for preventing this check mousedown and mouseup happened on .lg-item or lg-outer 1204 _this.$outer.on('mousedown.lg', function(e) { 1205 1206 if ($(e.target).is('.lg-outer') || $(e.target).is('.lg-item ') || $(e.target).is('.lg-img-wrap')) { 1207 mousedown = true; 1208 } else { 1209 mousedown = false; 1210 } 1211 1212 }); 1213 1214 _this.$outer.on('mouseup.lg', function(e) { 1215 1216 if ($(e.target).is('.lg-outer') || $(e.target).is('.lg-item ') || $(e.target).is('.lg-img-wrap') && mousedown) { 1217 if (!_this.$outer.hasClass('lg-dragging')) { 1218 _this.destroy(); 1219 } 1220 } 1221 1222 }); 1223 1224 } 1225 1226 }; 1227 1228 Plugin.prototype.destroy = function(d) { 1229 1230 var _this = this; 1231 1232 if (!d) { 1233 _this.$el.trigger('onBeforeClose.lg'); 1234 } 1235 1236 $(window).scrollTop(_this.prevScrollTop); 1237 1238 /** 1239 * if d is false or undefined destroy will only close the gallery 1240 * plugins instance remains with the element 1241 * 1242 * if d is true destroy will completely remove the plugin 1243 */ 1244 1245 if (d) { 1246 if (!_this.s.dynamic) { 1247 // only when not using dynamic mode is $items a jquery collection 1248 this.$items.off('click.lg click.lgcustom'); 1249 } 1250 1251 $.removeData(_this.el, 'lightGallery'); 1252 } 1253 1254 // Unbind all events added by lightGallery 1255 this.$el.off('.lg.tm'); 1256 1257 // Distroy all lightGallery modules 1258 $.each($.fn.lightGallery.modules, function(key) { 1259 if (_this.modules[key]) { 1260 _this.modules[key].destroy(); 1261 } 1262 }); 1263 1264 this.lGalleryOn = false; 1265 1266 clearTimeout(_this.hideBartimeout); 1267 this.hideBartimeout = false; 1268 $(window).off('.lg'); 1269 $('body').removeClass('lg-on lg-from-hash'); 1270 1271 if (_this.$outer) { 1272 _this.$outer.removeClass('lg-visible'); 1273 } 1274 1275 $('.lg-backdrop').removeClass('in'); 1276 1277 setTimeout(function() { 1278 if (_this.$outer) { 1279 _this.$outer.remove(); 1280 } 1281 1282 $('.lg-backdrop').remove(); 1283 1284 if (!d) { 1285 _this.$el.trigger('onCloseAfter.lg'); 1286 } 1287 1288 }, _this.s.backdropDuration + 50); 1289 }; 1290 1291 $.fn.lightGallery = function(options) { 1292 return this.each(function() { 1293 if (!$.data(this, 'lightGallery')) { 1294 $.data(this, 'lightGallery', new Plugin(this, options)); 1295 } else { 1296 try { 1297 $(this).data('lightGallery').init(); 1298 } catch (err) { 1299 console.error('lightGallery has not initiated properly'); 1300 } 1301 } 1302 }); 1303 }; 1304 1305 $.fn.lightGallery.modules = {}; 1306 1307})(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.