New version of Sciter2 is out.

March 10, 2013

Filed under: Sciter — Andrew @ 11:08 pm

And it got its own page: Sciter2.
RSS feed on the site is also connected now to Sciter2 logfile so you can use it to get notification about its new builds.

Sciter2 is used now in at least 5 applications in production with 5.5 mln installations (estimated) on computers worldwide.

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

February 24, 2013

Filed under: HTML and CSS,Sciter,Web Application Techologies — Andrew @ 8:26 pm

"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?

Use of CSS constants in script.

February 17, 2013

Filed under: HTML and CSS,Sciter,Script,Source code — Andrew @ 7:31 pm

In Sciter you can define CSS constants using @const declarations like this:

<style>
  @const TEST_STR:"test";
  @const TEST_COLOR: rgb(128,0,0);
  @const TEST_NUMBER: 128;
</style>

and use them not only in CSS ( as @TEST_COLOR for example ) but also in script using accessor like this:

var test_str = self.style.constant("TEST_STR");

If you think that self.style.constant is too narrative then you can define short “stringizer” function for it:

  function $const( name ) { return self.style.constant(name) || ""; }

and later use it as:

var t1 = $const(TEST_STR); // "test" string
var t2 = $const(TEST_COLOR); // object of type Color, color(128,0,0)
var t3 = $const(TEST_NUMBER); // integer, 128

TIScript, hidden treasures: for/in loop

February 7, 2013

Filed under: Sciter,Script,Source code — Andrew @ 9:12 am

Integer data type in TIScript is iteration-able, means the following works in TIScript:

for(var i in 100)
  stdout.println(i);

The code above will print numbers from 0 to 99 in stdout.

Usability of tree and paged lists

January 26, 2013

Filed under: How-to,Philosophy,Sciter,Usability,Web Application Techologies — Andrew @ 6:52 pm

I’ve found first answer in this topic on StackExchange extremely representative.

That reminded me discussion we had when were designing the first version of Evernote application.

Initially the Evernote has UI organized as “endless tape of notes”. Here is one of sketches that I did at that time:

Challenge there was to provide UI that allows the user to find notes quickly without need of excessive scrolling.

Each note may have so called tags (a.k.a. labels) assigned. By clicking on tag (left side bar) the tape will get filter applied – only notes with such tag are shown.

By expanding the tag (“+” sign) you can see intersection of notes that have this tags and some others. For example here click on hello->world (on the left) will give you set of notes with the condition has-tag:"hello" AND has-tag:"world" (see top bar):
Note tape with filter applied

And if you type “wonderful” in the search field you will get filter has-tag:"hello" AND has-tag:"world" AND has-text:"wonderful" applied.

This will give you single note:
tape with text filter

Pretty convenient I would say.

What does “::” construction mean in TIScript?

December 3, 2012

Filed under: Sciter,Script,Source code — Andrew @ 7:33 pm

Got this question in one of emails…

One of forms to declare anonymous function in TIScript is so called single statement lambda function:

':' [param-list] ':' <statement>;

Let’s say we have this JavaScript code:

var counter = 0;
var inc = function() { counter++; }

So each time when you call inc() the counter will be incremented.

By using TIScript’s lightweight syntax we can do exactly the same by declaring:

var counter = 0;
var inc = :: counter++; 

So first “:” here is exactly “function(” and second “:” is “)” in JS declaration.

You of course can use standard JS way of declaring functions in TIScript too, I just think that sometimes shorter forms are better. Like here:

var accounts = [...]; // list of accounts
accounts.sort( :a,b: a.balance - b.balance );

Instead of quite noisy:

accounts.sort( function(a,b){ return a.balance - b.balance });

Ruby has similar lightweight approach of declaring similar entity:

[1,2,3,4,5].each {|i| print "#{i} "}

That in JS will be

[1,2,3,4,5].each(function(i){ println("#",i);});
« Previous PageNext Page »