Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 3 of 3 total
Thread Sample of using addEventListener
Mon, Dec 12 2011 8:19 PMPermanent Link

Ron Levy

Tim,

Any example how to use addEventListener from within EWB?

Trying to add one for the onresize event of the window object - I am getting lots of problems.

Basically, if I have something like the following:


procedure TForm1.Form1Show(Sender: TObject);
begin
Application.Desktop.AutoWidth := true;
Application.Desktop.AutoHeight := true;

window.addEventListener('resize', Resizer, false);
end;

if I have Resizer defined as a stand alone procedure:


procedure Resizer(event : TEvent);
begin
 Form1.Label2.Caption := event.type;
end;


I get: there is no function or procedure declaration that matches the Label2().Caption reference

If I define it as a procedure of the form (TForm1.Resizer)

I get:

there is no function or procedure declaration that matches the addEventListener('resize', Resizer(), false) reference
Mon, Dec 12 2011 9:12 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Ron,

<< Any example how to use addEventListener from within EWB? >>

This is another one of those reasons why you don't want to necessarily use
plain JS. Smile EWB automatically generates code for event handlers that
captures the proper object instance scope in the event handler.  Plain JS
does not have such feature, and often doesn't have any idea which object
instance is handling a specific event.

Because of this, there is a special way that event handlers need to be
called.  What you want is something like this:

This is what I just added to the WebDOM unit yesterday:

interface

  function SetWindowEventHandler(const HandlerType: String;
                                 Handler: TEventHandler): TEventHandler;

  procedure ClearWindowEventHandler(const HandlerType: String;
                                    Handler: TEventHandler);

implementation

function SetWindowEventHandler(const HandlerType: String;
                                Handler: TEventHandler): TEventHandler;
begin
  { First see if the addEventListener method exists }
  if Assigned(window.addEventListener) then
     window.document.addEventListener(HandlerType,Handler,False)
  else if Assigned(window.attachEvent) then
     window.document.attachEvent('on'+HandlerType,Handler)
  else
     raise TEventError.Create('Cannot add window event handler for
"'+HandlerType+'" event');
  { Return the same handler (emitted code will use an anonymous function
here }
  Result:=Handler;
end;

procedure ClearWindowEventHandler(const HandlerType: String;
                                   Handler: TEventHandler);
begin
  { First see if the removeEventListener method exists }
  if Assigned(window.removeEventListener) then
     window.document.removeEventListener(HandlerType,Handler,False)
  else if Assigned(window.detachEvent) then
     window.document.detachEvent('on'+HandlerType,Handler)
  else
     raise TEventError.Create('Cannot remove window "'+HandlerType+'" event
handler');
end;

Notice that the "set" function returns the actual event handler that was
passed in.  This is how the event handler captures the scope of the calling
object instance (with a little help from the compiler).  You can then use
the returned value in the "clear" procedure to properly remove the event
handler when it is no longer needed.  However, please note that this *only*
applies to dealing with external events in the DOM classes.  Normal events
declared in normal classes do not require this type of manipulation.  For
example, if the OnResize event was part of a normal class like the TDesktop
class, then you would simply assign it like this:

Application.Desktop.OnResize:=ResizeEventHandler

This is why you'll notice that there are special Set/Clear
functions/procedures in the WebDOM unit for setting these external event
handlers.

This is the code that was added to the WebForms unit:

procedure TDesktop.SetEventHandlers;
begin
  inherited SetEventHandlers;
  FResizeScreenHandler:=SetWindowEventHandler('resize',ResizeScreenHandler);
end;

procedure TDesktop.ClearEventHandlers;
begin
  inherited ClearEventHandlers;
  ClearWindowEventHandler('resize',ResizeScreenHandler);
end;

procedure TDesktop.UpdateAutoHeight;
begin
  if FAutoHeight then
     begin
     Base.style.height:='';
     Base.style.height:='100%';
     end;
end;

procedure TDesktop.UpdateAutoWidth;
begin
  if FAutoWidth then
     begin
     Base.style.width:='';
     Base.style.width:='100%';
     end;
end;

function TDesktop.ResizeScreenHandler(event: TEvent): Boolean;
begin
  UpdateAutoHeight;
  UpdateAutoWidth;
  CancelEventBubble(event);
  Result:=True;
  SetEventResult(event,Result);
end;

<< if I have Resizer defined as a stand alone procedure: >>

EWB does not support function/procedure pointers, so you have to always use
a method pointer instead.  So all event handlers must be declared within a
class declaration.

I hope that helps, and please keep digging - it's good that someone is
getting into the nitty-gritty of the code. Smile

--
Tim Young
Elevate Software
www.elevatesoft.com
Tue, Dec 13 2011 6:48 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

And, there's a bug - there was a "document" reference in there that
shouldn't be there. Smile

The procedures should look like this:

function SetWindowEventHandler(const HandlerType: String;
                                Handler: TEventHandler): TEventHandler;
begin
  { First see if the addEventListener method exists }
  if Assigned(window.addEventListener) then
     window.addEventListener(HandlerType,Handler,False)
  else if Assigned(window.attachEvent) then
     window.attachEvent('on'+HandlerType,Handler)
  else
     raise TEventError.Create('Cannot add window event handler for
"'+HandlerType+'" event');
  { Return the same handler (emitted code will use an anonymous function
here }
  Result:=Handler;
end;

procedure ClearWindowEventHandler(const HandlerType: String;
                                   Handler: TEventHandler);
begin
  { First see if the removeEventListener method exists }
  if Assigned(window.removeEventListener) then
     window.removeEventListener(HandlerType,Handler,False)
  else if Assigned(window.detachEvent) then
     window.detachEvent('on'+HandlerType,Handler)
  else
     raise TEventError.Create('Cannot remove window "'+HandlerType+'" event
handler');
end;

--
Tim Young
Elevate Software
www.elevatesoft.com
Image