At the mean time, event handler assignment…

Sciter supports event handler assignment in jQuery style:

element.on("event", "selector", function(evt) {...});

That looks mostly OK but for some reason I feel it as “aesthetically non pleasant” so thinking about alternatives.

One feasible option/idea may look like this:

// subscribe function for "click" event on element
element << function "click" (evt) {...};

That above is a direct equivalent of

element.on("click", function (evt) {...});

And in full form, with selector

// subscribe function for "click" event on <button id=first> element
self << function ["click","button#first"] (evt) {...};

The main challenge here is to stay in constraints of JS syntax/grammar …

Components, React.js style…

legos

I am thinking about adding @component feature to Sciter a la React.js

Consider this construct:

@component Toggler {

  :root { flow: stack; }
  
  :root > option:nth-child(1) { ... }
  :root > option:nth-child(2) { ... }
  
  :root[on][off] :
  
    <option>{ attributes.on }</option> 
    <option>{ attributes.off }</option> 

  :root[on][off][mixed] :
  
    <option>{ attributes.on }</option> 
    <option>{ attributes.off }</option> 
    <option.mixed>{ attributes.mixed }</option> 

  // event handler 
  on :root click(evt) {
    ...
  }  
  // event handler on child element
  on option mousedown(evt) {
    ...
  }  

  // method  
  function foo() { ... }

  // property  
  property bar(v) { ... }

}

The @component is essentially a @set that contains not only style declarations but also [optional] markup of the component and code equivalent of

class Toggler:Behavior { 

   function attached() {
      this.$content(...); 
   }

   function foo() {  ... }
   property bar(v) { ... }
}

So if you have this markup:

<html> 
  <head>
    <link rel="components" href="components/">
  </head>
  <body>
    <toggler on="yey" off="ney">
  </body>
</html>

you will see that component instantiated and initialized in the DOM.

“collapsed” and “expanded” state flags in Sciter

Concept of collapsed/expanded sections (panels, fragments, etc.) is so widely used in UI that I’ve decided to add them to the core.

So there are two general purpose UI state flags that are accessible from script for read and write:

element.state.collapsed = true /*or false*/;
element.state.expanded = true /*or false*/;

These states are related to each other – the element can be in either collapsed or expanded state, but not in both. When you say element.state.expanded = true; then element.state.collapsed will be set to false. And vice versa. By default element is in neither state – neutral in this respect – not collapsed and not expanded.

In CSS these state are reflected in corresponding state pseudo-classes:

element:collapsed { ... }
element:expanded { ... }

In different scenarios collapsed or expanded state means different things. In some cases collapsed element means element is hidden / invisible as whole by defining in CSS:

element:collapsed { visibility:none; }

In other cases, like section with caption and content, the collapsed state means “hide content but show header always”

<section.collapsible>
 <header>section header</header>
 <div>
 ... content ...
 </div>
</section>

In this case CSS may contain this visibility rule:

section.collapsible:collapsed > div { visibility:none; }

So when section is in collapsed state its content div is hidden completely. And it could be other rules that define look of collapsed state, like +/- icons on the header, etc.

In script you can put simple trigger that expands/collapses sections with collapsible class:

self.on("click", "section.collapsible > header", function(evt) {
  // click on header
  var section = this.parent;
  // flip-flop collapsed state:
  section.state.collapsed = !section.state.collapsed; 
});