1/* 2 _ _ _____ _ _ 3 | | | __ \ | | (_) 4 ___ ___ _ __ ___ | | | |__) |_____ _____ __ _| | _ ___ 5 / __|/ __| '__/ _ \| | | _ // _ \ \ / / _ \/ _` | | | / __| 6 \__ \ (__| | | (_) | | | | \ \ __/\ V / __/ (_| | |_| \__ \ 7 |___/\___|_| \___/|_|_|_| \_\___| \_/ \___|\__,_|_(_) |___/ 8 _/ | 9 |__/ 10 11 "Declarative on-scroll reveal animations." 12 13/*============================================================================= 14 15 scrollReveal.js is inspired by cbpScroller.js, © 2014, Codrops. 16 17 Licensed under the MIT license. 18 https://www.opensource.org/licenses/mit-license.php 19 20 scrollReveal.js, © 2014 https://twitter.com/julianlloyd 21 22=============================================================================*/ 23 24;(function (window) { 25 26 'use strict'; 27 28 var docElem = window.document.documentElement; 29 30 function getViewportH () { 31 var client = docElem['clientHeight'], 32 inner = window['innerHeight']; 33 34 return (client < inner) ? inner : client; 35 } 36 37 function getOffset (el) { 38 var offsetTop = 0, 39 offsetLeft = 0; 40 41 do { 42 if (!isNaN(el.offsetTop)) { 43 offsetTop += el.offsetTop; 44 } 45 if (!isNaN(el.offsetLeft)) { 46 offsetLeft += el.offsetLeft; 47 } 48 } while (el = el.offsetParent) 49 50 return { 51 top: offsetTop, 52 left: offsetLeft 53 } 54 } 55 56 function isElementInViewport (el, h) { 57 var scrolled = window.pageYOffset, 58 viewed = scrolled + getViewportH(), 59 elH = el.offsetHeight, 60 elTop = getOffset(el).top, 61 elBottom = elTop + elH, 62 h = h || 0; 63 64 return (elTop + elH * h) <= viewed && (elBottom) >= scrolled; 65 } 66 67 function extend (a, b) { 68 for (var key in b) { 69 if (b.hasOwnProperty(key)) { 70 a[key] = b[key]; 71 } 72 } 73 return a; 74 } 75 76 77 function scrollReveal(options) { 78 this.options = extend(this.defaults, options); 79 this._init(); 80 } 81 82 83 84 scrollReveal.prototype = { 85 defaults: { 86 axis: 'y', 87 distance: '25px', 88 duration: '0.66s', 89 delay: '0s', 90 91 // if 0, the element is considered in the viewport as soon as it enters 92 // if 1, the element is considered in the viewport when it's fully visible 93 viewportFactor: 0.33 94 }, 95 96 /*=============================================================================*/ 97 98 _init: function () { 99 100 var self = this; 101 102 this.elems = Array.prototype.slice.call(docElem.querySelectorAll('[data-scrollReveal]')); 103 this.scrolled = false; 104 105 // Initialize all scrollreveals, triggering all 106 // reveals on visible elements. 107 this.elems.forEach(function (el, i) { 108 self.animate(el); 109 }); 110 111 var scrollHandler = function () { 112 if (!self.scrolled) { 113 self.scrolled = true; 114 setTimeout(function () { 115 self._scrollPage(); 116 }, 60); 117 } 118 }; 119 120 var resizeHandler = function () { 121 function delayed() { 122 self._scrollPage(); 123 self.resizeTimeout = null; 124 } 125 if (self.resizeTimeout) { 126 clearTimeout(self.resizeTimeout); 127 } 128 self.resizeTimeout = setTimeout(delayed, 200); 129 }; 130 131 window.addEventListener('scroll', scrollHandler, false); 132 window.addEventListener('resize', resizeHandler, false); 133 }, 134 135 /*=============================================================================*/ 136 137 _scrollPage: function () { 138 var self = this; 139 140 this.elems.forEach(function (el, i) { 141 if (isElementInViewport(el, self.options.viewportFactor)) { 142 self.animate(el); 143 } 144 }); 145 this.scrolled = false; 146 }, 147 148 /*=============================================================================*/ 149 150 parseLanguage: function (el) { 151 152 // Splits on a sequence of one or more commas, periods or spaces. 153 var words = el.getAttribute('data-scrollreveal').split(/[, ]+/), 154 enterFrom, 155 parsed = {}; 156 157 function filter (words) { 158 var ret = [], 159 160 blacklist = [ 161 "from", 162 "the", 163 "and", 164 "then", 165 "but" 166 ]; 167 168 words.forEach(function (word, i) { 169 if (blacklist.indexOf(word) > -1) { 170 return; 171 }
172 ret.push(word); 173 }); 174 175 return ret; 176 } 177 178 words = filter(words); 179 180 words.forEach(function (word, i) { 181 182 switch (word) { 183 case "enter": 184 enterFrom = words[i + 1]; 185 186 if (enterFrom == "top" || enterFrom == "bottom") { 187 parsed.axis = "y"; 188 } 189 190 if (enterFrom == "left" || enterFrom == "right") { 191 parsed.axis = "x"; 192 } 193 194 return; 195 196 case "after": 197 parsed.delay = words[i + 1]; 198 return; 199 200 case "wait": 201 parsed.delay = words[i + 1]; 202 return; 203 204 case "move": 205 parsed.distance = words[i + 1]; 206 return; 207 208 case "over": 209 parsed.duration = words[i + 1]; 210 return; 211 212 case "trigger": 213 parsed.eventName = words[i + 1]; 214 return; 215 216 default: 217 // Unrecognizable words; do nothing. 218 return; 219 } 220 }); 221 222 // After all values are parsed, letâs make sure our our 223 // pixel distance is negative for top and left entrances. 224 // 225 // ie. "move 25px from top" starts at 'top: -25px' in CSS. 226 227 if (enterFrom == "top" || enterFrom == "left") { 228 229 if (!typeof parsed.distance == "undefined") { 230 parsed.distance = "-" + parsed.distance; 231 } 232 233 else { 234 parsed.distance = "-" + this.options.distance; 235 } 236 237 } 238 239 return parsed; 240 }, 241 242 /*=============================================================================*/ 243 244 genCSS: function (el, axis) { 245 var parsed = this.parseLanguage(el); 246 247 var dist = parsed.distance || this.options.distance, 248 dur = parsed.duration || this.options.duration, 249 delay = parsed.delay || this.options.delay, 250 axis = parsed.axis || this.options.axis; 251 252 var transition = "-webkit-transition: all " + dur + " ease " + delay + ";" + 253 "-moz-transition: all " + dur + " ease " + delay + ";" + 254 "-o-transition: all " + dur + " ease " + delay + ";" + 255 "transition: all " + dur + " ease " + delay + ";"; 256 257 var initial = "-webkit-transform: translate" + axis + "(" + dist + ");" + 258 "-moz-transform: translate" + axis + "(" + dist + ");" + 259 "transform: translate" + axis + "(" + dist + ");" + 260 "opacity: 0;"; 261 262 var target = "-webkit-transform: translate" + axis + "(0);" + 263 "-moz-transform: translate" + axis + "(0);" + 264 "transform: translate" + axis + "(0);" + 265 "opacity: 1;"; 266 return { 267 transition: transition, 268 initial: initial, 269 target: target, 270 totalDuration: ((parseFloat(dur) + parseFloat(delay)) * 1000) 271 }; 272 }, 273 274 /*=============================================================================*/ 275 276 animate: function (el) { 277 var css = this.genCSS(el); 278 279 if (!el.getAttribute('data-sr-init')) { 280 el.setAttribute('style', css.initial); 281 el.setAttribute('data-sr-init', true); 282 } 283 284 if (el.getAttribute('data-sr-complete')) { 285 return; 286 } 287 288 if (isElementInViewport(el, this.options.viewportFactor)) { 289 el.setAttribute('style', css.target + css.transition); 290 291 setTimeout(function () { 292 el.removeAttribute('style'); 293 el.setAttribute('data-sr-complete', true); 294 }, css.totalDuration); 295 } 296 297 } 298 }; // end scrollReveal.prototype 299 300 document.addEventListener("DOMContentLoaded", function (evt) { 301 window.scrollReveal = new scrollReveal(); 302 }); 303 304})(window);
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.