line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
##---------------------------------------------------------------------------- |
2
|
|
|
|
|
|
|
## HTML Object - ~/lib/HTML/Object/DOM/List.pm |
3
|
|
|
|
|
|
|
## Version v0.2.1 |
4
|
|
|
|
|
|
|
## Copyright(c) 2022 DEGUEST Pte. Ltd. |
5
|
|
|
|
|
|
|
## Author: Jacques Deguest <jack@deguest.jp> |
6
|
|
|
|
|
|
|
## Created 2021/12/28 |
7
|
|
|
|
|
|
|
## Modified 2022/11/11 |
8
|
|
|
|
|
|
|
## All rights reserved |
9
|
|
|
|
|
|
|
## |
10
|
|
|
|
|
|
|
## |
11
|
|
|
|
|
|
|
## This program is free software; you can redistribute it and/or modify it |
12
|
|
|
|
|
|
|
## under the same terms as Perl itself. |
13
|
|
|
|
|
|
|
##---------------------------------------------------------------------------- |
14
|
|
|
|
|
|
|
package HTML::Object::DOM::List; |
15
|
|
|
|
|
|
|
BEGIN |
16
|
|
|
|
|
|
|
{ |
17
|
1
|
|
|
1
|
|
978
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
44
|
|
18
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
30
|
|
19
|
1
|
|
|
1
|
|
5
|
use parent qw( HTML::Object::EventTarget ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
20
|
1
|
|
|
1
|
|
66
|
use vars qw( $VERSION ); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
21
|
1
|
|
|
1
|
|
6
|
use HTML::Object::Event; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
13
|
|
22
|
1
|
|
|
1
|
|
284
|
use Want; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
56
|
|
23
|
1
|
|
|
1
|
|
30
|
our $VERSION = 'v0.2.1'; |
24
|
|
|
|
|
|
|
}; |
25
|
|
|
|
|
|
|
|
26
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
19
|
|
27
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1069
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub init |
30
|
|
|
|
|
|
|
{ |
31
|
0
|
|
|
0
|
1
|
|
my $self = shift( @_ ); |
32
|
0
|
|
|
|
|
|
$self->{children} = []; |
33
|
0
|
|
|
|
|
|
$self->{_init_strict_use_sub} = 1; |
34
|
0
|
0
|
|
|
|
|
$self->SUPER::init( @_ ) || return( $self->pass_error ); |
35
|
0
|
|
|
|
|
|
return( $self ); |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# This method is called from the package inheriting from us |
39
|
|
|
|
|
|
|
# $def is a dictionary hash reference providing specifics in a crisp way about the types of events and related properties concerned |
40
|
|
|
|
|
|
|
# Example: |
41
|
|
|
|
|
|
|
# { |
42
|
|
|
|
|
|
|
# addtrack => { |
43
|
|
|
|
|
|
|
# add => { property => 'children', type => 'add', event => 'addtrack' }, |
44
|
|
|
|
|
|
|
# }, |
45
|
|
|
|
|
|
|
# change => { |
46
|
|
|
|
|
|
|
# add => { property => 'selected', type => 'add', event => 'change' }, |
47
|
|
|
|
|
|
|
# remove => { property => 'selected', type => 'remove', event => 'change' }, |
48
|
|
|
|
|
|
|
# }, |
49
|
|
|
|
|
|
|
# removetrack => { |
50
|
|
|
|
|
|
|
# remove => { property => 'children', type => 'remove', event => 'removetrack' }, |
51
|
|
|
|
|
|
|
# }, |
52
|
|
|
|
|
|
|
# } |
53
|
|
|
|
|
|
|
sub addEventListener |
54
|
|
|
|
|
|
|
{ |
55
|
0
|
|
|
0
|
1
|
|
my $self = shift( @_ ); |
56
|
0
|
0
|
|
|
|
|
return( $self->error( "I was expecting 3 arguments, but got only ", scalar( @_ ), "." ) ) if( scalar( @_ ) < 3 ); |
57
|
0
|
|
|
|
|
|
my $def = shift( @_ ); |
58
|
0
|
|
|
|
|
|
my $type = shift( @_ ); |
59
|
0
|
|
|
|
|
|
my $code = shift( @_ ); |
60
|
0
|
0
|
0
|
|
|
|
return( $self->error( "Dictionary provided is not an hash reference." ) ) if( !defined( $def ) || ref( $def ) ne 'HASH' ); |
61
|
0
|
0
|
0
|
|
|
|
return( $self->error( "Event type provided contains illegal characters." ) ) if( !defined( $type ) || $type !~ /^\w+#/ ); |
62
|
0
|
0
|
0
|
|
|
|
return( $self->error( "Callback is not a code reference." ) ) if( !defined( $code ) || !length( "$code" ) || ref( $code ) ne 'CODE' ); |
|
|
|
0
|
|
|
|
|
63
|
|
|
|
|
|
|
# Before we enable the event listener we must make sure we are listening on events on relevant array or scalar |
64
|
0
|
0
|
|
|
|
|
if( CORE::exists( $def->{ $type } ) ) |
65
|
|
|
|
|
|
|
{ |
66
|
0
|
|
|
|
|
|
my $ref = $def->{ $type }; |
67
|
|
|
|
|
|
|
# add or remove |
68
|
0
|
|
|
|
|
|
OP: foreach my $op ( keys( %$ref ) ) |
69
|
|
|
|
|
|
|
{ |
70
|
0
|
|
|
|
|
|
my $this = $ref->{ $op }; |
71
|
0
|
|
|
|
|
|
for( qw( property type ) ) |
72
|
|
|
|
|
|
|
{ |
73
|
0
|
0
|
0
|
|
|
|
if( !CORE::exists( $this->{ $_ } ) || !defined( $this->{ $_ } ) || !CORE::length( $this->{ $_ } ) ) |
|
|
0
|
0
|
|
|
|
|
74
|
|
|
|
|
|
|
{ |
75
|
0
|
0
|
|
|
|
|
warnings::warn( "Dictionary property \"$_\" is missing or empty.\n" ) if( warnings::enabled( 'HTML::Object' ) ); |
76
|
0
|
|
|
|
|
|
next OP; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
elsif( $_ ne 'add' && $_ ne 'remove' ) |
79
|
|
|
|
|
|
|
{ |
80
|
0
|
|
|
|
|
|
warnings::warn( "Unknown data listener type \"$_\"\n" ); |
81
|
0
|
|
|
|
|
|
next OP; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
my $subref = $self->can( $this->{property} ); |
86
|
0
|
0
|
|
|
|
|
if( !defined( $subref ) ) |
87
|
|
|
|
|
|
|
{ |
88
|
0
|
0
|
0
|
|
|
|
warnings::warn( "This object class \"" . ( ref( $self ) || $self ) . "\" does not support method \"" . $this->{property} . "\".\n" ) if( warnings::enabled( 'HTML::Object' ) ); |
89
|
0
|
|
|
|
|
|
next; |
90
|
|
|
|
|
|
|
} |
91
|
0
|
|
|
|
|
|
my $data = $subref->( $self ); |
92
|
0
|
0
|
0
|
|
|
|
if( !$self->_is_object( $data ) || !$data->can( 'callback' ) ) |
93
|
|
|
|
|
|
|
{ |
94
|
0
|
0
|
0
|
|
|
|
warnings::warn( "Object from class \"" . ( ref( $data ) || $data ) . "\" does not have a \"callback\" method.\n" ) if( warnings::enabled( 'HTML::Object' ) ); |
95
|
0
|
|
|
|
|
|
next; |
96
|
|
|
|
|
|
|
} |
97
|
0
|
|
|
|
|
|
my $cb = $data->callback( $this->{type} ); |
98
|
|
|
|
|
|
|
# Callback already exists |
99
|
0
|
0
|
0
|
|
|
|
next if( defined( $cb ) && ref( $cb ) ); |
100
|
|
|
|
|
|
|
$data->callback( $this->{type} => sub |
101
|
|
|
|
|
|
|
{ |
102
|
0
|
|
|
0
|
|
|
my $hash = shift( @_ ); |
103
|
0
|
|
|
|
|
|
my $event = $self->_make_event( $type ); |
104
|
0
|
0
|
0
|
|
|
|
if( CORE::exists( $this->{callback} ) && ref( $this->{callback} ) eq 'CODE' ) |
105
|
|
|
|
|
|
|
{ |
106
|
0
|
|
|
|
|
|
$this->{callback}->( $self, { event => $event, added => $hash->{added}, removed => $hash->{removed}, type => $hash->{type} }); |
107
|
|
|
|
|
|
|
} |
108
|
0
|
|
|
|
|
|
$self->dispatchEvent( $event ); |
109
|
0
|
|
|
|
|
|
}); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
} |
112
|
0
|
|
|
|
|
|
return( $self->SUPER::addEventListener( $type => $code ) ); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
|
0
|
1
|
|
sub forEach { return( shift->children->foreach( @_ ) ); } |
116
|
|
|
|
|
|
|
|
117
|
0
|
|
|
0
|
1
|
|
sub length { return( shift->children->length ); } |
118
|
|
|
|
|
|
|
|
119
|
0
|
|
|
0
|
1
|
|
sub push { return( shift->children->push( @_ ) ); } |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub _make_event |
122
|
|
|
|
|
|
|
{ |
123
|
0
|
|
|
0
|
|
|
my $self = shift( @_ ); |
124
|
0
|
|
|
|
|
|
my $type = shift( @_ ); |
125
|
0
|
|
0
|
|
|
|
my $event = HTML::Object::Event->new( $type, |
126
|
|
|
|
|
|
|
bubbles => 0, |
127
|
|
|
|
|
|
|
cancellable => 0, |
128
|
|
|
|
|
|
|
target => $self, |
129
|
|
|
|
|
|
|
) || return( $self->pass_error ); |
130
|
0
|
|
|
|
|
|
return( $event ); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub AUTOLOAD |
134
|
|
|
|
|
|
|
{ |
135
|
0
|
|
|
0
|
|
|
my( $name ) = our $AUTOLOAD =~ /([^:]+)$/; |
136
|
0
|
|
|
|
|
|
my $self = shift( @_ ); |
137
|
0
|
|
|
|
|
|
my $children = $self->children; |
138
|
0
|
0
|
0
|
|
|
|
die( "No method \"\$name\" in class \"", ( ref( $self ) || $self ), "\".\n" ) if( !$children ); |
139
|
0
|
|
|
|
|
|
my $code = $children->can( $name ); |
140
|
0
|
0
|
0
|
|
|
|
die( "No method \"\$name\" in class \"", ( ref( $children ) || $children ), "\".\n" ) if( !$code ); |
141
|
0
|
|
|
|
|
|
eval( "sub $name { return( shift->children->$name( \@_ ) ); }\n\n" ); |
142
|
0
|
|
|
|
|
|
return( $code->( $children, @_ ) ); |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
1; |
146
|
|
|
|
|
|
|
# NOTE: POD |
147
|
|
|
|
|
|
|
__END__ |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=encoding utf-8 |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head1 NAME |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
HTML::Object::DOM::List - HTML Object DOM List Abstract Class |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head1 SYNOPSIS |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
package HTML::Object::DOM::VideoTrackList; |
158
|
|
|
|
|
|
|
use parent qw( HTML::Object::DOM::List ); |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
my $list = HTML::Object::DOM::VideoTrackList->new || d |
161
|
|
|
|
|
|
|
ie( HTML::Object::DOM::VideoTrackList->error, "\n" ); |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=head1 VERSION |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
v0.2.1 |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head1 DESCRIPTION |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
This is an abstract class designed to be inherited by L<HTML::Object::DOM::TextTrackCueList>, L<HTML::Object::DOM::TextTrackList> and L<HTML::Object::DOM::VideoTrackList> |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
It inherits from L<HTML::Object::EventTarget> |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head1 INHERITANCE |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
+-----------------------+ +---------------------------+ +-------------------------+ |
176
|
|
|
|
|
|
|
| HTML::Object::Element | --> | HTML::Object::EventTarget | --> | HTML::Object::DOM::List | |
177
|
|
|
|
|
|
|
+-----------------------+ +---------------------------+ +-------------------------+ |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 METHODS |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head2 addEventListener |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
This is a variant from the usual C<addEventListener> from L<HTML::Object::EventTarget>. This method takes 3 arguments: |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=over 4 |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=item 1. A dictionary hash reference |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
This dictionary contains a key for each event name and another hash reference as their value. That hash reference contains the following properties: |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=over 8 |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=item callback |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
Optional property whose value is a code reference to be called after creating the event and before dispatching it with L<HTML::Object::EventTarget/dispatchEvent>. The purpose is to give it a chance to add some property value to the event like C<track> for L<HTML::Object::DOM::TrackEvent> fired by L<HTML::Object::DOM::TextTrackCueList>, L<HTML::Object::DOM::TextTrackList> and L<HTML::Object::DOM::VideoTrackList> |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=item event |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
The event name. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=item property |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
The module property or method name. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item type |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
The type of callback to set for this property. Possible values are: C<add> or C<remove> |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=back |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=item 2. An event type |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=item 3. An event handler callback |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=back |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
When C<addEventListener> is called, it will check if, for the given even type passed, there is an entry in the dictionary, and if there is it will enable an internal callback on the associated module property when there is any change to its underlying value. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
This relies on L<Module::Generic::Array/callback> and L<Module::Generic::Scalar/callback> |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
That internal callback will be called when a change occurs, and will create an L<event|HTML::Object::Event> of type C<type> and call L<HTML::Object::EventTarget/dispatchEvent> passing it the newly created event. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
If a C<callback> was specified in the dictionary for this event type, the callback code will be executed, and the whatever value added or removed will be passed to the callback as an hash reference and an hash property C<added> or C<removed> depending if the operation was to add or remove a value. |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
After having set this internal callback to monitor change, if any, this will call its parent L<addEventListener> to register the event listener. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head2 forEach |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
Calls C<foreach> on the array object returned by L<HTML::Object::Element/children> method. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=head2 length |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Returns the size of the list, starting from C<1>. |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head2 push |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Provided with some data and they will be appended to this list object. |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=head1 AUTHOR |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Jacques Deguest E<lt>F<jack@deguest.jp>E<gt> |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head1 SEE ALSO |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
L<HTML::Object::EventTarget>, L<HTML::Object::Event>, L<HTML::Object::DOM::TextTrackCueList>, L<HTML::Object::DOM::TextTrackCueList>, L<HTML::Object::DOM::VideoTrackList> |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Copyright(c) 2021 DEGUEST Pte. Ltd. |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
All rights reserved |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=cut |