NAME
HTML::Object::EventTarget - HTML Object Event Target Class
SYNOPSIS
use HTML::Object::EventTarget;
my $eh = HTML::Object::EventTarget->new(
) || die( HTML::Object::EventTarget->error, "\n" );
$e->addEventListener( change => sub
{
my $event = shift( @_ ); # also available as $_
# do something with that event (HTML::Object::Event)
}, {capture => 0});
$e->dispatchEvent( $event );
my $event_handlers = $e->getEventListeners( 'click' );
say "Found ", $Event_handlers->length, " event handlers";
$e->handleEvent( $event );
$e->on( click => sub
{
my $event = shift( @_ );
# do something
});
# or
sub onclick : lvalue { return( shift->on( 'click', @_ ) ); }
$e->onclick = sub
{
my $event = shift( @_ );
# do something
};
$e->removeEventListener( $event_listener_object );
VERSION
v0.2.2
DESCRIPTION
This modules represents an event target and handler. This is implemented by HTML::Object::Document and HTML::Object::Element and its descendants.
Of course, being perl, there is only limited support for events.
CONSTRUCTOR
new
Creates a new HTML::Object::EventTarget object instance and returns it.
METHODS
addEventListener
Provided with a type
, a callback
and an optional hash or hash reference of options
and this will register an event handler (i.e. a callback subroutine) of a specific event type on the EventTarget.
When an event is "fired", the callback
is called, and the event object is passed as it sole argument. Also, $_
is set to the current element object on which the event got triggered.
It returns the newly created HTML::Object::EventListener upon success or "undef" in perlfunc upon error and sets an error
Possible options are:
- capture
-
A boolean value indicating that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.
Setting the capture flag controls whether an event listener is called in the Capture phase or Bubble phase.
For example:
<div id="div1"> <div id="div2"></div> </div> $div1->addEventListener('click', \&doSomething1, {capture => 1 }); $div2->addEventListener('click', \&doSomething2, {capture => 0 });
Triggering a
click
event ondiv2
yields the following[1]:$div2->trigger('click');
- 1. The
click
event starts in the capturing phase. The event looks if any ancestor element of element2 has a onclick event handler for the capturing phase. - 2. The event finds one on
div1
.doSomething1()
is executed. - 3. The event travels down to the target itself, no more event handlers for the capturing phase are found. The event moves to its bubbling phase and executes
doSomething2()
, which is registered todiv2
for the bubbling phase. - 4. The event travels upwards again and checks if any ancestor element of the target has an event handler for the bubbling phase. This is not the case, so nothing happens.
The reverse would be:
$div1->addEventListener('click', \&doSomething1, {capture => 0 }); $div2->addEventListener('click', \&doSomething2, {capture => 0 });
- 1. The click event starts in the capturing phase. The event looks if any ancestor element of
div2
has a onclick event handler for the capturing phase and doesn’t find any. - 2. The event travels down to the target itself. The event moves to its bubbling phase and executes
doSomething2()
, which is registered todiv2
for the bubbling phase. - 3. The event travels upwards again and checks if any ancestor element of the target has an event handler for the bubbling phase.
- 4. The event finds one on
div1
. NowdoSomething1()
is executed.
Setting an event listener like this:
$div1->onclick = \&doSomething1;
would register it in the bubbling phase, i.e. equivalent to:
$div1->addEventListener( click => \&doSomething1, { capture => 0 } );
[1] Koch, Peter-Paul "Event order" (Quirkcsmode) https://www.quirksmode.org/js/events_order.html
See for more information and this
- 1. The
- once
-
A boolean value indicating that the listener should be invoked at most once after being added. If true, the listener would be automatically removed when invoked.
- passive
-
This, under perl, does nothing and thus always defaults to false.
Under JavaScript, this would be a boolean value that, if true, indicates that the function specified by listener will never call
preventDefault()
. If a passive listener does callpreventDefault()
, the user agent will do nothing other than generate a console warning. See Improving scrolling performance with passive listeners to learn more. - post_processing
-
This is a non-standard addition and is a code reference (i.e. a subroutine reference or an anonymous subroutine) passed that will be called once the event handler has been set. It is passed the newly created event listener object.
This is used by HTML::Object::DOM::List for example, to enable event listening on array or scalar only when an event listener is registered. So, upon adding an event listener, this post-processing callback is called and this callback takes the appropriate step to start listening to a specific array or scalar.
- signal
-
A signal, such as
ALRM
,INT
, orTERM
. The listener will be removed when the givensignal
is called.
Example:
<table id="outside">
<tr><td id="t1">one</td></tr>
<tr><td id="t2">two</td></tr>
</table>
# Subroutine to change the content of $t2
sub modifyText
{
my $t2 = $doc->getElementById("t2");
if( $t2->firstChild->nodeValue eq "three" )
{
$t2->firstChild->nodeValue = "two";
}
else
{
$t2->firstChild->nodeValue = "three";
}
}
# Add event listener to table
my $el = $doc->getElementById("outside");
$el->addEventListener("click", \&modifyText, { capture => 0 } );
Then, do:
$el->trigger( 'click' );
You can also pass subroutine name that is in your package, or a fully qualified subroutine name. For example:
Assuming you are calling from the package My::Module, the following will search for a subroutine My::Module::my_callback
$el->addEventListener("click", 'my_callback', { capture => 0 } );
Or
$el->addEventListener("click", 'My:Module::my_callback', { capture => 0 } );
If it does not exists, it will return undef
and set an error.
dispatchEvent
Provided with an event, and this dispatches the event to this EventTarget.
It will first call "composedPath" to get the branch from this current element to the top one, and will start from the top in the capture
phase, checking every element from top up to the current one and calls "handleEvent", which, in turn, will check if there are any listeners registered in this capture
phase, and if there are calls each listener's "handleEvent" in HTML::Object::EventListener.
Then once the capture
phase is done, it executes the event listeners on the current element, if any.
Then finally, if the event "bubbles" in HTML::Object::Event property is true, it calls "handleEvent" on each of the element starting from the current element's parent to the top one. "handleEvent", in turn, will check if there are any event listeners registereed for the element in question for the bubbling
phase and call their event handler.
If the event property "cancelable" in HTML::Object::Event is set to true and a handler cancelled it at any point, then this whole process is interrupted.
The event current element is set each time, so you can check that to find out which one has cancelled it.
event_listeners
Sets or gets an hash reference of all the event listeners registered.
getEventListeners
Provided with an event type, such as click
, and this returns all the event listener objects registere for that event type in their order of registration. It returns an array object
my $listeners = $e->getEventListeners( 'click' );
say "Found ", $listeners->length, " event listeners.";
handleEvent
Provided with an event and this will process it via all the registered event listeners in the order they were registered.
It returns the current element object upon success, and upon error, it returns undef
and sets an error
hasEventListener
Provided with an optional event type and this returns the number of event listeners registered for the given type, if provided, or the total number of event listeners registered for all types.
on
This is a convenient method to set event listeners. It is to be called by a class, such as:
sub onclick : lvalue { return( shift->on( 'click' @_ ) ); }
Then, you can set a click
event listener for this element:
$e->onclick = sub
{
my $event = shift( @_ ); # Also available with $_
# Do some work
};
# or
$e->onclick(sub
{
my $event = shift( @_ ); # Also available with $_
# Do some work
});
removeEventListener
Provided with a event type
, a callback
code reference or a subroutine name (possibly including its package like MyPackage::my_sub
), or an event listener object, and an hash or hash reference of options and this removes an event listener from the EventTarget.
It returns the HTML::Object::EventListener thus removed upon success or "undef" in perlfunc upon error and sets an error
Possible options, to identify the event handler to remove, are:
- capture
-
A boolean value indicating that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.
For example:
my $eh = $e->addEventListener( click => sub{ # do something }, { capture => 1, once => 1 });
$eh->remove;
# or
$e->removeEventListener( click => $same_code_ref, { capture => 1 });
However, if the options provided differ from the ones initially set, it will not uniquely find the event handler. Only the capture
option is used to uniquely find the handler. For example:
This will fail to remove the handler, because the capture
parameter does not have the same value.
$e->removeEventListener( click => $same_code, { capture => 0 });
This will fail to remove the handler, because the callback
value is not the same as the original.
$e->removeEventListener( click => $some_other_code_ref, { capture => 1 });
AUTHOR
Jacques Deguest <jack@deguest.jp>
SEE ALSO
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
https://developer.mozilla.org/en-US/docs/Web/Events/Event_handlers
https://developer.mozilla.org/en-US/docs/Web/API/Event
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers
https://domevents.dev/ a very useful interactive playground app that enables learning about the behavior of the DOM Event system through exploration.
https://www.quirksmode.org/js/events_order.html discussion of capturing and bubbling — an excellently detailed piece by Peter-Paul Koch.
https://www.quirksmode.org/js/events_access.html discussion of the event object — another excellently detailed piece by Peter-Paul Koch.
COPYRIGHT & LICENSE
Copyright(c) 2021 DEGUEST Pte. Ltd.
All rights reserved This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.