1/* 2 The MIT License (MIT) 3 4 Copyright (c) 2014 Dirk Groenen 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy of 7 this software and associated documentation files (the "Software"), to deal in 8 the Software without restriction, including without limitation the rights to 9 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 the Software, and to permit persons to whom the Software is furnished to do so, 11 subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in all 14 copies or substantial portions of the Software. 15*/ 16 17(function($){ 18 $.fn.viewportChecker = function(useroptions){ 19 // Define options and extend with user 20 var options = { 21 classToAdd: 'visible', 22 classToRemove : 'invisible', 23 classToAddForFullView : 'full-visible', 24 removeClassAfterAnimation: false, 25 offset: 100, 26 repeat: false, 27 invertBottomOffset: true, 28 callbackFunction: function(elem, action){}, 29 scrollHorizontal: false, 30 scrollBox: window 31 }; 32 $.extend(options, useroptions); 33 34 // Cache the given element and height of the browser 35 var $elem = this, 36 boxSize = {height: $(options.scrollBox).height(), width: $(options.scrollBox).width()}; 37 /* 38 * Main method that checks the elements and adds or removes the class(es) 39 */ 40 this.checkElements = function(){ 41 var viewportStart, viewportEnd; 42 43 // Set some vars to check with 44 if (!options.scrollHorizontal){ 45 viewportStart = Math.max( 46 $('html').scrollTop(), 47 $('body').scrollTop(), 48 $(window).scrollTop() 49 ); 50 viewportEnd = (viewportStart + boxSize.height); 51 } 52 else{ 53 viewportStart = Math.max( 54 $('html').scrollLeft(), 55 $('body').scrollLeft(), 56 $(window).scrollLeft() 57 ); 58 viewportEnd = (viewportStart + boxSize.width); 59 } 60 61 // Loop through all given dom elements 62 $elem.each(function(){ 63 var $obj = $(this), 64 objOptions = {}, 65 attrOptions = {}; 66 67 // Get any individual attribution data 68 if ($obj.data('vp-add-class')) 69 attrOptions.classToAdd = $obj.data('vp-add-class'); 70 if ($obj.data('vp-remove-class')) 71 attrOptions.classToRemove = $obj.data('vp-remove-class'); 72 if ($obj.data('vp-add-class-full-view')) 73 attrOptions.classToAddForFullView = $obj.data('vp-add-class-full-view'); 74 if ($obj.data('vp-keep-add-class')) 75 attrOptions.removeClassAfterAnimation = $obj.data('vp-remove-after-animation'); 76 if ($obj.data('vp-offset')) 77 attrOptions.offset = $obj.data('vp-offset'); 78 if ($obj.data('vp-repeat')) 79 attrOptions.repeat = $obj.data('vp-repeat'); 80 if ($obj.data('vp-scrollHorizontal')) 81 attrOptions.scrollHorizontal = $obj.data('vp-scrollHorizontal'); 82 if ($obj.data('vp-invertBottomOffset')) 83 attrOptions.scrollHorizontal = $obj.data('vp-invertBottomOffset'); 84 85 // Extend objOptions with data attributes and default options 86 $.extend(objOptions, options); 87 $.extend(objOptions, attrOptions); 88 89 // If class already exists; quit 90 if ($obj.data('vp-animated') && !objOptions.repeat){ 91 return; 92 } 93 94 // Check if the offset is percentage based 95 if (String(objOptions.offset).indexOf("%") > 0) 96 objOptions.offset = (parseInt(objOptions.offset) / 100) * boxSize.height; 97 98 // Get the raw start and end positions 99 var rawStart = (!objOptions.scrollHorizontal) ? $obj.offset().top : $obj.offset().left, 100 rawEnd = (!objOptions.scrollHorizontal) ? rawStart + $obj.height() : rawStart + $obj.width(); 101 102 // Add the defined offset 103 var elemStart = Math.round( rawStart ) + objOptions.offset, 104 elemEnd = (!objOptions.scrollHorizontal) ? elemStart + $obj.height() : elemStart + $obj.width(); 105 106 if (objOptions.invertBottomOffset) 107 elemEnd -= (objOptions.offset * 2); 108 109 // Add class if in viewport 110 if ((elemStart < viewportEnd) && (elemEnd > viewportStart)){ 111 112 // Remove class 113 $obj.removeClass(objOptions.classToRemove); 114 $obj.addClass(objOptions.classToAdd); 115 116 // Do the callback function. Callback wil send the jQuery object as parameter 117 objOptions.callbackFunction($obj, "add"); 118 119 // Check if full element is in view 120 if (rawEnd <= viewportEnd && rawStart >= viewportStart) 121 $obj.addClass(objOptions.classToAddForFullView); 122 else 123 $obj.removeClass(objOptions.classToAddForFullView); 124 125 // Set element as already animated 126 $obj.data('vp-animated', true); 127 128 if (objOptions.removeClassAfterAnimation) { 129 $obj.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(){ 130 $obj.removeClass(objOptions.classToAdd); 131 }); 132 } 133 134 // Remove class if not in viewport and repeat is true 135 } else if ($obj.hasClass(objOptions.classToAdd) && (objOptions.repeat)){ 136 $obj.removeClass(objOptions.classToAdd + " " + objOptions.classToAddForFullView); 137 138 // Do the callback function. 139 objOptions.callbackFunction($obj, "remove"); 140 141 // Remove already-animated-flag 142 $obj.data('vp-animated', false); 143 } 144 }); 145 146 }; 147 148 /** 149 * Binding the correct event listener is still a tricky thing. 150 * People have expierenced sloppy scrolling when both scroll and touch 151 * events are added, but to make sure devices with both scroll and touch 152 * are handles too we always have to add the window.scroll event 153 *
154 * @see https://github.com/dirkgroenen/jQuery-viewport-checker/issues/25 155 * @see https://github.com/dirkgroenen/jQuery-viewport-checker/issues/27 156 */ 157 158 // Select the correct events 159 if( 'ontouchstart' in window || 'onmsgesturechange' in window ){ 160 // Device with touchscreen 161 $(document).bind("touchmove MSPointerMove pointermove", this.checkElements); 162 } 163 164 // Always load on window load 165 $(options.scrollBox).bind("load scroll", this.checkElements); 166 167 // On resize change the height var 168 $(window).resize(function(e){ 169 boxSize = {height: $(options.scrollBox).height(), width: $(options.scrollBox).width()}; 170 $elem.checkElements(); 171 }); 172 173 // trigger inital check if elements already visible 174 this.checkElements(); 175 176 // Default jquery plugin behaviour 177 return this; 178 }; 179})(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.