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