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