ramajs

web browser automation from your browser console
git clone https://tongong.net/git/ramajs.git
Log | Files | Refs | README | LICENSE

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 };