Home > CSS, Delphi, JavaScript, nodeJS, Object Pascal, OP4JS, Smart Mobile Studio > Smart wrappers, twirk like jQuery

Smart wrappers, twirk like jQuery

November 4, 2015 Leave a comment Go to comments

I was asked how to better implement a “JQuery like syntax” – but for Smart Pascal rather than surrendering to alien and cryptic JavaScript. Well, there are many ways to skin a cat, but below is a typical example of how can wrap interesting functionality more or less like jQuery does it; Except within the confines of Smart Pascal.

But naturally, object pascal is a much more rigid language. It has rules and clear principles which cant (and should not) be abused. Also, class helpers is the proper way to extend the functionality of classes through abstraction.

Anyways, here is a way you could do it:

  TEventReference = Class(TObject)
  private
    FInstance:  TW3TagObj;
    FEventName: String;
  public
    procedure   &To(EntryPoint:TProcedureRef);
    constructor Create(Obj:TW3TagObj;EventName:String);
  end;

  TControlReference = class(TObject)
  private
    FParent:    TW3Component;
    FInstance:  TW3TagObj;
  public
    function    Attach(EventName:String):TEventReference;
    constructor Create(AParent:TW3Component;AInstance:TW3TagObj);
  end;

  TSelector = class abstract
  public
    class function &Object(Container:TW3Component;ControlName:String):TControlReference;
  end;

//#############################################################################
// TEventReference
//#############################################################################

constructor TEventReference.Create(Obj:TW3TagObj;EventName:String);
begin
  inherited Create;
  FInstance := Obj;
  FEventName := EventName;
end;

procedure TEventReference.&To(EntryPoint:TProcedureRef);
begin
  w3_AddEvent(FInstance.Handle,FEventName,Entrypoint);
end;

//#############################################################################
// TControlReference
//#############################################################################

constructor TControlReference.Create(AParent:TW3Component;AInstance:TW3TagObj);
begin
  inherited Create;
  FParent := AParent;
  FInstance := AInstance;
end;

function TControlReference.Attach(EventName:String):TEventReference;
begin
  result := TEventReference.Create(Finstance,EventName);
end;

//#############################################################################
// TSelector
//#############################################################################

class function TSelector.&Object(Container:TW3Component;ControlName:String):TControlReference;
var
  x: Integer;
  mObj: TObject;
begin
  result := NIL;
  if Container<>NIL then
  begin
    controlname:=controlname.trim();
    if controlname.length>0 then
    begin
      mObj := Container.ChildByName(ControlName);
      if mObj<>NIL then
      result := TControlReference.Create(Container,TW3Component(mObj));
    end;
  end;
end;

What is this good for?

The above code does very little. It is just an example of how you can build chains of functionality using standard object-orientation. In this case all we do is to to:

  • Locate a component by name from a container
  • Bind to an event by name
  • Attach event handler to event

But it may be helpful for others to see how to do this, so I figured it was worth 5 minutes.

The syntax goes like this:

TSelector.Object(Form1,'w3button1').Attach('onclick').To( procedure ()
  begin
    // your event handler here
  end);

Note: Since JavaScript has automatic garbage collection you don’t need to worry about creating instances on the fly, they are collected and dropped by the VM as soon as they go out of scope.

To simplify things even more, we can declare TSelector as a global (unit) variable:

var
  JQuery: TSelector;

And now we can do the same thing, but using the variable name instead:

JQuery.object(Form1,'w3button1').Attach('onclick').To( procedure ()
  begin
    // your event handler here
  end);

More advanced stuff

if you want to make use of property and array references, which would be more natural to mimic jQuery and other classic JS libraries – you will have to create an instance and serve that through a function.

var
__JQUERY: TSelector;

function JQuery:TSelector;
begin
  result := __JQUERY;
end;

initialization
begin
  __JQUERY := TSelector.Create;
end;

With this in place we can add a default property, as such:

  TSelector = class(TObject)
  private
    function getForm(name:String):TW3CustomForm;
  public
    property Forms[name:String]:TW3CustomForm read getForm;default;
    class function &Object(Container:TW3Component;ControlName:String):TControlReference;
  end;

And now we can can support a more direct approach (must also alter the sub classes accordingly):

JQuery['form1'].with('w3button1').attach('onclick').to( procedure ()
  begin
    // your event handler here
  end);
Advertisements
  1. November 6, 2015 at 5:51 pm

    Something weird is the “abstract” keyword, the compiler does not even emit an error.
    Another thing I figured out is the eventName should be “click” instead of “onclick”.

    • Jon Lennart Aasenden
      November 10, 2015 at 8:02 am

      In what context? abstract class, method?

  2. December 17, 2015 at 11:41 am

    Using similar approach a just created a demo using SMS. I just created a wrapper aound Framework 7 (MIT license). Can I use MIT licence in smart mobile studio application?

    see live preview:

    https://rawgit.com/smartpascal/smartms/master/smsbasic/www/preview.html

  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: