/* Dieses Script wurde entwickelt von Mitja Stachowiak. Fuer Details lesen Sie unter "http://www.mitjastachowiak.de/components/ecmascript/framecommunicator/index.html" nach. */ var selfScriptSource_huwheigif = document.getElementsByTagName('script')[document.getElementsByTagName('script').length-1].src; var fapiStandard = 41; // window.fapi und window.fapiFull werden am Ende des Scripts gesetzt function getHostnameAndProtocol (loc) { if (!loc) loc = ''; let i = loc.indexOf('?'); if (i < 0) i = loc.length; let j = loc.indexOf('#'); if (j > 0 && j < i) i = j; j = -1; do { j = loc.indexOf('\/', j+1); } while (j >= 0 && !((j == 0 || loc.charAt(j-1) != '\/') && (j == loc.length-1 || loc.charAt(j+1) != '\/'))); if (j >= 0 && j < i) i = j; let h = loc.substring(0,i); return h; } function absolutePath (rel, absFrom) { // Diese Funktion wird nicht in diesem Script benoetigt, jedoch von vielen Scripts, die dieses verwenden. if (!absFrom) absFrom = self.location.href; let i = rel.indexOf('?'); if (i < 0) i = rel.length; let j = rel.indexOf('#'); if (j >= 0 && j < i) i = j; let Q = ''; if (i < rel.length) Q = rel.substring(i,rel.length); rel = rel.substring(0,i); // ab hier: Querystring/Anker wurde von rel abgetrennt und in Q gespeichert if (rel.indexOf(':') >= 0 && rel.charAt(0) != '\/') return rel+Q; // rel ist schon absolut; i = absFrom.indexOf('?'); if (i < 0) i = absFrom.length; j = absFrom.indexOf('#'); if (j >= 0 && j < i) i = j; j = absFrom.lastIndexOf('/',i); if (j >= 0 && j < i-1) i = j+1; j = absFrom.lastIndexOf(':',i); if (j > i) i = j+1; absFrom = absFrom.substring(0,i); // ab hier: abs ist ohne Anker, Querystring und Dateiname let host = getHostnameAndProtocol(absFrom); if (rel.indexOf('/') == 0) return host + rel + Q; // rel ist relativ zu Root while (rel.indexOf('./') == 0) rel = rel.substring(2,rel.length); while (rel.indexOf('../') == 0) { rel = rel.substring(3,rel.length); j = absFrom.lastIndexOf('/',absFrom.length-2); if (j >= host.length) absFrom = absFrom.substring(0,j+1); } if (absFrom.lastIndexOf('/') != absFrom.length-1) absFrom += '/'; // ab hier: fuer jedes ../ wurde ein Ordner von absFrom abgehaengt return absFrom + rel + Q; // rel ist relativ zur Seite } function relativePath (abs, absFrom) { if (!absFrom) absFrom = self.location.href; let h = getHostnameAndProtocol(abs); if (h == '' && abs.indexOf('\/') == 0) { // falls abs relativ zu Root ist, absolut machen abs = absolutePath(abs, absFrom); h = getHostnameAndProtocol(abs); } if (h == '') return abs; // abs ist schon relativ if (h != getHostnameAndProtocol(absFrom)) return abs; // abs kann nicht relativ werden let i = absFrom.length; let j = absFrom.indexOf('#'); if (j != -1 && j < i) i = j; j = absFrom.indexOf('?'); if (j != -1 && j < i) i = j; j = (absFrom.indexOf('\/', h.length) == h.length)?h.length+1:h.length; i = absFrom.lastIndexOf('\/', i); let fromPath = new Array(); if (i > j) fromPath = absFrom.substring(j, i).split('\/'); // ab hier: fromPath besteht nur noch aus den Ordnern von absFrom i = abs.length; j = abs.indexOf('#'); if (j != -1 && j < i) i = j; j = abs.indexOf('?'); if (j != -1 && j < i) i = j; j = (abs.indexOf('\/', h.length) == h.length)?h.length+1:h.length; i = abs.lastIndexOf('\/', i); let targetPath = new Array(); if (i > j) targetPath = abs.substring(j, i).split('\/'); // ab hier: targetPath besteht nur noch aus den Ordnern von abs if (abs.indexOf('\/', i) == i) i++; let datQ = abs.substring(i, abs.length); // alles nach den Ordnern i = 0; while (targetPath.length > i && fromPath.length > i && targetPath[i] == fromPath[i]) i++; let rel = ''; for (j = i; j < fromPath.length; j++) rel += '../'; for (j = i; j < targetPath.length; j++) rel += targetPath[j] + '/'; rel += datQ; return rel; } function createScrollRectEventListener (el, callback, win) { //console.log('ScrollRectListener startet for '+win.location.href+'!'); var o = new Object(); o.el = el; o.el2 = (el.tagName.toLowerCase() == 'html')?((el.getElementsByTagName('body').length == 0)?null:el.getElementsByTagName('body')[0]):el; // wenn el == documentElement, versuche, body zum einhaengen von heihtGetter zu finden o.callback = callback; o.win = win; o.lastH = -1; o.lastW = -1; o.pause = 0; o.pauseTimer = null; o.search = true; o.padding = 0; o.freed = false; o.resize = function () { if (o.freed) return; if (o.pause != 0) { o.pause = 2; return; } o.pause = 1; o.pauseTimer = win.setTimeout(function () { o.pauseTimer = null; if (o.pause == 2) { o.pause = 0; o.resize(); } else o.pause = 0; }, 50); try { o.win.document.body.width = '500px'; } catch (e) {} let w = o.el.scrollWidth; let h = o.el.scrollHeight; let wh = 0; if (o.win) try { wh = o.win.innerHeight; } catch (e) {} else wh = o.el.offsetHeight; if (h > wh + 4) o.search = true; // nach Overflow max-Suche wiederholen else if (o.el2) { // wenn scrollHeigt nicht groesser, als offsetHeight if (!o.heightGetter) { // beim Erstaufruf heightGetter einfuegen o.heightGetter = o.win.document.createElement('hr'); o.heightGetter.style.height = '1px'; // komisches null-height-Bug erkennen o.heightGetter.style.margin = '0px'; o.heightGetter.style.visibility = 'hidden'; o.heightGetter.style.clear = 'both'; o.el2.appendChild(o.heightGetter); o.max = o.heightGetter; } if (o.el2.lastChild != o.heightGetter) { o.el2.removeChild(o.heightGetter); o.el2.appendChild(o.heightGetter); } try { h = o.max.offsetTop + o.max.offsetHeight; if (isNaN(h)) { h = -1; o.search = true; } } catch (e) { h = -1; o.search = true; } if (h == 0) return; // null-height-Bug: Eine nicht mehr geladene Seite hat das Event ausgeloest if (o.search) { // Tiefstes Element suchen und in o.max speichern for (let i = 0; i < o.el2.childNodes.length; i++) { let _el = o.el2.childNodes[i]; if (_el.nodeType != 1) continue; let ch = _el.offsetTop + _el.offsetHeight; try { ch += parseInt(o.win.getComputedStyle(_el).marginBottom); } catch (e) {} if (!isNaN(ch) && ch > h) { h = ch; o.max = _el; } } try { o.padding = parseInt(o.win.getComputedStyle(o.max).marginBottom) + parseInt(o.win.getComputedStyle(o.el2).paddingBottom); } catch (e) { o.padding = 0; } if (isNaN(o.padding)) o.padding = 0; o.search = false; } h += o.padding; } else if (o.el.getElementsByTagName('body').length != 0) { // versuche body zu finden o.el2 = o.el.getElementsByTagName('body')[0]; o.resize(); return; } if (Math.abs(h + 2 - o.lastH) <= 2 && Math.abs(w + 2 - o.lastW) <= 2) return; // keine Aenderung seit letztem Event o.lastH = h; o.lastW = w; //console.log('New height for '+win.location.href+' = '+h); o.callback(o.el, w, h); } // destructor o.free = function () { if (o.freed) return; try { o.observer.disconnect(); } catch (e) { o.el.removeEventListener('DOMNodeInserted', o.resize); o.el.removeEventListener('DOMNodeRemoved', o.resize); o.el.removeEventListener('DOMCharacterDataModified', o.resize); o.el.removeEventListener('DOMAttrModified', o.resize); o.el.removeEventListener('DOMContentLoaded', o.resize); } o.win.removeEventListener('resize', o.resize); o.el.removeEventListener('overflow', o.resize); o.el.removeEventListener('overflowchanged', o.resize); if (o.pauseTimer) o.win.clearTimeout(o.pauseTimer); o.win.clearInterval(o.timer); if (o.heightGetter) o.el2.removeChild(o.heightGetter); o.freed = true; for (let key in o) if (typeof o[key] == 'object') o[key] = null; } // constructor try { o.observer = new MutationObserver(o.resize); let config = { attributes: true, childList: true, characterData: true, subtree: true }; o.observer.observe(el, config); } catch (e) { el.addEventListener('DOMNodeInserted', o.resize, false); el.addEventListener('DOMNodeRemoved', o.resize, false); el.addEventListener('DOMCharacterDataModified', o.resize, false); el.addEventListener('DOMAttrModified', o.resize, false); el.addEventListener('DOMContentLoaded', o.resize, false); } o.win.addEventListener('resize', o.resize, false); o.timer = o.win.setInterval(function () { o.search = true; o.resize() }, 10000); el.addEventListener('overflow', o.resize, false); el.addEventListener('overflowchanged', o.resize, false); o.resize(); return o; } function hostsAreFromSameDomain (host1, host2) { var hosts = ['', '']; for (var i = 0; i < 2; i++) { hosts[i] = getHostnameAndProtocol(arguments[i]).split('\/\/'); if (hosts[i].length == 2) hosts[i] = hosts[i][1]; // remove protocol if exists else hosts[i] = hosts[i][0]; hosts[i] = hosts[i].split(':')[0]; // remove port if exists hosts[i] = hosts[i].split('.'); } return hosts[0].length > 0 && hosts[1].length > 0 && hosts[0][hosts[0].length-1] == hosts[1][hosts[1].length-1] && (hosts[0].length == 1 || hosts[1].length == 1 || hosts[0][hosts[0].length-2] == hosts[1][hosts[1].length-2]); } function FrameCommunicator (iframe, debugLogName='') { this.debugLogName = debugLogName; // protected this.el = iframe; this.el.communicator = this; // restliche proterties stehen nach Konstruktor // init var _this = this; window.addEventListener('message', function (msg) { _this.interpretMessage.call(_this, msg); }, false); this.el.addEventListener('load', function () { _this.debugLog('onload fired'); _this.checkForNewSite(2); if (_this.onload) _this.onload(_this); }, false); } FrameCommunicator.prototype = { // private currentLoc : null, currentPostMsg : null, resizeRepeatH : 0, resizeRepeatW : 0, currentSiteHasFapi : false, debugLogName : '', // public readonly siteAllows : 0, contentHeight : -1, contentWidth : -1, contentHostname : '', contentURL : '', contentTitle : '', // public onContentResize : null, // wenn frame-seite ihre Groesse aendert onSiteReady : null, // wenn frame-seite geparst/geladen wurde - wie onload, aber eventuell frueher, noch vor DOMReady onURLChanged : null, // wenn frame-seite ihre URL aendert onTitleChanged : null, // wenn frame-seite ihren Titel aendert onload : null, // wenn frame-seite geladen - wie iframe.onload, wird jedoch erst aufgerufen, wenn Seitenhoehe bekannt ist _autoHeight : false, get autoHeight () { return this._autoHeight; }, set autoHeight (v) { this._autoHeight = v; if (v) this.el.style.height = (this.contentHeight >= 0)?(this.contentHeight+'px'):this.autoHeightValue; }, _autoWidth : false, get autoWidth () { return this._autoWidth; }, set autoWidth (v) { this._autoWidth = v; if (v) this.el.style.width = (this.contentWidth >= 0)?(this.contentWidth+'px'):this.autoWidthValue; }, autoHeightValue : '100%', autoWidthValue : '100px' } FrameCommunicator.prototype.checkForNewSite = /* private */ function (load, knownURL) { if (load & 1 != 0) this.currentSiteHasFapi = true; try { if (this.currentDoc != this.el.contentWindow.document.documentElement) { this.newSite(knownURL); return; } } catch (e) { try { if (this.el.contentWindow && this.currentLoc != this.el.contentWindow.location) { this.newSite(knownURL); return; } } catch (e) {} if (this.el.contentWindow.postMessage == this.el.contentWindow.postMessage && this.currentPostMsg != this.el.contentWindow.postMessage) this.newSite(knownURL); else if (load & 2 != 0 && this.el.contentWindow.postMessage != this.el.contentWindow.postMessage) this.newSite(knownURL); } } FrameCommunicator.prototype.setSrc = /* public */ function (url) { try { el.contentWindow.location.replace(url); // tries to change URL without browser history change } catch (e) { this.el.src = url; } this.checkForNewSite(0, url); } FrameCommunicator.prototype.newSite = /* private */ function (knownURL) { this.debugLog('New site detected...'); this.currentLoc = this.el.contentWindow.location; this.currentPostMsg = this.el.contentWindow.postMessage; try { this.currentDoc = this.el.contentWindow.document.documentElement; } catch (e) { this.currentDoc = null; } // Informationen ueber Seite loeschen this.contentHeight = -1; this.contentWidth = -1; this.contentHostname = (knownURL)?getHostnameAndProtocol(knownURL):''; this.contentURL = (knownURL)?knownURL:''; this.siteAllows = 0; this.contentHeight = -1; this.contentWidth = -1; this.contentTitle = ''; // Events ausfuehren if (this.onSiteReady) this.onSiteReady(); if (this.onContentResize) this.onContentResize(this.contentWidth, this.contentHeight); if (this.onURLChanged) this.onURLChanged(this.contentHostname, this.contentURL); if (this.onTitleChanged) this.onTitleChanged(this.contentTitle); // Versuchen, neue Informationen zu bekommen / FrameAPI in der Seite zu erzeugen try { if (this.el.contentWindow.fapi) { this.debugLog('Site is on same location ('+this.el.contentWindow.location.href+') and has fapi. Allow all messages...'); this.el.contentWindow.fapi.setTarget(this); this.el.contentWindow.fapi.setAllowed(65535); } else if (this.el.contentWindow.document.documentElement) { this.debugLog('Site is on same location ('+this.el.contentWindow.location.href+') and has no fapi. Create fapi with all messages...'); let scr = this.el.contentWindow.document.createElement('script'); scr.src = selfScriptSource_huwheigif; this.el.contentWindow.document.body.appendChild(scr); } } catch (e) {} } FrameCommunicator.prototype.checkForNewHostname = /* private */ function (host) { try { host = getHostnameAndProtocol(this.el.contentWindow.location.href); } catch (e) {} if (this.contentHostname == host) return; this.contentHostname = host; this.debugLog('New Hostname detected: '+this.contentHostname); if (this.contentURL.indexOf(host) != 0) this.contentURL = ''; if (this.onURLChanged) this.onURLChanged(this.contentHostname, this.contentURL); } FrameCommunicator.prototype.interpretMessage = /* private */ function (msg) { if (msg.source != this.el.contentWindow) { this.debugLog('Message "'+msg.data+'" dropped because from wrong source!'); return; } else this.debugLog('Message "'+msg.data+'" accepted!'); var data = msg.data.split('&'); this.checkForNewSite(1); this.checkForNewHostname(msg.origin); switch (data[0]) { case 'FrameCommunicator' : this.setState((data.length > 0)?parseInt(data[1]):0); break; case 'mousedown' : var x = undefined; var y = undefined; if (data.length >= 3) { x = parseInt(data[1]); y = parseInt(data[2]); } this.raiseMouseEvent('mousedown', x, y); break; case 'mouseup' : var x = undefined; var y = undefined; if (data.length >= 3) { x = parseInt(data[1]); y = parseInt(data[2]); } this.raiseMouseEvent('mouseup', x, y); break; case 'click' : this.raiseMouseEvent('click'); break; case 'resize' : this.resize(parseInt(data[1]), parseInt(data[2])); break; case 'URLchange' : if (data.length < 2) break; var url = decodeURIComponent(data[1]); var fromSameOrigin = false; try { if (this.el.contentWindow.document) fromSameOrigin = true; } catch (e) {} if (fromSameOrigin || msg.origin == getHostnameAndProtocol(url)) this.newURL(url); break; case 'TitleChange' : if (data.length < 2) break; this.setTitle(decodeURIComponent(data[1])); break; case 'mousewheel' : this.raiseMouseEvent('mousewheel', parseInt(data[1])); break; } } FrameCommunicator.prototype.raiseMouseEvent = /* protected */ function (type, x, y) { this.checkForNewSite(1); if (type == 'click') this.siteAllows |= 4; if (type == 'mousedown') this.siteAllows |= 8; if (type == 'mouseup') this.siteAllows |= 16; if (type == 'mousewheel') this.siteAllows |= 512; if (document.dispatchEvent) { var ev; // Bei MouseEvent sind offsetX/Y und pageX/y nicht ueberschreibbar! daher document.createEvent(). ev = document.createEvent("Events"); ev.initEvent(type, true, true); if (type == 'mousewheel') { ev.wheelDelta = x; } else if (!isNaN(x) && !isNaN(x)) { // falls gegeben, Cursorposition an Event haengen this.siteAllows |= 2; ev.offsetX = x; ev.offsetY = y; p = this.el; do { x += p.offsetLeft; y += p.offsetTop; p = p.offsetParent; } while (p); ev.pageX = x; ev.pageY = y; } this.el.dispatchEvent(ev); } else { var ev = document.createEventObject(); this.el.fireEvent('on' + type, ev); } } FrameCommunicator.prototype.debugLog = /* private */ function (msg) { if (this.debugLogName == '') return; var d = new Date(); console.log('['+d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate()+' '+d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds()+'] Frame "'+this.debugLogName+'": '+msg); } FrameCommunicator.prototype.setState = /* protected */ function (_allowed) { this.checkForNewSite(1); this.siteAllows = _allowed; } FrameCommunicator.prototype.resize = /* protected */ function (w, h) { if (isNaN(w)) w = -1; if (isNaN(h)) h = -1; this.debugLog('Resize w='+w+' h='+h); this.checkForNewSite(1); if (this.contentWidth == w && this.contentHeight == h) return; if (w != -1) this.siteAllows |= 64; if (h != -1) this.siteAllows |= 32; this.contentWidth = w; this.contentHeight = h; if (h >= 0 && this.autoHeight) { var ch = this.el.offsetHeight; if (h + 15 <= ch) this.resizeRepeatH++; if (this.resizeRepeatH > 5) return; // Rekursion verhindern if (h + 10 > ch || h < ch + 20) this.el.style.height = h + 15 + 'px'; if (this.resizeRepeatHTimer) window.clearTimeout(this.resizeRepeatHTimer); var _this = this; this.resizeRepeatHTimer = window.setTimeout(function () { _this.resizeRepeatH = 0; }, 100); } else if (this.autoHeight) this.el.style.height = this.autoHeightValue; if (w >= 0 && this.autoWidth) { var cw = this.el.offsetWidth; if (w <= cw) this.resizeRepeatW++; if (this.resizeRepeatW > 5) return; // Rekursion verhindern if (w > cw || w < cw - 5) this.el.style.width = w + 'px'; if (this.resizeRepeatWTimer) window.clearTimeout(this.resizeRepeatWTimer); var _this = this; this.resizeRepeatWTimer = window.setTimeout(function () { _this.resizeRepeatW = 0; }, 100); } else if (this.autoWidth) this.el.style.width = this.autoWidthValue; if (this.onContentResize) this.onContentResize(w, h); } FrameCommunicator.prototype.newURL = /* protected */ function (url) { this.checkForNewSite(1); if (!url) url = ''; if (url != '') this.siteAllows |= 128; this.contentHostname = getHostnameAndProtocol(url); this.contentURL = url; if (this.onURLChanged) this.onURLChanged(this.contentHostname, this.contentURL); } FrameCommunicator.prototype.setTitle = /* protected */ function (title) { this.checkForNewSite(1); this.siteAllows |= 256; this.contentTitle = title; if (this.onTitleChanged) this.onTitleChanged(title, this); } function FrameAPI (__allowed, _target) { // private var win = (_target)?_target.el.contentWindow:window; if (win.fapi) return win.fapi; win.fapi = this; var target = _target; var allowed = 0; var evListeners = new Object(); var _this = this; var lastURL = ''; var autoFrameSize = false; var debugLog = /* private */ function (msg) { if (!target || target.debugLogName == '') return; var d = new Date(); console.log('['+d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate()+' '+d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds()+'] Frame "'+target.debugLogName+'": '+msg); }; var mouseevent = /* private */ function (ev, type) { if (!ev) ev = win.event; if (type == 'DOMMouseScroll') type = 'mousewheel'; var msg = [type]; if (type == 'mousewheel') msg.push(ev.wheelDelta || -ev.detail); else if ((allowed & 2) && type != 'click') { msg.push(ev.clientX); msg.push(ev.clientY); } if (target) target.raiseMouseEvent.apply(target, msg); else win.parent.postMessage(msg.join('&'), '*'); }; var postState = /* private */ function () { /*if (target) target.setState(allowed); else */win.parent.postMessage('FrameCommunicator&'+allowed, '*'); }; var resize = /* private */ function (el, w, h) { try { if (autoFrameSize) return; } catch (e) { return; } if (!(allowed & 32) || isNaN(h)) h = -1; if (!(allowed & 64) || isNaN(w)) w = -1; /*if (target) target.resize(w, h); else */win.parent.postMessage('resize&'+w+'&'+h, '*'); }; var sendURL = /* private */ function () { if (lastURL == win.location.href) return; lastURL = win.location.href; /*if (target) target.newURL(lastURL); else */win.parent.postMessage('URLchange&'+encodeURIComponent(lastURL), '*'); }; var sendTitle = /* private */ function () { /*if (target) target.setTitle(win.document.title); else */win.parent.postMessage('TitleChange&'+encodeURIComponent(win.document.title), '*'); }; var redirectLink = /* private */ function (a) { if (a.href.indexOf('http') != 0) return; var hp = getHostnameAndProtocol(a.href); }; this.setTarget = /* public */ function (_target) { target = _target; }; this.overrideAutoFrameSize = /* public */ function () { autoFrameSize = true; /*if (target) target.resize(-1, -1); else */win.parent.postMessage('resize&-1&-1', '*'); }; this.redirectLinks = /* public */ function () { var observer = new MutationObserver(function(mutationsList, observer) { for (let mutation of mutationsList) if (mutation.type === 'childList') for (let i = 0; i < mutation.addedNodes.length; i++) if (mutation.addedNodes[i].nodeType == 1 && mutation.addedNodes[i].tagName == 'a') redirectLink(mutation-addedNodes[i]); }); observer.observe(document.documentElement, { childList: true, subtree: true }); let a = document.documentElement.getElementsByTagName('a'); for (var i = 0; i < a.length; i++) redirectLink(a[i]); }; this.setAllowed = /* public */ function (_allowed) { if (allowed == _allowed) { //if (evListeners['resize']) evListeners['resize'].resize(); debugLog('New allowed flags ignored, because already set ('+win.location.href+').'); return; } if (win.parent == win) { debugLog('New allowed flags ignored, because not in frame ('+win.location.href+').'); return; } allowed = _allowed; debugLog('New allowed flags accepted ('+win.location.href+').'); function addListener (name, type, f, el, b) { if (evListeners[name]) return; if (!el) el = win.document; var ev = new Object(); ev['event'] = type; ev['el'] = el; ev['fkt'] = function (ev) { f.call(_this, ev, type); } el.addEventListener(type, ev['fkt'], b); evListeners[name] = ev; } function rmListener (name) { if (!evListeners[name]) return; evListeners[name]['el'].removeEventListener(evListeners[name]['event'], evListeners[name]['fkt']); delete evListeners[name]; } if (allowed & 1) { postState(); addListener('postState', 'load', postState, win); } else rmListener('postState'); if (allowed & 4) addListener('mouseeventC', 'click', mouseevent); else rmListener('mouseeventC'); if (allowed & 8) addListener('mouseeventD', 'mousedown', mouseevent); else rmListener('mouseeventD'); if (allowed & 16) addListener('mouseeventU', 'mouseup', mouseevent); else rmListener('mouseeventU'); if (allowed & 96) { if (!evListeners['resize']) evListeners['resize'] = createScrollRectEventListener(win.document.documentElement, resize, win); } else { if (evListeners['resize']) { evListeners['resize'].free(); delete evListeners['resize']; } } if (allowed & 128) { lastURL = ''; sendURL(); addListener('sendURLL', 'load', sendURL, win); addListener('sendURLH', 'hashchange', sendURL, win); addListener('sendURLP', 'popstate', sendURL, win); try { // bekanntes Bug: Das abhoeren von replaceState und PushState funktioniert nach reload der Seite nicht! if (!evListeners['OldPushState']) { evListeners['OldPushState'] = win.history.pushState; win.history.pushState = function (obj, title, url) { evListeners['OldPushState'].call(win.history, obj, title, url); sendURL(); }; } if (!evListeners['OldReplaceState']) { evListeners['OldReplaceState'] = win.history.replaceState; win.history.replaceState = function (obj, title, url) { evListeners['OldReplaceState'].call(win.history, obj, title, url); sendURL(); }; } } catch (e) {} } else { rmListener('sendURLL'); rmListener('sendURLH'); rmListener('sendURLP'); try { if (evListeners['OldPushState']) { win.history.pushState = evListeners['OldPushState']; delete evListeners['OldPushState']; } if (evListeners['OldReplaceState']) { win.history.replaceState = evListeners['OldReplaceState']; delete evListeners['OldReplaceState']; } } catch (e) {} } if (allowed & 256) { sendTitle(); addListener('sendTitleL', 'load', sendTitle, win); try { if (!evListeners['titleObserver']) { evListeners['titleObserver'] = new MutationObserver(sendTitle); var config = { childList: true }; evListeners['titleObserver'].observe(win.document.getElementsByTagName('title')[0], config); } } catch (e) { addListener('sendTitleI', 'DOMNodeInserted', sendTitle, win.document.getElementsByTagName('title')[0]); } } else { rmListener('sendTitleL'); try { if (evListeners['titleObserver']) { evListeners['titleObserver'].disconnect(); delete evListeners['titleObserver']; } } catch (e) { rmListener('sendTitleI'); } } if (allowed & 512) { addListener('sendMousewheel1', 'mousewheel', mouseevent, win.document); addListener('sendMousewheel2', 'DOMMouseScroll', mouseevent, win.document); } else { rmListener('sendMousewheel1'); rmListener('sendMousewheel2'); } } // init if (__allowed) this.setAllowed(__allowed); } function fapiIndexLocation (loc) { if (navigator.userAgent.indexOf(' Atom\/') >= 0) return; // keep simple site without frame in Atom-preview if (/bot|googlebot|bingbot|crawler|spider|robot|crawling/i.test(navigator.userAgent)) return; // don't forward crawlers! if (loc != '' && parent == self) parent.location.href = absolutePath(loc, self.location.href) + '?' + self.location.href; } (function () { let fapiAllowed = fapiStandard; try { if (parent.fapi) fapiAllowed = 65535; } catch (e) { } if (!window.fapi) new FrameAPI(fapiAllowed); })();