Sciter offers three forms of DOM elements extensibility:
prototype property or manually in code by changing prototype property of existing DOM element.aspect property.Behavior classes are defined in code as script classes derived from stock Element class.
Declarative behaviors assignment in CSS is made using prototype property:
selector {
prototype: ClassName url(file.tis);
/* ... other CSS properties */
}
where:
input[type=foo] { prototype: MyWidget; } foo { display:block; prototype: MyWidget; }widget { prototype: MyWidget; }Behavior is a class derived from stock Element class or other behavior class. Template of such class:
class MyWidget : Element
{
// instance variables, each element will have its own copy of those
this var foo = "foo";
...
// class variables, shared by all instances of this class
var bar = "bar";
...
// life cycle methods:
// behavior's "constructor", called when element gets this class
function attached() { /* this is the element */ }
// behavior's "destructor", called when element looses the class
function detached() { /* this is the element */ }
// virtual properties
property baz(v) { ... }
// and methods
function boo() { ... }
// event handlers:
// any click
event click (evt, that) { /* Note: this is the element generated click
that is the subsciber element - the
one that has MyWidget class. */ }
// click event on <a class="next"> element
event click $(a.next) (evt, that) { ... /* Note: this is the a.next
element that generated click */ }
...
}
All methods, event handlers and properties are called by runtime with this variable set to the element this class is assigned to.
Main problem with Behaviors is that at any given moment of time the element can have only one script class assigned. Aspects allows to overcome such problem by defining set of functions to be called when element gets into the DOM.
Aspects are assigned by the aspect CSS property:
aspect: function-name [ url(of-function-implementation-file) ];
Where "function-name" is fully qualified name of the “aspect” function that is aimed to configure/setup some additional functionality on the element. And the url(...) is file name where the function is defined.
Principles of aspect handling:
The “aspect” function is an ordinary script function that gets called:
this set to the DOM element satisfying the CSS rule.The aspect CSS property uses non-standard inheritance – if the element has multiple matching rules with the aspect defined the used aspect property value is a list of all aspects from all matching rules. Thus if you have have these rules (example taken from the Plus engine):
[click] { aspect:Plus.Click; }
[dblclick] { aspect:Plus.DblClick; }
and the element defined in markup as
<b id="clickable" click="..." dblclick="...">text</b>
it will get two calls – Plus.Click() and Plus.DblClick() on it, as if you have the following in your CSS:
#clickable { aspect:"Plus.Click" "Plus.DblClick"; }
The aspect mechanism is actively used by Plus ( /samples/+plus/ ) and Lang ( /samples/+lang/ ) engines in Sciter SDK. Plus provides declarative data binding facilities "a la" AngularJS and Lang is about i18n support.
Aspect assignment can contain parameters defined in CSS:
#chart { aspect: MicroChart.Donut(fill: #f00 #0f0 #00f, thickness:0.2 ); }
This will call MicroChart.Donut function with single object parameter as if the following code is run:
const params = {
fill: [ color(255,0,0), color(0,255,0), color(0,0,255) ],
thickness: 0.2
};
MicroChart.Donut(params); // in fact as MicroChart.Donut.call(domElement,params);
If your aspect function supports parameters then it should have the following signature:
namespace MicroChart {
function Donut(params = {}) {
// do something with this element ...
}
}
this way it can be assigned either with or without params in CSS.
UI programming is all about handling of events of various kinds. In Sciter event handlers are ordinary functions that get assigned to elements in one of following ways:
You can define event function in-place and assign it to the DOM element by shift operator:
// basic event handler
elem << event click () { ... }
Note the click name-token above, that is an event defintion having the following format: name[.namespace] [$(selector)] where:
. namespace is an arbitrary event namespace name a la jQuery, optional;Here is an example of "change" events handling coming from any <input type=text> element inside the document:
elem << event change $(input[type=text]) {
// this is the input[type=text] so
var changedValue = this.value;
...
}
Event namespaces are used for identification purposes, when you need, for example to unsubscribe particualr group of event handlers:
elem >> ".mygroup"; // remove all event handlers having .mygroup namespace.
Element.on("name.namespace", "selector", function ) method of Element class can be used to attach function to the element to handle event given by "name".
And Element.off(...) is used to unsubscribe event handlers.