UserJS. Part 4: libretki framework
libretki is a framework designed to simplify the creation of userjs and provide a ready-made set of useful functions.
Other articles in the series:
The core of the system is represented by the libretki.core.js file , which is a development of loader.js from the second article. The kernel also provides some basic functions. If all you need is the ability to attach other files, kernels are enough.
A typical script using libretki:
The func function is now available as habrahabr.example.func. The unsafe object is used as a namespace for functions that are unsafe to render outside userjs, such as file access.
A set of small essentials of prime necessity: working with collections ( forEach , map , filter , ...), with optional arguments ( optional ), updating objects ( modifyObject ) and other utilities without any special focus.
Used by almost all other scripts.
Example:
Convenient work with cookies, instead of directly accessing document.cookies and parsing the result, provides the functions set , get and del .
Example:
Serialization and deserialization of objects in JSON format.
Example:
Storing objects in cookies. It is a simple combination of cookies and json libraries and, in principle, redundant, but remained for historical reasons.
Example:
Retrieving elements and values using XPath. It is a thin layer over document.evaluate , but eliminates the need to remember specific constants and fields.
Example:
Provides functions for quickly and conveniently creating elements, as well as functions for modifying the tree ("append", "prepend", "before", "after", ...) and adding / removing classes.
Example:
Animation of elements. It was created for the toolbar, so for now it contains only animations “fadeIn”, “fadeOut” and “moveY”.
Example:
A common toolbar on which each script can add its own buttons. The toolbar appears when you hover over a small square in the upper left corner of the page. You can add simple buttons and toggle buttons. It doesn’t look very good - I’m not a designer, I threw some kind of gradient and then plunged into the code. Example:

A service is code that listens and responds to XDM messages. Services are necessary for the safe use of advanced userjs from any page.
On bare JavaScript, a service and using code look like this:
Service:
Using:
As you can see, the case is troublesome and has several disadvantages:
Libretki takes care of all these difficulties.
Safe and convenient use of XDM. Allows you to organize several services at the same address, distinguishing them by name. Used by JSON to pass objects. Prevents access to the service scripts from the page.
Classes:
Example service on Server / Channel:
customer:
Same on SeqServer / SeqClient:
Simplifies the task of creating a service. Just write:
use:
Significantly less code compared to the initial version, right? Now you can begin to create useful services.
Allows you to save data accessible from any page. Implemented by saving cookies on the page 'http://0.0.0.0/'.
Example:
Requires Java.
Example:
Allows you to create, delete and rename files and folders, scan folders. Requires Java.
Example:
I will not give an example of using XMLHttpRequest, everything is as usual, only you need to use "libretki.xmlhttprequest.XMLHttpRequest".
XMLHttpRequest emulation is made to simplify the adaptation of someone else's code. If you write userjs from scratch, the “fetch” function is much more convenient:
This set of scripts is packaged in a separate archive. I will not describe individual scripts, I can only say that they help when working in the mode of displaying cached images. Since my channel is narrow, I always use this mode. You can upload individual images in various ways - by hovering the mouse over it, holding down the key, selecting an area on the screen, highlighting a piece of text, loading images visible in the window, etc.
In the libretki / tools folder, you can find several tools executed as HTML pages.
The interface for setting script parameters.
Set the required parameters and do not forget to click the "Save" button. It works without Java, but then you have to save the settings file manually.

List of installed userjs with the ability to turn on and off. Can be used as a browser sidebar. Requires Java.

Automates the creation of bookmarklets for various teams. Select a command, configure its arguments, give the command a name and drag the resulting link to the toolbar or bookmarks.

You can download libretki at libretki.kriomant.net .
Installation is still quite complicated:
In the "libretki / examples" folder there are examples of using some features. Since some features are specially hidden from the scripts on the page, for the corresponding examples to work, you must place the file “libretki / examples / libretki.allow-unsafe.js” in the scripts folder.
In the process of writing are installers for Windows and Linux.
First feedback is required. He announced libretki on OperaFan, it seems that a lot of people downloaded, but did not leave a single review. Express your attitude:
Secondly, libretki needs a logo and website design, I myself am not a foot in this business. The place and domain are already there.
Other articles in the series:
Core
The core of the system is represented by the libretki.core.js file , which is a development of loader.js from the second article. The kernel also provides some basic functions. If all you need is the ability to attach other files, kernels are enough.
A typical script using libretki:
if (! ('libretki' in window)) {libretki = {__scripts: []}; } libretki .__ scripts.push ({ name: 'habrahabr.example', requires: ['libretki.utilities'], init: function (unsafe) { // some code ... libretki.core.namespace ('habrahabr.example', { func: function () {/ * ... * /}, }); } });
The func function is now available as habrahabr.example.func. The unsafe object is used as a namespace for functions that are unsafe to render outside userjs, such as file access.
Function libraries
Utilities (libretki.utilities)
A set of small essentials of prime necessity: working with collections ( forEach , map , filter , ...), with optional arguments ( optional ), updating objects ( modifyObject ) and other utilities without any special focus.
Used by almost all other scripts.
Example:
var positive = libretki.utilities.filter (arr, function (item) {return item.value> 0;}); libretki.utilities.forEach (positive, function (item) {item.func ();});
Managing cookies (libretki.cookies)
Convenient work with cookies, instead of directly accessing document.cookies and parsing the result, provides the functions set , get and del .
Example:
libretki.cookies.set ('name', 'value'); var value = libretki.cookies.get ('name');
JSON (libretki.json)
Serialization and deserialization of objects in JSON format.
Example:
var str = libretki.json.stringify ({name: 'name', value: 'value', active: true}); var obj = libretki.json.parse (str);
Storing objects in cookies (libretki.cookies_json)
Storing objects in cookies. It is a simple combination of cookies and json libraries and, in principle, redundant, but remained for historical reasons.
Example:
libretki.cookies_json.set ('name', {value: 'value', active: true}); var obj = libretki.cookies_json.get ('name');
XPath (libretki.xpath)
Retrieving elements and values using XPath. It is a thin layer over document.evaluate , but eliminates the need to remember specific constants and fields.
Example:
var nodes = libretki.xpath.getNodes (document.body, '// img [@ class = "adv"]'); var value = libretki.xpath.getNumber (tbody, 'tr / td [@ id = "header"] / @ colspan');
Modifying a document using the DOM (libretki.visual.dom)
Provides functions for quickly and conveniently creating elements, as well as functions for modifying the tree ("append", "prepend", "before", "after", ...) and adding / removing classes.
Example:
var dom = libretki.visual.dom; dom.before (elem, dom.html.a ({href: "http: // ...", className: "outlink"}, [ dom.html.img ({src: "..."}), "link content" ]);
Animation (libretki.visual.animation)
Animation of elements. It was created for the toolbar, so for now it contains only animations “fadeIn”, “fadeOut” and “moveY”.
Example:
libretki.visual.animation.fadeOut (elem, {time: 500});
General toolbar (libretki.visual.toolbar)
A common toolbar on which each script can add its own buttons. The toolbar appears when you hover over a small square in the upper left corner of the page. You can add simple buttons and toggle buttons. It doesn’t look very good - I’m not a designer, I threw some kind of gradient and then plunged into the code. Example:

// Add our button. libretki.toolbar.onShow (function (toolbar) { var group = new libretki.toolbar.ButtonsGroup ("Example"); var button = new libretki.toolbar.CommandButton ("Alert", "data: image / svg + xml; base64, ...", function () { alert ("Example"); }); group.addButton (button); toolbar.addGroup (group); });
Services
A service is code that listens and responds to XDM messages. Services are necessary for the safe use of advanced userjs from any page.
On bare JavaScript, a service and using code look like this:
Service:
if (location.href == 'http://0.0.0.0/') { window.addEventListener ('message', function (ev) { var fields = ev.data.split ('|'); if (fields [0] == 'set') { // ... ev.source.postMessage ('ok'); } else if (fields [0] == 'get') { // ... ev.source.postMessage (value); } }, true); }
Using:
window.addEventListener ('message', function (ev) { // Processing the response from the service. }); var frame = document.createElement ('iframe'); frame.onload = function () { // Here you can use the service. frame.contentWindow.postMessage ('get | key'); }; frame.src = 'http://0.0.0.0/'; frame.style = 'display: none;'; document.documentElement.appendChild (frame);
As you can see, the case is troublesome and has several disadvantages:
- you can only pass strings, so you have to manually parse them;
- each service has to upload a separate frame with a different address;
- it is difficult to process responses when using multiple services;
- possibly inadvertently creating multiple frames with the same address;
- the service may be accessible to scripts from the page, which is unsafe.
Libretki takes care of all these difficulties.
Cross-domain messaging (libretki.xdm)
Safe and convenient use of XDM. Allows you to organize several services at the same address, distinguishing them by name. Used by JSON to pass objects. Prevents access to the service scripts from the page.
Classes:
- Server - accepts messages and can respond to them;
- Client - sends messages, but cannot receive replies;
- Channel - client and server in one person, can send messages and receive replies to them;
- SeqClient, SeqServer are analogues of Channel and Server, respectively, but if the former do not track the correspondence between the request and the response, then these let you know the answer to which request came. Also detects missing messages.
Example service on Server / Channel:
if (location.href == 'http://0.0.0.0/') { new Server ('habrahabr.example', function (msg, client) { switch (msg.command) { case 'get': client.post ({command: 'get', key: msg.key, value: get_value (msg.key)}); break; case 'set': set_value (msg.key, msg.value); client.post ({command: 'set', key: msg.key, success: true}); break; } } }
customer:
load_page ('http://0.0.0.0/', function (win) { var channel = new Channel (win, 'habrahabr.example', function (msg) { switch (msg.command) { case 'get': data [msg.key] = msg.value; break; case 'set': if (msg.success) written [msg.key] = true; break; } } channel.post ({command: 'get', key: 'some'}); channel.post ({command: 'set', key: 'some', value: 'bla'}); });
Same on SeqServer / SeqClient:
new SeqServer ('habrahabr.example', function (msg) { switch (msg.command) { case 'get': return get_value (msg.key); case 'set': set_value (msg.key, msg.value); return true; } });
load_page ('http://0.0.0.0/', function (win) { var client = new SeqClient (win, 'habrahabr.example'); client.post ({command: 'get', key: 'some'}, function (result) { data ['some'] = result; }); client.post ({command: 'set', key: 'some', value: 'bla'}, function (result) { if (result) written ['some'] = true; }); });
Remote procedure call (libretki.xdm.rpc)
Simplifies the task of creating a service. Just write:
unsafe.libretki.xdm.rpc.service ('http://0.0.0.0/', 'habrahabr.example', { get: function (key) {return data [key]; }, set: function (key, value) {data [key] = value; }, });
use:
var ex = unsafe .__ services.habrahabr.example; // Returns not just the result of the execution, but the function to be called // to get the result. This is to ensure that exceptions can be passed. ex.get ('key', function (res) {data ['key'] = res ();}); ex.set ('key', 'value', function (res) {res (); written ['key'] = true;});
Significantly less code compared to the initial version, right? Now you can begin to create useful services.
Shared Data Warehouse (libretki.xdm.storage)
Allows you to save data accessible from any page. Implemented by saving cookies on the page 'http://0.0.0.0/'.
Example:
var storage = unsafe.__services.libretki.storage; storage.set ('habrahabr_auth', {login: 'login', password: '123qwe'}); storage.get ('habrahabr_auth', function (res) { var data = res (); login (data.login, data.password); });
Clipboard (libretki.xdm.clipboard)
Requires Java.
Example:
var clipboard = unsafe .__ services.libretki.clipboard; clipboard.set ('text'); clipboard.get (function (res) { var text = res (); alert ('Clipboard content:' + text); });
Access to the file system (libretki.xdm.io.file)
Allows you to create, delete and rename files and folders, scan folders. Requires Java.
Example:
var file = unsafe .__ services.libretki.io.file; file.exists ('/ some / path', function (res) {alert (res ());}); // Read a maximum of 10 lines. file.readLines ('/ another / path', 'utf-8', 10, function (res) { var lines = res (); });
Cross-domain XMLHttpRequest (libretki.xmlhttprequest)
I will not give an example of using XMLHttpRequest, everything is as usual, only you need to use "libretki.xmlhttprequest.XMLHttpRequest".
XMLHttpRequest emulation is made to simplify the adaptation of someone else's code. If you write userjs from scratch, the “fetch” function is much more convenient:
libretki.xmlhttprequest.fetch ('http: //some.url/path', { username: 'user', method: 'POST', content: 'blabla', onOpened: function () {}, onDone: function (status, headers, response) {}, onError: function () {}, });
A set of scripts for downloading images in the “Show cached only” mode (libretki.imaginate)
This set of scripts is packaged in a separate archive. I will not describe individual scripts, I can only say that they help when working in the mode of displaying cached images. Since my channel is narrow, I always use this mode. You can upload individual images in various ways - by hovering the mouse over it, holding down the key, selecting an area on the screen, highlighting a piece of text, loading images visible in the window, etc.
Instruments
In the libretki / tools folder, you can find several tools executed as HTML pages.
Customization (libretki / tools / libretki.settings.html)
The interface for setting script parameters.
Set the required parameters and do not forget to click the "Save" button. It works without Java, but then you have to save the settings file manually.

Script Management (libretki / tools / libretki.scripts.html)
List of installed userjs with the ability to turn on and off. Can be used as a browser sidebar. Requires Java.

Creating Buttons (libretki / tools / libretki.bookmarklets.html)
Automates the creation of bookmarklets for various teams. Select a command, configure its arguments, give the command a name and drag the resulting link to the toolbar or bookmarks.

Where to get
You can download libretki at libretki.kriomant.net .
Installation
Installation is still quite complicated:
- unzip the contents of the archive into the user scripts folder;
- install Java if you want to use file access or clipboard;
- find out the location of the Java policy file ("opera: config # Java | SecurityPolicy"), copy it somewhere, add permissions using the sample in libretki / opera.policy , specify the path to the new file in the settings;
- open libretki / tools / libretki.settings.html and click "Save", this is necessary to generate a unique code that is used for XDM
Examples
In the "libretki / examples" folder there are examples of using some features. Since some features are specially hidden from the scripts on the page, for the corresponding examples to work, you must place the file “libretki / examples / libretki.allow-unsafe.js” in the scripts folder.
Plans
In the process of writing are installers for Windows and Linux.
Problems
First feedback is required. He announced libretki on OperaFan, it seems that a lot of people downloaded, but did not leave a single review. Express your attitude:
- it is a useless thing;
- too hard to install;
- weighs too much;
- lack of documentation;
- another.
Secondly, libretki needs a logo and website design, I myself am not a foot in this business. The place and domain are already there.