1// add target="_blank" to external links 2var links = document.links; 3for (var i = 0, l = links.length; i < l; i++) { 4 if (links[i].hostname != window.location.hostname && !links[i].href.startsWith('javascript:')) { 5 links[i].target = '_blank'; 6 links[i].setAttribute('rel', 'noreferrer'); 7 } 8} 9 10// IE11 endsWith polyfill 11if (!String.prototype.endsWith) { 12 String.prototype.endsWith = function (suffix) { 13 return this.indexOf(suffix, this.length - suffix.length) !== -1; 14 }; 15} 16 17// check if session and localStorage are available, 18// if not, set a flag and provide a fallback solution via window.getStorage 19try { 20 window.localStorage; 21 window.sessionStorage; 22 window._storageDisabled = false; 23} 24catch (e) { 25 console.log("sessionStorage and/or localStorage not available, falling back to in-memory storage: ", e); 26 27 // store factory to retrieve in-memory session 28 window.getStorage = function () { 29 return { 30 _items: new Map(), 31 setItem(key, val) { 32 this._items.set(key, val); 33 }, 34 getItem(key) { 35 return this._items.has(key) ? this._items.get(key) : null; 36 } 37 } 38 } 39 // set flag 40 window._storageDisabled = true; 41} 42 43/* BODY CLASS HANDLING */ 44var body = document.querySelector('body'); 45body.classList.remove('no-js'); 46body.classList.add('javascript'); 47if ('ontouchstart' in document.documentElement) body.classList.add('is-touch'); 48 49/** 50* @desc Prefetching internal links on hover 51* @version 1.0.0 52* @author d.kressler 53*/ 54var Prefetcher = function (params) { 55 defaults = { 56 'onHover': true, 57 storage: window._storageDisabled ? window.getStorage() : localStorage 58 }; 59 var opt = J.merge(defaults, params); 60 61 var addFetch = function (href) { 62 var elm = document.createElement('link'); 63 elm.rel = "prefetch"; 64 elm.href = href; 65 prefetched.push(href); 66 opt.storage.setItem('prefetched', prefetched.toString()); 67 document.head.appendChild(elm); 68 69 return prefetched; 70 }; 71 var prefetched = opt.storage.getItem('prefetched'); 72 if (prefetched === null) prefetched = []; 73 else prefetched = prefetched.split(','); 74 75 var links = document.querySelectorAll('a[data-prefetch]'); 76 for (var i = 0; i < links.length; i++) addFetch(links[i].href); 77 78 if (opt.onHover) { 79 var hLinks = document.querySelectorAll('a[href|="http"]:not([data-prefetch=false])'); 80 var origin = window.location.origin; 81 for (var i = 0; i < hLinks.length; i++) { 82 hLinks[i].addEventListener('mouseover', function () { 83 if 84 ( 85 ( 86 this.href.indexOf(origin) > -1 87 || this.href.indexOf('http') !== 0 88 ) 89 && prefetched.indexOf(this.href) == -1 90 && this.href != window.location.href 91 && this.href.endsWith('.jpg') === false 92 && this.href.endsWith('.png') === false 93 && this.href.endsWith('.gif') === false 94 ) { 95 addFetch(this.href); 96 } 97 }); 98 } 99 } 100}; 101 102/* Replace all a[href^="tel"] by span elements */ 103function phonelink() { var e = document.querySelectorAll('a[href^="tel:"]'), t = document.querySelectorAll('a[href^="whatsapp://"]'); for (i = 0; i < e.length; i++) { var r = e[i], a = r.className, l = r.innerHTML, n = '<span class="' + a + '">' + l + "</span>"; r.outerHTML = n } for (i = 0; i < t.length; i++) { var r = t[i]; r.setAttribute("href", r.getAttribute("href").replace("whatsapp://", "https://web.whatsapp.com/")) } } 104 105/* REPLACE a[href^="tel"] BY SPAN ELEMENT IF NOT MOBILE DEVICE */ 106if (!('ontouchstart' in window || navigator.maxTouchPoints) && document.getElementById('log_container') === null) phonelink(); 107 108/* MAILMASK */ 109function maillink() { var maillinks = document.querySelectorAll('a[data-email]'); for (i = 0; i < maillinks.length; i++) { var data = JSON.parse(maillinks[i].getAttribute('data-email')), escape = maillinks[i].querySelector('span.escape'); maillinks[i].href = "mailto:" + data.name + "@" + data.host; if (escape) escape.outerHTML = '@'; } }; 110maillink(); 111 112/* 113 * css breakpoints in javascript object 114 * https://github.com/ma-zou/breakpoints_from_css/blob/master/script.js 115*/ 116window.breakpoint = function (width, direction) { 117 var breakpoints = new Array(); 118 for (bp in cssData['gridMap']) { 119 if (cssData['gridMap'][bp].width === '$rowMaxWidth') breakpoints[bp] = parseInt(cssData['rowMaxWidth'].replace('px', '')) / 16 + 'em'; 120 else breakpoints[bp] = parseInt(cssData['gridMap'][bp].width.replace('px', '')) / 16 + 'em'; 121 } 122 direction = (typeof direction === 'undefined') ? 'min' : direction; 123 if (typeof width === 'undefined') { 124 return breakpoints 125 } else { 126 if (direction === 'min') return window.matchMedia("(min-width: " + breakpoints[width] + ")").matches; 127 else return window.matchMedia("(max-width: " + breakpoints[width].replace(/(\d|\W)*/, function (m) { return parseFloat(m) - 0.0625 }) + ")").matches 128 } 129} 130/** 131 * @author Dominik Kressler 132 * @thanks Eric Holtkamp 133 * @date 2020-05-05 134 * 135 */ 136window.currentBp = function () { 137 let bp = breakpoint();
138 let checkWidth = (window.innerWidth + 1) / parseInt(cssData['base-font-size']); 139 let values = Object.values(bp).map(function (x) { return parseFloat(x); }); 140 values.sort(function (a, b) { return a - b; }); 141 let result = false; 142 143 for (let i = 0, c = values.length; i < c; i++) { 144 if (i < values.length - 1 && checkWidth >= values[i] && checkWidth <= values[(i + 1)]) { 145 result = values[i]; 146 break; 147 } 148 } 149 if (result === false) result = values[values.length - 1]; 150 151 return Object.keys(bp)[Object.values(bp).indexOf(result + 'em')]; 152}; 153 154/* 155 * new scrollDir(document.body); 156 * Adds a class to an element to indicate the scroll direction 157 */ 158function ScrollDir(elm) { 159 var lastScrollTop = 0; 160 document.addEventListener('scroll', function (e) { 161 var scrollTop = window.pageYOffset || document.documentElement.scrollTop; 162 if (scrollTop > lastScrollTop) { 163 elm.classList.add('scrolling-down'); 164 elm.classList.remove('scrolling-up'); 165 } 166 else if (scrollTop != lastScrollTop) { 167 elm.classList.remove('scrolling-down'); 168 elm.classList.add('scrolling-up'); 169 } 170 lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; 171 }); 172} 173 174window.addEventListener('keydown', function (e) { if (e.which == 13 && document.activeElement.getAttribute('tabindex') != null) document.activeElement.click(); }); 175 176/** 177 * @desc J Library with handy helper functions 178 * @version 1.0.0 179 * @author Dominik Kressler 180 * @author Malte Zoudlik 181*/ 182var J = function () { 183 return this 184}; 185J.prototype.mergeDeep = function () { 186 var self = this; 187 Object.keys(arguments).forEach(obj => { 188 Object.keys(self).forEach(val => { 189 if (arguments[obj].hasOwnProperty(val)) { 190 var tmp = arguments[obj][val] instanceof Array ? arguments[obj][val] : [arguments[obj][val]]; 191 self[val] = self[val].concat(tmp); 192 } 193 }); 194 }); 195 return self; 196} 197J.prototype.merge = function (obj1, obj2) { 198 for (var p in obj2) { 199 try { 200 if (obj2[p].constructor == Object) { 201 obj1[p] = obj1[p].mergeDeep(obj2[p]); 202 } else { 203 obj1[p] = obj2[p]; 204 } 205 } 206 catch (e) { 207 obj1[p] = obj2[p]; 208 } 209 } 210 return obj1; 211}; 212J.prototype.isOnScreen = function (node, offset) { 213 if (typeof node != 'object') return true; 214 215 if (typeof offset == 'undefined') offset = 0; 216 217 var bounding = node.getBoundingClientRect(); 218 var isOnScreen = ( 219 bounding.top + bounding.height >= 0 220 && bounding.left + bounding.width >= 0 221 && bounding.right - bounding.width <= (window.innerWidth || document.documentElement.clientWidth) 222 && bounding.bottom - bounding.height <= ((window.innerHeight || document.documentElement.clientHeight) + offset) 223 ); 224 225 if (isOnScreen) { 226 node.classList.add('isOnScreen'); 227 } 228 else node.classList.remove('isOnScreen'); 229 230 return isOnScreen; 231}; 232J.prototype.isNodeElement = function (element) { 233 return element instanceof Element || element instanceof HTMLDocument; 234}; 235J.prototype.deepValue = function (obj, path) { 236 for (var i = 0, path = path.split('.'), len = path.length; i < len; i++) { 237 if (obj[path[i]] == null || typeof obj[path[i]] == "undefined") obj = ''; 238 else obj = obj[path[i]]; 239 }; 240 return obj; 241}; 242J.prototype.isURL = function (str) { 243 var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol 244 '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name 245 '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address 246 '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path 247 '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string 248 '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator 249 return pattern.test(str); 250}; 251J = new J(); 252 253if (typeof String.prototype.replaceAll !== "undefined") { 254 String.prototype.replaceAll = function (search, replacement) { 255 var target = this; 256 return target.replace(new RegExp(search, 'g'), replacement); 257 }; 258}
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.