vendor: 44,160 bytes, lines 1-1311
1/*! 2 * # Semantic UI 2.2.10 - Visibility 3 * http://github.com/semantic-org/semantic-ui/ 4 * 5 * 6 * Released under the MIT license 7 * http://opensource.org/licenses/MIT 8 * 9 */ 10 11;(function ($, window, document, undefined) { 12 13"use strict"; 14 15window = (typeof window != 'undefined' && window.Math == Math) 16 ? window 17 : (typeof self != 'undefined' && self.Math == Math) 18 ? self 19 : Function('return this')() 20; 21 22$.fn.visibility = function(parameters) { 23 var 24 $allModules = $(this), 25 moduleSelector = $allModules.selector || '', 26 27 time = new Date().getTime(), 28 performance = [], 29 30 query = arguments[0], 31 methodInvoked = (typeof query == 'string'), 32 queryArguments = [].slice.call(arguments, 1), 33 returnedValue, 34 35 moduleCount = $allModules.length, 36 loadedCount = 0 37 ; 38 39 $allModules 40 .each(function() { 41 var 42 settings = ( $.isPlainObject(parameters) ) 43 ? $.extend(true, {}, $.fn.visibility.settings, parameters) 44 : $.extend({}, $.fn.visibility.settings), 45 46 className = settings.className, 47 namespace = settings.namespace, 48 error = settings.error, 49 metadata = settings.metadata, 50 51 eventNamespace = '.' + namespace, 52 moduleNamespace = 'module-' + namespace, 53 54 $window = $(window), 55 56 $module = $(this), 57 $context = $(settings.context), 58 59 $placeholder, 60 61 selector = $module.selector || '', 62 instance = $module.data(moduleNamespace), 63 64 requestAnimationFrame = window.requestAnimationFrame 65 || window.mozRequestAnimationFrame 66 || window.webkitRequestAnimationFrame 67 || window.msRequestAnimationFrame 68 || function(callback) { setTimeout(callback, 0); }, 69 70 element = this, 71 disabled = false, 72 73 contextObserver, 74 observer, 75 module 76 ; 77 78 module = { 79 80 initialize: function() { 81 module.debug('Initializing', settings); 82 83 module.setup.cache(); 84 85 if( module.should.trackChanges() ) { 86 87 if(settings.type == 'image') { 88 module.setup.image(); 89 } 90 if(settings.type == 'fixed') { 91 module.setup.fixed(); 92 } 93 94 if(settings.observeChanges) { 95 module.observeChanges(); 96 } 97 module.bind.events(); 98 } 99 100 module.save.position(); 101 if( !module.is.visible() ) { 102 module.error(error.visible, $module); 103 } 104 105 if(settings.initialCheck) { 106 module.checkVisibility(); 107 } 108 module.instantiate(); 109 }, 110 111 instantiate: function() { 112 module.debug('Storing instance', module); 113 $module 114 .data(moduleNamespace, module) 115 ; 116 instance = module; 117 }, 118 119 destroy: function() { 120 module.verbose('Destroying previous module'); 121 if(observer) { 122 observer.disconnect(); 123 } 124 if(contextObserver) { 125 contextObserver.disconnect(); 126 } 127 $window 128 .off('load' + eventNamespace, module.event.load) 129 .off('resize' + eventNamespace, module.event.resize) 130 ; 131 $context 132 .off('scroll' + eventNamespace, module.event.scroll) 133 .off('scrollchange' + eventNamespace, module.event.scrollchange) 134 ; 135 if(settings.type == 'fixed') { 136 module.resetFixed(); 137 module.remove.placeholder(); 138 } 139 $module 140 .off(eventNamespace) 141 .removeData(moduleNamespace) 142 ; 143 }, 144 145 observeChanges: function() { 146 if('MutationObserver' in window) { 147 contextObserver = new MutationObserver(module.event.contextChanged); 148 observer = new MutationObserver(module.event.changed); 149 contextObserver.observe(document, { 150 childList : true, 151 subtree : true 152 }); 153 observer.observe(element, { 154 childList : true, 155 subtree : true 156 }); 157 module.debug('Setting up mutation observer', observer); 158 } 159 }, 160 161 bind: { 162 events: function() { 163 module.verbose('Binding visibility events to scroll and resize'); 164 if(settings.refreshOnLoad) { 165 $window 166 .on('load' + eventNamespace, module.event.load) 167 ; 168 } 169 $window 170 .on('resize' + eventNamespace, module.event.resize) 171 ; 172 // pub/sub pattern 173 $context 174 .off('scroll' + eventNamespace) 175 .on('scroll' + eventNamespace, module.event.scroll) 176 .on('scrollchange' + eventNamespace, module.event.scrollchange) 177 ; 178 } 179 }, 180 181 event: { 182 changed: function(mutations) { 183 module.verbose('DOM tree modified, updating visibility calculations'); 184 module.timer = setTimeout(function() { 185 module.verbose('DOM tree modified, updating sticky menu'); 186 module.refresh(); 187 }, 100); 188 }, 189 contextChanged: function(mutations) { 190 [].forEach.call(mutations, function(mutation) { 191 if(mutation.removedNodes) { 192 [].forEach.call(mutation.removedNodes, function(node) { 193 if(node == element || $(node).find(element).length > 0) { 194 module.debug('Element removed from DOM, tearing down events'); 195 module.destroy(); 196 } 197 }); 198 } 199 }); 200 }, 201 resize: function() { 202 module.debug('Window resized'); 203 if(settings.refreshOnResize) { 204 requestAnimationFrame(module.refresh); 205 } 206 }, 207 load: function() { 208 module.debug('Page finished loading'); 209 requestAnimationFrame(module.refresh); 210 }, 211 // publishes scrollchange event on one scroll 212 scroll: function() { 213 if(settings.throttle) { 214 clearTimeout(module.timer); 215 module.timer = setTimeout(function() { 216 $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]); 217 }, settings.throttle); 218 } 219 else { 220 requestAnimationFrame(function() { 221 $context.triggerHandler('scrollchange' + eventNamespace, [ $context.scrollTop() ]); 222 }); 223 } 224 }, 225 // subscribes to scrollchange 226 scrollchange: function(event, scrollPosition) { 227 module.checkVisibility(scrollPosition); 228 }, 229 }, 230 231 precache: function(images, callback) { 232 if (!(images instanceof Array)) { 233 images = [images]; 234 } 235 var 236 imagesLength = images.length, 237 loadedCounter = 0, 238 cache = [], 239 cacheImage = document.createElement('img'), 240 handleLoad = function() { 241 loadedCounter++; 242 if (loadedCounter >= images.length) { 243 if ($.isFunction(callback)) { 244 callback(); 245 } 246 } 247 } 248 ; 249 while (imagesLength--) { 250 cacheImage = document.createElement('img'); 251 cacheImage.onload = handleLoad; 252 cacheImage.onerror = handleLoad; 253 cacheImage.src = images[imagesLength]; 254 cache.push(cacheImage); 255 } 256 }, 257 258 enableCallbacks: function() { 259 module.debug('Allowing callbacks to occur'); 260 disabled = false; 261 }, 262 263 disableCallbacks: function() { 264 module.debug('Disabling all callbacks temporarily'); 265 disabled = true; 266 }, 267 268 should: { 269 trackChanges: function() { 270 if(methodInvoked) { 271 module.debug('One time query, no need to bind events'); 272 return false; 273 } 274 module.debug('Callbacks being attached'); 275 return true; 276 } 277 }, 278 279 setup: { 280 cache: function() { 281 module.cache = { 282 occurred : {}, 283 screen : {}, 284 element : {}, 285 }; 286 }, 287 image: function() { 288 var 289 src = $module.data(metadata.src) 290 ; 291 if(src) { 292 module.verbose('Lazy loading image', src); 293 settings.once = true; 294 settings.observeChanges = false; 295 296 // show when top visible 297 settings.onOnScreen = function() { 298 module.debug('Image on screen', element); 299 module.precache(src, function() { 300 module.set.image(src, function() { 301 loadedCount++; 302 if(loadedCount == moduleCount) { 303 settings.onAllLoaded.call(this); 304 } 305 settings.onLoad.call(this); 306 }); 307 }); 308 }; 309 } 310 }, 311 fixed: function() { 312 module.debug('Setting up fixed'); 313 settings.once = false; 314 settings.observeChanges = false; 315 settings.initialCheck = true; 316 settings.refreshOnLoad = true; 317 if(!parameters.transition) { 318 settings.transition = false; 319 } 320 module.create.placeholder(); 321 module.debug('Added placeholder', $placeholder); 322 settings.onTopPassed = function() { 323 module.debug('Element passed, adding fixed position', $module); 324 module.show.placeholder(); 325 module.set.fixed(); 326 if(settings.transition) { 327 if($.fn.transition !== undefined) { 328 $module.transition(settings.transition, settings.duration); 329 } 330 } 331 }; 332 settings.onTopPassedReverse = function() { 333 module.debug('Element returned to position, removing fixed', $module); 334 module.hide.placeholder(); 335 module.remove.fixed(); 336 }; 337 } 338 }, 339 340 create: { 341 placeholder: function() { 342 module.verbose('Creating fixed position placeholder'); 343 $placeholder = $module 344 .clone(false) 345 .css('display', 'none') 346 .addClass(className.placeholder) 347 .insertAfter($module) 348 ; 349 } 350 }, 351 352 show: { 353 placeholder: function() { 354 module.verbose('Showing placeholder'); 355 $placeholder 356 .css('display', 'block') 357 .css('visibility', 'hidden') 358 ; 359 } 360 }, 361 hide: { 362 placeholder: function() { 363 module.verbose('Hiding placeholder'); 364 $placeholder 365 .css('display', 'none') 366 .css('visibility', '') 367 ; 368 } 369 }, 370 371 set: { 372 fixed: function() { 373 module.verbose('Setting element to fixed position'); 374 $module 375 .addClass(className.fixed) 376 .css({ 377 position : 'fixed', 378 top : settings.offset + 'px', 379 left : 'auto', 380 zIndex : settings.zIndex 381 }) 382 ; 383 settings.onFixed.call(element); 384 }, 385 image: function(src, callback) { 386 $module 387 .attr('src', src) 388 ; 389 if(settings.transition) { 390 if( $.fn.transition !== undefined) { 391 if($module.hasClass(className.visible)) { 392 module.debug('Transition already occurred on this image, skipping animation'); 393 return; 394 } 395 $module.transition(settings.transition, settings.duration, callback); 396 } 397 else { 398 $module.fadeIn(settings.duration, callback); 399 } 400 } 401 else { 402 $module.show(); 403 } 404 } 405 }, 406 407 is: { 408 onScreen: function() { 409 var 410 calculations = module.get.elementCalculations() 411 ; 412 return calculations.onScreen; 413 }, 414 offScreen: function() { 415 var 416 calculations = module.get.elementCalculations() 417 ; 418 return calculations.offScreen; 419 }, 420 visible: function() { 421 if(module.cache && module.cache.element) { 422 return !(module.cache.element.width === 0 && module.cache.element.offset.top === 0); 423 } 424 return false; 425 }, 426 verticallyScrollableContext: function() { 427 var 428 overflowY = ($context.get(0) !== window) 429 ? $context.css('overflow-y') 430 : false 431 ; 432 return (overflowY == 'auto' || overflowY == 'scroll'); 433 }, 434 horizontallyScrollableContext: function() { 435 var 436 overflowX = ($context.get(0) !== window) 437 ? $context.css('overflow-x') 438 : false 439 ; 440 return (overflowX == 'auto' || overflowX == 'scroll'); 441 } 442 }, 443 444 refresh: function() { 445 module.debug('Refreshing constants (width/height)'); 446 if(settings.type == 'fixed') { 447 module.resetFixed(); 448 } 449 module.reset(); 450 module.save.position(); 451 if(settings.checkOnRefresh) { 452 module.checkVisibility(); 453 } 454 settings.onRefresh.call(element); 455 }, 456 457 resetFixed: function () { 458 module.remove.fixed(); 459 module.remove.occurred(); 460 }, 461 462 reset: function() { 463 module.verbose('Resetting all cached values'); 464 if( $.isPlainObject(module.cache) ) { 465 module.cache.screen = {}; 466 module.cache.element = {}; 467 } 468 }, 469 470 checkVisibility: function(scroll) { 471 module.verbose('Checking visibility of element', module.cache.element); 472 473 if( !disabled && module.is.visible() ) { 474 475 // save scroll position 476 module.save.scroll(scroll); 477 478 // update calculations derived from scroll 479 module.save.calculations(); 480 481 // percentage 482 module.passed(); 483 484 // reverse (must be first) 485 module.passingReverse(); 486 module.topVisibleReverse(); 487 module.bottomVisibleReverse(); 488 module.topPassedReverse(); 489 module.bottomPassedReverse(); 490 491 // one time 492 module.onScreen(); 493 module.offScreen(); 494 module.passing(); 495 module.topVisible(); 496 module.bottomVisible(); 497 module.topPassed(); 498 module.bottomPassed(); 499 500 // on update callback 501 if(settings.onUpdate) { 502 settings.onUpdate.call(element, module.get.elementCalculations()); 503 } 504 } 505 }, 506 507 passed: function(amount, newCallback) { 508 var 509 calculations = module.get.elementCalculations(), 510 amountInPixels 511 ; 512 // assign callback 513 if(amount && newCallback) { 514 settings.onPassed[amount] = newCallback; 515 } 516 else if(amount !== undefined) { 517 return (module.get.pixelsPassed(amount) > calculations.pixelsPassed); 518 } 519 else if(calculations.passing) { 520 $.each(settings.onPassed, function(amount, callback) { 521 if(calculations.bottomVisible || calculations.pixelsPassed > module.get.pixelsPassed(amount)) { 522 module.execute(callback, amount); 523 } 524 else if(!settings.once) { 525 module.remove.occurred(callback); 526 } 527 }); 528 } 529 }, 530 531 onScreen: function(newCallback) { 532 var 533 calculations = module.get.elementCalculations(), 534 callback = newCallback || settings.onOnScreen, 535 callbackName = 'onScreen' 536 ; 537 if(newCallback) { 538 module.debug('Adding callback for onScreen', newCallback); 539 settings.onOnScreen = newCallback; 540 } 541 if(calculations.onScreen) { 542 module.execute(callback, callbackName); 543 } 544 else if(!settings.once) { 545 module.remove.occurred(callbackName); 546 } 547 if(newCallback !== undefined) { 548 return calculations.onOnScreen; 549 } 550 }, 551 552 offScreen: function(newCallback) { 553 var 554 calculations = module.get.elementCalculations(), 555 callback = newCallback || settings.onOffScreen, 556 callbackName = 'offScreen' 557 ; 558 if(newCallback) { 559 module.debug('Adding callback for offScreen', newCallback); 560 settings.onOffScreen = newCallback; 561 } 562 if(calculations.offScreen) { 563 module.execute(callback, callbackName); 564 } 565 else if(!settings.once) { 566 module.remove.occurred(callbackName); 567 } 568 if(newCallback !== undefined) { 569 return calculations.onOffScreen; 570 } 571 }, 572 573 passing: function(newCallback) { 574 var 575 calculations = module.get.elementCalculations(), 576 callback = newCallback || settings.onPassing, 577 callbackName = 'passing' 578 ; 579 if(newCallback) { 580 module.debug('Adding callback for passing', newCallback); 581 settings.onPassing = newCallback; 582 } 583 if(calculations.passing) { 584 module.execute(callback, callbackName); 585 } 586 else if(!settings.once) { 587 module.remove.occurred(callbackName); 588 } 589 if(newCallback !== undefined) { 590 return calculations.passing; 591 } 592 }, 593 594 595 topVisible: function(newCallback) { 596 var 597 calculations = module.get.elementCalculations(), 598 callback = newCallback || settings.onTopVisible, 599 callbackName = 'topVisible' 600 ; 601 if(newCallback) { 602 module.debug('Adding callback for top visible', newCallback); 603 settings.onTopVisible = newCallback; 604 } 605 if(calculations.topVisible) { 606 module.execute(callback, callbackName); 607 } 608 else if(!settings.once) { 609 module.remove.occurred(callbackName); 610 } 611 if(newCallback === undefined) { 612 return calculations.topVisible; 613 } 614 }, 615 616 bottomVisible: function(newCallback) { 617 var 618 calculations = module.get.elementCalculations(), 619 callback = newCallback || settings.onBottomVisible, 620 callbackName = 'bottomVisible' 621 ; 622 if(newCallback) { 623 module.debug('Adding callback for bottom visible', newCallback); 624 settings.onBottomVisible = newCallback; 625 } 626 if(calculations.bottomVisible) { 627 module.execute(callback, callbackName); 628 } 629 else if(!settings.once) { 630 module.remove.occurred(callbackName); 631 } 632 if(newCallback === undefined) { 633 return calculations.bottomVisible; 634 } 635 }, 636 637 topPassed: function(newCallback) { 638 var 639 calculations = module.get.elementCalculations(), 640 callback = newCallback || settings.onTopPassed, 641 callbackName = 'topPassed' 642 ; 643 if(newCallback) { 644 module.debug('Adding callback for top passed', newCallback); 645 settings.onTopPassed = newCallback; 646 } 647 if(calculations.topPassed) { 648 module.execute(callback, callbackName); 649 } 650 else if(!settings.once) { 651 module.remove.occurred(callbackName); 652 } 653 if(newCallback === undefined) { 654 return calculations.topPassed; 655 } 656 }, 657 658 bottomPassed: function(newCallback) { 659 var 660 calculations = module.get.elementCalculations(), 661 callback = newCallback || settings.onBottomPassed, 662 callbackName = 'bottomPassed' 663 ; 664 if(newCallback) { 665 module.debug('Adding callback for bottom passed', newCallback); 666 settings.onBottomPassed = newCallback; 667 } 668 if(calculations.bottomPassed) { 669 module.execute(callback, callbackName); 670 } 671 else if(!settings.once) { 672 module.remove.occurred(callbackName); 673 } 674 if(newCallback === undefined) { 675 return calculations.bottomPassed; 676 } 677 }, 678 679 passingReverse: function(newCallback) { 680 var 681 calculations = module.get.elementCalculations(), 682 callback = newCallback || settings.onPassingReverse, 683 callbackName = 'passingReverse' 684 ; 685 if(newCallback) { 686 module.debug('Adding callback for passing reverse', newCallback); 687 settings.onPassingReverse = newCallback; 688 } 689 if(!calculations.passing) { 690 if(module.get.occurred('passing')) { 691 module.execute(callback, callbackName); 692 } 693 } 694 else if(!settings.once) { 695 module.remove.occurred(callbackName); 696 } 697 if(newCallback !== undefined) { 698 return !calculations.passing; 699 } 700 }, 701 702 703 topVisibleReverse: function(newCallback) { 704 var 705 calculations = module.get.elementCalculations(), 706 callback = newCallback || settings.onTopVisibleReverse, 707 callbackName = 'topVisibleReverse' 708 ; 709 if(newCallback) { 710 module.debug('Adding callback for top visible reverse', newCallback); 711 settings.onTopVisibleReverse = newCallback; 712 } 713 if(!calculations.topVisible) { 714 if(module.get.occurred('topVisible')) { 715 module.execute(callback, callbackName); 716 } 717 } 718 else if(!settings.once) { 719 module.remove.occurred(callbackName); 720 } 721 if(newCallback === undefined) { 722 return !calculations.topVisible; 723 } 724 }, 725 726 bottomVisibleReverse: function(newCallback) { 727 var 728 calculations = module.get.elementCalculations(), 729 callback = newCallback || settings.onBottomVisibleReverse, 730 callbackName = 'bottomVisibleReverse' 731 ; 732 if(newCallback) { 733 module.debug('Adding callback for bottom visible reverse', newCallback); 734 settings.onBottomVisibleReverse = newCallback; 735 } 736 if(!calculations.bottomVisible) { 737 if(module.get.occurred('bottomVisible')) { 738 module.execute(callback, callbackName); 739 } 740 } 741 else if(!settings.once) { 742 module.remove.occurred(callbackName); 743 } 744 if(newCallback === undefined) { 745 return !calculations.bottomVisible; 746 } 747 }, 748 749 topPassedReverse: function(newCallback) { 750 var 751 calculations = module.get.elementCalculations(), 752 callback = newCallback || settings.onTopPassedReverse, 753 callbackName = 'topPassedReverse' 754 ; 755 if(newCallback) { 756 module.debug('Adding callback for top passed reverse', newCallback); 757 settings.onTopPassedReverse = newCallback; 758 } 759 if(!calculations.topPassed) { 760 if(module.get.occurred('topPassed')) { 761 module.execute(callback, callbackName); 762 } 763 } 764 else if(!settings.once) { 765 module.remove.occurred(callbackName); 766 } 767 if(newCallback === undefined) { 768 return !calculations.onTopPassed; 769 } 770 }, 771 772 bottomPassedReverse: function(newCallback) { 773 var 774 calculations = module.get.elementCalculations(), 775 callback = newCallback || settings.onBottomPassedReverse, 776 callbackName = 'bottomPassedReverse' 777 ; 778 if(newCallback) { 779 module.debug('Adding callback for bottom passed reverse', newCallback); 780 settings.onBottomPassedReverse = newCallback; 781 } 782 if(!calculations.bottomPassed) { 783 if(module.get.occurred('bottomPassed')) { 784 module.execute(callback, callbackName); 785 } 786 } 787 else if(!settings.once) { 788 module.remove.occurred(callbackName); 789 } 790 if(newCallback === undefined) { 791 return !calculations.bottomPassed; 792 } 793 }, 794 795 execute: function(callback, callbackName) { 796 var 797 calculations = module.get.elementCalculations(), 798 screen = module.get.screenCalculations() 799 ; 800 callback = callback || false; 801 if(callback) { 802 if(settings.continuous) { 803 module.debug('Callback being called continuously', callbackName, calculations); 804 callback.call(element, calculations, screen); 805 } 806 else if(!module.get.occurred(callbackName)) { 807 module.debug('Conditions met', callbackName, calculations); 808 callback.call(element, calculations, screen); 809 } 810 } 811 module.save.occurred(callbackName); 812 }, 813 814 remove: { 815 fixed: function() { 816 module.debug('Removing fixed position'); 817 $module 818 .removeClass(className.fixed) 819 .css({ 820 position : '', 821 top : '', 822 left : '', 823 zIndex : '' 824 }) 825 ; 826 settings.onUnfixed.call(element); 827 }, 828 placeholder: function() { 829 module.debug('Removing placeholder content'); 830 if($placeholder) { 831 $placeholder.remove(); 832 } 833 }, 834 occurred: function(callback) { 835 if(callback) { 836 var 837 occurred = module.cache.occurred 838 ; 839 if(occurred[callback] !== undefined && occurred[callback] === true) { 840 module.debug('Callback can now be called again', callback); 841 module.cache.occurred[callback] = false; 842 } 843 } 844 else { 845 module.cache.occurred = {}; 846 } 847 } 848 }, 849 850 save: { 851 calculations: function() { 852 module.verbose('Saving all calculations necessary to determine positioning'); 853 module.save.direction(); 854 module.save.screenCalculations(); 855 module.save.elementCalculations(); 856 }, 857 occurred: function(callback) { 858 if(callback) { 859 if(module.cache.occurred[callback] === undefined || (module.cache.occurred[callback] !== true)) { 860 module.verbose('Saving callback occurred', callback); 861 module.cache.occurred[callback] = true; 862 } 863 } 864 }, 865 scroll: function(scrollPosition) { 866 scrollPosition = scrollPosition + settings.offset || $context.scrollTop() + settings.offset; 867 module.cache.scroll = scrollPosition; 868 }, 869 direction: function() { 870 var 871 scroll = module.get.scroll(), 872 lastScroll = module.get.lastScroll(), 873 direction 874 ; 875 if(scroll > lastScroll && lastScroll) { 876 direction = 'down'; 877 } 878 else if(scroll < lastScroll && lastScroll) { 879 direction = 'up'; 880 } 881 else { 882 direction = 'static'; 883 } 884 module.cache.direction = direction; 885 return module.cache.direction; 886 }, 887 elementPosition: function() { 888 var 889 element = module.cache.element, 890 screen = module.get.screenSize() 891 ; 892 module.verbose('Saving element position'); 893 // (quicker than $.extend) 894 element.fits = (element.height < screen.height); 895 element.offset = $module.offset(); 896 element.width = $module.outerWidth(); 897 element.height = $module.outerHeight(); 898 // compensate for scroll in context 899 if(module.is.verticallyScrollableContext()) { 900 element.offset.top += $context.scrollTop() - $context.offset().top; 901 } 902 if(module.is.horizontallyScrollableContext()) { 903 element.offset.left += $context.scrollLeft - $context.offset().left; 904 } 905 // store 906 module.cache.element = element; 907 return element; 908 }, 909 elementCalculations: function() { 910 var 911 screen = module.get.screenCalculations(), 912 element = module.get.elementPosition() 913 ; 914 // offset 915 if(settings.includeMargin) { 916 element.margin = {}; 917 element.margin.top = parseInt($module.css('margin-top'), 10); 918 element.margin.bottom = parseInt($module.css('margin-bottom'), 10); 919 element.top = element.offset.top - element.margin.top; 920 element.bottom = element.offset.top + element.height + element.margin.bottom; 921 } 922 else { 923 element.top = element.offset.top; 924 element.bottom = element.offset.top + element.height; 925 } 926 927 // visibility 928 element.topPassed = (screen.top >= element.top); 929 element.bottomPassed = (screen.top >= element.bottom); 930 element.topVisible = (screen.bottom >= element.top) && !element.bottomPassed; 931 element.bottomVisible = (screen.bottom >= element.bottom) && !element.topPassed; 932 element.pixelsPassed = 0; 933 element.percentagePassed = 0; 934 935 // meta calculations 936 element.onScreen = (element.topVisible && !element.bottomPassed); 937 element.passing = (element.topPassed && !element.bottomPassed); 938 element.offScreen = (!element.onScreen); 939 940 // passing calculations 941 if(element.passing) { 942 element.pixelsPassed = (screen.top - element.top); 943 element.percentagePassed = (screen.top - element.top) / element.height; 944 } 945 module.cache.element = element; 946 module.verbose('Updated element calculations', element); 947 return element; 948 }, 949 screenCalculations: function() { 950 var 951 scroll = module.get.scroll() 952 ; 953 module.save.direction(); 954 module.cache.screen.top = scroll; 955 module.cache.screen.bottom = scroll + module.cache.screen.height; 956 return module.cache.screen; 957 }, 958 screenSize: function() { 959 module.verbose('Saving window position'); 960 module.cache.screen = { 961 height: $context.height() 962 }; 963 }, 964 position: function() { 965 module.save.screenSize(); 966 module.save.elementPosition(); 967 } 968 }, 969 970 get: { 971 pixelsPassed: function(amount) { 972 var 973 element = module.get.elementCalculations() 974 ; 975 if(amount.search('%') > -1) { 976 return ( element.height * (parseInt(amount, 10) / 100) ); 977 } 978 return parseInt(amount, 10); 979 }, 980 occurred: function(callback) { 981 return (module.cache.occurred !== undefined) 982 ? module.cache.occurred[callback] || false 983 : false 984 ; 985 }, 986 direction: function() { 987 if(module.cache.direction === undefined) { 988 module.save.direction(); 989 } 990 return module.cache.direction; 991 }, 992 elementPosition: function() { 993 if(module.cache.element === undefined) { 994 module.save.elementPosition(); 995 } 996 return module.cache.element; 997 }, 998 elementCalculations: function() { 999 if(module.cache.element === undefined) { 1000 module.save.elementCalculations(); 1001 } 1002 return module.cache.element; 1003 }, 1004 screenCalculations: function() { 1005 if(module.cache.screen === undefined) { 1006 module.save.screenCalculations(); 1007 } 1008 return module.cache.screen; 1009 }, 1010 screenSize: function() { 1011 if(module.cache.screen === undefined) { 1012 module.save.screenSize(); 1013 } 1014 return module.cache.screen; 1015 }, 1016 scroll: function() { 1017 if(module.cache.scroll === undefined) { 1018 module.save.scroll(); 1019 } 1020 return module.cache.scroll; 1021 }, 1022 lastScroll: function() { 1023 if(module.cache.screen === undefined) { 1024 module.debug('First scroll event, no last scroll could be found'); 1025 return false; 1026 } 1027 return module.cache.screen.top; 1028 } 1029 }, 1030 1031 setting: function(name, value) { 1032 if( $.isPlainObject(name) ) { 1033 $.extend(true, settings, name); 1034 } 1035 else if(value !== undefined) { 1036 settings[name] = value; 1037 } 1038 else { 1039 return settings[name]; 1040 } 1041 }, 1042 internal: function(name, value) { 1043 if( $.isPlainObject(name) ) { 1044 $.extend(true, module, name); 1045 } 1046 else if(value !== undefined) { 1047 module[name] = value; 1048 } 1049 else { 1050 return module[name]; 1051 } 1052 }, 1053 debug: function() { 1054 if(!settings.silent && settings.debug) { 1055 if(settings.performance) { 1056 module.performance.log(arguments); 1057 } 1058 else { 1059 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 1060 module.debug.apply(console, arguments); 1061 } 1062 } 1063 }, 1064 verbose: function() { 1065 if(!settings.silent && settings.verbose && settings.debug) { 1066 if(settings.performance) { 1067 module.performance.log(arguments); 1068 } 1069 else { 1070 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 1071 module.verbose.apply(console, arguments); 1072 } 1073 } 1074 }, 1075 error: function() { 1076 if(!settings.silent) { 1077 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 1078 module.error.apply(console, arguments); 1079 } 1080 }, 1081 performance: { 1082 log: function(message) { 1083 var 1084 currentTime, 1085 executionTime, 1086 previousTime 1087 ; 1088 if(settings.performance) { 1089 currentTime = new Date().getTime(); 1090 previousTime = time || currentTime; 1091 executionTime = currentTime - previousTime; 1092 time = currentTime; 1093 performance.push({ 1094 'Name' : message[0], 1095 'Arguments' : [].slice.call(message, 1) || '', 1096 'Element' : element, 1097 'Execution Time' : executionTime 1098 }); 1099 } 1100 clearTimeout(module.performance.timer); 1101 module.performance.timer = setTimeout(module.performance.display, 500); 1102 }, 1103 display: function() { 1104 var 1105 title = settings.name + ':', 1106 totalTime = 0 1107 ; 1108 time = false; 1109 clearTimeout(module.performance.timer); 1110 $.each(performance, function(index, data) { 1111 totalTime += data['Execution Time']; 1112 }); 1113 title += ' ' + totalTime + 'ms'; 1114 if(moduleSelector) { 1115 title += ' \'' + moduleSelector + '\''; 1116 } 1117 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 1118 console.groupCollapsed(title); 1119 if(console.table) { 1120 console.table(performance); 1121 } 1122 else { 1123 $.each(performance, function(index, data) { 1124 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 1125 }); 1126 } 1127 console.groupEnd(); 1128 } 1129 performance = []; 1130 } 1131 }, 1132 invoke: function(query, passedArguments, context) { 1133 var 1134 object = instance, 1135 maxDepth, 1136 found, 1137 response 1138 ; 1139 passedArguments = passedArguments || queryArguments; 1140 context = element || context; 1141 if(typeof query == 'string' && object !== undefined) { 1142 query = query.split(/[\. ]/); 1143 maxDepth = query.length - 1; 1144 $.each(query, function(depth, value) { 1145 var camelCaseValue = (depth != maxDepth) 1146 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 1147 : query 1148 ; 1149 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 1150 object = object[camelCaseValue]; 1151 } 1152 else if( object[camelCaseValue] !== undefined ) { 1153 found = object[camelCaseValue]; 1154 return false; 1155 } 1156 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 1157 object = object[value]; 1158 } 1159 else if( object[value] !== undefined ) { 1160 found = object[value]; 1161 return false; 1162 } 1163 else { 1164 module.error(error.method, query); 1165 return false; 1166 } 1167 }); 1168 } 1169 if ( $.isFunction( found ) ) { 1170 response = found.apply(context, passedArguments); 1171 } 1172 else if(found !== undefined) { 1173 response = found; 1174 } 1175 if($.isArray(returnedValue)) { 1176 returnedValue.push(response); 1177 } 1178 else if(returnedValue !== undefined) { 1179 returnedValue = [returnedValue, response]; 1180 } 1181 else if(response !== undefined) { 1182 returnedValue = response; 1183 } 1184 return found; 1185 } 1186 }; 1187 1188 if(methodInvoked) { 1189 if(instance === undefined) { 1190 module.initialize(); 1191 } 1192 instance.save.scroll(); 1193 instance.save.calculations(); 1194 module.invoke(query); 1195 } 1196 else { 1197 if(instance !== undefined) { 1198 instance.invoke('destroy'); 1199 } 1200 module.initialize(); 1201 } 1202 }) 1203 ; 1204 1205 return (returnedValue !== undefined) 1206 ? returnedValue 1207 : this 1208 ; 1209}; 1210 1211$.fn.visibility.settings = { 1212 1213 name : 'Visibility', 1214 namespace : 'visibility', 1215 1216 debug : false, 1217 verbose : false, 1218 performance : true, 1219 1220 // whether to use mutation observers to follow changes 1221 observeChanges : true, 1222 1223 // check position immediately on init 1224 initialCheck : true, 1225 1226 // whether to refresh calculations after all page images load 1227 refreshOnLoad : true, 1228 1229 // whether to refresh calculations after page resize event 1230 refreshOnResize : true, 1231 1232 // should call callbacks on refresh event (resize, etc) 1233 checkOnRefresh : true, 1234 1235 // callback should only occur one time 1236 once : true, 1237 1238 // callback should fire continuously whe evaluates to true 1239 continuous : false, 1240 1241 // offset to use with scroll top 1242 offset : 0, 1243 1244 // whether to include margin in elements position 1245 includeMargin : false, 1246 1247 // scroll context for visibility checks 1248 context : window, 1249 1250 // visibility check delay in ms (defaults to animationFrame) 1251 throttle : false, 1252 1253 // special visibility type (image, fixed) 1254 type : false, 1255 1256 // z-index to use with visibility 'fixed' 1257 zIndex : '10', 1258 1259 // image only animation settings 1260 transition : 'fade in', 1261 duration : 1000, 1262 1263 // array of callbacks for percentage 1264 onPassed : {}, 1265 1266 // standard callbacks 1267 onOnScreen : false, 1268 onOffScreen : false, 1269 onPassing : false, 1270 onTopVisible : false, 1271 onBottomVisible : false, 1272 onTopPassed : false, 1273 onBottomPassed : false, 1274 1275 // reverse callbacks 1276 onPassingReverse : false, 1277 onTopVisibleReverse : false, 1278 onBottomVisibleReverse : false, 1279 onTopPassedReverse : false, 1280 onBottomPassedReverse : false, 1281 1282 // special callbacks for image 1283 onLoad : function() {}, 1284 onAllLoaded : function() {}, 1285 1286 // special callbacks for fixed position 1287 onFixed : function() {}, 1288 onUnfixed : function() {}, 1289 1290 // utility callbacks 1291 onUpdate : false, // disabled by default for performance 1292 onRefresh : function(){}, 1293 1294 metadata : { 1295 src: 'src' 1296 }, 1297 1298 className: { 1299 fixed : 'fixed', 1300 placeholder : 'placeholder', 1301 visible : 'visible' 1302 }, 1303 1304 error : { 1305 method : 'The method you called is not defined.', 1306 visible : 'Element is hidden, you must call refresh after element becomes visible' 1307 } 1308 1309}; 1310 1311})( jQuery, window, document );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.