1class ExternLinksWarner{ 2 constructor(modal, config){ 3 this.setModal(modal) 4 this.setConfig(config) 5 this.markExternalLinks() 6 this.listenToExternalLinks() 7 } 8 9 setModal(modal){ 10 this.modal = modal 11 this.setModalCancelEvent() 12 this.setModalDismissEvent() 13 this.modal.appendTo(this.constructor.htmlBody) 14 } 15 16 setModalDismissEvent(){ 17 this.constructor.htmlBody.addEventListener('click', e => { 18 if(this.modal.isOpen){ 19 this.modal.cancelBtn.click() 20 } 21 }) 22 } 23 24 setModalCancelEvent(){ 25 this.modal.onCancel(e => { 26 this.modal.hide() 27 this.modal.resetContent() 28 }) 29 return this 30 } 31 32 setConfig(config){ 33 this.config = config 34 } 35 36 listenToExternalLinks(){ 37 this.markedExternalLinks.map((aTag)=>{ 38 aTag.addEventListener('click', (...args) => this.handelClickEvent(aTag, ...args)) 39 }) 40 } 41 42 handelClickEvent(aTag, e){ 43 e.preventDefault() 44 e.stopPropagation() 45 const externLink = aTag.href, 46 target = aTag.target || '_self', 47 modalText = this.parseModalText(externLink) 48 this.modal.setBodyText(modalText) 49 this.modal.onContinue(e => { 50 window.open(externLink, target) 51 }) 52 this.modal.show() 53 } 54 55 parseModalText(externalLink){ 56 const bodyText = this.getBodyText(externalLink) 57 return this.constructor.injectHosts(bodyText, externalLink) 58 } 59 60 getBodyText(externalLink){ 61 const bodyText = this.config.bodyText, 62 bodyTextAlt = this.config.bodyTextAlt 63 if(bodyTextAlt !== undefined && this.constructor.hasTextBothHostPlaceholder(bodyText) && this.constructor.quellHost === this.constructor.zielHost(externalLink)){ 64 return bodyTextAlt 65 } 66 return bodyText 67 } 68 69 markExternalLinks(){ 70 const externalLinks = this.externalLinks() 71 externalLinks.map(aTag => this.addExternalLinkClass(aTag)) 72 } 73 74 addExternalLinkClass(aTag){ 75 aTag.classList.add(this.config.externalLinkClass) 76 } 77 78 externalLinks(){ 79 const aTags = this.constructor.allATags 80 return aTags.filter(aTag => this.hasExternalLink(aTag)) 81 } 82 83 hasExternalLink(aTag){ 84 return this.isLinkExternal(aTag.href); 85 } 86 87 isLinkExternal(url){ 88 return !this.constructor.isSpecialLinkWithKeyWord(url) && (this.isSpecialExternalUrl(url) || !this.targetsInternalDomain(url)) 89 } 90 91 absoluteUrl(url){ 92 return new URL(url, document.baseURI).href; 93 } 94 95 isSpecialExternalUrl(url){ 96 return this.absoluteSpecialExternalLinks.includes(url) 97 } 98 99 targetsInternalDomain(url){ 100 return this.internalDomains.includes(this.constructor.domainFromUrl(url)) 101 } 102 103 setAbsoluteSpecialExternalLinks(){ 104 const absoluteSpecialExternalLinks = this.config.specialExternalLinks.map(this.absoluteUrl) 105 this.config.absoluteSpecialExternalLinks = absoluteSpecialExternalLinks 106 return absoluteSpecialExternalLinks 107 } 108 109 get markedExternalLinks(){ 110 return Array.from(document.getElementsByClassName(this.config.externalLinkClass)) 111 } 112 113 get internalDomains(){ 114 return this.config.excludedDomains.concat([ExternLinksWarner.mainDomain, undefined]) 115 } 116 117 get absoluteSpecialExternalLinks(){ 118 return this.config.absoluteSpecialExternalLinks || this.setAbsoluteSpecialExternalLinks() 119 } 120 121 static domainFromUrl(url){ 122 return ExternLinksWarner.domainFromHost(ExternLinksWarner.hostFromUrl(url)) 123 } 124 125 static hostFromUrl(url){ 126 return new URL(url).host 127 } 128 129 static domainFromHost(host){ 130 return host.substring(host.lastIndexOf(".", host.lastIndexOf(".") - 1) + 1); 131 } 132 133 static injectHosts(text, externalHost){ 134 return text.replace(ExternLinksWarner.quellHostPlaceholder, ExternLinksWarner.quellHost).replace(ExternLinksWarner.zielHostPlaceholder, ExternLinksWarner.zielHost(externalHost)) 135 } 136 137 static hasTextQuellHostPlaceholder(text){ 138 return text.includes(ExternLinksWarner.quellHostPlaceholder) 139 } 140 141 static hasTextZielHostPlaceholder(text){ 142 return text.includes(ExternLinksWarner.zielHostPlaceholder) 143 } 144 145 static hasTextBothHostPlaceholder(text){ 146 return ExternLinksWarner.hasTextQuellHostPlaceholder(text) && ExternLinksWarner.hasTextZielHostPlaceholder(text) 147 } 148 149 static zielHost(externalLink){ 150 return ExternLinksWarner.hostFromUrl(externalLink) 151 } 152 153 static isSpecialLinkWithKeyWord(link){ 154 return ExternLinksWarner.hasLinkKeyword(link) 155 } 156 157 static hasLinkKeyword(link){ 158 return ExternLinksWarner.specialKeywords.some(keyword => link.startsWith(keyword)) 159 } 160 161 static get quellHost(){ 162 return location.host 163 } 164 165 static get quellHostPlaceholder(){ 166 return '{quell-host}'; 167 } 168 169 static get zielHostPlaceholder(){ 170 return '{ziel-host}'; 171 } 172 173 static get allATags(){ 174 return Array.from(document.querySelectorAll('a[href]')) 175 } 176 177 static get mainDomain(){ 178 return ExternLinksWarner.domainFromHost(location.host); 179 } 180 181 static get htmlBody(){ 182 return document.getElementsByTagName('body')[0] 183 } 184 185 static get specialKeywords(){ 186 return [ 187 "mailto:", "tel:", "javascript:" 188 ] 189 } 190}
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.