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