Note this document is written intentionally close to ReactJS/JSX introduction.
Consider this variable declaration in Sciter's script:
const velement = <h1 id="hw">Hello, world!</h1>;
It is called SSX, and it is an integral part of Sciter's script syntax. Therefore parsing of such SSX literals does not require invocation of any preprocessor as in browser with JSX.
That above is neither a string nor HTML but exactly this tuple declaration:
const velement = [h1: { id:"hw"}, ["Hello, world!"] ];
Technically SSX is not strictly required - we can use tuple literals directly. It is just that such HTML-ish syntax is more familiar.
Here we declare a variable name and use it in tuple construction:
const name = "Alice"; const velement = <h1>Hello, {name}</h1>;
That above can be written exactly as this:
const velement = [h1: {}, [name] ];
And you can put any valid script expression inside those curly braces:
const velement = <div>1 + 1 is { 1 + 1 }</div>;
As SSX literal is actually a tuple literal then we can use it in our code as any other literals:
function getGreeting(user) { if (user) return <h1>Hello, {formatName(user)}!</h1>; else return <h1>Hello, Stranger.</h1>; }
The above function returns one of two tuples defined there.
You may use quotes to specify string literals as attributes:
const velement = <div tabindex="0"></div>;
You may also provide value of attribute from a variable or expression:
const velement = <img src={user.avatarUrl}></img>;
Note: you should either use quotes (for string values) or curly braces (for expressions), but not both in the same attribute.
If tag is empty then you may close it immediately with />
:
const velement = <img src={user.avatarUrl} />;
Note: SSX does not support "tail-less" HTML tags like: <img>
, <input>
or <br>
. These one must be explicitly closed: <img />
, <input />
or <br />
.
Yet SSX may contain children:
const velement = <div> <h1>Hello!</h1> <h2>Good to see you here.</h2> </div>;
Along with attributes you may want to define runtime states of elements:
const velement = <li :expanded={ isOpen(item) } > <caption>Hello!</caption> <div></div> </div>;
States here correspond to so called pseudo-classes in CSS: :active
, :hover
, :checked
and so on.
To specify current runtime value of <input> elements use :value
runtime state attribute - it reflects current value of the input at runtime:
<input|text(firstname) :value="John" />
Note that just value attribute: <input|text(firstname) value="Initial value" />
specifies initial value that is set once upon creation of the element.
SSX follows HTML parsing shortcut rules used in Sciter and so:
<input(firstName) />
is an equivalent of name attribute declaration: <input name="firstName" />
<input|text />
is an equivalent of type attribute declaration: <input type="text" />
<input .search />
is an equivalent of class attribute declaration: <input class="search" />
<input #lookup />
is an equivalent of id attribute declaration: <input id="lookup" />
To define properties, states and content of DOM elements we normally use SSX declarations. But in some cases you may wish "to talk to DOM elements directly", so to get reference to physical DOM element and call its runtime methods from script.
In order to get reference to DOM element you can either use
this.elLookup = container.select("input#lookup");
or its "stringizer" form:
this.elLookup = container.$(input#lookup);
Alternatively you can ask SSX to provide you the reference to the element:
<input #lookup @{this.lookup} />
This @{variable location expression}
, when used in attributes, means the following request: "when you (runtime) will create physical DOM element for this vnode please set reference of the DOM element to the given variable".
SSX generates tuple literals with predefined structure. Tuples of such structure are known as VNODEs - virtual DOM node definitions:
[tag: {attributes}, [children] ] //or [tag: {attributes}, [children], {states} ]
Where:
div
, p
, section
, etc.Some methods of Element class allow to populate DOM by the vnode definitions:
container.content(<div>Hello wonderful world</div>);
After that the container will have single child element: <div>
var arr = [1,2,3]; var children = arr.map( (n) => <li>item #{n}</li> ); container.content(children);
The container will have three <li>
children with texts "item #1", "item #3" and "item #3".
List of Element class functions that accept VNODEs and so SSX declarations: children with texts "item #1", "item #3" and "item #3".
element.content(vnode | array of vnodes)
- content of the element is replaced by these elements;element.append(vnode | array of vnodes)
- these element[s] will be added to the end of element's content;element.prepend(vnode | array of vnodes)
- these element[s] will be added to the end of element's content;element.insert(vnode | array of vnodes, atIndex)
- these element[s] will be added at atIndex position;element.merge(vnode)
- patch existing DOM element by vnode definition, see below for more details;Element.merge(vnode)
- DOM reconciliation (a.k.a patching) by vnodeThe element.merge(vnode)
element
atts
object by removing, creating or changing DOM attributes. merge()
is called for that pair recursively. The merge()
function uses the following match criteria. Particular element/vnode pair is considered as matching if:
Otherwise DOM element and vnode treated as not matching. function uses the following match criteria
Otherwise DOM element and vnode treated as not matching.