File Coverage

blib/lib/WWW/Mechanize/Plugin/DOM/Window.pm
Criterion Covered Total %
statement 68 222 30.6
branch 0 56 0.0
condition 0 25 0.0
subroutine 22 65 33.8
pod 18 19 94.7
total 108 387 27.9


line stmt bran cond sub pod time code
1             package WWW::Mechanize::Plugin::DOM::Window;
2              
3 2     2   13 use strict; use warnings; no warnings qw 'utf8 parenthesis';
  2     2   4  
  2     2   83  
  2         11  
  2         4  
  2         68  
  2         10  
  2         3  
  2         113  
4              
5             our $VERSION = '0.014';
6              
7 2     2   12 use Hash::Util::FieldHash::Compat 'fieldhash';
  2         3  
  2         28  
8 2     2   2256 use HTML::DOM::Interface 0.019 ':all';
  2         11333  
  2         467  
9 2     2   19 use HTML::DOM::NodeList::Magic;
  2         5  
  2         60  
10 2     2   1797 use HTML::DOM::View 0.018;
  2         1054  
  2         56  
11 2     2   14 use Scalar::Util 'weaken';
  2         2  
  2         94  
12 2     2   3035 use Time::HiRes 'time';
  2         3665  
  2         10  
13              
14             our @ISA = qw[ HTML::DOM::View
15             HTML::DOM::EventTarget ];
16              
17 2     2   448 no constant 1.03 ();
  2         42  
  2         106  
18 2         7 use constant::lexical +{ do {
19 2         4 my $x; map +($_=>$x++), qw[
  2         37  
20             lert cnfm prmp loco meck topp frms prnt
21             ] # we use ‘meck’ so as not to conflict with the method
22 2     2   1710 }};
  2         12291  
23              
24 2     2   416 use overload fallback=>1, (qw/@{} %{}/, ('_frames_collection')x2)[0,3,1,2];
  2         25  
  2         26  
25              
26             fieldhash my %timeouts; # keyed by document
27             fieldhash my %navi; # keyed by mech
28              
29             # This does not follow the same format as %HTML::DOM::Interface; this cor-
30             # responds to the format of hashes *within* %H:D:I. The other format does
31             # not apply here, since we can’t bind the class like other classes. This
32             # needs to be bound to the global object (at least in JavaScript).
33             our %Interface = (
34             %{$HTML::DOM::Interface{AbstractView}},
35             %{$HTML::DOM::Interface{EventTarget}},
36             alert => VOID|METHOD,
37             confirm => BOOL|METHOD,
38             prompt => STR|METHOD,
39             location => OBJ,
40             setTimeout => NUM|METHOD,
41             clearTimeout => NUM|METHOD,
42             open => OBJ|METHOD,
43             window => OBJ|READONLY,
44             self => OBJ|READONLY,
45             navigator => OBJ|READONLY,
46             top => OBJ|READONLY,
47             frames => OBJ|READONLY,
48             length => NUM|READONLY,
49             parent => OBJ|READONLY,
50             );
51              
52             sub new {
53 0     0 0   my $self = bless\[], shift;
54 0           weaken($$self->[meck] = my $mech = shift);
55 0           $$self->[loco] = ('WWW::Mechanize::Plugin::DOM::Location')->new(
56             $mech
57             );
58 0           $self;
59             }
60              
61             sub alert {
62 0     0 1   my $self = shift;
63 0 0   0     &{$$self->[lert]||sub{print @_,"\n";()}}(@_);
  0            
  0            
  0            
64             }
65             sub confirm {
66 0     0 1   my $self = shift;
67 0   0       ($$self->[cnfm]||$$self->[meck]->die(
68             "There is no default confirm function"
69             ))->(@_)
70             }
71             sub prompt {
72 0     0 1   my $self = shift;
73 0   0       ($$self->[prmp]||$$self->[meck]->die(
74             "There is no default prompt function"
75             ))->(@_)
76             }
77              
78 0     0 1   sub set_alert_function { $${$_[0]}[lert] = $_[1]; }
  0            
79 0     0 1   sub set_confirm_function { $${$_[0]}[cnfm] = $_[1]; }
  0            
80 0     0 1   sub set_prompt_function { $${$_[0]}[prmp] = $_[1]; }
  0            
81              
82             sub location {
83 0     0 1   my $self = shift;
84 0 0         $$self->[loco]->href(@_) if @_;
85 0           $$self->[loco];
86             }
87              
88             sub navigator {
89 0     0 1   my $mech = ${+shift}->[meck];
  0            
90 0   0       $navi{$mech} ||=
91             new WWW::Mechanize::Plugin::DOM::Navigator:: $mech;
92             }
93              
94             sub setTimeout {
95 0     0 1   my $doc = shift->document;
96 0           my $time = time;
97 0           my ($code, $ms) = @_;
98 0           $ms /= 1000;
99 0   0       my $t_o = $timeouts{$doc}||=[];
100 0           $$t_o[my $id = @$t_o] =
101             [$ms+$time, $code];
102 0           return $id;
103             }
104              
105             sub clearTimeout {
106 0     0 1   delete $timeouts{shift->document}[shift];
107 0           return;
108             }
109              
110             sub open {
111 0     0 1   ${+shift}->[meck]->get(shift);
  0            
112             # ~~~ Just a placeholder for now.
113 0           return;
114             }
115              
116             # ~~~ This really doesn’t belong here, but in DOM.pm. But it needs to
117             # access the same info as the timeout methods above. Maybe those should
118             # delegate to DOM.pm methods.
119             sub _check_timeouts {
120 0     0     my $time = time;
121 0           my $self = shift;
122 0           local *_;
123 0   0       my $t_o = $timeouts{$self->document}||return;
124 0           for my $id(0..$#$t_o) {
125 0 0         next unless $_ = $$t_o[$id];
126 0 0 0       $$_[0] <= $time and
127             ($$self->[meck]->plugin('JavaScript')||return)
128             ->eval($$_[1]),
129             delete $$t_o[$id];
130             }
131             return
132 0           }
133              
134             # ~~~ This may be moved to Plugin::DOM proper later.
135             sub _count_timers {
136 0     0     my $self = shift;
137 0   0       my $t_o = $timeouts{$self->document}||return 0;
138 0           my $count;
139 0           for my $id(0..$#$t_o) {
140 0 0         next unless $_ = $$t_o[$id];
141 0           ++$count
142             }
143 0           $count;
144             }
145              
146 0     0 1   sub window { $_[0] }
147             *self = *frames = *window;
148 0     0 1   sub length { $_[0]->_frames_collection->length }
149              
150             sub top {
151 0     0 1   my $self = shift;
152 0 0         $$self->[topp] || do {
153 0           my $parent = $self;
154 0           while() {
155 0 0         $$parent->[prnt] or
156             weaken( $$self->[topp] = $parent), last;
157 0           $parent = $$parent->[prnt];
158             }
159 0           $$self->[topp]
160             };
161             }
162              
163             sub parent {
164 0     0 1   my $self = shift;
165 0 0         $$self->[prnt] || $self;
166             }
167              
168 0     0     sub _set_parent { weaken( ${$_[0]}->[prnt] = $_[1] ) }
  0            
169              
170             sub event_listeners_enabled {
171 0     0 1   ${+shift}->[meck]->plugin("DOM")->scripts_enabled
  0            
172             }
173              
174             sub _frames_collection {
175 0     0     my $self = shift;
176 0   0       $$self->[frms] ||= do{
177 0           my $doc = $self->document;
178             WWW::Mechanize::Plugin::DOM::Frames->new(
179             HTML::DOM::NodeList::Magic->new(
180 0     0     sub { $doc->look_down(_tag => qr/^i?frame\z/) },
181 0           $doc
182             ))
183             }
184             }
185              
186             # ~~~ Will we need this?
187             #sub _reset_frames_collection { delete ${+shift}->[frms] }
188              
189             sub document {
190 0     0 1   my $self = shift;
191 0 0         @_ || return $self->SUPER::document;
192 0           delete $$self->[frms];
193 0           $self->SUPER::document(@_);
194             }
195              
196 0     0 1   sub mech { $${+shift}[meck] }
  0            
197              
198              
199             package WWW::Mechanize::Plugin::DOM::Location;
200              
201 2     2   4115 use URI;
  2         5  
  2         58  
202 2     2   13 use HTML::DOM::Interface qw'STR METHOD VOID';
  2         3  
  2         185  
203 2     2   14 use Scalar::Util 'weaken';
  2         4  
  2         319  
204              
205             our $VERSION = '0.014';
206              
207 2     2   13 use overload fallback => 1, '""' => sub{${+shift}->uri};
  2     0   5  
  2         18  
  0         0  
  0         0  
208              
209             $$_{~~__PACKAGE__} = 'Location',
210             $$_{Location} = {
211             hash => STR,
212             host => STR,
213             hostname => STR,
214             href => STR,
215             pathname => STR,
216             port => STR,
217             protocol => STR,
218             search => STR,
219             reload => VOID|METHOD,
220             replace => VOID|METHOD,
221             }
222             for \%WWW::Mechanize::Plugin::DOM::Interface;
223              
224             sub new { # usage: new .....::Location $uri, $mech
225 0     0     my $class = shift;
226 0           weaken (my $mech = shift);
227 0           my $self = bless \$mech, $class;
228 0           $self;
229             }
230              
231             sub hash {
232 0     0     my $loc = shift;
233 0           my $old = (my $uri = $$loc->uri)->fragment;
234 0 0         $old = "#$old" if defined $old;
235 0 0         if (@_){
236 0           shift() =~ /#?(.*)/s;
237 0           (my $uri_copy = $uri->clone)->fragment($1);
238 0 0         $uri_copy->eq($uri) or $$loc->get($uri);
239             }
240 0 0         $old||''
241             }
242              
243             sub host {
244 0     0     my $loc = shift;
245 0 0         if (@_) {
246 0           (my $uri = $$loc->uri->clone)->host(shift);
247 0           $$loc->get($uri);
248             }
249             else {
250 0           $$loc->uri->host;
251             }
252             }
253              
254             sub hostname {
255 0     0     my $loc = shift;
256 0 0         if (@_) {
257 0           (my $uri = $$loc->uri->clone)->host_port(shift);
258 0           $$loc->get($uri);
259             }
260             else {
261 0           $$loc->uri->host_port;
262             }
263             }
264              
265             sub href {
266 0     0     my $loc = shift;
267 0 0         if (@_) {
268 0           $$loc->get(shift);
269             }
270             else {
271 0           $$loc->uri->as_string;
272             }
273             }
274              
275             sub pathname {
276 0     0     my $loc = shift;
277 0 0         if (@_) {
278 0           (my $uri = $$loc->uri->clone)->path(shift);
279 0           $$loc->get($uri);
280             }
281             else {
282 0           $$loc->uri->path;
283             }
284             }
285              
286             sub port {
287 0     0     my $loc = shift;
288 0 0         if (@_) {
289 0           (my $uri = $$loc->uri->clone)->port(shift);
290 0           $$loc->get($uri);
291             }
292             else {
293 0           $$loc->uri->port;
294             }
295             }
296              
297             sub protocol {
298 0     0     my $loc = shift;
299 0 0         if (@_) {
300 0           shift() =~ /(.*):?/s;
301 0           (my $uri = $$loc->uri->clone)->scheme($1);
302 0           $$loc->get($uri);
303             }
304             else {
305 0           $$loc->uri->scheme . ':';
306             }
307             }
308              
309             sub search {
310 0     0     my $loc = shift;
311 0 0         if (@_){
312 0           shift() =~ /(\??)(.*)/s;
313 0 0 0       (my $uri_copy = (my $uri = $$loc->uri)->clone)->query(
314             $1&&length$2 ? $2 : undef
315             );
316 0 0         $uri_copy->eq($uri) or $$loc->get($uri);
317             } else {
318 0           my $q = $$loc->uri->query;
319 0 0         defined $q ? "?$q" : "";
320             }
321             }
322              
323              
324             # ~~~ Safari doesn't support forceGet. Do I need to?
325             sub reload { # args (forceGet)
326 0     0     ${+shift}->reload
  0            
327             }
328             sub replace { # args (URL)
329 0     0     my $mech = ${+shift};
  0            
330 0           $mech->back();
331 0           $mech->get(shift);
332             }
333              
334              
335             package WWW::Mechanize::Plugin::DOM::Navigator;
336              
337 2     2   2694 use HTML::DOM::Interface qw'STR READONLY';
  2         6  
  2         137  
338 2     2   11 use Scalar::Util 'weaken';
  2         4  
  2         251  
339              
340             our $VERSION = '0.014';
341              
342             $$_{~~__PACKAGE__} = 'Navigator',
343             $$_{Navigator} = {
344             appName => STR|READONLY,
345             appVersion => STR|READONLY,
346             userAgent => STR|READONLY,
347             }
348             for \%WWW::Mechanize::Plugin::DOM::Interface;
349              
350 2     2   13 no constant 1.03 ();
  2         51  
  2         60  
351             use constant::lexical {
352 2         17 mech => 0,
353             name => 1,
354             vers => 2,
355 2     2   13 };
  2         4  
356              
357             sub new {
358 0     0     weaken((my $self = bless[],pop)->[mech] = pop);
359 0           $self;
360             }
361              
362             sub appName {
363 0     0     my $self = shift;
364 0           my $old = $self->[name];
365 0 0         defined $old or $old = ref $self->[mech];
366 0 0         @_ and $self->[name] = shift;
367 0           return $old;
368             }
369              
370             sub appVersion {
371 0     0     my $self = shift;
372 0           my $old = $self->[vers];
373 0 0         if(!defined $old) {
374 0           $old = $self->userAgent;
375 0 0         $old =~ /(\d.*)/s
376             ? $old = $1
377             : $old = ref($self->[mech])->VERSION;
378             }
379 0 0         @_ and $self->[vers] = shift;
380 0           return $old;
381             }
382              
383             sub userAgent {
384 0     0     shift->[mech]->agent;
385             }
386              
387              
388             # ~~~ This is horribly inefficient and clunky. It probably needs to be
389             # programmed in full here, or at least the ‘Collection’ part (a tiny
390             # bit of copy&paste).
391             package WWW::Mechanize::Plugin::DOM::Frames;
392              
393             our $VERSION = '0.014';
394              
395 2     2   1038 use HTML::DOM::Collection;
  2         6  
  2         270  
396             our @ISA = "HTML::DOM::Collection";
397              
398             use overload fallback => 1,'@{}' => sub {
399 0     0     [map $_->contentWindow, @{shift->${\'SUPER::(@{}'}}]
  0            
  0            
400 2     2   12 };
  2         5  
  2         15  
401              
402 0   0 0     sub FETCH { (shift->SUPER::FETCH(@_)||return)->contentWindow }
403              
404              
405              
406             # ------------------ DOCS --------------------#
407              
408             1;
409              
410              
411             =head1 NAME
412              
413             WWW::Mechanize::Plugin::DOM::Window - Window object for the DOM plugin
414              
415             =head1 VERSION
416              
417             Version 0.014
418              
419             THIS MODULE IS DEPRECATED. Please use L instead.
420              
421             =head1 DESCRIPTION
422              
423             This module provides the window object. It inherits from
424             L and L.
425              
426             =head1 METHODS
427              
428             =over
429              
430             =item location
431              
432             Returns the location object (see L).
433             If you pass an argument, it sets the C
434             attribute of the location object.
435              
436             =item alert
437              
438             =item confirm
439              
440             =item prompt
441              
442             Each of these calls the function assigned by one of the following methods:
443              
444             =item set_alert_function
445              
446             =item set_confirm_function
447              
448             =item set_prompt_function
449              
450             Use these to set the functions called by the above methods. There are no
451             default C and C functions. The default C prints to
452             the currently selected file handle, with a line break tacked on the end.
453              
454             =item navigator
455              
456             Returns the navigator object. This currently has three properties,
457             C
458             (set to C) C (C<< ref($mech)->VERSION >>) and
459             C (same as C<< $mech->agent >>).
460              
461             You can pass values to C and C to set them.
462              
463             =item setTimeout ( $code, $ms );
464              
465             This schedules the C<$code> to run after C<$ms> seconds have elapsed,
466             returning a
467             number uniquely identifying the time-out.
468              
469             =item clearTimeout ( $timeout_id )
470              
471             The cancels the time-out corresponding to the C<$timeout_id>.
472              
473             =item open ( $url )
474              
475             This is a temporary placeholder. Right now it ignores all its args
476             except the first, and goes to the given URL, such that C<< ->open(foo) >>
477             is equivalent to C<< ->location('foo') >>.
478              
479             =item window
480              
481             =item self
482              
483             =item frames
484              
485             These three return the window object itself.
486              
487             =item top
488              
489             Returns the 'top' window, which is the window itself if there are no
490             frames.
491              
492             =item parent
493              
494             Returns the parent frame, if there is one, or the window object itself
495             otherwise.
496              
497             =item mech
498              
499             This returns the L object that corresponds to the window.
500              
501             =item length
502              
503             This returns the number of frames.
504              
505             =back
506              
507             =head1 FRAMES
508              
509             You can access frames by index or by name by using the window object as an
510             array or hash, respectively.
511              
512             =head1 THE C<%Interface> HASH
513              
514             The hash named C<%WWW::Mechanize::Plugin::DOM::Window::Interface> lists the
515             interface members for the window object. It follows the same format as
516             hashes I L<%HTML::DOM::Interface|HTML::DOM::Interface>, like this:
517              
518             (
519             alert => VOID|METHOD,
520             confirm => BOOL|METHOD,
521             ...
522             )
523              
524             It does not include C.
525              
526             =head1 SEE ALSO
527              
528             =over 4
529              
530             =item -
531              
532             L
533              
534             =item -
535              
536             L
537              
538             =item -
539              
540             L
541              
542             =item -
543              
544             L
545              
546             =back