rama.js
about
The simplest way to automate web tasks is using the language of the web - Javascript and the normal web apis by just running the code from the developer console. This way you don't need to install any program, extension or separate browser to just automate this one feature. Additionally you don't need to learn any new tools or apis.
But running simple tasks from the browser console has one big downside: All activities of your script have to take place on that specific website instance. rama.js tries to change this. It works by opening an iframe and providing a simple api to control it. So you can for example automate clicking on a link and the script will keep running on the new page.
However due to the same-origin policy all actions are still limited to pages on that specific domain. I think you can turn that off in most browsers, but it's generally a very bad idea as it opens security vulnerabilities.
name
rama.js is not named after the Hindu God Rama but after the Swedish verb att rama in = to frame.
installation
There obviously is no npm-package for this as this would not benefit anyone. To
use rama.js just paste rama.js
or the minified version rama.min.js
in your
console or add them to the top of your script.
documentation
iframe functions
rama.new(settings<optional>)
Creates a new <iframe>
and returns the rframe
-object. A settings object can
optionally be passed in. Possible settings are:
name
/id
: for the new iframe (see below). Default is something likerama-273
parent
: parent DOM element. Default is thebody
-tagurl
: url to open (Can beabout:blank
). Default is the current url of the main window
let client = rama.new({
url: "about:blank",
parent: document.getElementById("iframe-wrapper")
});
rframe.t or rframe.tag (read-only)
Access the <iframe>
-tag.
client.t.classList.add("invisible");
rframe.d or rframe.document (read-only)
Access the document
inside the <iframe>
. There is also the handy shorthand
rframe.d.qsa(selector)
for Array.from(rframe.d.querySelectorAll(selector))
.
let testElement = client.d.getElementById("test-element");
let testElements = client.d.qsa(".test");
rframe.w or rframe.window (read-only)
Access the window
-object of the <iframe>
.
client.w.history.back();
rframe.name or rframe.id (read-only)
There is a good description for this on MDN web docs:
A targetable name for the embedded browsing context. This can be used in the target attribute of the
<a>
,<form>
, or<base>
elements; the formtarget attribute of the<input>
or<button>
elements; or the windowName parameter in thewindow.open()
method.
document.getElementById("links-to-frame").target = client.name;
rframe.waitForReload()
Pretty self-explanatory: Returns a Promise to wait for a reload of the iframe.
button.click();
await client.waitForReload();
// do something on the new page
rframe.waitFor(testFunction, delay<optional>)
Retruns a Promise, which resolves when testFunction
evaluates to true. The
rframe
-object is passed to testFunction
. At the moment the implementation is
a bit hacky as it uses setInterval()
. The delay for setInterval()
can be
changed through the delay
parameter, the default is 500 (measured in
milliseconds).
await client.waitFor(
(client) => client.d.querySelector("#some-div").style.display == "block"
);
// do something now that your checks succeeded
rframe.waitForSelector(selector, delay<optional>)
Returns a Promise which resolves when any element on the page matches the given
selector. Useful for web-frameworks where at rframe.waitForReload()
not
everything on the page is ready. Works by using rframe.waitFor()
: the optional
delay
attribute gets passed through.
button.click();
await client.waitForReload();
await client.waitForSelector("#some-div-somewhere");
// do something on the new page
rframe.close()
Removes the iframe from the DOM.
client.close();
rama.clearpage()
Clears the current window by setting the <body>
to display: none
. Changes
the standard parent for new iframes to the <html>
-tag to keep them visible.
rama.clearpage();
custom styling
All frames can be accessed with the CSS selector/class rama-frame
.
Additionally every single frame has its id/name also as id on the iframe tag.
other functions
rama.js also provides some other functions not directly related to iframes, to make web scripting easier:
rama.loadjs(url)
Creates a new script tag with the specified url. Useful for loading external libraries. Returns a Promise, which resolves, when the scripts finished loading.
await rama.loadjs(
"https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs/qrcode.min.js"
);
rama.loadcss(csstext)
Injects the given CSS into a new <style>
-tag.
rama.loadcss("h1 {color: red;}");
rama.clearcss()
Removes all <style>
and <link rel="stylesheet">
-tags.
NOTICE: inline styles given to specific elements stay!
rama.clearcss();
examples
See examples folder
contributing
Issues and Pull-Requests are welcome.
The code is formatted with prettier: the configuration can be found in
.prettierrc
. To generate rama.min.js
terser is used:
terser -c -m -o rama.min.js -- rama.js
other projects
There are several other approaches to web scripting, which could fit your needs better:
- professional test frameworks like puppeteer or selenium
- userscripts. A large collection can be found on openuserjs
- get the content with a utility like curl and parse it yourself
I think however, at the moment this is the only project with this main idea. But one can never be sure that there isn't some other similar project hidden somewhere on the internet. So if you built or found one please write me a mail, as I'm very curious about other ideas.