File Coverage

lib/HTML/Object/DOM/Element/Select.pm
Criterion Covered Total %
statement 108 141 76.6
branch 24 56 42.8
condition 15 37 40.5
subroutine 25 34 73.5
pod 15 17 88.2
total 187 285 65.6


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## HTML Object - ~/lib/HTML/Object/DOM/Element/Select.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2021 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2021/12/23
7             ## Modified 2022/09/18
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::Element::Select;
15             BEGIN
16             {
17 2     2   2803 use strict;
  2         5  
  2         59  
18 2     2   11 use warnings;
  2         6  
  2         57  
19 2     2   10 use parent qw( HTML::Object::DOM::Element );
  2         3  
  2         11  
20 2     2   130 use vars qw( $VERSION );
  2         5  
  2         96  
21 2     2   524 use HTML::Object::DOM::Element::Shared qw( :select );
  2         5  
  2         499  
22 2     2   39 our $VERSION = 'v0.2.0';
23             };
24              
25 2     2   17 use strict;
  2         7  
  2         36  
26 2     2   9 use warnings;
  2         11  
  2         3228  
27              
28             sub init
29             {
30 1     1 1 90 my $self = shift( @_ );
31 1         144 $self->{_init_strict_use_sub} = 1;
32 1 50       11 $self->SUPER::init( @_ ) || return( $self->pass_error );
33 1 50       5 $self->{tag} = 'select' if( !CORE::length( "$self->{tag}" ) );
34 1         12 $self->{options} = [];
35 1         3 $self->{_select_reset} = 1;
36             my $callback = sub
37             {
38 9     9   1350 my $def = shift( @_ );
39             # Our children were modified from outside our package.
40             # We need to check if it affects our rows and reset the cache accordingly
41 9 100 66     80 unless( $def->{caller}->[0] eq ref( $self ) ||
42             $def->{caller}->[0] eq 'HTML::Object::DOM::Element::Select' )
43             {
44 7         26 $self->reset(1);
45             }
46 9         55 return(1);
47 1         6 };
48 1         5 $self->children->callback( add => $callback );
49 1         164 $self->children->callback( remove => $callback );
50 1         123 return( $self );
51             }
52              
53             sub add
54             {
55 1     1 1 104 my $self = shift( @_ );
56 1 50       6 return( $self->error({
57             message => sprintf( "At least 1 argument is required, but only %d was provided.", scalar( @_ ) ),
58             class => 'HTML::Object::SyntaxError',
59             }) ) if( scalar( @_ ) < 1 );
60 1         4 my( $elem, $pos ) = @_;
61 1 0 33     5 return( $self->error({
62             message => "Element provided is neither a HTML::Object::DOM::Element::Option object nor a HTML::Object::DOM::Element::OptGroup object.",
63             class => 'HTML::Object::TypeError',
64             }) ) if( !$self->_is_a( $elem => 'HTML::Object::DOM::Element::Option' ) && !$self->_is_a( $elem => 'HTML::Object::DOM::Element::OptGroup' ) );
65 1         48 my $options = $self->options;
66 1         12 my $size = $options->size;
67 1 50 33     40001 if( defined( $pos ) && CORE::length( $pos ) )
68             {
69 0 0 0     0 if( !$self->_is_a( $elem => 'HTML::Object::DOM::Element::Option' ) &&
    0 0        
70             !$self->_is_a( $elem => 'HTML::Object::DOM::Element::OptGroup' ) &&
71             !$self->_is_integer( $pos ) )
72             {
73 0         0 return( $self->error({
74             message => "The offset position before which to insert the element, if provided, must be an object or an integer, but I got '" . overload::StrVal( $pos ) . "'.",
75             class => 'HTML::Object::TypeError',
76             }) );
77             }
78             elsif( $self->_is_a( $elem => 'HTML::Object::DOM::Element::Option' ) ||
79             $self->_is_a( $elem => 'HTML::Object::DOM::Element::OptGroup' ) )
80             {
81             # Check if it is an ancestor, as per the specifications
82 0         0 my $lineage = $self->lineage;
83 0         0 my $lineagePos = $lineage->pos( $elem );
84 0 0       0 if( defined( $lineagePos ) )
85             {
86 0         0 return( $self->error({
87             message => "Element to be added to this select element is an ancestor.",
88             class => 'HTML::Object::HierarchyRequestError',
89             }) );
90             }
91            
92 0         0 my $tmpPos = $options->pos( $elem );
93 0 0       0 if( defined( $tmpPos ) )
94             {
95 0         0 $pos = $tmpPos;
96             }
97             else
98             {
99 0         0 undef( $pos );
100             }
101             }
102             else
103             {
104 0 0       0 if( $pos < 0 )
    0          
105             {
106 0         0 $pos = $pos + $size;
107             }
108             elsif( $pos > $size )
109             {
110 0         0 undef( $pos );
111             }
112             }
113             }
114 1         14 $elem->detach;
115 1         4 $elem->parent( $self );
116 1         31 my $children = $self->children;
117 1 50 33     74 if( defined( $pos ) && CORE::length( $pos ) )
118             {
119 0         0 my $kid = $options->index( $pos );
120 0         0 my $real_pos = $children->pos( $kid );
121 0         0 $children->splice( $real_pos, 0, $elem );
122             }
123             else
124             {
125 1         6 $children->push( $elem );
126             }
127 1         16 $self->reset(1);
128 1         6 return( $self );
129             }
130              
131             # Note: property autofocus
132 0     0 1 0 sub autofocus : lvalue { return( shift->_set_get_property( 'autofocus', @_ ) ); }
133              
134 0     0 1 0 sub blur { return; }
135              
136             # Note: method checkValidity is inherited
137              
138             # Note: property disabled is inherited
139              
140 0     0 1 0 sub focus { return; }
141              
142             # Note: property form read-only is inherited
143              
144 1     1 1 1097 sub item { return( shift->options->index( @_ ) ); }
145              
146             # Note: property labels read-only is inherited
147              
148             # Note: property length
149 0     0 1 0 sub length : lvalue { return( shift->_set_get_property( 'length', @_ ) ); }
150              
151             # Note: property multiple
152 0     0 1 0 sub multiple : lvalue { return( shift->_set_get_property( 'multiple', @_ ) ); }
153              
154             # Note: property name is inherited
155              
156             # Note: method namedItem is inherited from HTML::Object::DOM::Collection
157 1     1 1 1125 sub namedItem { return( shift->options->namedItem( @_ ) ); }
158              
159 0     0 0 0 sub onchange : lvalue { return( shift->on( 'change', @_ ) ); }
160              
161 0     0 0 0 sub oninput : lvalue { return( shift->on( 'input', @_ ) ); }
162              
163             # Note: property options read-only
164             # sub options { return( shift->_set_get_object( 'options', 'HTML::Object::DOM::Element::OptionsCollection', @_ ) ); }
165             sub options
166             {
167 35     35 1 4495 my $self = shift( @_ );
168 35 100 100     175 return( $self->{_select_options} ) if( $self->{_select_options} && !$self->_is_select_reset );
169 20     64   81 my $list = $self->children->grep(sub{ $self->_is_a( $_ => 'HTML::Object::DOM::Element::Option' ) });
  64         2833  
170             # The content of the collection is refreshed, but the collection object itself does not change, so the user can poll it
171 20 100       2730 unless( $self->{_select_options} )
172             {
173 1 50       11 $self->_load_class( 'HTML::Object::DOM::Element::OptionsCollection' ) || return( $self->pass_error );
174 1   50     59 $self->{_select_options} = HTML::Object::DOM::Element::OptionsCollection->new ||
175             return( $self->pass_error( HTML::Object::DOM::Element::OptionsCollection->error ) );
176             }
177 20         95 $self->{_select_options}->set( $list );
178 20         302 $self->_remove_select_reset;
179 20         86 return( $self->{_select_options} );
180             }
181              
182             sub remove
183             {
184 1     1 1 41621 my $self = shift( @_ );
185 1         3 my $pos = shift( @_ );
186 1 50 33     24 return( $self->error({
      33        
187             message => "Index value provided ($pos) is not an integer",
188             class => 'HTML::Object::IndexSizeError',
189             }) ) if( !defined( $pos ) || !CORE::length( "$pos" ) || !$self->_is_integer( $pos ) );
190 1         19 my $options = $self->options;
191 1 50       6 return( $self->error({
192             message => "Index value provided ($pos) is greater than the zero-based total number of options.",
193             class => 'HTML::Object::IndexSizeError',
194             }) ) if( $pos > $options->size );
195 1         40043 my $elem = $options->index( $pos );
196 1         191 my $real_pos = $self->children->pos( $elem );
197 1 50       145 return( $self->error({
198             message => "Could not find the real index position of element found at offset '$pos'.",
199             class => 'HTML::Object::HierarchyRequestError',
200             }) ) if( !defined( $real_pos ) );
201 1         5 $self->children->splice( $real_pos, 1 );
202 1         17 $elem->parent( undef );
203 1         27 $self->reset(1);
204 1         5 return( $elem );
205             }
206              
207             # Note: method reportValidity is inherited
208              
209             # Note: property required is inherited
210              
211             sub reset
212             {
213 68     68 1 167 my $self = shift( @_ );
214 68 100       183 if( scalar( @_ ) )
215             {
216 20         80 $self->_reset_select;
217             # Force the rebuilding of the collection of selected options
218 20         56 CORE::delete( $self->{_selected_options} );
219 20         39 CORE::delete( $self->{selectedindex} );
220 20         83 return( $self->SUPER::reset( @_ ) );
221             }
222 48         181 return( $self );
223             }
224              
225             # Note: property selectedIndex
226             # This is called by the HTML::Object::DOM::Element::Option when selected
227             # sub selectedIndex : lvalue { return( shift->_set_get_number( 'selectedindex', @_ ) ); }
228             sub selectedIndex : lvalue { return( shift->_lvalue({
229             set => sub
230             {
231 0     0   0 my( $self, $val ) = @_;
232 0 0       0 return( $self->error({
233             message => "Index value provided is not an integer.",
234             class => 'HTML::Object::TypeError',
235             }) ) if( !$self->_is_integer( $val ) );
236 0         0 my $options = $self->options;
237 0 0       0 return( $self->error({
238             message => "Index value provided is greater than the zero-based total number (" . $options->size . ") of options available.",
239             class => 'HTML::Object::IndexSizeError',
240             }) ) if( $val > $options->size );
241 0         0 $self->{selectedindex} = $val;
242 0         0 my $elem = $options->index( $val );
243 0 0       0 return( $self->error({
244             message => "Somehow, the element found at position $val is not an HTML::Object::DOM::Element::Option object.",
245             class => 'HTML::Object::HierarchyRequestError',
246             }) ) if( !$self->_is_a( $elem => 'HTML::Object::DOM::Element::Option' ) );
247 0         0 $elem->defaultSelected = 1;
248 0         0 return( $elem );
249             },
250             get => sub
251             {
252 2     2   1206 my $self = shift( @_ );
253 2 50 33     21 return( $self->{selectedindex} ) if( $self->{selectedindex} && !$self->_is_select_reset );
254             # Get all options
255 2         8 my $options = $self->options;
256             # Get all selected ones; could be empty
257 2         11 my $selected = $self->selectedOptions;
258 2 100       16 return if( $selected->is_empty );
259             # Get the first selected one
260 1         25 my $elem = $selected->index(0);
261             # Find its index position among all options
262 1         66 my $pos = $options->pos( $elem );
263             # and return it.
264 1         31 return( $self->{selectedindex} = $pos );
265             },
266 2     2 1 81796 }, @_ ) ); }
267              
268             # Note: property selectedOptions read-only
269             sub selectedOptions
270             {
271 4     4 1 42457 my $self = shift( @_ );
272 4 100 66     20 return( $self->{_selected_options} ) if( $self->{_selected_options} && !$self->_is_select_reset );
273 2     6   6 my $list = $self->options->filter(sub{ $_->defaultSelected });
  6         3515  
274             $self->children->for(sub
275             {
276 14     14   568 my( $i, $elem ) = @_;
277            
278 2         1877 });
279             # The content of the collection is refreshed, but the collection object itself does not change, so the user can poll it
280 2 50       53 unless( $self->{_selected_options} )
281             {
282 2 50       9 $self->_load_class( 'HTML::Object::DOM::Collection' ) || return( $self->pass_error );
283 2   50     94 $self->{_selected_options} = HTML::Object::DOM::Collection->new ||
284             return( $self->pass_error( HTML::Object::DOM::Collection->error ) );
285             }
286 2         11 $self->{_selected_options}->set( $list );
287 2         103 $self->_remove_select_reset;
288 2         14 return( $self->{_selected_options} );
289             }
290              
291             # Note: method setCustomValidity is inherited
292              
293             # Note: property size
294 0     0 1 0 sub size : lvalue { return( shift->_set_get_property( 'size', @_ ) ); }
295              
296             # Note: property type read-only is inherited
297              
298             # Note: property validationMessage read-only is inherited
299              
300             # Note: property validity read-only is inherited
301              
302             # Note: property value is inherited
303              
304             # Note: property willValidate read-only is inherited
305              
306 36     36   300 sub _is_select_reset { return( CORE::length( shift->{_select_reset} ) ); }
307              
308 22     22   61 sub _remove_select_reset { return( CORE::delete( shift->{_select_reset} ) ); }
309              
310             sub _reset_select
311             {
312 20     20   34 my $self = shift( @_ );
313 20         54 $self->{_select_reset}++;
314             # Force it to recompute
315 20         62 $self->options;
316 20         177 return( $self );
317             }
318              
319             1;
320             # NOTE: POD
321             __END__
322              
323             =encoding utf-8
324              
325             =head1 NAME
326              
327             HTML::Object::DOM::Element::Select - HTML Object DOM Select Class
328              
329             =head1 SYNOPSIS
330              
331             use HTML::Object::DOM::Element::Select;
332             my $select = HTML::Object::DOM::Element::Select->new ||
333             die( HTML::Object::DOM::Element::Select->error, "\n" );
334              
335             =head1 VERSION
336              
337             v0.2.0
338              
339             =head1 DESCRIPTION
340              
341             This interface represents a C<<select>> HTML Element. These elements also share all of the properties and methods of other HTML elements via the L<HTML::Object::DOM::Element> interface.
342              
343             =head1 INHERITANCE
344              
345             +-----------------------+ +---------------------------+ +-------------------------+ +----------------------------+ +------------------------------------+
346             | HTML::Object::Element | --> | HTML::Object::EventTarget | --> | HTML::Object::DOM::Node | --> | HTML::Object::DOM::Element | --> | HTML::Object::DOM::Element::Select |
347             +-----------------------+ +---------------------------+ +-------------------------+ +----------------------------+ +------------------------------------+
348              
349             =head1 PROPERTIES
350              
351             Inherits properties from its parent L<HTML::Object::DOM::Element>
352              
353             =head2 autofocus
354              
355             A boolean value reflecting the autofocus L<HTML attribute|HTML::Object::DOM::Attribute>, which indicates whether the control should have input focus when the page loads, unless the user overrides it, for example by typing in a different control. Only one form-associated element in a document can have this attribute specified.
356              
357             Example:
358              
359             <select id="mySelect" autofocus>
360             <option>Option 1</option>
361             <option>Option 2</option>
362             </select>
363              
364             # Check if the autofocus attribute on the <select>
365             my $hasAutofocus = $doc->getElementById('mySelect')->autofocus;
366              
367             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/autofocus>
368              
369             =head2 disabled
370              
371             A boolean value reflecting the disabled L<HTML attribute|HTML::Object::DOM::Attribute>, which indicates whether the control is disabled. If it is disabled, it does not accept clicks.
372              
373             Example:
374              
375             <label>
376             Allow drinks?
377             <input id="allow-drinks" type="checkbox" />
378             </label>
379              
380             <label for="drink-select">Drink selection:</label>
381             <select id="drink-select" disabled>
382             <option value="1">Water</option>
383             <option value="2">Beer</option>
384             <option value="3">Pepsi</option>
385             <option value="4">Whisky</option>
386             </select>
387              
388             my $allowDrinksCheckbox = $doc->getElementById( 'allow-drinks' );
389             my $drinkSelect = $doc->getElementById( 'drink-select' );
390              
391             $allowDrinksCheckbox->addEventListener( change => sub
392             {
393             if( $event->target->checked )
394             {
395             $drinkSelect->disabled = 0; # false
396             }
397             else
398             {
399             $drinkSelect->disabled = 1; # true
400             }
401             }, { capture => 0});
402              
403             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/disabled>
404              
405             =head2 form
406              
407             Read-only.
408              
409             An L<HTML::Object::DOM::Element::Form> referencing the form that this element is associated with. If the element is not associated with of a <form> element, then it returns C<undef>.
410              
411             Example:
412              
413             <form id="pet-form">
414             <label for="pet-select">Choose a pet</label>
415             <select name="pets" id="pet-select">
416             <option value="dog">Dog</option>
417             <option value="cat">Cat</option>
418             <option value="parrot">Parrot</option>
419             </select>
420              
421             <button type="submit">Submit</button>
422             </form>
423              
424             <label for="lunch-select">Choose your lunch</label>
425             <select name="lunch" id="lunch-select">
426             <option value="salad">Salad</option>
427             <option value="sandwich">Sandwich</option>
428             </select>
429              
430             my $petSelect = $doc->getElementById( 'pet-select' );
431             my $petForm = $petSelect->form; # <form id="pet-form">
432              
433             my $lunchSelect = $doc->getElementById( 'lunch-select' );
434             my $lunchForm = $lunchSelect->form; # undef
435              
436             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/form>
437              
438             =head2 labels
439              
440             Read-only.
441              
442             A L<HTML::Object::DOM::NodeList> of L<label elements|HTML::Object::DOM::Element::Label> associated with the element.
443              
444             Example:
445              
446             <label id="label1" for="test">Label 1</label>
447             <select id="test">
448             <option value="1">Option 1</option>
449             <option value="2">Option 2</option>
450             </select>
451             <label id="label2" for="test">Label 2</label>
452              
453             window->addEventListener( DOMContentLoaded => sub
454             {
455             my $select = $doc->getElementById( 'test' );
456             for( my $i = 0; $i < $select->labels->length; $i++ )
457             {
458             say( $select->labels->[$i]->textContent ); # "Label 1" and "Label 2"
459             }
460             });
461              
462             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/labels>
463              
464             =head2 length
465              
466             An unsigned long that reflects the number of L<option elements|HTML::Object::DOM::Element::Option> in this select element.
467              
468             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/length>
469              
470             =head2 multiple
471              
472             A boolean value reflecting the multiple L<HTML attribute|HTML::Object::DOM::Attribute>, which indicates whether multiple items can be selected.
473              
474             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/multiple>
475              
476             =head2 name
477              
478             A string reflecting the name L<HTML attribute|HTML::Object::DOM::Attribute>, containing the name of this control used by servers and DOM search functions.
479              
480             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/name>
481              
482             =head2 options
483              
484             Read-only.
485              
486             An L<OptionsCollection|HTML::Object::DOM::Element::OptionsCollection> representing the set of L<option elements|HTML::Object::DOM::Element::Option> contained by this element.
487              
488             Example:
489              
490             <label for="test">Label</label>
491             <select id="test">
492             <option value="1">Option 1</option>
493             <option value="2">Option 2</option>
494             </select>
495              
496             window->addEventListener( DOMContentLoaded => sub
497             {
498             my $select = $doc->getElementById( 'test' );
499             for( my $i = 0; $i < $select->options->length; $i++ )
500             {
501             say( $select->options->[$i]->label ); # "Option 1" and "Option 2"
502             }
503             });
504              
505             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/options>
506              
507             =head2 required
508              
509             A boolean value reflecting the required L<HTML attribute|HTML::Object::DOM::Attribute>, which indicates whether the user is required to select a value before submitting the form.
510              
511             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/required>
512              
513             =head2 selectedIndex
514              
515             A long reflecting the index of the first selected L<option element|HTML::Object::DOM::Element::Option>. The value C<undef> indicates no element is selected.
516              
517             Example:
518              
519             <p id="p">selectedIndex: 0</p>
520             <select id="select">
521             <option selected>Option A</option>
522             <option>Option B</option>
523             <option>Option C</option>
524             <option>Option D</option>
525             <option>Option E</option>
526             </select>
527              
528             my $selectElem = $doc->getElementById('select');
529             my $pElem = $doc->getElementById('p');
530              
531             # When a new <option> is selected
532             $selectElem->addEventListener( change => sub
533             {
534             my $index = $selectElem->selectedIndex;
535             # Add that data to the <p>
536             $pElem->innerHTML = 'selectedIndex: ' . $index;
537             })
538              
539             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/selectedIndex>
540              
541             =head2 selectedOptions
542              
543             Read-only.
544              
545             An L<Collection|HTML::Object::DOM::Collection> representing the set of L<option elements|HTML::Object::DOM::Element::Option> that are selected.
546              
547             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/selectedOptions>
548              
549             =head2 size
550              
551             A long reflecting the size L<HTML attribute|HTML::Object::DOM::Attribute>, which contains the number of visible items in the control. The default is 1, unless multiple is true, in which case it is 4.
552              
553             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/size>
554              
555             =head2 type
556              
557             Read-only.
558              
559             A string represeting the form control's type. When multiple is true, it returns C<select-multiple>; otherwise, it returns C<select-one>.
560              
561             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/type>
562              
563             =head2 validationMessage
564              
565             Read-only.
566              
567             A string representing a localized message that describes the validation constraints that the control does not satisfy (if any). This attribute is the empty string if the control is not a candidate for constraint validation (willValidate is false), or it satisfies its constraints.
568              
569             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/validationMessage>
570              
571             =head2 validity
572              
573             Read-only.
574              
575             A L<ValidityState|HTML::Object::DOM::ValidityState> object reflecting the validity state that this control is in.
576              
577             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/validity>
578              
579             =head2 value
580              
581             A string reflecting the value of the form control. Returns the value property of the first selected option element if there is one, otherwise the empty string.
582              
583             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/value>
584              
585             =head2 willValidate
586              
587             Read-only.
588              
589             A boolean value that indicates whether the button is a candidate for constraint validation. It is false if any conditions bar it from constraint validation.
590              
591             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/willValidate>
592              
593             =head1 METHODS
594              
595             Inherits methods from its parent L<HTML::Object::DOM::Element>
596              
597             =head2 add
598              
599             Provided with an C<item> and optionally an position offset C<before> which to insert the item and this adds an element to the collection of option elements for this select element.
600              
601             =over 4
602              
603             =item C<item> is an L<Option element|HTML::Object::DOM::Element::Option> or L<OptGroup element|HTML::Object::DOM::Element::OptGroup>
604              
605             =item C<before> is optional and an element of the collection, or an index of type long, representing the item should be inserted before. If this parameter is C<undef> (or the index does not exist), the new element is appended to the end of the collection.
606              
607             =back
608              
609             Example:
610              
611             my $sel = $doc->createElement( 'select' );
612             my $opt1 = $doc->createElement( 'option' );
613             my $opt2 = $doc->createElement( 'option' );
614              
615             $opt1->value = 1;
616             $opt1->text = "Option: Value 1";
617              
618             $opt2->value = 2;
619             $opt2->text = "Option: Value 2";
620              
621             # No second argument; no 'before' argument
622             $sel->add( $opt1, undef );
623             # Equivalent to above
624             $sel->add( $opt2 );
625              
626             Produces the following, conceptually:
627              
628             <select>
629             <option value="1">Option: Value 1</option>
630             <option value="2">Option: Value 2</option>
631             </select>
632              
633             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/add>
634              
635             =head2 blur
636              
637             Under perl, of course, this does nothing.
638              
639             Under JavaScript, this removes the input focus from this element. This method is now implemented on L<HTML::Object::DOM::Element>.
640              
641             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/blur>
642              
643             =head2 checkValidity
644              
645             Checks whether the element has any constraints and whether it satisfies them. If the element fails its constraints, the browser fires a cancelable invalid event at the element (and returns false).
646              
647             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/checkValidity>
648              
649             =head2 focus
650              
651             Under perl, of course, this does nothing.
652              
653             Under JavaScript, this gives input focus to this element. This method is now implemented on L<HTML::Object::DOM::Element>.
654              
655             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/focus>
656              
657             =head2 item
658              
659             Gets an item from the options collection for this L<select element|HTML::Object::DOM::Select> by providing a zero-based index position.
660              
661             Example:
662              
663             <select id="myFormControl">
664             <option id="o1">Opt 1</option>
665             <option id="o2">Opt 2</option>
666             </select>
667              
668             # Returns the OptionElement representing #o2
669             my $sel = $doc->getElementById( 'myFormControl' );
670             my $elem1 = $sel->item(1); # Opt 2
671              
672             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/item>
673              
674             =head2 namedItem
675              
676             Gets the item in the options collection with the specified name. The name string can match either the id or the name attribute of an option node.
677              
678             Example:
679              
680             <select id="myFormControl">
681             <option id="o1">Opt 1</option>
682             <option id="o2">Opt 2</option>
683             </select>
684              
685             my $elem1 = $doc->getElementById( 'myFormControl' )->namedItem( 'o1' ); # Returns the OptionElement representing #o1
686              
687             This is, in effect, a shortcut for C<$select->options->namedItem>
688              
689             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/namedItem>
690              
691             =head2 remove
692              
693             Removes the element at the specified index (zero-based) from the options collection for this select element and return it.
694              
695             Example:
696              
697             <select id="existingList" name="existingList">
698             <option value="1">Option: Value 1</option>
699             <option value="2">Option: Value 2</option>
700             <option value="3">Option: Value 3</option>
701             </select>
702              
703             my $sel = $doc->getElementById( 'existingList' );
704             my $removed = $sel->remove(1);
705              
706             HTML is now:
707              
708             <select id="existingList" name="existingList">
709             <option value="1">Option: Value 1</option>
710             <option value="3">Option: Value 3</option>
711             </select>
712              
713             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/remove>
714              
715             =head2 reportValidity
716              
717             This method reports the problems with the constraints on the element, if any, to the user. If there are problems, it fires a cancelable invalid event at the element, and returns false; if there are no problems, it returns true.
718              
719             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/reportValidity>
720              
721             =head2 setCustomValidity
722              
723             Sets the custom validity message for the selection element to the specified message. Use the empty string to indicate that the element does not have a custom validity error.
724              
725             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/setCustomValidity>
726              
727             =head1 EVENTS
728              
729             Event listeners for those events can also be found by prepending C<on> before the event type:
730              
731             C<click> event listeners can be set also with C<onclick> method:
732              
733             $e->onclick(sub{ # do something });
734             # or as an lvalue method
735             $e->onclick = sub{ # do something };
736              
737             Note that, under perl, almost no event are fired, but you can trigger them yourself.
738              
739             =head2 change
740              
741             Fires when the user selects an option, but since there is no user interaction, this event is fired when the C<selectedIndex> value changes, which you can change yourself.
742              
743             Example:
744              
745             <label>Choose an ice cream flavor:
746             <select class="ice-cream" name="ice-cream">
747             <option value="">Select One …</option>
748             <option value="chocolate">Chocolate</option>
749             <option value="sardine">Sardine</option>
750             <option value="vanilla">Vanilla</option>
751             </select>
752             </label>
753              
754             <div class="result"></div>
755              
756             my $selectElement = $doc->querySelector('.ice-cream');
757              
758             $selectElement->addEventListener( change => sub
759             {
760             my $result = $doc->querySelector( '.$result' );
761             $result->textContent = "You like " . $event->target->value;
762             });
763              
764             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event>
765              
766             =head2 input
767              
768             Fires when the value of an <input>, <select>, or <textarea> element has been changed.
769              
770             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event>
771              
772             =head2 reset
773              
774             Reset the cache flag so that some data will be recomputed. The cache is design to avoid doing useless computing repeatedly when there is no change of data.
775              
776             =head1 AUTHOR
777              
778             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
779              
780             =head1 SEE ALSO
781              
782             L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement>, L<Mozilla documentation on select element|https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select>
783              
784             =head1 COPYRIGHT & LICENSE
785              
786             Copyright(c) 2021 DEGUEST Pte. Ltd.
787              
788             All rights reserved
789              
790             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
791              
792             =cut