1// JavaScript flexImages v1.0.2 2// https://github.com/Pixabay/JavaScript-flexImages 3var flexImages=function(){function e(e){function t(e,r,n,i){function o(e){n.maxRows&&g>n.maxRows||n.truncate&&e&&g>1?c[a][0].style.display="none":(c[a][4]&&(c[a][3].setAttribute("src",c[a][4]),c[a][4]=""),c[a][0].style.width=l+"px",c[a][0].style.height=h+"px",c[a][0].style.display="block")}for(var a,l,s,d,f=1,g=1,u=e.clientWidth-2,c=[],m=0,h=n.rowHeight,w=0;w<r.length;w++)if(c.push(r[w]),m+=r[w][2]+n.margin,m>=u){var p=c.length*n.margin;for(f=(u-p)/(m-p),h=Math.ceil(n.rowHeight*f),s=0,l,a=0;a<c.length;a++)l=Math.ceil(c[a][2]*f),s+=l+n.margin,s>u&&(l-=s-u),o();c=[],m=0,g++}for(a=0;a<c.length;a++)l=Math.floor(c[a][2]*f),d=Math.floor(n.rowHeight*f),o(!0);i||u==e.clientWidth||t(e,r,n,!0)}if(document.querySelector){var r={selector:0,container:".item",object:"img",rowHeight:180,maxRows:0,truncate:0};for(var n in e)e.hasOwnProperty(n)&&(r[n]=e[n]);for(var i="object"==typeof r.selector?[r.selector]:document.querySelectorAll(r.selector),o=0;o<i.length;o++){var a=i[o],l=a.querySelectorAll(r.container),s=[],d=(new Date).getTime();if(l.length){var f=window.getComputedStyle?getComputedStyle(l[0],null):l[0].currentStyle;r.margin=(parseInt(f.marginLeft)||0)+(parseInt(f.marginRight)||0)+(Math.round(parseFloat(f.borderLeftWidth))||0)+(Math.round(parseFloat(f.borderRightWidth))||0);for(var g=0;g<l.length;g++){var u=l[g],c=parseInt(u.getAttribute("data-w")),m=c*(r.rowHeight/parseInt(u.getAttribute("data-h"))),h=u.querySelector(r.object);s.push([u,c,m,h,h.getAttribute("data-src")])}t(a,s,r);var w=function(){t(a,s,r)};document.addEventListener?(window["flexImages_listener"+d]=w,window.removeEventListener("resize",window["flexImages_listener"+a.getAttribute("data-flex-t")]),delete window["flexImages_listener"+a.getAttribute("data-flex-t")],window.addEventListener("resize",window["flexImages_listener"+d])):a.onresize=w,a.setAttribute("data-flex-t",d)}}}}return e}();!function(){"function"==typeof define&&define.amd?define("flexImages",function(){return flexImages}):"undefined"!=typeof module&&module.exports?module.exports=flexImages:window.flexImages=flexImages}(); 4 5/* 6 * Lightcase - jQuery Plugin 7 * The smart and flexible Lightbox Plugin. 8 * 9 * @author Cornel Boppart <[email protected]> 10 * @copyright Author 11 * 12 * @version 2.5.0 (11/03/2018) 13 */ 14 15;(function ($) { 16 17 'use strict'; 18 19 var _self = { 20 cache: {}, 21 22 support: {}, 23 24 objects: {}, 25 26 /** 27 * Initializes the plugin 28 * 29 * @param {object} options 30 * @return {object} 31 */ 32 init: function (options) { 33 return this.each(function () { 34 $(this).unbind('click.lightcase').bind('click.lightcase', function (event) { 35 event.preventDefault(); 36 $(this).lightcase('start', options); 37 }); 38 }); 39 }, 40 41 /** 42 * Starts the plugin 43 * 44 * @param {object} options 45 * @return {void} 46 */ 47 start: function (options) { 48 _self.origin = lightcase.origin = this; 49 50 _self.settings = lightcase.settings = $.extend(true, { 51 idPrefix: 'lightcase-', 52 classPrefix: 'lightcase-', 53 attrPrefix: 'lc-', 54 transition: 'elastic', 55 transitionOpen: null, 56 transitionClose: null, 57 transitionIn: null, 58 transitionOut: null, 59 cssTransitions: true, 60 speedIn: 250, 61 speedOut: 250, 62 width: null, 63 height: null, 64 maxWidth: 800, 65 maxHeight: 500, 66 forceWidth: false, 67 forceHeight: false, 68 liveResize: true, 69 fullScreenModeForMobile: true, 70 mobileMatchExpression: /(iphone|ipod|ipad|android|blackberry|symbian)/, 71 disableShrink: false, 72 fixedRatio: true, 73 shrinkFactor: .75, 74 overlayOpacity: .9, 75 slideshow: false, 76 slideshowAutoStart: true, 77 breakBeforeShow: false, 78 timeout: 5000, 79 swipe: true, 80 useKeys: true, 81 useCategories: true, 82 useAsCollection: false, 83 navigateEndless: true, 84 closeOnOverlayClick: true, 85 title: null, 86 caption: null, 87 showTitle: true, 88 showCaption: true, 89 showSequenceInfo: true, 90 inline: { 91 width: 'auto', 92 height: 'auto' 93 }, 94 ajax: { 95 width: 'auto', 96 height: 'auto', 97 type: 'get', 98 dataType: 'html', 99 data: {} 100 }, 101 iframe: { 102 width: 800, 103 height: 500, 104 frameborder: 0 105 }, 106 flash: { 107 width: 400, 108 height: 205, 109 wmode: 'transparent' 110 }, 111 video: { 112 width: 400, 113 height: 225, 114 poster: '', 115 preload: 'auto', 116 controls: true, 117 autobuffer: true, 118 autoplay: true, 119 loop: false 120 }, 121 attr: 'data-rel', 122 href: null, 123 type: null, 124 typeMapping: { 125 'image': 'jpg,jpeg,gif,png,bmp', 126 'flash': 'swf', 127 'video': 'mp4,mov,ogv,ogg,webm', 128 'iframe': 'html,php', 129 'ajax': 'json,txt', 130 'inline': '#' 131 }, 132 errorMessage: function () { 133 return '<p class="' + _self.settings.classPrefix + 'error">' + _self.settings.labels['errorMessage'] + '</p>'; 134 }, 135 labels: { 136 'errorMessage': 'Source could not be found...', 137 'sequenceInfo.of': ' of ', 138 'close': 'Close', 139 'navigator.prev': 'Prev', 140 'navigator.next': 'Next', 141 'navigator.play': 'Play', 142 'navigator.pause': 'Pause' 143 }, 144 markup: function () { 145 _self.objects.body.append(
146 _self.objects.overlay = $('<div id="' + _self.settings.idPrefix + 'overlay"></div>'), 147 _self.objects.loading = $('<div id="' + _self.settings.idPrefix + 'loading" class="' + _self.settings.classPrefix + 'icon-spin"></div>'), 148 _self.objects.case = $('<div id="' + _self.settings.idPrefix + 'case" aria-hidden="true" role="dialog"></div>') 149 ); 150 _self.objects.case.after( 151 _self.objects.close = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-close"><span>' + _self.settings.labels['close'] + '</span></a>'), 152 _self.objects.nav = $('<div id="' + _self.settings.idPrefix + 'nav"></div>') 153 ); 154 _self.objects.nav.append( 155 _self.objects.prev = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-prev"><span>' + _self.settings.labels['navigator.prev'] + '</span></a>').hide(), 156 _self.objects.next = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-next"><span>' + _self.settings.labels['navigator.next'] + '</span></a>').hide(), 157 _self.objects.play = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-play"><span>' + _self.settings.labels['navigator.play'] + '</span></a>').hide(), 158 _self.objects.pause = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-pause"><span>' + _self.settings.labels['navigator.pause'] + '</span></a>').hide() 159 ); 160 _self.objects.case.append( 161 _self.objects.content = $('<div id="' + _self.settings.idPrefix + 'content"></div>'), 162 _self.objects.info = $('<div id="' + _self.settings.idPrefix + 'info"></div>') 163 ); 164 _self.objects.content.append(
165 _self.objects.contentInner = $('<div class="' + _self.settings.classPrefix + 'contentInner"></div>') 166 ); 167 _self.objects.info.append( 168 _self.objects.sequenceInfo = $('<div id="' + _self.settings.idPrefix + 'sequenceInfo"></div>'), 169 _self.objects.title = $('<h4 id="' + _self.settings.idPrefix + 'title"></h4>'), 170 _self.objects.caption = $('<p id="' + _self.settings.idPrefix + 'caption"></p>') 171 ); 172 }, 173 onInit: {}, 174 onStart: {}, 175 onBeforeCalculateDimensions: {}, 176 onAfterCalculateDimensions: {}, 177 onBeforeShow: {}, 178 onFinish: {}, 179 onResize: {}, 180 onClose: {}, 181 onCleanup: {} 182 }, 183 options, 184 // Load options from data-lc-options attribute 185 _self.origin.data ? _self.origin.data('lc-options') : {}); 186 187 _self.objects.document = $('html'); 188 _self.objects.body = $('body'); 189 190 // Call onInit hook functions 191 _self._callHooks(_self.settings.onInit); 192 193 _self.objectData = _self._setObjectData(this); 194 195 _self._addElements(); 196 _self._open(); 197 198 _self.dimensions = _self.getViewportDimensions(); 199 }, 200 201 /** 202 * Getter method for objects 203 * 204 * @param {string} name 205 * @return {object} 206 */ 207 get: function (name) { 208 return _self.objects[name]; 209 }, 210 211 /** 212 * Getter method for objectData 213 * 214 * @return {object} 215 */ 216 getObjectData: function () { 217 return _self.objectData; 218 }, 219 220 /** 221 * Sets the object data 222 * 223 * @param {object} object 224 * @return {object} objectData 225 */ 226 _setObjectData: function (object) { 227 var $object = $(object), 228 objectData = { 229 this: $(object), 230 title: _self.settings.title || $object.attr(_self._prefixAttributeName('title')) || $object.attr('title'), 231 caption: _self.settings.caption || $object.attr(_self._prefixAttributeName('caption')) || $object.children('img').attr('alt'), 232 url: _self._determineUrl(), 233 requestType: _self.settings.ajax.type, 234 requestData: _self.settings.ajax.data, 235 requestDataType: _self.settings.ajax.dataType, 236 rel: $object.attr(_self._determineAttributeSelector()), 237 type: _self.settings.type || _self._verifyDataType(_self._determineUrl()), 238 isPartOfSequence: _self.settings.useAsCollection || _self._isPartOfSequence($object.attr(_self.settings.attr), ':'), 239 isPartOfSequenceWithSlideshow: _self._isPartOfSequence($object.attr(_self.settings.attr), ':slideshow'), 240 currentIndex: $(_self._determineAttributeSelector()).index($object), 241 sequenceLength: $(_self._determineAttributeSelector()).length 242 }; 243 244 // Add sequence info to objectData 245 objectData.sequenceInfo = (objectData.currentIndex + 1) + _self.settings.labels['sequenceInfo.of'] + objectData.sequenceLength; 246 247 // Add next/prev index 248 objectData.prevIndex = objectData.currentIndex - 1; 249 objectData.nextIndex = objectData.currentIndex + 1; 250 251 return objectData; 252 }, 253 254 /** 255 * Prefixes a data attribute name with defined name from 'settings.attrPrefix' 256 * to ensure more uniqueness for all lightcase related/used attributes. 257 * 258 * @param {string} name 259 * @return {string} 260 */ 261 _prefixAttributeName: function (name) { 262 return 'data-' + _self.settings.attrPrefix + name; 263 }, 264 265 /** 266 * Determines the link target considering 'settings.href' and data attributes 267 * but also with a fallback to the default 'href' value. 268 * 269 * @return {string} 270 */ 271 _determineLinkTarget: function () { 272 return _self.settings.href || $(_self.origin).attr(_self._prefixAttributeName('href')) || $(_self.origin).attr('href'); 273 }, 274 275 /** 276 * Determines the attribute selector to use, depending on 277 * whether categorized collections are beeing used or not. 278 * 279 * @return {string} selector 280 */ 281 _determineAttributeSelector: function () { 282 var $origin = $(_self.origin), 283 selector = ''; 284 285 if (typeof _self.cache.selector !== 'undefined') { 286 selector = _self.cache.selector; 287 } else if (_self.settings.useCategories === true && $origin.attr(_self._prefixAttributeName('categories'))) { 288 var categories = $origin.attr(_self._prefixAttributeName('categories')).split(' '); 289 290 $.each(categories, function (index, category) { 291 if (index > 0) { 292 selector += ','; 293 } 294 selector += '[' + _self._prefixAttributeName('categories') + '~="' + category + '"]'; 295 }); 296 } else { 297 selector = '[' + _self.settings.attr + '="' + $origin.attr(_self.settings.attr) + '"]'; 298 } 299 300 _self.cache.selector = selector; 301 302 return selector; 303 }, 304 305 /** 306 * Determines the correct resource according to the 307 * current viewport and density. 308 * 309 * @return {string} url 310 */ 311 _determineUrl: function () { 312 var dataUrl = _self._verifyDataUrl(_self._determineLinkTarget()), 313 width = 0, 314 density = 0, 315 supportLevel = '', 316 url; 317 318 $.each(dataUrl, function (index, src) { 319 switch (_self._verifyDataType(src.url)) { 320 case 'video': 321 var video = document.createElement('video'), 322 videoType = _self._verifyDataType(src.url) + '/' + _self._getFileUrlSuffix(src.url); 323 324 // Check if browser can play this type of video format 325 if (supportLevel !== 'probably' && supportLevel !== video.canPlayType(videoType) && video.canPlayType(videoType) !== '') { 326 supportLevel = video.canPlayType(videoType); 327 url = src.url; 328 } 329 break; 330 default: 331 if ( 332 // Check density 333 _self._devicePixelRatio() >= src.density && 334 src.density >= density && 335 // Check viewport width 336 _self._matchMedia()('screen and (min-width:' + src.width + 'px)').matches && 337 src.width >= width 338 ) { 339 width = src.width; 340 density = src.density; 341 url = src.url; 342 } 343 break; 344 } 345 }); 346 347 return url; 348 }, 349 350 /** 351 * Normalizes an url and returns information about the resource path, 352 * the viewport width as well as density if defined. 353 * 354 * @param {string} url Path to resource in format of an url or srcset 355 * @return {object} 356 */ 357 _normalizeUrl: function (url) { 358 var srcExp = /^\d+$/; 359 360 return url.split(',').map(function (str) { 361 var src = { 362 width: 0, 363 density: 0 364 }; 365
366 str.trim().split(/\s+/).forEach(function (url, i) { 367 if (i === 0) { 368 return src.url = url; 369 } 370 371 var value = url.substring(0, url.length - 1), 372 lastChar = url[url.length - 1], 373 intVal = parseInt(value, 10), 374 floatVal = parseFloat(value); 375 if (lastChar === 'w' && srcExp.test(value)) { 376 src.width = intVal; 377 } else if (lastChar === 'h' && srcExp.test(value)) { 378 src.height = intVal; 379 } else if (lastChar === 'x' && !isNaN(floatVal)) { 380 src.density = floatVal; 381 } 382 }); 383 384 return src; 385 }); 386 }, 387 388 /** 389 * Verifies if the link is part of a sequence 390 * 391 * @param {string} rel 392 * @param {string} expression 393 * @return {boolean} 394 */ 395 _isPartOfSequence: function (rel, expression) { 396 var getSimilarLinks = $('[' + _self.settings.attr + '="' + rel + '"]'), 397 regexp = new RegExp(expression); 398 399 return (regexp.test(rel) && getSimilarLinks.length > 1); 400 }, 401 402 /** 403 * Verifies if the slideshow should be enabled 404 * 405 * @return {boolean} 406 */ 407 isSlideshowEnabled: function () { 408 return (_self.objectData.isPartOfSequence && (_self.settings.slideshow === true || _self.objectData.isPartOfSequenceWithSlideshow === true)); 409 }, 410 411 /** 412 * Loads the new content to show 413 * 414 * @return {void} 415 */ 416 _loadContent: function () { 417 if (_self.cache.originalObject) { 418 _self._restoreObject(); 419 } 420 421 _self._createObject(); 422 }, 423 424 /** 425 * Creates a new object 426 * 427 * @return {void} 428 */ 429 _createObject: function () { 430 var $object; 431 432 // Create object 433 switch (_self.objectData.type) { 434 case 'image': 435 $object = $(new Image()); 436 $object.attr({ 437 // The time expression is required to prevent the binding of an image load 438 'src': _self.objectData.url, 439 'alt': _self.objectData.title 440 }); 441 break; 442 case 'inline': 443 $object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>'); 444 $object.html(_self._cloneObject($(_self.objectData.url))); 445 446 // Add custom attributes from _self.settings 447 $.each(_self.settings.inline, function (name, value) { 448 $object.attr(_self._prefixAttributeName(name), value); 449 }); 450 break; 451 case 'ajax': 452 $object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>'); 453 454 // Add custom attributes from _self.settings 455 $.each(_self.settings.ajax, function (name, value) { 456 if (name !== 'data') { 457 $object.attr(_self._prefixAttributeName(name), value); 458 } 459 }); 460 break; 461 case 'flash': 462 $object = $('<embed src="' + _self.objectData.url + '" type="application/x-shockwave-flash"></embed>'); 463 464 // Add custom attributes from _self.settings 465 $.each(_self.settings.flash, function (name, value) { 466 $object.attr(name, value); 467 }); 468 break; 469 case 'video': 470 $object = $('<video></video>'); 471 $object.attr('src', _self.objectData.url); 472 473 // Add custom attributes from _self.settings 474 $.each(_self.settings.video, function (name, value) { 475 $object.attr(name, value); 476 }); 477 break; 478 default: 479 $object = $('<iframe></iframe>'); 480 $object.attr({ 481 'src': _self.objectData.url 482 }); 483 484 // Add custom attributes from _self.settings 485 $.each(_self.settings.iframe, function (name, value) { 486 $object.attr(name, value); 487 }); 488 break; 489 } 490 491 _self._addObject($object); 492 _self._loadObject($object); 493 }, 494 495 /** 496 * Adds the new object to the markup 497 * 498 * @param {object} $object 499 * @return {void} 500 */ 501 _addObject: function ($object) { 502 // Add object to content holder 503 _self.objects.contentInner.html($object); 504 505 // Start loading 506 _self._loading('start'); 507 508 // Call onStart hook functions 509 _self._callHooks(_self.settings.onStart); 510 511 // Add sequenceInfo to the content holder or hide if its empty 512 if (_self.settings.showSequenceInfo === true && _self.objectData.isPartOfSequence) { 513 _self.objects.sequenceInfo.html(_self.objectData.sequenceInfo); 514 _self.objects.sequenceInfo.show(); 515 } else { 516 _self.objects.sequenceInfo.empty(); 517 _self.objects.sequenceInfo.hide(); 518 } 519 // Add title to the content holder or hide if its empty 520 if (_self.settings.showTitle === true && _self.objectData.title !== undefined && _self.objectData.title !== '') { 521 _self.objects.title.html(_self.objectData.title); 522 _self.objects.title.show(); 523 } else { 524 _self.objects.title.empty(); 525 _self.objects.title.hide(); 526 } 527 // Add caption to the content holder or hide if its empty 528 if (_self.settings.showCaption === true && _self.objectData.caption !== undefined && _self.objectData.caption !== '') { 529 _self.objects.caption.html(_self.objectData.caption); 530 _self.objects.caption.show(); 531 } else { 532 _self.objects.caption.empty(); 533 _self.objects.caption.hide(); 534 } 535 }, 536 537 /** 538 * Loads the new object 539 * 540 * @param {object} $object 541 * @return {void} 542 */ 543 _loadObject: function ($object) { 544 // Load the object 545 switch (_self.objectData.type) { 546 case 'inline': 547 if ($(_self.objectData.url)) { 548 _self._showContent($object); 549 } else { 550 _self.error(); 551 } 552 break; 553 case 'ajax': 554 $.ajax( 555 $.extend({}, _self.settings.ajax, { 556 url: _self.objectData.url, 557 type: _self.objectData.requestType, 558 dataType: _self.objectData.requestDataType, 559 data: _self.objectData.requestData, 560 success: function (data, textStatus, jqXHR) { 561 // Check for X-Ajax-Location 562 if (jqXHR.getResponseHeader('X-Ajax-Location')) { 563 _self.objectData.url = jqXHR.getResponseHeader('X-Ajax-Location'); 564 _self._loadObject($object); 565 } 566 else { 567 // Unserialize if data is transferred as json 568 if (_self.objectData.requestDataType === 'json') { 569 _self.objectData.data = data; 570 } else { 571 $object.html(data); 572 } 573 _self._showContent($object); 574 } 575 }, 576 error: function (jqXHR, textStatus, errorThrown) { 577 _self.error(); 578 } 579 }) 580 ); 581 break; 582 case 'flash': 583 _self._showContent($object); 584 break; 585 case 'video': 586 if (typeof($object.get(0).canPlayType) === 'function' || _self.objects.case.find('video').length === 0) { 587 _self._showContent($object); 588 } else { 589 _self.error(); 590 } 591 break; 592 default: 593 if (_self.objectData.url) { 594 $object.on('load', function () { 595 _self._showContent($object); 596 }); 597 $object.on('error', function () { 598 _self.error(); 599 }); 600 } else { 601 _self.error(); 602 } 603 break; 604 } 605 }, 606 607 /** 608 * Throws an error message if something went wrong 609 * 610 * @return {void} 611 */ 612 error: function () { 613 _self.objectData.type = 'error'; 614 var $object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>'); 615 616 $object.html(_self.settings.errorMessage); 617 _self.objects.contentInner.html($object); 618 619 _self._showContent(_self.objects.contentInner); 620 }, 621 622 /** 623 * Calculates the dimensions to fit content 624 * 625 * @param {object} $object 626 * @return {void} 627 */ 628 _calculateDimensions: function ($object) { 629 _self._cleanupDimensions(); 630 631 if (!$object) return; 632 633 // Set default dimensions 634 var dimensions = { 635 ratio: 1, 636 objectWidth: $object.attr('width') ? $object.attr('width') : $object.attr(_self._prefixAttributeName('width')), 637 objectHeight: $object.attr('height') ? $object.attr('height') : $object.attr(_self._prefixAttributeName('height')) 638 }; 639 640 if (!_self.settings.disableShrink) { 641 // Add calculated maximum width/height to dimensions 642 dimensions.maxWidth = parseInt(_self.dimensions.windowWidth * _self.settings.shrinkFactor); 643 dimensions.maxHeight = parseInt(_self.dimensions.windowHeight * _self.settings.shrinkFactor); 644 645 // If the auto calculated maxWidth/maxHeight greather than the user-defined one, use that. 646 if (dimensions.maxWidth > _self.settings.maxWidth) { 647 dimensions.maxWidth = _self.settings.maxWidth; 648 } 649 if (dimensions.maxHeight > _self.settings.maxHeight) { 650 dimensions.maxHeight = _self.settings.maxHeight; 651 } 652 653 // Calculate the difference between screen width/height and image width/height 654 dimensions.differenceWidthAsPercent = parseInt(100 / dimensions.maxWidth * dimensions.objectWidth); 655 dimensions.differenceHeightAsPercent = parseInt(100 / dimensions.maxHeight * dimensions.objectHeight); 656 657 switch (_self.objectData.type) { 658 case 'image': 659 case 'flash': 660 case 'video': 661 case 'iframe': 662 case 'ajax': 663 case 'inline': 664 if (_self.objectData.type === 'image' || _self.settings.fixedRatio === true) { 665 if (dimensions.differenceWidthAsPercent > 100 && dimensions.differenceWidthAsPercent > dimensions.differenceHeightAsPercent) { 666 dimensions.objectWidth = dimensions.maxWidth; 667 dimensions.objectHeight = parseInt(dimensions.objectHeight / dimensions.differenceWidthAsPercent * 100); 668 } 669 if (dimensions.differenceHeightAsPercent > 100 && dimensions.differenceHeightAsPercent > dimensions.differenceWidthAsPercent) { 670 dimensions.objectWidth = parseInt(dimensions.objectWidth / dimensions.differenceHeightAsPercent * 100); 671 dimensions.objectHeight = dimensions.maxHeight; 672 } 673 if (dimensions.differenceHeightAsPercent > 100 && dimensions.differenceWidthAsPercent < dimensions.differenceHeightAsPercent) { 674 dimensions.objectWidth = parseInt(dimensions.maxWidth / dimensions.differenceHeightAsPercent * dimensions.differenceWidthAsPercent); 675 dimensions.objectHeight = dimensions.maxHeight; 676 } 677 break; 678 } 679 case 'error': 680 if (!isNaN(dimensions.objectWidth) && dimensions.objectWidth > dimensions.maxWidth) { 681 dimensions.objectWidth = dimensions.maxWidth; 682 } 683 break; 684 default: 685 if ((isNaN(dimensions.objectWidth) || dimensions.objectWidth > dimensions.maxWidth) && !_self.settings.forceWidth) { 686 dimensions.objectWidth = dimensions.maxWidth; 687 } 688 if (((isNaN(dimensions.objectHeight) && dimensions.objectHeight !== 'auto') || dimensions.objectHeight > dimensions.maxHeight) && !_self.settings.forceHeight) { 689 dimensions.objectHeight = dimensions.maxHeight; 690 } 691 break; 692 } 693 } 694 695 if (_self.settings.forceWidth) { 696 try { 697 dimensions.objectWidth = _self.settings[_self.objectData.type].width; 698 } catch (e) { 699 dimensions.objectWidth = _self.settings.width || dimensions.objectWidth; 700 } 701 702 dimensions.maxWidth = null; 703 } 704 if ($object.attr(_self._prefixAttributeName('max-width'))) { 705 dimensions.maxWidth = $object.attr(_self._prefixAttributeName('max-width')); 706 } 707 708 if (_self.settings.forceHeight) { 709 try { 710 dimensions.objectHeight = _self.settings[_self.objectData.type].height; 711 } catch (e) { 712 dimensions.objectHeight = _self.settings.height || dimensions.objectHeight; 713 } 714 715 dimensions.maxHeight = null; 716 } 717 if ($object.attr(_self._prefixAttributeName('max-height'))) { 718 dimensions.maxHeight = $object.attr(_self._prefixAttributeName('max-height')); 719 } 720 _self._adjustDimensions($object, dimensions); 721 }, 722 723 /** 724 * Adjusts the dimensions 725 * 726 * @param {object} $object 727 * @param {object} dimensions 728 * @return {void} 729 */
730 _adjustDimensions: function ($object, dimensions) { 731 // Adjust width and height 732 $object.css({ 733 'width': dimensions.objectWidth, 734 'height': dimensions.objectHeight, 735 'max-width': dimensions.maxWidth, 736 'max-height': dimensions.maxHeight 737 }); 738 739 _self.objects.contentInner.css({ 740 'width': $object.outerWidth(), 741 'height': $object.outerHeight(), 742 'max-width': '100%' 743 }); 744 745 _self.objects.case.css({ 746 'width': _self.objects.contentInner.outerWidth(), 747 'max-width': '100%' 748 }); 749 750 // Adjust margin 751 _self.objects.case.css({ 752 'margin-top': parseInt(-(_self.objects.case.outerHeight() / 2)), 753 'margin-left': parseInt(-(_self.objects.case.outerWidth() / 2)) 754 }); 755 }, 756 757 /** 758 * Handles the _loading 759 * 760 * @param {string} process 761 * @return {void} 762 */ 763 _loading: function (process) { 764 if (process === 'start') { 765 _self.objects.case.addClass(_self.settings.classPrefix + 'loading'); 766 _self.objects.loading.show(); 767 } else if (process === 'end') { 768 _self.objects.case.removeClass(_self.settings.classPrefix + 'loading'); 769 _self.objects.loading.hide(); 770 } 771 }, 772 773 774 /** 775 * Gets the client screen dimensions 776 * 777 * @return {object} dimensions 778 */ 779 getViewportDimensions: function () { 780 return { 781 windowWidth: $(window).innerWidth(), 782 windowHeight: $(window).innerHeight() 783 }; 784 }, 785 786 /** 787 * Verifies the url 788 * 789 * @param {string} dataUrl 790 * @return {object} dataUrl Clean url for processing content 791 */ 792 _verifyDataUrl: function (dataUrl) { 793 if (!dataUrl || dataUrl === undefined || dataUrl === '') { 794 return false; 795 } 796 797 if (dataUrl.indexOf('#') > -1) { 798 dataUrl = dataUrl.split('#'); 799 dataUrl = '#' + dataUrl[dataUrl.length - 1]; 800 } 801 802 return _self._normalizeUrl(dataUrl.toString()); 803 }, 804 805 // 806 /** 807 * Tries to get the (file) suffix of an url 808 * 809 * @param {string} url 810 * @return {string} 811 */ 812 _getFileUrlSuffix: function (url) { 813 var re = /(?:\.([^.]+))?$/; 814 return re.exec(url.toLowerCase())[1]; 815 }, 816 817 /** 818 * Verifies the data type of the content to load 819 * 820 * @param {string} url 821 * @return {string|boolean} Array key if expression matched, else false 822 */ 823 _verifyDataType: function (url) { 824 var typeMapping = _self.settings.typeMapping; 825 826 // Early abort if dataUrl couldn't be verified 827 if (!url) { 828 return false; 829 } 830 831 // Verify the dataType of url according to typeMapping which 832 // has been defined in settings. 833 for (var key in typeMapping) { 834 if (typeMapping.hasOwnProperty(key)) { 835 var suffixArr = typeMapping[key].split(','); 836 837 for (var i = 0; i < suffixArr.length; i++) { 838 var suffix = suffixArr[i].toLowerCase(), 839 regexp = new RegExp('\.(' + suffix + ')$', 'i'), 840 str = url.toLowerCase().split('?')[0].substr(-5); 841 842 if (regexp.test(str) === true || (key === 'inline' && (url.indexOf(suffix) > -1))) { 843 return key; 844 } 845 } 846 } 847 } 848 849 // If no expression matched, return 'iframe'. 850 return 'iframe'; 851 }, 852 853 /** 854 * Extends html markup with the essential tags 855 * 856 * @return {void} 857 */ 858 _addElements: function () { 859 if (typeof _self.objects.case !== 'undefined' && $('#' + _self.objects.case.attr('id')).length) { 860 return; 861 } 862 863 _self.settings.markup(); 864 }, 865 866 /** 867 * Shows the loaded content 868 * 869 * @param {object} $object 870 * @return {void} 871 */ 872 _showContent: function ($object) { 873 // Add data attribute with the object type 874 _self.objects.document.attr(_self._prefixAttributeName('type'), _self.objectData.type); 875 876 _self.cache.object = $object; 877 878 // Call onBeforeShow hook functions 879 _self._callHooks(_self.settings.onBeforeShow); 880 881 if (_self.settings.breakBeforeShow) return; 882 _self.show(); 883 }, 884 885 /** 886 * Starts the 'inTransition' 887 * @return {void} 888 */ 889 _startInTransition: function () { 890 switch (_self.transition.in()) { 891 case 'scrollTop': 892 case 'scrollRight': 893 case 'scrollBottom': 894 case 'scrollLeft': 895 case 'scrollHorizontal': 896 case 'scrollVertical': 897 _self.transition.scroll(_self.objects.case, 'in', _self.settings.speedIn); 898 _self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn); 899 break; 900 case 'elastic': 901 if (_self.objects.case.css('opacity') < 1) { 902 _self.transition.zoom(_self.objects.case, 'in', _self.settings.speedIn); 903 _self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn); 904 } 905 case 'fade': 906 case 'fadeInline': 907 _self.transition.fade(_self.objects.case, 'in', _self.settings.speedIn); 908 _self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn); 909 break; 910 default: 911 _self.transition.fade(_self.objects.case, 'in', 0); 912 break; 913 } 914 915 // End loading. 916 _self._loading('end'); 917 _self.isBusy = false;
918 919 // Set index of the first item opened 920 if (!_self.cache.firstOpened) { 921 _self.cache.firstOpened = _self.objectData.this; 922 } 923 924 // Fade in the info with delay 925 _self.objects.info.hide(); 926 setTimeout(function () { 927 _self.transition.fade(_self.objects.info, 'in', _self.settings.speedIn); 928 }, _self.settings.speedIn); 929 930 // Call onFinish hook functions 931 _self._callHooks(_self.settings.onFinish); 932 }, 933 934 /** 935 * Processes the content to show 936 * 937 * @return {void} 938 */ 939 _processContent: function () { 940 _self.isBusy = true; 941 942 // Fade out the info at first 943 _self.transition.fade(_self.objects.info, 'out', 0); 944 945 switch (_self.settings.transitionOut) { 946 case 'scrollTop': 947 case 'scrollRight': 948 case 'scrollBottom': 949 case 'scrollLeft': 950 case 'scrollVertical': 951 case 'scrollHorizontal': 952 if (_self.objects.case.is(':hidden')) { 953 _self.transition.fade(_self.objects.contentInner, 'out', 0); 954 _self.transition.fade(_self.objects.case, 'out', 0, 0, function () { 955 _self._loadContent(); 956 }); 957 } else { 958 _self.transition.scroll(_self.objects.case, 'out', _self.settings.speedOut, function () { 959 _self._loadContent(); 960 }); 961 } 962 break; 963 case 'fade': 964 if (_self.objects.case.is(':hidden')) { 965 _self.transition.fade(_self.objects.case, 'out', 0, 0, function () { 966 _self._loadContent(); 967 }); 968 } else { 969 _self.transition.fade(_self.objects.case, 'out', _self.settings.speedOut, 0, function () { 970 _self._loadContent(); 971 }); 972 } 973 break; 974 case 'fadeInline': 975 case 'elastic': 976 if (_self.objects.case.is(':hidden')) { 977 _self.transition.fade(_self.objects.case, 'out', 0, 0, function () { 978 _self._loadContent(); 979 }); 980 } else { 981 _self.transition.fade(_self.objects.contentInner, 'out', _self.settings.speedOut, 0, function () { 982 _self._loadContent(); 983 }); 984 } 985 break; 986 default: 987 _self.transition.fade(_self.objects.case, 'out', 0, 0, function () { 988 _self._loadContent(); 989 }); 990 break; 991 } 992 }, 993 994 /** 995 * Handles events for gallery buttons 996 * 997 * @return {void} 998 */ 999 _handleEvents: function () { 1000 _self._unbindEvents(); 1001 1002 _self.objects.nav.children().not(_self.objects.close).hide(); 1003 1004 // If slideshow is enabled, show play/pause and start timeout. 1005 if (_self.isSlideshowEnabled()) { 1006 // Only start the timeout if slideshow autostart is enabled and slideshow is not pausing 1007 if ( 1008 (_self.settings.slideshowAutoStart === true || _self.isSlideshowStarted) && 1009 !_self.objects.nav.hasClass(_self.settings.classPrefix + 'paused') 1010 ) { 1011 _self._startTimeout(); 1012 } else { 1013 _self._stopTimeout(); 1014 } 1015 } 1016 1017 if (_self.settings.liveResize) { 1018 _self._watchResizeInteraction(); 1019 } 1020 1021 _self.objects.close.click(function (event) { 1022 event.preventDefault(); 1023 _self.close(); 1024 }); 1025 1026 if (_self.settings.closeOnOverlayClick === true) { 1027 _self.objects.overlay.css('cursor', 'pointer').click(function (event) { 1028 event.preventDefault(); 1029 1030 _self.close(); 1031 }); 1032 } 1033 1034 if (_self.settings.useKeys === true) { 1035 _self._addKeyEvents(); 1036 } 1037 1038 if (_self.objectData.isPartOfSequence) { 1039 _self.objects.nav.attr(_self._prefixAttributeName('ispartofsequence'), true); 1040 _self.objects.nav.data('items', _self._setNavigation()); 1041 1042 _self.objects.prev.click(function (event) { 1043 event.preventDefault(); 1044 1045 if (_self.settings.navigateEndless === true || !_self.item.isFirst()) { 1046 _self.objects.prev.unbind('click'); 1047 _self.cache.action = 'prev'; 1048 _self.objects.nav.data('items').prev.click(); 1049 1050 if (_self.isSlideshowEnabled()) { 1051 _self._stopTimeout(); 1052 } 1053 } 1054 }); 1055 1056 _self.objects.next.click(function (event) { 1057 event.preventDefault(); 1058 1059 if (_self.settings.navigateEndless === true || !_self.item.isLast()) { 1060 _self.objects.next.unbind('click'); 1061 _self.cache.action = 'next'; 1062 _self.objects.nav.data('items').next.click(); 1063 1064 if (_self.isSlideshowEnabled()) { 1065 _self._stopTimeout(); 1066 } 1067 } 1068 }); 1069 1070 if (_self.isSlideshowEnabled()) { 1071 _self.objects.play.click(function (event) { 1072 event.preventDefault(); 1073 _self._startTimeout(); 1074 }); 1075 _self.objects.pause.click(function (event) { 1076 event.preventDefault(); 1077 _self._stopTimeout(); 1078 }); 1079 } 1080 1081 // Enable swiping if activated 1082 if (_self.settings.swipe === true) { 1083 if ($.isPlainObject($.event.special.swipeleft)) { 1084 _self.objects.case.on('swipeleft', function (event) { 1085 event.preventDefault(); 1086 _self.objects.next.click(); 1087 if (_self.isSlideshowEnabled()) { 1088 _self._stopTimeout(); 1089 } 1090 }); 1091 } 1092 if ($.isPlainObject($.event.special.swiperight)) { 1093 _self.objects.case.on('swiperight', function (event) { 1094 event.preventDefault(); 1095 _self.objects.prev.click(); 1096 if (_self.isSlideshowEnabled()) { 1097 _self._stopTimeout(); 1098 } 1099 }); 1100 } 1101 } 1102 } 1103 }, 1104 1105 /** 1106 * Adds the key events 1107 * 1108 * @return {void} 1109 */ 1110 _addKeyEvents: function () { 1111 $(document).bind('keyup.lightcase', function (event) {
1112 // Do nothing if lightcase is in process 1113 if (_self.isBusy) { 1114 return; 1115 } 1116 1117 switch (event.keyCode) { 1118 // Escape key 1119 case 27: 1120 _self.objects.close.click(); 1121 break; 1122 // Backward key 1123 case 37: 1124 if (_self.objectData.isPartOfSequence) { 1125 _self.objects.prev.click(); 1126 } 1127 break; 1128 // Forward key 1129 case 39: 1130 if (_self.objectData.isPartOfSequence) { 1131 _self.objects.next.click(); 1132 } 1133 break; 1134 } 1135 }); 1136 }, 1137 1138 /** 1139 * Starts the slideshow timeout 1140 * 1141 * @return {void} 1142 */ 1143 _startTimeout: function () { 1144 _self.isSlideshowStarted = true; 1145 1146 _self.objects.play.hide(); 1147 _self.objects.pause.show(); 1148 1149 _self.cache.action = 'next'; 1150 _self.objects.nav.removeClass(_self.settings.classPrefix + 'paused'); 1151 1152 _self.timeout = setTimeout(function () { 1153 _self.objects.nav.data('items').next.click(); 1154 }, _self.settings.timeout); 1155 }, 1156 1157 /** 1158 * Stops the slideshow timeout 1159 * 1160 * @return {void} 1161 */ 1162 _stopTimeout: function () { 1163 _self.objects.play.show(); 1164 _self.objects.pause.hide(); 1165 1166 _self.objects.nav.addClass(_self.settings.classPrefix + 'paused'); 1167 1168 clearTimeout(_self.timeout); 1169 }, 1170 1171 /** 1172 * Sets the navigator buttons (prev/next) 1173 * 1174 * @return {object} items 1175 */ 1176 _setNavigation: function () { 1177 var $links = $((_self.cache.selector || _self.settings.attr)), 1178 sequenceLength = _self.objectData.sequenceLength - 1, 1179 items = { 1180 prev: $links.eq(_self.objectData.prevIndex), 1181 next: $links.eq(_self.objectData.nextIndex) 1182 }; 1183 1184 if (_self.objectData.currentIndex > 0) { 1185 _self.objects.prev.show(); 1186 } else { 1187 items.prevItem = $links.eq(sequenceLength); 1188 } 1189 if (_self.objectData.nextIndex <= sequenceLength) { 1190 _self.objects.next.show(); 1191 } else { 1192 items.next = $links.eq(0); 1193 } 1194 1195 if (_self.settings.navigateEndless === true) { 1196 _self.objects.prev.show(); 1197 _self.objects.next.show(); 1198 } 1199 1200 return items; 1201 }, 1202 1203 /** 1204 * Item information/status 1205 * 1206 */ 1207 item: { 1208 /** 1209 * Verifies if the current item is first item. 1210 * 1211 * @return {boolean} 1212 */ 1213 isFirst: function () { 1214 return (_self.objectData.currentIndex === 0); 1215 }, 1216 1217 /** 1218 * Verifies if the current item is first item opened. 1219 * 1220 * @return {boolean} 1221 */ 1222 isFirstOpened: function () { 1223 return _self.objectData.this.is(_self.cache.firstOpened); 1224 }, 1225 1226 /** 1227 * Verifies if the current item is last item. 1228 * 1229 * @return {boolean} 1230 */ 1231 isLast: function () { 1232 return (_self.objectData.currentIndex === (_self.objectData.sequenceLength - 1)); 1233 } 1234 }, 1235 1236 /** 1237 * Clones the object for inline elements 1238 * 1239 * @param {object} $object 1240 * @return {object} $clone 1241 */ 1242 _cloneObject: function ($object) { 1243 var $clone = $object.clone(), 1244 objectId = $object.attr('id'); 1245 1246 // If element is hidden, cache the object and remove 1247 if ($object.is(':hidden')) { 1248 _self._cacheObjectData($object); 1249 $object.attr('id', _self.settings.idPrefix + 'temp-' + objectId).empty(); 1250 } else { 1251 // Prevent duplicated id's 1252 $clone.removeAttr('id'); 1253 } 1254 1255 return $clone.show(); 1256 }, 1257 1258 /** 1259 * Verifies if it is a mobile device 1260 * 1261 * @return {boolean} 1262 */ 1263 isMobileDevice: function () { 1264 var deviceAgent = navigator.userAgent.toLowerCase(), 1265 agentId = deviceAgent.match(_self.settings.mobileMatchExpression); 1266 1267 return agentId ? true : false; 1268 }, 1269 1270 /** 1271 * Verifies if css transitions are supported 1272 * 1273 * @return {string|boolean} The transition prefix if supported, else false. 1274 */ 1275 isTransitionSupported: function () { 1276 var body = _self.objects.body.get(0), 1277 isTransitionSupported = false, 1278 transitionMapping = { 1279 'transition': '', 1280 'WebkitTransition': '-webkit-', 1281 'MozTransition': '-moz-', 1282 'OTransition': '-o-', 1283 'MsTransition': '-ms-' 1284 }; 1285 1286 for (var key in transitionMapping) { 1287 if (transitionMapping.hasOwnProperty(key) && key in body.style) { 1288 _self.support.transition = transitionMapping[key]; 1289 isTransitionSupported = true; 1290 } 1291 } 1292 1293 return isTransitionSupported; 1294 }, 1295 1296 /** 1297 * Transition types 1298 * 1299 */ 1300 transition: { 1301 /** 1302 * Returns the correct transition type according to the status of interaction. 1303 * 1304 * @return {string} Transition type 1305 */ 1306 in: function () { 1307 if (_self.settings.transitionOpen && !_self.cache.firstOpened) { 1308 return _self.settings.transitionOpen; 1309 } 1310 return _self.settings.transitionIn; 1311 }, 1312 1313 /** 1314 * Fades in/out the object 1315 * 1316 * @param {object} $object 1317 * @param {string} type 1318 * @param {number} speed 1319 * @param {number} opacity 1320 * @param {function} callback 1321 * @return {void} Animates an object 1322 */ 1323 fade: function ($object, type, speed, opacity, callback) { 1324 var isInTransition = type === 'in', 1325 startTransition = {}, 1326 startOpacity = $object.css('opacity'), 1327 endTransition = {}, 1328 endOpacity = opacity ? opacity: isInTransition ? 1 : 0; 1329 1330 if (!_self.isOpen && isInTransition) return; 1331 1332 startTransition['opacity'] = startOpacity; 1333 endTransition['opacity'] = endOpacity; 1334 1335 $object.css(_self.support.transition + 'transition', 'none'); 1336 $object.css(startTransition).show(); 1337 1338 // Css transition 1339 if (_self.support.transitions) { 1340 endTransition[_self.support.transition + 'transition'] = speed + 'ms ease'; 1341 1342 setTimeout(function () { 1343 $object.css(endTransition); 1344 1345 setTimeout(function () { 1346 $object.css(_self.support.transition + 'transition', ''); 1347 1348 if (callback && (_self.isOpen || !isInTransition)) { 1349 callback(); 1350 } 1351 }, speed); 1352 }, 15); 1353 } else { 1354 // Fallback to js transition 1355 $object.stop(); 1356 $object.animate(endTransition, speed, callback); 1357 } 1358 }, 1359 1360 /** 1361 * Scrolls in/out the object 1362 * 1363 * @param {object} $object 1364 * @param {string} type 1365 * @param {number} speed 1366 * @param {function} callback 1367 * @return {void} Animates an object 1368 */ 1369 scroll: function ($object, type, speed, callback) { 1370 var isInTransition = type === 'in', 1371 transition = isInTransition ? _self.settings.transitionIn : _self.settings.transitionOut, 1372 direction = 'left', 1373 startTransition = {}, 1374 startOpacity = isInTransition ? 0 : 1, 1375 startOffset = isInTransition ? '-50%' : '50%', 1376 endTransition = {}, 1377 endOpacity = isInTransition ? 1 : 0, 1378 endOffset = isInTransition ? '50%' : '-50%'; 1379 1380 if (!_self.isOpen && isInTransition) return; 1381 1382 switch (transition) { 1383 case 'scrollTop': 1384 direction = 'top'; 1385 break; 1386 case 'scrollRight': 1387 startOffset = isInTransition ? '150%' : '50%'; 1388 endOffset = isInTransition ? '50%' : '150%'; 1389 break; 1390 case 'scrollBottom': 1391 direction = 'top'; 1392 startOffset = isInTransition ? '150%' : '50%'; 1393 endOffset = isInTransition ? '50%' : '150%'; 1394 break; 1395 case 'scrollHorizontal': 1396 startOffset = isInTransition ? '150%' : '50%'; 1397 endOffset = isInTransition ? '50%' : '-50%'; 1398 break; 1399 case 'scrollVertical': 1400 direction = 'top'; 1401 startOffset = isInTransition ? '-50%' : '50%'; 1402 endOffset = isInTransition ? '50%' : '150%'; 1403 break; 1404 } 1405 1406 if (_self.cache.action === 'prev') { 1407 switch (transition) { 1408 case 'scrollHorizontal': 1409 startOffset = isInTransition ? '-50%' : '50%'; 1410 endOffset = isInTransition ? '50%' : '150%'; 1411 break; 1412 case 'scrollVertical': 1413 startOffset = isInTransition ? '150%' : '50%'; 1414 endOffset = isInTransition ? '50%' : '-50%'; 1415 break; 1416 } 1417 } 1418 1419 startTransition['opacity'] = startOpacity; 1420 startTransition[direction] = startOffset; 1421 1422 endTransition['opacity'] = endOpacity; 1423 endTransition[direction] = endOffset; 1424 1425 $object.css(_self.support.transition + 'transition', 'none'); 1426 $object.css(startTransition).show(); 1427 1428 // Css transition 1429 if (_self.support.transitions) { 1430 endTransition[_self.support.transition + 'transition'] = speed + 'ms ease'; 1431 1432 setTimeout(function () { 1433 $object.css(endTransition); 1434 1435 setTimeout(function () { 1436 $object.css(_self.support.transition + 'transition', ''); 1437 1438 if (callback && (_self.isOpen || !isInTransition)) { 1439 callback(); 1440 } 1441 }, speed); 1442 }, 15); 1443 } else { 1444 // Fallback to js transition 1445 $object.stop(); 1446 $object.animate(endTransition, speed, callback); 1447 } 1448 }, 1449 1450 /** 1451 * Zooms in/out the object 1452 * 1453 * @param {object} $object 1454 * @param {string} type 1455 * @param {number} speed 1456 * @param {function} callback 1457 * @return {void} Animates an object 1458 */ 1459 zoom: function ($object, type, speed, callback) { 1460 var isInTransition = type === 'in', 1461 startTransition = {}, 1462 startOpacity = $object.css('opacity'), 1463 startScale = isInTransition ? 'scale(0.75)' : 'scale(1)', 1464 endTransition = {}, 1465 endOpacity = isInTransition ? 1 : 0, 1466 endScale = isInTransition ? 'scale(1)' : 'scale(0.75)'; 1467 1468 if (!_self.isOpen && isInTransition) return; 1469 1470 startTransition['opacity'] = startOpacity; 1471 startTransition[_self.support.transition + 'transform'] = startScale; 1472 1473 endTransition['opacity'] = endOpacity; 1474 1475 $object.css(_self.support.transition + 'transition', 'none'); 1476 $object.css(startTransition).show(); 1477 1478 // Css transition 1479 if (_self.support.transitions) { 1480 endTransition[_self.support.transition + 'transform'] = endScale; 1481 endTransition[_self.support.transition + 'transition'] = speed + 'ms ease'; 1482 1483 setTimeout(function () { 1484 $object.css(endTransition); 1485 1486 setTimeout(function () { 1487 $object.css(_self.support.transition + 'transform', ''); 1488 $object.css(_self.support.transition + 'transition', ''); 1489 1490 if (callback && (_self.isOpen || !isInTransition)) { 1491 callback(); 1492 } 1493 }, speed); 1494 }, 15); 1495 } else { 1496 // Fallback to js transition 1497 $object.stop(); 1498 $object.animate(endTransition, speed, callback); 1499 } 1500 } 1501 }, 1502 1503 /** 1504 * Calls all the registered functions of a specific hook 1505 * 1506 * @param {object} hooks 1507 * @return {void} 1508 */ 1509 _callHooks: function (hooks) { 1510 if (typeof(hooks) === 'object') { 1511 $.each(hooks, function(index, hook) { 1512 if (typeof(hook) === 'function') { 1513 hook.call(_self.origin); 1514 } 1515 }); 1516 } 1517 }, 1518 1519 /** 1520 * Caches the object data 1521 * 1522 * @param {object} $object 1523 * @return {void} 1524 */ 1525 _cacheObjectData: function ($object) { 1526 $.data($object, 'cache', { 1527 id: $object.attr('id'), 1528 content: $object.html() 1529 }); 1530 1531 _self.cache.originalObject = $object; 1532 }, 1533 1534 /** 1535 * Restores the object from cache 1536 * 1537 * @return void 1538 */ 1539 _restoreObject: function () { 1540 var $object = $('[id^="' + _self.settings.idPrefix + 'temp-"]'); 1541 1542 $object.attr('id', $.data(_self.cache.originalObject, 'cache').id); 1543 $object.html($.data(_self.cache.originalObject, 'cache').content); 1544 }, 1545 1546 /** 1547 * Executes functions for a window resize. 1548 * It stops an eventual timeout and recalculates dimensions. 1549 * 1550 * @param {object} dimensions 1551 * @return {void} 1552 */ 1553 resize: function (event, dimensions) { 1554 if (!_self.isOpen) return; 1555 1556 if (_self.isSlideshowEnabled()) { 1557 _self._stopTimeout(); 1558 } 1559 1560 if (typeof dimensions === 'object' && dimensions !== null) { 1561 if (dimensions.width) { 1562 _self.cache.object.attr( 1563 _self._prefixAttributeName('width'), 1564 dimensions.width 1565 ); 1566 } 1567 if (dimensions.maxWidth) { 1568 _self.cache.object.attr( 1569 _self._prefixAttributeName('max-width'), 1570 dimensions.maxWidth 1571 ); 1572 } 1573 if (dimensions.height) { 1574 _self.cache.object.attr( 1575 _self._prefixAttributeName('height'), 1576 dimensions.height 1577 ); 1578 } 1579 if (dimensions.maxHeight) { 1580 _self.cache.object.attr( 1581 _self._prefixAttributeName('max-height'), 1582 dimensions.maxHeight 1583 ); 1584 } 1585 } 1586 1587 _self.dimensions = _self.getViewportDimensions(); 1588 _self._calculateDimensions(_self.cache.object); 1589 1590 // Call onResize hook functions 1591 _self._callHooks(_self.settings.onResize); 1592 }, 1593 1594 /** 1595 * Watches for any resize interaction and caches the new sizes. 1596 * 1597 * @return {void} 1598 */ 1599 _watchResizeInteraction: function () { 1600 $(window).resize(_self.resize); 1601 }, 1602 1603 /** 1604 * Stop watching any resize interaction related to _self. 1605 * 1606 * @return {void} 1607 */ 1608 _unwatchResizeInteraction: function () { 1609 $(window).off('resize', _self.resize); 1610 }, 1611 1612 /** 1613 * Switches to the fullscreen mode 1614 * 1615 * @return {void} 1616 */ 1617 _switchToFullScreenMode: function () { 1618 _self.settings.shrinkFactor = 1; 1619 _self.settings.overlayOpacity = 1; 1620 1621 $('html').addClass(_self.settings.classPrefix + 'fullScreenMode'); 1622 }, 1623 1624 /** 1625 * Enters into the lightcase view 1626 * 1627 * @return {void} 1628 */ 1629 _open: function () { 1630 _self.isOpen = true; 1631 1632 _self.support.transitions = _self.settings.cssTransitions ? _self.isTransitionSupported() : false;
1633 _self.support.mobileDevice = _self.isMobileDevice(); 1634 1635 if (_self.support.mobileDevice) { 1636 $('html').addClass(_self.settings.classPrefix + 'isMobileDevice'); 1637 1638 if (_self.settings.fullScreenModeForMobile) { 1639 _self._switchToFullScreenMode(); 1640 } 1641 } 1642 1643 if (!_self.settings.transitionIn) { 1644 _self.settings.transitionIn = _self.settings.transition; 1645 } 1646 if (!_self.settings.transitionOut) { 1647 _self.settings.transitionOut = _self.settings.transition; 1648 } 1649 1650 switch (_self.transition.in()) { 1651 case 'fade': 1652 case 'fadeInline': 1653 case 'elastic': 1654 case 'scrollTop': 1655 case 'scrollRight': 1656 case 'scrollBottom': 1657 case 'scrollLeft': 1658 case 'scrollVertical': 1659 case 'scrollHorizontal': 1660 if (_self.objects.case.is(':hidden')) { 1661 _self.objects.close.css('opacity', 0); 1662 _self.objects.overlay.css('opacity', 0); 1663 _self.objects.case.css('opacity', 0); 1664 _self.objects.contentInner.css('opacity', 0); 1665 } 1666 _self.transition.fade(_self.objects.overlay, 'in', _self.settings.speedIn, _self.settings.overlayOpacity, function () { 1667 _self.transition.fade(_self.objects.close, 'in', _self.settings.speedIn); 1668 _self._handleEvents(); 1669 _self._processContent(); 1670 }); 1671 break; 1672 default: 1673 _self.transition.fade(_self.objects.overlay, 'in', 0, _self.settings.overlayOpacity, function () { 1674 _self.transition.fade(_self.objects.close, 'in', 0); 1675 _self._handleEvents(); 1676 _self._processContent(); 1677 }); 1678 break; 1679 } 1680 1681 _self.objects.document.addClass(_self.settings.classPrefix + 'open'); 1682 _self.objects.case.attr('aria-hidden', 'false'); 1683 }, 1684 1685 /** 1686 * Shows the lightcase by starting the transition 1687 */ 1688 show: function () { 1689 // Call onCalculateDimensions hook functions 1690 _self._callHooks(_self.settings.onBeforeCalculateDimensions); 1691 1692 _self._calculateDimensions(_self.cache.object); 1693 1694 // Call onAfterCalculateDimensions hook functions 1695 _self._callHooks(_self.settings.onAfterCalculateDimensions); 1696 1697 _self._startInTransition(); 1698 }, 1699 1700 /** 1701 * Escapes from the lightcase view 1702 * 1703 * @return {void} 1704 */ 1705 close: function () { 1706 _self.isOpen = false; 1707 1708 if (_self.isSlideshowEnabled()) { 1709 _self._stopTimeout(); 1710 _self.isSlideshowStarted = false; 1711 _self.objects.nav.removeClass(_self.settings.classPrefix + 'paused'); 1712 } 1713 1714 _self.objects.loading.hide(); 1715 1716 _self._unbindEvents(); 1717 1718 _self._unwatchResizeInteraction(); 1719 1720 $('html').removeClass(_self.settings.classPrefix + 'open'); 1721 _self.objects.case.attr('aria-hidden', 'true'); 1722 1723 _self.objects.nav.children().hide(); 1724 _self.objects.close.hide(); 1725 1726 // Call onClose hook functions 1727 _self._callHooks(_self.settings.onClose); 1728 1729 // Fade out the info at first 1730 _self.transition.fade(_self.objects.info, 'out', 0); 1731 1732 switch (_self.settings.transitionClose || _self.settings.transitionOut) { 1733 case 'fade': 1734 case 'fadeInline': 1735 case 'scrollTop': 1736 case 'scrollRight': 1737 case 'scrollBottom': 1738 case 'scrollLeft': 1739 case 'scrollHorizontal': 1740 case 'scrollVertical': 1741 _self.transition.fade(_self.objects.case, 'out', _self.settings.speedOut, 0, function () { 1742 _self.transition.fade(_self.objects.overlay, 'out', _self.settings.speedOut, 0, function () { 1743 _self.cleanup(); 1744 }); 1745 }); 1746 break; 1747 case 'elastic': 1748 _self.transition.zoom(_self.objects.case, 'out', _self.settings.speedOut, function () { 1749 _self.transition.fade(_self.objects.overlay, 'out', _self.settings.speedOut, 0, function () { 1750 _self.cleanup(); 1751 }); 1752 }); 1753 break; 1754 default: 1755 _self.cleanup(); 1756 break; 1757 } 1758 }, 1759 1760 /** 1761 * Unbinds all given events 1762 * 1763 * @return {void} 1764 */ 1765 _unbindEvents: function () { 1766 // Unbind overlay event 1767 _self.objects.overlay.unbind('click'); 1768 1769 // Unbind key events 1770 $(document).unbind('keyup.lightcase'); 1771 1772 // Unbind swipe events 1773 _self.objects.case.unbind('swipeleft').unbind('swiperight'); 1774 1775 // Unbind navigator events 1776 _self.objects.prev.unbind('click'); 1777 _self.objects.next.unbind('click'); 1778 _self.objects.play.unbind('click'); 1779 _self.objects.pause.unbind('click'); 1780 1781 // Unbind close event 1782 _self.objects.close.unbind('click'); 1783 }, 1784 1785 /** 1786 * Cleans up the dimensions 1787 * 1788 * @return {void} 1789 */ 1790 _cleanupDimensions: function () { 1791 var opacity = _self.objects.contentInner.css('opacity'); 1792 1793 _self.objects.case.css({ 1794 'width': '', 1795 'height': '', 1796 'top': '', 1797 'left': '', 1798 'margin-top': '', 1799 'margin-left': '' 1800 }); 1801 1802 _self.objects.contentInner.removeAttr('style').css('opacity', opacity); 1803 _self.objects.contentInner.children().removeAttr('style'); 1804 }, 1805 1806 /** 1807 * Cleanup after aborting lightcase 1808 * 1809 * @return {void} 1810 */ 1811 cleanup: function () { 1812 _self._cleanupDimensions(); 1813 1814 _self.objects.loading.hide(); 1815 _self.objects.overlay.hide(); 1816 _self.objects.case.hide(); 1817 _self.objects.prev.hide(); 1818 _self.objects.next.hide(); 1819 _self.objects.play.hide(); 1820 _self.objects.pause.hide(); 1821 1822 _self.objects.document.removeAttr(_self._prefixAttributeName('type')); 1823 _self.objects.nav.removeAttr(_self._prefixAttributeName('ispartofsequence')); 1824 1825 _self.objects.contentInner.empty().hide(); 1826 _self.objects.info.children().empty(); 1827 1828 if (_self.cache.originalObject) { 1829 _self._restoreObject(); 1830 } 1831 1832 // Call onCleanup hook functions 1833 _self._callHooks(_self.settings.onCleanup); 1834 1835 // Restore cache 1836 _self.cache = {}; 1837 }, 1838 1839 /** 1840 * Returns the supported match media or undefined if the browser 1841 * doesn't support match media. 1842 * 1843 * @return {mixed} 1844 */ 1845 _matchMedia: function () { 1846 return window.matchMedia || window.msMatchMedia; 1847 }, 1848 1849 /** 1850 * Returns the devicePixelRatio if supported. Else, it simply returns 1851 * 1 as the default. 1852 * 1853 * @return {number} 1854 */ 1855 _devicePixelRatio: function () { 1856 return window.devicePixelRatio || 1; 1857 }, 1858 1859 /** 1860 * Checks if method is public 1861 * 1862 * @return {boolean} 1863 */ 1864 _isPublicMethod: function (method) { 1865 return (typeof _self[method] === 'function' && method.charAt(0) !== '_'); 1866 }, 1867 1868 /** 1869 * Exports all public methods to be accessible, callable 1870 * from global scope. 1871 * 1872 * @return {void} 1873 */ 1874 _export: function () { 1875 window.lightcase = {}; 1876 1877 $.each(_self, function (property) { 1878 if (_self._isPublicMethod(property)) { 1879 lightcase[property] = _self[property]; 1880 } 1881 }); 1882 } 1883 }; 1884 1885 _self._export(); 1886 1887 $.fn.lightcase = function (method) { 1888 // Method calling logic (only public methods are applied)
1889 if (_self._isPublicMethod(method)) { 1890 return _self[method].apply(this, Array.prototype.slice.call(arguments, 1)); 1891 } else if (typeof method === 'object' || !method) { 1892 return _self.init.apply(this, arguments); 1893 } else { 1894 $.error('Method ' + method + ' does not exist on jQuery.lightcase'); 1895 } 1896 }; 1897})(jQuery);
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.