Home > JavaScript, Object Pascal, OP4JS, QTX, Smart Mobile Studio > Getting a handle on things

Getting a handle on things

This is a nice addition to QTXLibrary, and perhaps it will one day find it’s way into the Smart RTL.

Under native languages, a Handle is just a longword number. It is usually a reference number you get when you call a DLL driver (like a parking slip, to remember where you parked), a graphics library or the operative system (e.g “window handle”, “graphics context handle” and various other handles). In some rare cases a handle is the numeric version of a pointer – but hopefully everyone has left that practice back in the late 90’s early 2k’s.

Smart Mobile Studio Handles

Under smart mobile studio a handle is a reference, in most cases it’s a reference handle to either a HTML element (usually a DIV element, which is the basis for 90% of all SMS controls), a timer (returned by setTimeOut() in JavaScript) or a graphics context. The latter two are hardly ever accessed directly – except by advanced programmers who want to link to external libraries.

So, what does all of these handles have in common? Well, they all have to be tested before used, that’s one thing they have in common. And also, even if the handle is valid – there is no guarantee that they are part of the visible DOM. That’s another thing they all have in common.

A graphics context can be created “off screen”, so it’s not connected to a HTML element and thus invisible. A DIV element (which is wrapped by TW3CustomControl) can likewise be created “off screen” by providing NIL as a parameter to the constructor. This means that it’s valid and ready to be used — but no visible output can be measured from it.

Another thing handles have in common, is that we tend to do stuff with them when they become valid. For instance, it’s typical to attach events which executes whenever the document has loaded — and also whenever a HTML elements has been created and attached to the DOM.

When you sum up the chores for handles, what we get is a very small but effective handle-helper which will make tedious tests trivial. And it looks like this:


type

  TQTXHandleHelper = helper for THandle
  public
    function  Valid:Boolean;
    function  Ready:Boolean;
    procedure ReadyExecute(OnReady:TProcedureRef);

    Function  Defined:Boolean;
    function  Equals(const aHandle:THandle):Boolean;
    function  Parent:THandle;
    function  Root:THandle;
  end;

//############################################################################
// TQTXHandleHelper
//############################################################################

function TQTXHandleHelper.Root:THandle;
var
  mAncestor:  THandle;
Begin
  if self.valid then
  Begin
    while (mAncestor.parentNode) do
    result:=mAncestor.parentNode;
  end else
  result:=undefined;
end;

Function TQTXHandleHelper.Defined:Boolean;
Begin
  asm
    @result = !(self == undefined);
  end;
end;

function TQTXHandleHelper.Valid:Boolean;
Begin
  asm
    @Result = !( (@self == undefined) || (@self == null) );
  end;
end;

function TQTXHandleHelper.Parent:THandle;
Begin
  if self.valid then
  result:=self.parentNode else
  result:=undefined;
end;

function TQTXHandleHelper.Ready:Boolean;
Begin
  result:=self.Valid and TQTXTools.getElementInDOM(self);
end;

function TQTXHandleHelper.Equals(const aHandle:THandle):Boolean;
Begin
  asm
    @result = (@self == @aHandle);
  end;
end;

procedure TQTXHandleHelper.ReadyExecute(OnReady:TProcedureRef);
Begin
  if Valid then
  begin
    if assigned(OnReady) then
    Begin
      (* Element already in DOM? Execute now *)
      if Ready then
      OnReady() else

      (* Try again in 100ms *)
      w3_callback(
        procedure ()
        begin
          self.ReadyExecute(OnReady);
        end,100);
    end;
  end;
end;

Valid

The valid function checks if the handle is valid. Under JavaScript that means not just to check for “null” – but also to check for “unassigned”.

Ready

This is a very important check. It tests if the handle has been injected into the DOM and that it can actually be operated on. You must always check the readiness of a handle before you attempt to alter an element.

ReadyExecute

This is typically used in constructors, where you can attach an anonymous procedure to execute whenever the handle becomes ready. Excellent procedure to use for components that needs a “nudge” to trigger an internal resize to layout the child elements.

Defined

Check that the handle is not undefined (unassigned).

Equals

Compares the present handle with another handle, returns true if the handle is identical.

Parent

Returns the parent (owner) of the element a handle represents. For elements living on a form, the form handle is returned since that is the parent of the child elements.

Root

Returns the topmost root of an element. For elements not yet injected into the DOM this will be NIL, for elements injected this will either be document or the host container for the smart app.

Using the helper

The helper is extremely easy to use. Once you include the QTXUtils.pas unit, all handles will support the helper. And now you can write more clearly accessible code as such:

if  ObjectReady //constructor complete? 
and Handle.Ready then //object injected into DOM?
Begin
  self.fxZoomIn(0.3); //Use CSS3 effect
end;

Enjoy!

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: