📜 ⬆️ ⬇️

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:

Core


')
The system kernel is represented by the file libretki.core.js , 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 connect other files, the kernel is sufficient.

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 it is unsafe to give away userjs, such as file access.

Function libraries



Utilities (libretki.utilities)

A set of small convenience essentials: working with collections ( forEach , map , filter , ...), with optional arguments ( optional ), updating objects ( modifyObject ) and other utilities without 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 ();});


Cookies management (libretki.cookies)


Comfortable working 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)

Getting items and values ​​using XPath. It is a thin layer above document.evaluate , but it eliminates memorization of 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 with DOM (libretki.visual.dom)

It provides functions for quick and easy creation of elements, as well as functions for modifying the tree (“append”, “prepend”, “before”, “after”, ...) and adding / deleting 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 elements. It was created for the toolbar, so for now it only contains animations “fadeIn”, “fadeOut” and “moveY”.

Example:
 libretki.visual.animation.fadeOut (elem, {time: 500});


General toolbar (libretki.visual.toolbar)

A common toolbar to which each script can add its own buttons. The toolbar is displayed 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 in some kind of gradient and plunged into the code.

toolbar.png - image uploaded to Picamatic

Example:
 // Add our own 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 a code that listens and responds to XDM messages. Services are necessary for the safe use of advanced userjs from any page.

On the bare JavaScript service and using the 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) {
   // Handle 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, it is troublesome and has several disadvantages:

Libretki assumes all these difficulties.

Cross-domain messaging (libretki.xdm)

Safe and convenient use of XDM. It allows you to organize several services at the same address, distinguishing them by name. Used by JSON to transfer objects. Prevents access to service scripts from the page.

Classes:

Sample Server / Channel service:
 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'});
 });


The 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)

Even more 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 done so that you can pass exceptions.
 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, is not it? Now you can take up the creation of useful services.

Shared data storage (libretki.xdm.storage)

Allows you to save data available 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 you an example of using XMLHttpRequest, everything is as usual, only you need to use "libretki.xmlhttprequest.XMLHttpRequest".

Emulation XMLHttpRequest is made to simplify the adaptation of someone else's code. If you are writing 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 uploading 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 will only say that they help when working in the mode of displaying cached images. Since my channel is narrow, I use this mode all the time. You can load individual images in various ways - by hovering the mouse on it, holding down the key, selecting the area on the screen, selecting a piece of text, loading the images visible in the window, etc.

Instruments



In the libretki / tools folder you can find several tools executed as HTML pages.

Setup (libretki / tools / libretki.settings.html)


Interface settings scripts.

Configure 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.

settings.png - Picamatic - upload your images

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.

scripts.png - Picamatic - upload your images

Creating buttons (libretki / tools / libretki.bookmarklets.html)


Automates the creation of bookmarklets for various commands. Select a command, customize its arguments, give the command a name, and drag the resulting link to the toolbar or bookmark.

bookmarklets.png - image uploaded to Picamatic

Where to get


Download libretki at libretki.kriomant.net .

Installation


Installation is still quite complicated:
  1. Unpack the contents of the archive into the folder of user scripts;
  2. Install Java if you want to use file access or clipboard;
  3. 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;
  4. open libretki / tools / libretki.settings.html and click “Save”, this is necessary to generate the unique code that is used for XDM


Examples


In the folder "libretki / examples" there are examples of using some features. Since some features are specifically hidden from scripts on the page, for the respective 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


Firstly, feedback is required. Announced libretki on OperaFan, like some people have downloaded, but have not left a single review. Express your attitude:

Secondly, libretki needs a logo and site design, I myself in this matter do not have a foot to tooth. Place and domain already exist.

Source: https://habr.com/ru/post/62045/


All Articles