vendor: 11,050 bytes, lines 1-265
1var ScrollOut = (function () { 2 'use strict'; 3 4 function clamp(v, min, max) { 5 return min > v ? min : max < v ? max : v; 6 } 7 function sign(x) { 8 return (+(x > 0) - +(x < 0)); 9 } 10 function round(n) { 11 return Math.round(n * 10000) / 10000; 12 } 13 14 var cache = {}; 15 function replacer(match) { 16 return '-' + match[0].toLowerCase(); 17 } 18 function hyphenate(value) { 19 return cache[value] || (cache[value] = value.replace(/([A-Z])/g, replacer)); 20 } 21 22 /** find elements */ 23 function $(e, parent) { 24 return !e || e.length === 0 25 ? // null or empty string returns empty array 26 [] 27 : e.nodeName 28 ? // a single element is wrapped in an array 29 [e] 30 : // selector and NodeList are converted to Element[] 31 [].slice.call(e[0].nodeName ? e : (parent || document.documentElement).querySelectorAll(e)); 32 } 33 function setAttrs(el, attrs) { 34 // tslint:disable-next-line:forin 35 for (var key in attrs) { 36 if (key.indexOf('_')) { 37 el.setAttribute('data-' + hyphenate(key), attrs[key]); 38 } 39 } 40 } 41 function setProps(cssProps) { 42 return function (el, props) { 43 for (var key in props) { 44 if (key.indexOf('_') && (cssProps === true || cssProps[key])) { 45 el.style.setProperty('--' + hyphenate(key), round(props[key])); 46 } 47 } 48 }; 49 } 50 51 var clearTask; 52 var subscribers = []; 53 function loop() { 54 clearTask = 0; 55 subscribers.slice().forEach(function (s2) { return s2(); }); 56 enqueue(); 57 } 58 function enqueue() { 59 if (!clearTask && subscribers.length) { 60 clearTask = requestAnimationFrame(loop); 61 } 62 } 63 function subscribe(fn) { 64 subscribers.push(fn); 65 enqueue(); 66 return function () { 67 subscribers = subscribers.filter(function (s) { return s !== fn; }); 68 if (!subscribers.length && clearTask) { 69 cancelAnimationFrame(clearTask); 70 clearTask = 0; 71 } 72 }; 73 } 74 75 function unwrap(value, el, ctx, doc) { 76 return typeof value === 'function' ? value(el, ctx, doc) : value; 77 } 78 function noop() { } 79 80 /** 81 * Creates a new instance of ScrollOut that marks elements in the viewport with 82 * an "in" class and marks elements outside of the viewport with an "out" 83 */ 84 // tslint:disable-next-line:no-default-export 85 function main (opts) { 86 // Apply default options. 87 opts = opts || {}; 88 // Debounce onChange/onHidden/onShown. 89 var onChange = opts.onChange || noop; 90 var onHidden = opts.onHidden || noop; 91 var onShown = opts.onShown || noop; 92 var onScroll = opts.onScroll || noop; 93 var props = opts.cssProps ? setProps(opts.cssProps) : noop; 94 var se = opts.scrollingElement; 95 var container = se ? $(se)[0] : window; 96 var doc = se ? $(se)[0] : document.documentElement; 97 var rootChanged = false; 98 var scrollingElementContext = {}; 99 var elementContextList = []; 100 var clientOffsetX, clientOffsety; 101 var sub; 102 function index() { 103 elementContextList = $(opts.targets || '[data-scroll]', $(opts.scope || doc)[0]).map(function (el) { return ({ element: el }); }); 104 } 105 function update() { 106 // Calculate position, direction and ratio. 107 var clientWidth = doc.clientWidth; 108 var clientHeight = doc.clientHeight; 109 var scrollDirX = sign(-clientOffsetX + (clientOffsetX = doc.scrollLeft || window.pageXOffset)); 110 var scrollDirY = sign(-clientOffsety + (clientOffsety = doc.scrollTop || window.pageYOffset)); 111 var scrollPercentX = doc.scrollLeft / (doc.scrollWidth - clientWidth || 1); 112 var scrollPercentY = doc.scrollTop / (doc.scrollHeight - clientHeight || 1); 113 // Detect if the root context has changed. 114 rootChanged = 115 rootChanged || 116 scrollingElementContext.scrollDirX !== scrollDirX || 117 scrollingElementContext.scrollDirY !== scrollDirY || 118 scrollingElementContext.scrollPercentX !== scrollPercentX || 119 scrollingElementContext.scrollPercentY !== scrollPercentY; 120 scrollingElementContext.scrollDirX = scrollDirX; 121 scrollingElementContext.scrollDirY = scrollDirY; 122 scrollingElementContext.scrollPercentX = scrollPercentX; 123 scrollingElementContext.scrollPercentY = scrollPercentY; 124 var childChanged = false; 125 for (var index_1 = 0; index_1 < elementContextList.length; index_1++) { 126 var ctx = elementContextList[index_1]; 127 var element = ctx.element; 128 // find the distance from the element to the scrolling container 129 var target = element; 130 var offsetX = 0; 131 var offsetY = 0; 132 do { 133 offsetX += target.offsetLeft; 134 offsetY += target.offsetTop; 135 target = target.offsetParent; 136 } while (target && target !== container); 137 // Get element dimensions. 138 var elementHeight = element.clientHeight || element.offsetHeight || 0; 139 var elementWidth = element.clientWidth || element.offsetWidth || 0; 140 // Find visible ratios for each element. 141 var visibleX = (clamp(offsetX + elementWidth, clientOffsetX, clientOffsetX + clientWidth) - 142 clamp(offsetX, clientOffsetX, clientOffsetX + clientWidth)) / 143 elementWidth; 144 var visibleY = (clamp(offsetY + elementHeight, clientOffsety, clientOffsety + clientHeight) - 145 clamp(offsetY, clientOffsety, clientOffsety + clientHeight)) / 146 elementHeight; 147 var intersectX = visibleX === 1 ? 0 : sign(offsetX - clientOffsetX); 148 var intersectY = visibleY === 1 ? 0 : sign(offsetY - clientOffsety); 149 var viewportX = clamp((clientOffsetX - (elementWidth / 2 + offsetX - clientWidth / 2)) / (clientWidth / 2), -1, 1); 150 var viewportY = clamp((clientOffsety - (elementHeight / 2 + offsetY - clientHeight / 2)) / (clientHeight / 2), -1, 1); 151 var visible = void 0; 152 if (opts.offset) { 153 visible = unwrap(opts.offset, element, ctx, doc) <= clientOffsety ? 1 : 0; 154 } 155 else if ((unwrap(opts.threshold, element, ctx, doc) || 0) < visibleX * visibleY) { 156 visible = 1; 157 } 158 else { 159 visible = 0; 160 } 161 var changedVisible = ctx.visible !== visible; 162 var changed = ctx._changed || 163 changedVisible || 164 ctx.visibleX !== visibleX || 165 ctx.visibleY !== visibleY || 166 ctx.index !== index_1 || 167 ctx.elementHeight !== elementHeight || 168 ctx.elementWidth !== elementWidth || 169 ctx.offsetX !== offsetX || 170 ctx.offsetY !== offsetY || 171 ctx.intersectX !== ctx.intersectX || 172 ctx.intersectY !== ctx.intersectY || 173 ctx.viewportX !== viewportX || 174 ctx.viewportY !== viewportY; 175 if (changed) { 176 childChanged = true; 177 ctx._changed = true; 178 ctx._visibleChanged = changedVisible; 179 ctx.visible = visible; 180 ctx.elementHeight = elementHeight; 181 ctx.elementWidth = elementWidth; 182 ctx.index = index_1; 183 ctx.offsetX = offsetX; 184 ctx.offsetY = offsetY; 185 ctx.visibleX = visibleX; 186 ctx.visibleY = visibleY; 187 ctx.intersectX = intersectX; 188 ctx.intersectY = intersectY; 189 ctx.viewportX = viewportX; 190 ctx.viewportY = viewportY; 191 ctx.visible = visible; 192 } 193 } 194 if (!sub && (rootChanged || childChanged)) { 195 sub = subscribe(render); 196 } 197 } 198 function render() { 199 maybeUnsubscribe(); 200 // Update root attributes if they have changed. 201 if (rootChanged) { 202 rootChanged = false; 203 setAttrs(doc, { 204 scrollDirX: scrollingElementContext.scrollDirX, 205 scrollDirY: scrollingElementContext.scrollDirY 206 }); 207 props(doc, scrollingElementContext); 208 onScroll(doc, scrollingElementContext, elementContextList); 209 } 210 var len = elementContextList.length; 211 for (var x = len - 1; x > -1; x--) { 212 var ctx = elementContextList[x]; 213 var el = ctx.element; 214 var visible = ctx.visible; 215 var justOnce = el.hasAttribute('scrollout-once') || false; // Once 216 if (ctx._changed) { 217 ctx._changed = false; 218 props(el, ctx); 219 } 220 if (ctx._visibleChanged) { 221 setAttrs(el, { scroll: visible ? 'in' : 'out' }); 222 onChange(el, ctx, doc); 223 (visible ? onShown : onHidden)(el, ctx, doc); 224 } 225 // if this is shown multiple times, keep it in the list 226 if (visible && (opts.once || justOnce)) { // or if this element just display it once 227 elementContextList.splice(x, 1); 228 } 229 } 230 } 231 function maybeUnsubscribe() { 232 if (sub) { 233 sub(); 234 sub = undefined; 235 } 236 } 237 // Run initialize index. 238 index(); 239 update(); 240 render(); 241 // Collapses sequential updates into a single update. 242 var updateTaskId = 0; 243 var onUpdate = function () { 244 updateTaskId = updateTaskId || setTimeout(function () { 245 updateTaskId = 0; 246 update(); 247 }, 0); 248 }; 249 // Hook up document listeners to automatically detect changes. 250 window.addEventListener('resize', onUpdate); 251 container.addEventListener('scroll', onUpdate); 252 return { 253 index: index, 254 update: update, 255 teardown: function () { 256 maybeUnsubscribe(); 257 window.removeEventListener('resize', onUpdate); 258 container.removeEventListener('scroll', onUpdate); 259 } 260 }; 261 } 262 263 return main; 264 265}());
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.