That article is quite old, and a lot has been added since then.
Lambdas, property expressions and partial classes - not to mention better "delphi" support.
The only real difference between native delphi and smart mobile, is that you dont have raw disk access (except for nodeJS projects, there you have full system access like any other server side language), no pointers, and also that JS is heavily callback based. So the RTL have differences quite simply because VCL cannot be shamelessly copied without destroying all that is cool with HTML5 (and breaking copyright laws).
Other than that, it's actually easier to make advanced custom controls (by inheriting from TW3CustomControl) under SMS than Delphi. TeeChart was one of the first components that were converted, and it took only a few hours (the author said). You also get the full benefit of CSS, both via code and stylesheets. And yes, inheritance is there as well - which is nothing short of fantastic work on our part if i say so myself. It took a long time to get this right.
The CSS names match the classes, so if you have a custom control called "TW3MyCoolControl" then it will automatically try to use a CSS style with the same name. Most iOS and Android controls are emulated and there are plenty of skins to pick from.
But the really cool thing is that you get to use inheritance and classes just like in Delphi/FPC -- but under javascript. Which has no such concepts. It produces code that is compact, fast and very robust. You get components, a OOP framework, class helpers galore, an IDE to work with - and javascript suddenly becomes exciting and fun!
About direct Delphi translation:
Obviously you cant compile a delphi/fpc program into javascript directly since you dont have pointers in javascript, and also dealing with resource files and native callbacks just wont work at all.
But you can write code that you can compile both under Delphi / FPC and Smart. As long as you stay clear of pointers, and also remember that events have no "of object" postfixed, then roughly 90% of the language is identical.
Property expression are very helpful. Where you used to write:
Property Active:Boolean read getActive;
and ..
Function getActive:Boolean;
Begin
result:=FActive and (FCount>0);
end;
You can now declare this straight in the interface section of the class:
Property Active:Boolean read (FActive=True and FCount>0);
To access the DOM, you can either link to the methods as external, for instance:
function someJSFunction(aValue:Integer;aData:Variant):variant;external;
or via an ASM section..
function myWrapper(aValue:Integer;aData:Variant):Variant;
Begin
asm
(@result) = someJSFunction(@aValue,@aData);
end;
end;
It really is very, very fun to work with once you get the hang of it.
Here is the button class implementation in full. Styling is done in the CSS, so as you can see it's very easy to create your own re-usable components:
unit w3button;
interface
uses W3System, W3Components;
type
TW3Button = class(TW3CustomControl)
private
function getCaption: String;
procedure setCaption(Value: String);
protected
function makeElementTagObj: THandle; override;
procedure InitializeObject; override;
published
property Caption: String read getCaption write setCaption;
end;
implementation
{ **************************************************************************** }
{ TW3Button }
{ **************************************************************************** }
procedure TW3Button.InitializeObject;
begin
inherited InitializeObject;
Width := 100;
Height := 32;
end;
function TW3Button.makeElementTagObj:THandle;
begin
Result := w3_createHtmlElement('button');
end;
function TW3Button.getCaption: String;
begin
if (Handle) then
Result := Handle.innerHTML;
end;
procedure TW3Button.setCaption(Value: String);
begin
if (Handle) then
Handle.innerHTML := Value;
end;
end.
Which compiles into:
[code language="javascript"]
var TW3Button= {
$ClassName:"TW3Button",
$Parent:TW3CustomControl,
$Init:function ($) {
TW3CustomControl.$Init($);
}
/// function TW3Button.getCaption() : String
/// [line: 39, column: 20, file: w3button]
,getCaption:function(Self) {
var Result="";
if ($Check(Self," in TW3Button.getCaption [line: 41, column: 7, file: w3button]").FHandle) {
Result=$Check(Self," in TW3Button.getCaption [line: 42, column: 13, file: w3button]").FHandle.innerHTML.toString();
}
return Result
}
/// procedure TW3Button.setCaption(Value: String)
/// [line: 45, column: 21, file: w3button]
,setCaption:function(Self, Value$6) {
if ($Check(Self," in TW3Button.setCaption [line: 47, column: 7, file: w3button]").FHandle) {
$Check(Self," in TW3Button.setCaption [line: 48, column: 9, file: w3button]").FHandle.innerHTML=Value$6;
}
}
/// function TW3Button.makeElementTagObj() : Variant
/// [line: 34, column: 20, file: w3button]
,makeElementTagObj:function(Self) {
return w3_createHtmlElement("button");
}
/// procedure TW3Button.InitializeObject()
/// [line: 27, column: 21, file: w3button]
,InitializeObject:function(Self) {
TW3CustomControl.InitializeObject(Self);
TW3MovableControl.SetWidth$($Check(Self," in TW3Button.InitializeObject [line: 30, column: 3, file: w3button]"),100);
TW3MovableControl.setHeight$($Check(Self," in TW3Button.InitializeObject [line: 31, column: 3, file: w3button]"),32);
}
,Destroy:TW3TagObj.Destroy
,AfterUpdate:TW3CustomControl.AfterUpdate
,FinalizeObject:TW3CustomControl.FinalizeObject
,InitializeObject$:function($){return $.ClassType.InitializeObject($)}
,makeElementTagId:TW3TagObj.makeElementTagId
,makeElementTagObj$:function($){return $.ClassType.makeElementTagObj($)}
,StyleTagObject:TW3CustomControl.StyleTagObject
,Resize:TW3MovableControl.Resize
,setHeight:TW3MovableControl.setHeight
,SetWidth:TW3MovableControl.SetWidth
,supportAdjustment:TW3MovableControl.supportAdjustment
,Invalidate:TW3CustomControl.Invalidate
};
[/code]
Also, TObject supports Interfaces, so you dont need TInterfacedObject. Interfaces are emulated in it's own dictionary so they are just as fast as everything else.
But to see what the fuzz is about, download the demo for windows and have a look (note, our servers are overloaded, to many users downloading right now, but be patient if you dont get through immediately):
www.smartmobilestudio.comIt's pretty awesome and it will save you months of hacking away in HTML5
The next update is due any day now -- there you will find live debugging, just like in Delphi
A better presentation of the product can be found here:
http://jonlennartaasenden.wordpress.com/products/smart-mobile-studio/