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.