1/** 2 * replace external link target and rel attributes 3 * to open external links in a new tab 4 * @param {string} selector css selector for all links to handle 5 */ 6function handleExternalLinks(selector) { 7 selector = selector ?? `a[href]:not([href*="${window.location.hostname}"]):not([href^="javascript"])` 8 const links = document.querySelectorAll(selector); 9 links.forEach(link => { 10 if (link.hostname !== window.location.hostname) { 11 if (!link.target) { 12 link.target = '_blank'; 13 } 14 if (!link.hasAttribute("rel")) { 15 link.setAttribute('rel', 'noreferrer'); 16 } 17 } 18 }); 19} 20 21/** 22 * body class handling for no-js and touch devices 23 */ 24function applyBodyClasses() { 25 const body = document.body; 26 body.classList.remove('no-js'); 27 body.classList.add('javascript'); 28 if ('ontouchstart' in document.documentElement) body.classList.add('is-touch'); 29} 30 31/** 32 * create email links from data-email placeholders 33 */ 34function createEmailLinks() { 35 const mailLinks = document.querySelectorAll('a[data-email]'); 36 mailLinks.forEach(link => { 37 const data = JSON.parse(link.getAttribute('data-email')), 38 escape = link.querySelector('span.escape'); 39 link.href = `mailto:${data.name}@${data.host}` 40 if (escape) escape.outerHTML = '@'; 41 }); 42} 43 44/** 45 * check if a current css breakpoint of viewport width is matching 46 * @param {string} width name of the breakpoint 47 * @param {string} direction direction, can be either "min", or "max" 48 * @returns boolean 49 */ 50function breakpoint(width, direction) { 51 const breakpoints = new Array(); 52 for (bp in cssData['gridMap']) { 53 if (cssData['gridMap'][bp].width === '$rowMaxWidth') breakpoints[bp] = parseInt(cssData['rowMaxWidth'].replace('px', '')) / 16 + 'em'; 54 else breakpoints[bp] = parseInt(cssData['gridMap'][bp].width.replace('px', '')) / 16 + 'em'; 55 } 56 direction = (typeof direction === 'undefined') ? 'min' : direction; 57 if (typeof width === 'undefined') { 58 return breakpoints 59 } else { 60 if (direction === 'min') return window.matchMedia("(min-width: " + breakpoints[width] + ")").matches; 61 else return window.matchMedia("(max-width: " + breakpoints[width].replace(/(\d|\W)*/, function (m) { return parseFloat(m) - 0.0625 }) + ")").matches 62 } 63} 64 65/** 66 * returns the current css breakpoints name as a string, e.g. "large" 67 * @author Dominik Kressler 68 * @thanks Eric Holtkamp 69 * @date 2020-05-05 70 * 71 */ 72function currentBp() { 73 const bp = breakpoint(); 74 const checkWidth = (window.innerWidth + 1) / parseInt(cssData['base-font-size']); 75 const values = Object.values(bp).map(function (x) { return parseFloat(x); }); 76 values.sort(function (a, b) { return a - b; }); 77 let result = false;
78 79 for (let i = 0, c = values.length; i < c; i++) { 80 if (i < values.length - 1 && checkWidth >= values[i] && checkWidth <= values[(i + 1)]) { 81 result = values[i]; 82 break; 83 } 84 } 85 if (result === false) result = values[values.length - 1]; 86 87 return Object.keys(bp)[Object.values(bp).indexOf(result + 'em')]; 88} 89 90/** 91 * add direction of scrolling as body class 92 * @param {HTMLElement} element the element to apply classes to 93 */ 94function addScrollDirection(element) { 95 let lastScrollTop = 0; 96 document.addEventListener('scroll', function (e) { 97 const scrollTop = window.scrollY || document.documentElement.scrollTop; 98 if (scrollTop > lastScrollTop) { 99 element.classList.add('scrolling-down'); 100 element.classList.remove('scrolling-up'); 101 } 102 else if (scrollTop != lastScrollTop) { 103 element.classList.remove('scrolling-down'); 104 element.classList.add('scrolling-up'); 105 } 106 lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; 107 }); 108} 109 110/** 111 * allow clicking elements with a matching tab index by pressing "Enter" 112 */ 113function handleEnterKeyClick() { 114 window.addEventListener('keydown', function (e) { 115 if (e.key === "Enter" && document.activeElement.getAttribute('tabindex') != null) { 116 document.activeElement.click(); 117 } 118 }); 119} 120 121/** 122 * add class to element if scroll detection injection 123 * @param {string or number} scrollDetect detect a element or fix number for init 124 * @param {string} scrollClassName name of scroll class for element 125 * @param {HTMLElement} element the element to apply classes to 126 */ 127function addScrollClass(scrollDetect = 100, scrollClassName = 'scrolled', element = document.body) { 128 if (typeof scrollDetect === "string") { 129 scrollDetect = document.querySelector(scrollDetect).getBoundingClientRect().height 130 } 131 132 function init() { 133 const scrollTop = window.scrollY || document.documentElement.scrollTop; 134 if (scrollTop >= scrollDetect) { 135 element.classList.add(scrollClassName) 136 } 137 else { 138 element.classList.remove(scrollClassName) 139 } 140 } 141 142 init() 143 144 window.addEventListener('scroll', () => { 145 init() 146 }, false) 147} 148 149/** 150 * summarize all basics functions 151 */ 152function basics() { 153 applyBodyClasses(); 154 createEmailLinks(); 155 handleExternalLinks(); 156 addScrollDirection(document.body); 157 handleEnterKeyClick(); 158}
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.