Lambda functions in TIScript

I’ve added new short notation for anonymous (lambda functions) in TIScript build #2.0.0.3
Example of such notation – sort array a in descending order:

a.sort(:v1,v2:v2 - v3);

This is a direct equivalent of:

a.sort( function(v1,v2) { return v2 - v3; } );

Therefore anonymous functions in TIScript can be declared in place in of the three forms:

    1. classic JavaScript form:
      function ( < parameters > ) { < statements > }
    2. single expression lambda function form
      : < parameters > : < statement >;
    3. “block with parameters” form
      : < parameters > { < statements > }

Color-chooser, part III. Prototype… of what?

This is a continuation of: Color-chooser, part II. Three pieces of the Puzzle.

First of all:  Sciter executes scripts after completion of document tree parsing. This is major difference from how conventional browser deals with scripts. So script execution in Sciter is deterministic – code in script files executed when DOM is loaded and in the order of how script files are included in the master HTML document.

Next phase after DOM and scripts are getting loaded is a binding of behaviors: Sciter scans DOM tree for elements having prototype attribute defined in CSS and assigns script classes of behaviors to correspondent DOM elements.  Thus, if you have following CSS declaration:

input[type="color-chooser"]
{ 
     background: …. ; /* and other rendering styles */
     prototype: ColorChooser /* behavioral style definition */
}

and existing variable ColorChooser of type Behavior somewhere in your scripts, that DOM element is said to be of class of ColorChooser.


Each object (DOM elements are also first class script objects) in the script is a collection of properties – pairs of a key and a value. That value can be a function.


Each object has special prototype field. That prototype field establishes instance/class relationship- links objects and their classes.


Method invocation like obj.foo() simply means following instruction: try to find property foo in obj collection of properties and if it is is not found then try to find it in object referred by prototype variable, etc. If such foo value is found in the chain and it is a function – call it with this environment variable set to the obj.


"Class" object can also have prototype field set – it is said that one class is derived from another.


Here is what happens when DOM element has prototype defined in CSS:


As you may see Sciter in this case simply changes value of prototype field of the DOM object from reference to Element (class) object to the reference of your custom Behavior class-object.


The last phase of behavior assignment: after changing prototype field of the DOM object Sciter tries to call method attached() if it is defined in the behavior. Method attached() by its concept is close to a constructor method. Variable this inside method code points to the DOM element this behavior has been assigned to. The only difference between attached and constructor is that at the moment of invocation of the attached() DOM element already exists and is a "citizen" of the DOM.


NB: the prototype attribute in Sciter is read/write entity thus you can change behavior of the element in your code at any time. You may need this if, say, some element has clearly two or more states in which it should behave significantly differently.

Color-chooser, part II. Three pieces of the Puzzle.

Functionality of our color-chooser requires some code to be designed as we definitely need to handle UI events and do some initialization of our component.

Typical OOP solution for that is to design such code in a form of some class. Then we need some mechanism that will allow us to "bind" such class with the DOM element we have defined in HTML as:

< input type="color-chooser" />

In other words we need to define (or declare) our own behavior for some class of DOM elements.
In Sciter we can do this as a simple definition like this (script):

type ColorChooser : Behavior { /* declaration of behavior class object */

  function attached() 
  {  
    /* initialization code 
        'this' here is the DOM element the behavior attached to. */ 
  }
  function onMouse(evt) 
  { 
    /* event handling code
       'this' here is the DOM element the behavior attached to. */
  }
}

At this stage we have behavior class defined and DOM element we want this behavior to be assigned to.


Sciter allows us to bind these two entitites declaratively by using CSS and special prototype attribute. Here is an example of such definition – all DOM elements satisfying given CSS selector will have following attributes:

/* all input elements having type attribute equals color-chooser */
input[type="color-chooser"] 
{
    background: .... ; /* and other rendering styles */
    prototype: ColorChooser /* behavioral style definition */
}

Done. If we will put together all these three pieces of the puzzle we will have our <input type="color-chooser"> look and behave as a color chooser control. In fact all other input elements in Sciter are simply DOM elements that have specific styles and behaviors assigned.


In the next article I will explain what really happens "under the hood" – how existing element is getting "subclassed".