UI programming you said?

December 2, 2008

Filed under: Philosophy,Sciter,Script,Web Application Techologies — Andrew @ 11:13 pm

Usually business applications are split in three tiers: user interface layer (UI), business logic layer (BLL) and data access layer (DAL). That split is also known as Model-view-controller architectural pattern.

Ideally each layer should be isolated from the rest. For many good reasons. In any case each layer operates using its own vocabulary (namespace if you wish). For example “Account” in UI means some set of fields (<fieldset> literally). In BLL it is an instance of some class with attributes and methods describing logic. And in DAL it could be just a record in DB with associated triggers and stored procedures.

Code that works on each layer(domain) is serving different tasks. Ideally each such layer may require different programming languages that are optimal for each particular layer. E.g. DB layer as a rule uses TSQL as it better suits DB manipulation needs.

The same thing is about UI. Usually UI tasks are just sequence of rules like “if user clicks here than enable that thing over there”. Such tasks may or may not be handled equally well by universal languages like C++.

Ideally UI layer should have its own language that is better suitable for UI needs. In the same way as DB has its own language (couple of them actually: DB schema definition language and transaction definition language).

Consider following task: you have toolbar with “save” button and two widgets that do different things in onSave() methods. In C++/htmlayout you would need to create separate dispatcher that knows about “current” element and reroutes “save” button clicks to different widgets. That will require separate external entity for these two widgets.

And in Sciter you would write this as:

class MyWidget: Behavior
{
  function onFocus()
  {
    var me = this;
    // bind toolbar buttons to this widget methods:
    self.$("button#save").onClick = function() { me.doSave(); }
    self.$("button#new").onClick = function() { me.doNew(); }
    self.$("button#open").onClick = function() { me.doOpen(); }
  }
  function doSave() { ... }
}

when MyWidget gets focus the code in onFocus() replaces onClick event handlers of the toolbar buttons by new functions like function() { me.doSave(); } that will call methods of this particular widget.

You can simulate things like this in C++ of course but it will be significantly more complex. Try to imagine how you would do this in WTL or MFC or any other GUI toolkit. Less code – less errors and so on.

After many years of designing various UI and UI toolkits I shall admit that UI automation/programming is not quite OOP task in general. Usually it is better describable in terms of something close to functional programming but with the ability to define classes/objects.

UI is an assembly of sometimes very different UI components/controls. That requires language that is flexible enough to glue them together. That is my vision on TIScript in Sciter.

And of course markup and CSS are also Good Things for the UI. Especially CSS.

Announce: ScIDE

August 3, 2008

Filed under: HTML and CSS,Sciter,Script,Web Application Techologies — Andrew @ 10:40 am

ScIDE is a compact and handy source code editor with syntax highlighting (colorizing).

ScIDE is a system of HTML, CSS and scripting files that are running inside the Sciter. So ScIDE is so-called .scapp – Sciter application.

ScIDE screenshot

You can run ScIDE:

  1. inside Sciter.exe player (part of main SDK distribution) or
  2. as a separate application ScIDE.exe that is available as a separate install-by-unzip ScIDE distribution.
    ScIDE.exe is a simple bootstrap exe of Embeddable Sciter – sciter-x.dll. Its sources are in the SDK.
  3. sciter-x.dll can be embedded in other applications so ScIDE or its parts may appear in other applications too.

ScIDE uses Scintilla editing engine wrapped as so called native behavior module. Sources of the behavior + slightly modified version of Scintilla are here.

ScIDE is lightweight and very fast despite of the fact that it uses scripting. Script is used as a glue sticking UI components together.

So far ScIDE knows about html, php, asp, css, js, tis, h/hpp and c/cpp files. These colorizing schemas are defined in /scapps/sciter.ide/scintilla/schemas/*.tis files and can be extended by script.

Visual style of the whole application is totally CSS driven so can be customized in different ways.

CSSS! and computational complexity of selectors.

July 25, 2008

Filed under: HTML and CSS,Philosophy,Web Application Techologies — Andrew @ 12:51 pm

Lets say we have following markup:

<ul>
   <li>First</li>
   <li>Second (with <a href=#>hyperlink</a>)</li>
   <li>Third</li>
   <li>Fourth (with <a href=#>hyperlink</a> too)</li>
</ul>

and the styling task: all <li> that have <a> elements inside have yellow background.

If we would have hypothetic selector :with-child(selector) then we could write this as:

li:with-child(a:link) { background:yellow; }

Problem with this selector lies in its complexity – to compute such selectors you need to scan whole subtree of the element (<li> here). That is a task of complexity O(n). n here is a number of children of the element. Potentially it could be the whole DOM ( html:with-child(a:link) ).

And again that O(n) is not that bad if it happens only once but for the case:

html:with-child(a:hover) p { ... }

all <p> elements of the document should get new styles each time when some <a> in document will get :hover state. And that is really bad. Standard methods of optimizing such cases (e.g. caching) may not be acceptable as they may require significant amount of RAM and/or again CPU resources.

… back to the original task of styling "<li> that have <a> elements inside". It is still possible to solve it while keeping resource consumption at the same level.

Imagine that we would have some magic engine that will assign, say, attribute has-a-inside to such <li> elements. Then our task of styling <li>s will turn into simple rule that is known to be effective:

li[has-a-inside] { background:yellow; }

In real world scenarios people these days use JavaScript for that. Requires some programming but works reasonably well.

But our desire to do this solely by CSS as JS is not always available. Here is the method of how to accomplish this by CSSS! (so called active CSS) introduced in recent versions of h-smile core (htmlayout and the Sciter).

In CSSS! we need to create one helper rule that will create attribute has-a-inside for each <li> with <a> inside:

li
{
  assigned!: self.has-a-inside = self.$1( a[href] )? "true" # null;
}

This rule simply means:

When element li will get this style declaration first time (so when assigned!) this statement do:

  1. assign "true" to the attribute has-a-inside if that li element (self) has at least one element inside matching the selector a[href].
  2. or assign null to that attribute – so to remove it form the element.

The only rule left is the one that I’ve already mentioned:

li[has-a-inside]
{
  background:yellow;
}

Thus after loading such document all <li>s with hyperlinks will have yellow background. Done.

Of course it is not so abstractedly perfect if to compare with with-child(a[href]). E.g. our solution will not reflect dynamic DOM updates but that was the problem we were trying to solve anyway.

Nevertheless it will allow to solve the task in most of practical cases and will at least not make selectors matching implementation worse than it is now.

CSS, selectors and computational complexity

July 23, 2008

Filed under: HTML and CSS,Philosophy,Web Application Techologies — Andrew @ 10:57 am

CSS (Cascading style sheets) has pretty extensive set of so called selectors. Example:

ul[type="1"] > li
{
  list-style-type: decimal;
}

Selector here means following: each li element that is immediate child of ul that has attribute type with the value "1" has that style.

Selectors and assosiated styles constitute static system of styles. And so they obey following rule (the law of CSS selectors):

At any given moment of time all elements in the DOM that satisfy set of selectors have corresponding styles applied.

Such static nature of CSS selectors establish some obvious (and not so) limitations on what could be done with selectors and what types of selectors CSS can support. For example:

  • Selectors cannot use information defined by styles. Imagine hypothetical selector and style:
    div:visible { visibility:hidden; }
    

    Such pseudo-class always fails and so breaks the rule defined above. There is simply no such moment of time when the rule above is valid.

  • Selectors can use only those features/characteristics of the DOM that can be evaluated at constant (or near) time. Otherwise observer will be able to catch moment of time when the rule will not be true.
    • Consequence of this: selectors that require scan of number of elements of the DOM unknown upfront ( have complexity O(n) in other words ) are "persons non grata" in CSS.

There is nothing wrong in principle with O(n) complexity. At the end resolution of all styles of the DOM that has n number of elements is O(n). The problem arises when you use selectors that each has O(n) complexity. Total complexity in this case will be O(n*n) and that is the cause of troubles.  In case of frequent dynamic updates each such update may require re-computation of all styles of all elements so web page may easily become non-responsive – CPU will be busy resolving styles without doing any good to the user.

Imagine that we have selector like:

ul:not-exist(a:hover) {color:red;}

where :not-exist(…) is true when DOM does not contain element in brackets.

Computation of such pseudo-class is a task of complexity O(n) where n is a number of elements in the DOM.

No one of currently supported selectors in CSS selector module (http://www.w3.org/TR/css3-selectors/) have complexity of O(n). But there are selectors like : only-of-type pseudo-class that are "not good" as in some conditions their computation are as complex as O(n).

Next article will explain what could be done in CSS to overcome complexity problem and still be able to accomplish tasks like ul:not-exist(a:hover) {color:red;}

Some numbers if you wish:

Let’s assume that we have

  1. DOM with 1000 elements and
  2. single selector that has complexity  O(n) that requre 1 microsecond for computation.

Total time requred for the DOM to get its styles will be:

1000 * 1000 * 1μS = 1000000 μS = 1 S (one second)

Lets double number of elements in the DOM so we will get:

2000 * 2000 * 1μS = 4000000 μS = 4 S.

So by simply doubling number of elements we’ve increased time needed by four.

In real time scenario (on complex sites) it will easily make such sites too heavy to deal with.

JavaScript. Private members (instance variables).

March 13, 2008

Filed under: Sciter,Script,Source code,Web Application Techologies — Andrew @ 1:28 pm

As you know JavaScript has no concept of private members in objects. Objects there are “racks of properties” that anyone can change.

Here is a simple way of making “objects” in JS that have private instance variables. Such variables can be changed only by [public] methods you provide.

Consider following code:

  function CreateMyObject()
  {
    var m_first = 0;
    var m_second = 0;

    var envelope = // our public interface
    {
        getFirst: function() { return m_first; },
        setFirst: function(v) { m_first = v; },
        getSecond: function() { return m_second; },
        setSecond: function(v) { m_second = v; }
    };
    return envelope;
  }  

  var f = CreateMyObject();

  var n = f.getFirst(); // calling our methods

Here we have CreateMyObject() that behaves as a constructor of our object. It returns envelope object that has four methods. Only these methods can update or retrieve state of m_first and m_second variables. There are literally no other ways to access them from anywhere else other than set of methods provided.

Under the hood: In this example each interface method that we’ve created is a closure in fact: such methods have access to environment of outer function (CreateMyObject in this case) so they can access variables in this environment. Making a closure can be a memory expensive operation so avoid their use when you expect many instances of such objects.

Sciter. Working with persistent data (database)

March 2, 2008

Filed under: Sciter,Script,Source code,Web Application Techologies — Andrew @ 9:08 pm

Here is an example of minimalistic application working with DB (persistent data) in Sciter.

Screenshot of DB form.

This sample is using three files:

  1. simple-db-form.htm – main file of our application;
  2. db.tis – open or create database;
  3. form.tis – behavior that handles showing/saving data from list of input elements on the form.

db.tis – open or create database

This file contains single procedure that will open or create new storage if does not exist:

function openDatabase(pathname = "records.db")
{
  var ndb = Storage.open(pathname);
  if(!ndb.root)
  {
    // new db, initialize structure
    ndb.root =
      { // root of our db is an object having single field 'records'
        records: ndb.createIndex(#integer) // main index, int -> item
      };
  }
  return ndb;
}

Structure of our storage is simple – its root node contains single field records of type Index. In our example this index maps integer – number of the record to the record itself – object that may have arbitrary structure.

form.tis – showing/saving data from input elements on a form

// Form handler class
type Form: Behavior
{
  function show(rec)
  {
    if(this.shown) this.save(); // save previously shown record.
    this.shown = rec;
    function load_value(el)
    {
      var name = el.attributes#name;
      el.value = rec[symbol(name)];
    }
    this.select(load_value, "[name]");
    // call load_value for each element having "name" defined.
    // De facto this means that form content defines structure of the record.
  }
  function save()
  {
    var shown = this.shown;
    function store_value(el)
    {
      var name = el.attributes#name;
      shown[symbol(name)] = el.value;
    }
    this.select(store_value, "[name]");
    // call store_value for each element having "name" defined.
  }
}

This behavior class has two methods:

  • show(rec) – show fields of object rec in fields of the form and
  • save() – stores content of input elements of the form in fields of last shown rec object

simple-db-form.htm – main file of our application

And last part is our main file that defines UI layout and assembles all parts together:

<html>
<head>
  <style>
    form#record
    {
      prototype:Form;
    }
    ...
  </style>
  <script type="text/tiscript">
    include "form.tis";
    include "db.tis";

    var form = self.select("form#record");
    var rec_no = self.select("#rec-no");

    var db = openDatabase();
    var no = 0;

    function gotoRecNo( n )
    {
      no = n;
      if( no < 0 ) no = 0;
      else if( no >= db.root.records.length ) no = db.root.records.length - 1;
      form.show( db.root.records[no] );
      rec_no.text = String.printf("%d of %d", no, db.root.records.length); rec_no.update();
    }

    function gotoNewRecord()
    {
      // create new record
      var newidx = db.root.records.length;
      db.root.records[ newidx ] = { first:0, second:"", third:"<html><\/html>" };
      gotoRecNo(newidx);
    }

    // handlers of navigatonal buttons
    function self #first .onClick() { gotoRecNo(0); }
    function self #prev  .onClick() { gotoRecNo(no - 1); }
    function self #next  .onClick() { gotoRecNo(no + 1); }
    function self #last  .onClick() { gotoRecNo(db.root.records.length - 1); }
    function self #new   .onClick() { gotoNewRecord(); }

    function view.onLoad()   { if(db.root.records.length) gotoRecNo(0);
                                        else gotoNewRecord(); }
    function view.onUnload() { form.save(); db.close(); }

  </script>
<head>
<body>
  <h1>Simple DB form</h1>
  <form #record>
    <table>
      <tr><td>First (number)</td><td><input name="first" type="number"/></td></tr>
      <tr><td>Second (text)</td><td><input name="second" type="text"/></td></tr>
      <tr><td>Third (richtext(html))</td><td><richtext name="third" /></td></tr>
    </table>
  </form>
  <div #nav>
    <button #first title="to first record">|<</button>
    <button #prev title="to prev record"><</button>
    <button #next title="to next record">></button>
    <button #last title="to last record">>|</button>
    <button #new title="create new record">new</button>
    record: <span #rec-no>?</span>
  </div>
</body>
</html>

Done. We have simple form that allows us to create records with text, numeric and richtext (html) fields.


Code above is not the best one from architectural point of view – its goal is to show basic principles, not more.
You can find this sample in [Sciter SDK]/samples/ideas/db/ folder.

« Previous PageNext Page »