Sciter,

Adding basic <video> support to Sciter.

The <video> element (behavior:video in fact) is rendered windowlessly as normal DOM element so can participate in animations, transforms and to have other DOM element rendered on it.

Here is a screenshot of Sciter made when it is playing video (standard 30 fps rate) under animation and transformation on semi-transparent background.

sciter video demo

DOM Inspector and “how to remove border from an input element”

This how to remove border from input element is a popular question that I am getting time to time from new users.
And there are variations of it about dropdown select button, calendar cell, context menu and so on.

In this post I’d like to explain general method of solving such problems instead of answering “define the following …”

Each input element in Sciter is a plain DOM element or composition of plain DOM elements.

Input elements (and not only inputs) are getting their “primordial” styling by applying rules from Sciter’s internal “master.css” style sheet. To find out styles of particular DOM element start DOM inspector by clicking on its icon in Sciter.exe window.

To highlight needed DOM element click on it by mouse with CTRL+SHIFT keys pressed on keyboard. Or select the element in DOM tree in inspector’s window:

dom inspector

Inspector will show effective style rules applied to the element and also its final (used) styles.

As you see here that <input> element has no border at all. But it has
background-image: url(theme:edit-normal); background-repeat:stretch; instead – background image that is stretched to fill whole element’s area.

The theme:.... images are kind of virtual ones – their rendering is delegated to host OS UI theming services. Therefore background of this particular <input> element is drawn by host OS.

And finally here is the answer on “how to remove border from the input element”.

To suppress borders and any default background drawing declare the following:

 
input#my {
  border: none;  /* remove any border */
  background: none; /* remove any (default) background */
}

Mac OSX, DPI and font sizes mess

Most of applications on Mac OS X use fixed 72 DPI settings despite of all these Retina and other high-DPI monitors. I understand that this is legacy we’ve got from last century. But c’mon, it is 2014 out there …

Even conventional browsers that supposed to handle scaling well by using CSS rules are failing to render simple things like:

  <div style="width:3in; width:3in; border:1px solid">
    is it 3 inch square?
  </div>

you will see everything but not 3 inches square here.

I am not getting what’s the problem to implement proper scaling. Here it is in Sciter on Mac:
DPI screenshot

Screenshot is taken on Mac with Dell UltraSharp U2711 monitor.

Model-View-Whatever, the Plus engine for Sciter.

Preface

I would say that human history is a history of reinventing "wheels" of various kinds.

This time we see concept of data binding reincarnated with slightly pathetic name Model-View-Controller. Of course, as many people as many meaning they give to the MVC abbreviation but, nevertheless, it is all around basic idea of data binding – you have data (the Model these days) declaratevily bound with UI "controls" (the View). I believe Microsoft’s VisualBasic 4 and its IDE was the very first usable implementation of the idea. There was no Controller concept at that moment so their implementation was quite limiting – while you can implement 90% of your data editing needs using simple declarations you will spend 90% of your design time fighting with the rest of 10% of needed functionality.

The Plus framework for Sciter.

The Plus framework you can find in Sciter SDK is quite compact (400 LOC) and relatively simple implementation of that old data binding concept with controller means.

Note, the Plus is not an attempt to solve every html/css/script UI problem as AngularJS does. It is just a data binding mechanism with the concept of @observing functions (controllers in my interpretation).

Basics

Model in Plus interpretation is some tiscript namespace object that contains data variables (and optionally functions) to be bound with particular container in HTML DOM.

For example if you declare this script:

namespace Data {
  var correspondent = "world"; // variable to be bound
} 

and corresponding markup:

<section model="Data">
   Whom to greet: <input name="correspondent"> ?
   <p>The greeting: Hello <output name="correspondent">!</p>
</section>

and include in your document "plus.css" file you will get live data binding between Data.correspondent data variable and two DOM elements: two ways with input[name=correspondent] and one way (only view) binding with output[name=correspondent]. So when you type something in that input you will see the data also rendered in output element.  To see this alive load sdk/samples/+plus/demos/0-basic-variable-binding.htm in sciter.exe from its SDK.

The model and name DOM attributes.

Note that <section> element contains model="Data" attribute. It instructs the Plus engine to establish data binding between content of this section and members of namsepace Data {} in script. Name of the bound namespace can be any suitable, not just Data.

Any DOM element inside that section[model] may have name attribute defined. On binding initialization the Plus will try to find data element in the model with that name and if such data variable is found it will made two or one way (for <output> elements) binding between .value of that DOM element and the data variable. The name can be compound – may contain ‘.‘ (dot)-separated list of names. This way  you can bind DOM elements with object fields inside the model:

namespace Contact {
  var name = { first: "Albert", last: "Einshtein" };
  var phone = "....";
  ... 
}

and markup:

<form model="Contact" id="contact-details"> 
  <label for="name.first">First name></label> <input name="name.first">
  <label for="name.last">Last name></label> <input name="name.last">
  ...
</form>

Celsius to Fahrenheit convertor.

Controllers, the @observing function decorator.

File plus.tis (the Plus engine implementation) contains declaration of function decorator named @observing. With that decorator you can define functions that will be triggered (called by the engine) when variable(s) they are observing change.

As an example let’s define simple Celsius to Fahrenheit conversion tool that should work in two directions – when you define celcius value it will calculate its fahrenheit representation. And vice versa. Something similar to the form on the right:

First we will define our Data namespace:

      include "../plus.tis"; // model below uses @observing decorator defined in plus.tis  
      namespace Data // our model
      {  
        var celsius = 0; 
        var fahrenheit = 32;
        
        // this function is observing 'celsius' and calculates 'fahrenheit'
        @observing "celsius"
          function toFahrenheit() {
            fahrenheit = celsius * 9 / 5 + 32;
          }
        // this function is observing 'fahrenheit' and calculates 'celsius'
        @observing "fahrenheit"
          function toCelcius() {
            celsius = (fahrenheit - 32) * 5 / 9;
          }        
      }    

Note two functions above: function toFahrenheit() is observing celcius variable. When celcius variable will change, for example as a result of changes in <input|number(celsius)> field, the toFahrenheit() function will be triggered and will set value of fahrenheit variable. As we have another input bound with the fahrenheit variable:

<body model="Data">
  <p><input|number(celsius)>°C and <input|number(fahrenheit)>°F</p>
</body>

we will see in it results of calculation. This works in both directions – from fahrenheit to celcius and from celcius to fahrenheit.

To see this alive load sdk/samples/+plus/demos/1-basic-function-binding.htm sample in sciter.exe.

That’s it for now. In the next article I’ll explain use of repeatable attribute to bind arrays of objects with rpepatable sections and other samples. If you don’t want to wait check other samples in sdk/samples/+plus/demos/ folder of the SDK. They are self descriptive.

MVC or not MVC? The Formation Engine for jQuery

Various JavaScript frameworks provide data binding facilities (Knockout, AngularJS, etc.) these days.

They are based on kind-of-MVC concept: you have some data (structure, model), view rendering that data in html and some code in between that commonly named as controllers.

How successful/convenient those frameworks are subject of separate topic. For me they are too intrusive I would say. On some views/pages they make sense, on others final solution looks too ugly.

Anyway, here is an alternative idea…

Instead of separating data structure and its view we simply can create construction that is a data model and its view at the same time 🙂

I named that magic “construction” as Formation. Formation is essentially a collection of DOM elements organized in a tree that reproduces structure of the data (or model if you wish). Value of the formation is JSON data structure – the model per se.

Consider this example

Here you see collection of inputs and subsections (on the top).
On the bottom/right corner you see the Formation tree created of <section#inputs> container.

On the left you see live data of the Formation (editable textarea). Changes there reflect state of elements. In the same way changes in inputs reflect text in this textarea.

The Formation implementation does two major things:

  • creates formation trees and
  • initializes custom DOM elements (check that in HTML source – that friends list).

Couple of words about custom elements support in formations:

When formation sees custom DOM element ( any DOM element with tag name containing ‘-‘ inside ) it tries to find its initializer in registry of jQuery plugins – that famous $.fn collection. And calls it if it was found. You can check js/jquery.list-input.js – it is normal jQuery plugin with the name matching that custom element tag name: “INPUT-LIST”.

To create/get formation of some container you can call either

  1. global [window.] formation( domel_or_$_wrapper ) function or
  2. $(selector).formation() plugin.

You can store created formation in some variable and access DOM elements in it in quite effective manner:

var inputs = $("section#inputs").formation();
$(inputs.firstName).on("change", function() {...});

Accessing formation members directly is faster than accessing them using jQuery selectors as these are just direct references.

You can download complete sample to play with from here.

Future Formation plans: to implement so called repeatable formations, so if you have this markup:

<ul repeatable name="stockItems">
   <li><output name="name">  <output name="price" type="currency"></li>
</ul>

and will feed it (through formation) by this data:

[
  {name:"Apple", price: 1.05 },
  {name:"Orange", price: 0.52 } 
]

it will render two <li>s in the list.

Another ng-inspired idea is to have class switches as Formation elements, this class declaration:

<div class="{someSwitch:collapsed|expanded}" >...</div>

will cause corresponding formation to have element named “someSwitch” that can be assigned false/true or 0|1 values to change class to either <div class=”collapsed”> or to <div class=”expanded”>…

UPDATE: see discussion about the Formation on jQuery forum : forum.jquery.com/topic/mvc-or-not-mvc-the-formation-engine

Sciter HTML parsing flavour

HTML parser in Sciter v.3 supports attribute shortcuts allowing to write HTML in more compact form. Compare these two declarations that are identical (to the Sciter):

Compact:

 
  <input|currency(itemPrice) value=1000> 

and standard:

 
  <input type="currency" name="itemPrice" value=1000> 

As you see the first one is slightly shorter and better readable (subjective of course).

Here is full list of supported attribute shortcuts:

  • #nameid, attribute name that starts from ‘#’ is parsed as id=”name”
  • .nameclass, this is an equivalent of class="name". Element may have multiple “dot attributes”. All of them are combined into single class attribute. So this <div.container.collapsed> is treated as this: <div class=”container collapsed”>
  • |nametype, attribute name that starts from ‘|’ is parsed as type="name"
  • (someName)name, attribute name enclosed into ‘(‘ and ‘)’ is parsed as name="someName"

Just in case 🙂

Q.tis – micro port of jQuery for Sciter.

I’ve published today Sciter 2.0.2.2 with q.tis – micro-port of essential jQuery features.
Here is the list of supported functions.

It is just enough to put include "t.tis"; in your code and any existing DOM function that returns array of elements will
“automagically” produce the q-collection.

In my implementation I am using the fact that functions like Element.selectAll("selector") return array object that is instanceof ElementList.
ElementList as any class is extensible in run-time. So I’ve just added bunch of function ElementList.jqueryMethod() {} to bring that functionality to the Sciter.

The beauty of the approach is that you can use as the q() function (analog of $() in jQuery) as Sciter’s standard $$() to write something like this:

var itemsWithLinks = $$(ul.topics > li).$has(a:link);

to get list of list items that have <a>’s inside.
The same but in classic style and without use of “stringizers”:

var itemsWithLinks = q("ul.topics > li").has("a:link");

You may also find handy jquery-alike event handling. Methods element.on(), element.off(), element.one() and element.trigger() are available as for q-collections as for DOM element instances.

Making TIScript syntax compatible with CSS.

Time to time when I need to define some CSS constructs in script I feel myself non-comfortable – CSS and JavaScript/TIScript use different syntax’es.

Consider this code in JavaScript:

  function switchState() 
  {
    element.style.backgroundColor = "rgb(126,0,0)";
    element.style.transform = "rotate(45deg) translate(10px,10px)";
  }

Not so aesthetically pleasing. And not so effective as string parsing is involved.

And yet if for example you will need to get current rotation angle from style, increment it by some value and write it back then you will need to implement non trivial parsing using CSS rules and opposite toString translation for changed rule.

I’ve explored quite many JS frameworks that are capable working with styles – all they have good chunk of parsing CSS code.

But browser already parses the CSS and builds internal structures that represent CSS values. Code is there, why not to reuse it?

One way of dealing with this is to expose CSS internal structures using so called CSSOM. But that’s really too much work and result is still too narrative I would say.

Ideally that should look like this:

  function switchState() 
  {
    element.style.set {
      background-color: rgb(126,0,0),
      transform: rotate(45deg) translate(10px,10px) 
    }
  }

And in principle JS syntax can be extended to support such constructions without conflicts with existing code:

  1. Allow names with hyphens like background-color in object literals.
  2. Allow values with units like 45deg, 10px and the like. That will require new data types in JS but they are handy anyway
  3. Add so called tagged tuples to the language. In terms of CSS this rotate(45deg) is not a function call but rather tuple (data structure with the name). In terms of TIScript this can be written as [rotate:45deg] – one element tuple with the tag ‘rotate’.
  4. Add whitespace as a valid list separator, at least in object literals, so this
       { transform: rotate(45deg) translate(10px,10px) }
    

    will be an equivalent of

       { transform:[rotate(45deg), translate(10px,10px)] }
    

    And that would be pretty much it.

In fact CSS syntax (that may look like a mess sometimes) uses in reality two types of lists and one tuple<2> (in order of precedence):

  1. comma separated lists: background: url(1.png),url(2.png);
  2. white-space separated lists: background: no-repeat url(1.png);
  3. pair-tuples: font: 12pt 10pt/14pt "arial";

But that would be next step. At the moment I am trying to add values with units and whitespace lists…

W3C: “Selectors API Level 1” is out but …

"Selectors API Level 1" document started in 2006 has reached status of W3C Recommendation these days. Which means we may see it implemented uniformly across all browsers ( those browsers that are alive yet 😉 ).  

But I am disappointed by features provided by this API. It de-facto contains 6 methods but only two of them (first two in the table below) are really useful.

jQuery and Sciter have full set of selector methods needed in practice, but the Selector API just scratched the surface as you see below.

Let’s take a look on what this API gives us and compare with similar features available in Sciter/HTMLayout and jQuery.

function W3C Selectors Sciter jQuery
find first matching element in a document document.querySelector("selector")
: Element
self.select("selector")
: Element
$("selector").first()
: $Obj
find all matching elements in a document document.querySelectorAll("selector")
: staticNodeList
self.selectAll("selector")
: array (of Elements)
$("selector")
: $Obj
find first matching sub-element of an element
using global selector
element.querySelector("selector")
: Element
(See below) (See below)
find all matching sub-elements of an element
using global selector
element.querySelectorAll("selector")
: staticNodeList
(See below) (See below)
find first matching sub-element of an element
using local selector
N/A element.select("selector")
: Element
$obj.find("selector").first()
: $Obj
find all matching sub-elements of an element
using local selector
N/A element.selectAll("selector")
: array (of Elements)
$obj.find("selector")
: $Obj
find first matching sub-element of an element
using rooted local selector
N/A element.select(":root > cont1 > cont2")
: Element
$obj.find("> cont1 > cont2").first()
: $Obj
find all matching sub-elements of an element
using rooted local selector
N/A element.selectAll(":root > cont1 > cont2")
: array (of Elements)
$obj.find("> cont1 > cont2")
: $Obj
find first parent matching the selector N/A element.selectParent("selector")
: Element
$obj.first().closest("selector")
: $Obj
find all parents matching the selector N/A element.selectAllParents("selector")
: array (of Elements)
$obj.first().parents("selector")
: $Obj
check if the element satisfies given selector N/A element.match("selector")
: true | false
$obj.first().is("selector")
: true | false

Where:

  • global selector – selector that uses document root as a selector root.
  • local selector – selector that uses the element itself as a selector root.
  • rooted local selector – selector that contains explicit reference of the element itself as first component.
    For example, in Sciter, this call: ul.selectAll(":root>li") will find all <li> elements that are direct children of the ul element.

The element.querySelector[All]() method defined in the Selector API is just a variation of document.querySelector[All]() but on subset of descendants of the element. Consider this HTML fragment:

<ul>
  <section id=test>
    <ol>
      <li>one</li>
      <li>one</li>
    </ol>
  </section>
</ul>

With the use of the Selector API this code:

var section = document.getElementById("test");
var nListItems = section.querySelectorAll("ul li");

will give you two [items].

But the same thing with jQuery (or Sciter):

var nListItems = $("#test").find("ul li");

will give you zero items. jQuery and Sciter use local selectors (rooted or not).

So methods provided by the Selectors API cannot be used by jQuery to implement its all selector look up methods natively. Only one of them – global look-up can use this API, All local look up methods shall still use home brewed selector implementation in script.

I haven’t seen anyone requesting such strange element.querySelectorAll method and have no clue why it was included in the spec. If someone really needs such local look up using global selectors then it is a matter of writing something like this (in Sciter or jQuery):

section.selectAll("*").filter( :child: child.match("ul li") );

But I don’t know why someone will ever need such method…

The Selectors API has mark "Level 1" so I hope rest of methods will be added soon in Level 2.

So far the mountain has brought forth a mouse. And yet it took 6 years to do so, eh?