PageSourceSearch

https://www.mechernich.de/typo3conf/ext/lemm_block_external_links/…/Scripts/ExternalLinksWarner.js?1674658660

js mechernich.de collected 2026-10-01 12:36:37 UTC 5,454 bytes, 190 lines download raw bytes

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.