1// Utility function 2function Util () {}; 3 4/* 5 class manipulation functions 6*/ 7Util.hasClass = function(el, className) { 8 if (el.classList) return el.classList.contains(className); 9 else return !!el.getAttribute('class').match(new RegExp('(\\s|^)' + className + '(\\s|$)')); 10}; 11 12Util.addClass = function(el, className) { 13 var classList = className.split(' '); 14 if (el.classList) el.classList.add(classList[0]); 15 else if (!Util.hasClass(el, classList[0])) el.setAttribute('class', el.getAttribute('class') + " " + classList[0]); 16 if (classList.length > 1) Util.addClass(el, classList.slice(1).join(' ')); 17}; 18 19Util.removeClass = function(el, className) { 20 var classList = className.split(' '); 21 if (el.classList) el.classList.remove(classList[0]); 22 else if(Util.hasClass(el, classList[0])) { 23 var reg = new RegExp('(\\s|^)' + classList[0] + '(\\s|$)'); 24 el.setAttribute('class', el.getAttribute('class').replace(reg, ' ')); 25 } 26 if (classList.length > 1) Util.removeClass(el, classList.slice(1).join(' ')); 27}; 28 29Util.toggleClass = function(el, className, bool) { 30 if(bool) Util.addClass(el, className); 31 else Util.removeClass(el, className); 32}; 33 34Util.setAttributes = function(el, attrs) { 35 for(var key in attrs) { 36 el.setAttribute(key, attrs[key]); 37 } 38}; 39 40/* 41 DOM manipulation 42*/ 43Util.getChildrenByClassName = function(el, className) { 44 var children = el.children, 45 childrenByClass = []; 46 for (var i = 0; i < el.children.length; i++) { 47 if (Util.hasClass(el.children[i], className)) childrenByClass.push(el.children[i]); 48 } 49 return childrenByClass; 50}; 51 52Util.is = function(elem, selector) { 53 if(selector.nodeType){ 54 return elem === selector; 55 } 56 57 var qa = (typeof(selector) === 'string' ? document.querySelectorAll(selector) : selector), 58 length = qa.length, 59 returnArr = []; 60 61 while(length--){ 62 if(qa[length] === elem){ 63 return true; 64 } 65 } 66 67 return false; 68}; 69 70/* 71 Animate height of an element 72*/ 73Util.setHeight = function(start, to, element, duration, cb, timeFunction) { 74 var change = to - start, 75 currentTime = null; 76 77 var animateHeight = function(timestamp){ 78 if (!currentTime) currentTime = timestamp; 79 var progress = timestamp - currentTime; 80 if(progress > duration) progress = duration; 81 var val = parseInt((progress/duration)*change + start); 82 if(timeFunction) { 83 val = Math[timeFunction](progress, start, to - start, duration); 84 } 85 element.style.height = val+"px"; 86 if(progress < duration) { 87 window.requestAnimationFrame(animateHeight); 88 } else { 89 if(cb) cb(); 90 } 91 }; 92 93 //set the height of the element before starting animation -> fix bug on Safari 94 element.style.height = start+"px"; 95 window.requestAnimationFrame(animateHeight); 96}; 97 98/* 99 Smooth Scroll 100*/ 101 102Util.scrollTo = function(final, duration, cb, scrollEl) { 103 var element = scrollEl || window; 104 var start = element.scrollTop || document.documentElement.scrollTop, 105 currentTime = null; 106 107 if(!scrollEl) start = window.scrollY || document.documentElement.scrollTop; 108 109 var animateScroll = function(timestamp){ 110 if (!currentTime) currentTime = timestamp; 111 var progress = timestamp - currentTime; 112 if(progress > duration) progress = duration; 113 var val = Math.easeInOutQuad(progress, start, final-start, duration); 114 element.scrollTo(0, val); 115 if(progress < duration) { 116 window.requestAnimationFrame(animateScroll); 117 } else { 118 cb && cb(); 119 } 120 }; 121 122 window.requestAnimationFrame(animateScroll); 123}; 124 125/* 126 Focus utility classes 127*/ 128 129//Move focus to an element 130Util.moveFocus = function (element) { 131 if( !element ) element = document.getElementsByTagName("body")[0]; 132 element.focus(); 133 if (document.activeElement !== element) { 134 element.setAttribute('tabindex','-1'); 135 element.focus(); 136 } 137}; 138 139/* 140 Misc 141*/ 142 143Util.getIndexInArray = function(array, el) { 144 return Array.prototype.indexOf.call(array, el); 145}; 146 147Util.cssSupports = function(property, value) { 148 if('CSS' in window) { 149 return CSS.supports(property, value); 150 } else { 151 var jsProperty = property.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase();}); 152 return jsProperty in document.body.style; 153 } 154}; 155 156// merge a set of user options into plugin defaults 157// https://gomakethings.com/vanilla-javascript-version-of-jquery-extend/ 158Util.extend = function() { 159 // Variables 160 var extended = {}; 161 var deep = false;
162 var i = 0; 163 var length = arguments.length; 164 165 // Check if a deep merge 166 if ( Object.prototype.toString.call( arguments[0] ) === '[object Boolean]' ) { 167 deep = arguments[0]; 168 i++; 169 } 170 171 // Merge the object into the extended object 172 var merge = function (obj) { 173 for ( var prop in obj ) { 174 if ( Object.prototype.hasOwnProperty.call( obj, prop ) ) { 175 // If deep merge and property is an object, merge properties 176 if ( deep && Object.prototype.toString.call(obj[prop]) === '[object Object]' ) { 177 extended[prop] = extend( true, extended[prop], obj[prop] ); 178 } else { 179 extended[prop] = obj[prop]; 180 } 181 } 182 } 183 }; 184 185 // Loop through each object and conduct a merge 186 for ( ; i < length; i++ ) { 187 var obj = arguments[i]; 188 merge(obj); 189 } 190 191 return extended; 192}; 193 194// Check if Reduced Motion is enabled 195Util.osHasReducedMotion = function() { 196 if(!window.matchMedia) return false; 197 var matchMediaObj = window.matchMedia('(prefers-reduced-motion: reduce)'); 198 if(matchMediaObj) return matchMediaObj.matches; 199 return false; // return false if not supported 200}; 201 202/* 203 Polyfills 204*/ 205//Closest() method 206if (!Element.prototype.matches) { 207 Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; 208} 209 210if (!Element.prototype.closest) { 211 Element.prototype.closest = function(s) { 212 var el = this; 213 if (!document.documentElement.contains(el)) return null; 214 do { 215 if (el.matches(s)) return el; 216 el = el.parentElement || el.parentNode; 217 } while (el !== null && el.nodeType === 1); 218 return null; 219 }; 220} 221 222//Custom Event() constructor 223if ( typeof window.CustomEvent !== "function" ) { 224 225 function CustomEvent ( event, params ) { 226 params = params || { bubbles: false, cancelable: false, detail: undefined }; 227 var evt = document.createEvent( 'CustomEvent' ); 228 evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); 229 return evt; 230 } 231 232 CustomEvent.prototype = window.Event.prototype; 233 234 window.CustomEvent = CustomEvent; 235} 236 237/* 238 Animation curves 239*/ 240Math.easeInOutQuad = function (t, b, c, d) { 241 t /= d/2; 242 if (t < 1) return c/2*t*t + b; 243 t--; 244 return -c/2 * (t*(t-2) - 1) + b; 245}; 246 247Math.easeInQuart = function (t, b, c, d) { 248 t /= d; 249 return c*t*t*t*t + b; 250}; 251 252Math.easeOutQuart = function (t, b, c, d) { 253 t /= d; 254 t--; 255 return -c * (t*t*t*t - 1) + b; 256}; 257 258Math.easeInOutQuart = function (t, b, c, d) { 259 t /= d/2; 260 if (t < 1) return c/2*t*t*t*t + b; 261 t -= 2; 262 return -c/2 * (t*t*t*t - 2) + b; 263}; 264 265Math.easeOutElastic = function (t, b, c, d) { 266 var s=1.70158;var p=d*0.7;var a=c; 267 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 268 if (a < Math.abs(c)) { a=c; var s=p/4; } 269 else var s = p/(2*Math.PI) * Math.asin (c/a); 270 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 271}; 272 273 274/* JS Utility Classes */ 275 276// make focus ring visible only for keyboard navigation (i.e., tab key) 277(function() { 278 var focusTab = document.getElementsByClassName('js-tab-focus'), 279 shouldInit = false, 280 outlineStyle = false, 281 eventDetected = false; 282 283 function detectClick() { 284 if(focusTab.length > 0) { 285 resetFocusStyle(false); 286 window.addEventListener('keydown', detectTab); 287 } 288 window.removeEventListener('mousedown', detectClick); 289 outlineStyle = false; 290 eventDetected = true; 291 }; 292 293 function detectTab(event) { 294 if(event.keyCode !== 9) return; 295 resetFocusStyle(true); 296 window.removeEventListener('keydown', detectTab); 297 window.addEventListener('mousedown', detectClick); 298 outlineStyle = true; 299 }; 300 301 function resetFocusStyle(bool) { 302 var outlineStyle = bool ? '' : 'none'; 303 for(var i = 0; i < focusTab.length; i++) { 304 focusTab[i].style.setProperty('outline', outlineStyle); 305 } 306 }; 307 308 function initFocusTabs() { 309 if(shouldInit) { 310 if(eventDetected) resetFocusStyle(outlineStyle); 311 return; 312 } 313 shouldInit = focusTab.length > 0; 314 window.addEventListener('mousedown', detectClick); 315 }; 316 317 initFocusTabs(); 318 window.addEventListener('initFocusTabs', initFocusTabs); 319}()); 320 321function resetFocusTabsStyle() { 322 window.dispatchEvent(new CustomEvent('initFocusTabs')); 323};
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.