rama.js (4947B)
1 // no "let" or "var" here so that pasting updated versions of the code to the 2 // developer console does not fire redeclaration-errors 3 rama = { 4 // #################### iframe functions #################### 5 // for ids -> no id gets used twice 6 number: 0, 7 // to make this settig globally changeable 8 stdparent: document.querySelector("body"), 9 10 new: function (config) { 11 // parse the settings object 12 const defaultConfig = { 13 url: window.location.href, 14 parent: this.stdparent, 15 name: "rama-" + this.number 16 }; 17 this.number++; 18 if (typeof config !== "object") config = {}; 19 if (!config.hasOwnProperty("url")) config.url = defaultConfig.url; 20 if (!config.hasOwnProperty("parent")) 21 config.parent = defaultConfig.parent; 22 if (!config.hasOwnProperty("name")) config.name = defaultConfig.name; 23 if (config.hasOwnProperty("id")) config.name = config.id; 24 console.log(config); 25 26 // create the iframe 27 let iframeTag = document.createElement("iframe"); 28 iframeTag.name = config.name; 29 iframeTag.src = config.url; 30 iframeTag.id = config.name; 31 iframeTag.classList.add("rama-frame"); 32 config.parent.appendChild(iframeTag); 33 34 // create the rframe object 35 // Is this the correct way to create an object? it works... 36 const rframe = { 37 tag: iframeTag, 38 t: iframeTag, 39 // .d & .document are added when the page loads (see below) 40 w: iframeTag.contentWindow, 41 window: iframeTag.contentWindow, 42 name: config.name, 43 id: config.name, 44 45 waitForReload: function () { 46 return new Promise((resolve) => { 47 iframeTag.addEventListener("load", resolve, { once: true }); 48 }); 49 }, 50 waitFor: function (testFunction, delay) { 51 // - kind of hacky implementation with setInterval() ... 52 // - You could use MutationObservers here but that seems to be 53 // performance-wise the worse choice 54 // - when MutationObservers aren't used there is actually no 55 // reason to define this function on this specific object 56 // rather than global 57 return new Promise((resolve) => { 58 if (!delay) delay = 500; 59 60 let interval = window.setInterval(() => { 61 if (testFunction(rframe)) { 62 window.clearInterval(interval); 63 resolve(); 64 } 65 }, delay); 66 }); 67 }, 68 waitForSelector: function (selector, delay) { 69 return this.waitFor( 70 (c) => c.d && !!c.d.querySelector(selector), 71 delay 72 ); 73 }, 74 close: function () { 75 this.tag.parentElement.removeChild(this.tag); 76 } 77 }; 78 // add events for the .document attribute (changes at reload) 79 iframeTag.addEventListener("load", () => { 80 rframe.document = iframeTag.contentDocument; 81 // qsa() function 82 rframe.document.qsa = function (selector) { 83 return Array.from(rframe.document.querySelectorAll(selector)); 84 }; 85 rframe.d = rframe.document; 86 }); 87 return rframe; 88 }, 89 90 clearpage: function () { 91 // Not the best practice to put content outside the <body> tag but it 92 // enables us in this case to completely switch to the iframe window 93 this.stdparent = document.querySelector("html"); 94 this.loadcss( 95 ".rama-frame { width: 100vw; height: 100vh; " + 96 "position: fixed; top: 0; left: 0; } " + 97 "body { display: none; } " + 98 "html { overflow: hidden; } " 99 ); 100 }, 101 102 // #################### non-iframe functions #################### 103 loadjs: function (url) { 104 // modified version of script by Frank Gambino on 105 // https://stackoverflow.com/a/39008859 106 return new Promise((resolve, reject) => { 107 let scriptTag = document.createElement("script"); 108 scriptTag.src = url; 109 scriptTag.addEventListener("load", resolve); 110 scriptTag.addEventListener("error", (e) => reject(e.error)); 111 document.head.appendChild(scriptTag); 112 }); 113 }, 114 115 loadcss: function (csstext) { 116 let styleTag = document.createElement("style"); 117 styleTag.innerHTML = csstext; 118 document.head.appendChild(styleTag); 119 }, 120 121 clearcss: function () { 122 Array.from( 123 document.querySelectorAll("style, link[rel='stylesheet']") 124 ).forEach((e) => e.parentElement.removeChild(e)); 125 } 126 };