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