HTML::O...ntTarget(3)

๐Ÿ“ฆ version 0.6.0, in alpine 3.24

๐Ÿ’– HTML::Object::EventTarget(3) โ€” the event target chapter of your fave saga ๐ŸŽ€

okay so bestie, welcome to HTML::Object::EventTarget, aka the HTML Object Event Target Class โœจ this is part 1 of the page, so don't go anywhere, more is coming ๐Ÿซถ

It's a User Contributed Perl Documentation situation, and the page itself is HTML::Object::EventTarget(3) โ€” filing that here so you have it, iykyk ๐Ÿ’…


๐ŸŒธ NAME ๐ŸŒธ

HTML::Object::EventTarget โ€” the HTML Object Event Target Class, no cap ๐Ÿ’–


โœจ SYNOPSIS โœจ

okay so here's the whole vibe in code, copy it exactly, don't be out here improvising ๐Ÿ™ˆ

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 );

like, literally every single method you'd expect is in there โ€” addEventListener, dispatchEvent, getEventListeners, handleEvent, on, removeEventListener โ€” all present and accounted for ๐Ÿ‘‘ and yes bestie, that # also available as $_ comment is doing the lord's work, keep it ๐Ÿ’…


๐Ÿฆ‹ VERSION ๐Ÿฆ‹

v0.3.0

that's the version, periodt ๐Ÿ’œ


๐ŸŒˆ DESCRIPTION ๐ŸŒˆ

so this module represents an event target and handler โ€” that's the whole main character energy of it ๐Ÿ’–

it's implemented by HTML::Object::Document and HTML::Object::Element and its descendants, so like, it's the backbone the fam builds on ๐Ÿซถ

Of course, being perl, there is only limited support for events. ๐Ÿ˜ญ that's just the way it is, ngl โ€” perl's built different and it's doing its best, okay??


๐ŸŽ€ CONSTRUCTOR ๐ŸŽ€

๐Ÿ’ซ new ๐Ÿ’ซ

Creates a new HTML::Object::EventTarget object instance and returns it. that's it, that's the whole thing โ€” instantiate and slay โœจ๐Ÿ”ฅ


more parts incoming bestie, don't close the tab ๐Ÿงš๐Ÿ’œ

๐Ÿ’… METHODS ๐Ÿ’…

addEventListener

Okay so bestie, you hand this method a type, a callback, and optionally a hash or a hash reference of options, and it registers an event handler (that's just a callback subroutine, iykyk) for a specific event type on the EventTarget. Slay.

When an event gets "fired", your callback gets called, and the event object is passed in as its sole argument. Also, $_ is set to the current element object that the event got triggered on. Cute, right?

It returns the newly created HTML::Object::EventListener upon success, or undef in perlfunc upon error, and sets an error.

Possible options are the whole moment here:
  • capture โ€” a boolean value saying 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 the 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 on div2 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 to div2 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 to div2 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. Now doSomething1() 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 https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling_and_capture and this https://www.quirksmode.org/js/events_order.html

  • once โ€” a boolean value indicating that the listener should be invoked at most once after being added. If true, the listener gets automatically removed when invoked. One and done, periodt.
  • passive โ€” under perl this does literally 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 call preventDefault(), 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 it's a code reference (so, a subroutine reference or an anonymous subroutine) that gets called once the event handler has been set. It's 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, or TERM. The listener will be removed when the given signal is called. Iconic.

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 a subroutine name that lives 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 exist, it will return undef and set an error.

See for more information https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener


dispatchEvent

You give this one an event, and it dispatches the event to this EventTarget. Go little event, go ๐Ÿฆ‹

It will first call composedPath to get the branch from this current element all the way up to the top one, and it starts from the top in the capture phase, checking every element from top up to the current one, and calls handleEvent, which, in turn, checks 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 elements starting from the current element's parent up to the top one. handleEvent, in turn, checks if there are any event listeners registered for the element in question for the bubbling phase and calls 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. Deadass, it just stops.

The event current element is set each time, so you can check that to find out which one has cancelled it. Detective mode ๐Ÿ”

See for more information https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent

See also https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#bubbling_and_capturing_explained

event_listeners

Sets or gets a hash reference of all the event listeners registered. That's it, that's the whole vibe.

getEventListeners

Give it an event type, such as click, and it returns all the event listener objects registered 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 you provided one), or the total number of event listeners registered for all types. A little headcount, bestie ๐Ÿงš

on

This is a convenient method for setting event listeners. It's meant to be called by a class, like this:

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

Give it an event type, a callback code reference or a subroutine name (possibly including its package like MyPackage::my_sub), or an event listener object โ€” plus a hash or hash reference of options โ€” and this removes an event listener from the EventTarget. Bye bestie ๐Ÿ‘‹

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 you provide differ from the ones originally 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 });

See for more information https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener


๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Jacques Deguest <jack@deguest.jp>

โœจ SEE ALSO โœจ

okay bestie, you've made it to the reading list ๐Ÿ’– these are the links that'll actually make the DOM event system click for you โ€” go click through them, i'm literally begging ๐Ÿซถ

bestie note: those quirksmode pieces are old-school but the knowledge is chef's kiss โ€” Peter-Paul Koch is like the final boss of DOM events and he's on your side fr fr ๐Ÿ’œ

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. ๐Ÿ’– (yes, same terms as Perl โ€” go nuts, but respect the terms, periodt ๐ŸŒˆ)


and that's a wrap on the whole thing, bestie!! ๐ŸŽ‰ you read all three parts, you absolute legend, main character energy fr ๐Ÿ‘‘โœจ

perl v5.42.2 ยท 2026-02-15 ยท HTML::O...ntTarget(3) โ€” mwah, go forth and slay your event targets ๐Ÿ’…๐Ÿฆ‹๐ŸŒธ

๐Ÿ“ฆ where this page comes from