Changeset 351
- Timestamp:
- 03/12/08 21:17:38 (2 months ago)
- Files:
-
- trunk/src/ingy/pQuery/Changes (modified) (1 diff)
- trunk/src/ingy/pQuery/README (modified) (6 diffs)
- trunk/src/ingy/pQuery/lib/pQuery.pm (modified) (15 diffs)
- trunk/src/ingy/pQuery/lib/pQuery/DOM.pm (modified) (2 diffs)
- trunk/src/ingy/pQuery/t/TestpQuery.pm (added)
- trunk/src/ingy/pQuery/t/contructors.t (modified) (1 diff)
- trunk/src/ingy/pQuery/t/ideas (added)
- trunk/src/ingy/pQuery/t/misc.t (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/ingy/pQuery/Changes
r347 r351 1 --- 2 version: 0.03 3 date: Thu Mar 13 04:14:09 GMT 2008 4 changes: 5 - Added PQUERY 6 - Ported and documented more methods 7 - Implemented the previous state stack 8 1 9 --- 2 10 version: 0.02 trunk/src/ingy/pQuery/README
r347 r351 19 19 the same goal. 20 20 21 pQuery exports a single function called "pQuery". This function acts a 21 pQuery exports a single function called "pQuery". (Actually, it also 22 exports the special "PQUERY" function. Read below.) This function acts a 22 23 constructor and does different things depending on the arguments you 23 24 give it. This is discussed in the CONSTRUCTORS section below. … … 35 36 object or a new derived object. All pQuery METHODS are described below. 36 37 38 THE ROYAL PQUERY 39 The power of jQuery is that single method calls can apply to many DOM 40 objects. pQuery does the exact same thing but can take this one step 41 further. A single PQUERY object can contain several DOMs! 42 43 Consider this example: 44 45 > perl -MpQuery -le 'PQUERY(\ 46 map "http://search.cpan.org/~$_/", qw(ingy gugod miyagawa))\ 47 ->find("table")->eq(1)->find("tr")\ 48 ->EACH(sub{\ 49 printf("%40s - %s Perl distributions\n", $_->url, $_->length - 1)\ 50 })' 51 http://search.cpan.org/~ingy/ - 88 Perl distributions 52 http://search.cpan.org/~gugod/ - 86 Perl distributions 53 http://search.cpan.org/~miyagawa/ - 138 Perl distributions 54 55 The power lies in "PQUERY", a special constructor that creates a wrapper 56 object for many pQuery objects, and applies all methods called on it to 57 all the pQuery objects it contains. 58 37 59 CONSTRUCTORS 38 60 The pQuery constructor is an exported function called "pQuery". It does 39 61 different things depending on the arguments you pass it. 40 62 41 AURL63 URL 42 64 If you pass pQuery a URL, it will attempt to get the page and use its 43 65 HTML to create a pQuery::DOM object. The pQuery object will contain the … … 57 79 pQuery("<p>Hello <b>world</b>.</p>"); 58 80 81 FILE 82 If you pass pQuery a string that ends with .html and contains no 83 whitespace, pQuery will assume it is the name of a file containing html 84 and will read the contents and parse the HTML into a new DOM. 85 86 pQuery("my/webpage.html"); 87 59 88 Selector String 60 89 You can create a pQuery object with a selector string just like in … … 90 119 my $html = pQuery->get("http://google.com")->content; 91 120 121 PQUERY(@list_of_pQuery_constructor_args) 122 The PQUERY constructor takes a list of any of the above pQuery forms and 123 creates a PQUERY object with one pQuery object per argument. 124 92 125 METHODS 93 126 This is a reference of all the methods you can call on a pQuery object. 94 127 They are almost entirely ported from jQuery. 128 129 pquery() 130 Returns the version number of the pQuery module. 131 132 =size() 133 134 Returns the number of elements in the pQuery object. 135 136 =length() 137 138 Also returns the number of elements in the pQuery object. 95 139 96 140 each($sub) … … 108 152 The "each" method returns the pQuery object that called it. 109 153 154 EACH($sub) 155 This method can only be called on PQUERY objects. The sub is called once 156 for every pQuery object within the PQUERY object. If you call "each()" 157 on a PQUERY object, it iterates on all the DOM objects of each pQuery 158 object (as you would expect). 159 110 160 find($selector) 111 161 This method will search all the pQuery::DOM elements of the its caller … … 160 210 ->each(sub { ... }); # Do something with the tables 161 211 162 NOTE: Not implemented yet. :( 163 164 get($url) 212 get($index) get($url) 213 If this method is passed an integer, it will return that specific 214 element from the array of elements in the pQuery object. 215 165 216 This method will fetch the HTML content of the URL and return a 166 217 HTML::Response object. 167 218 168 219 my $html = pQuery.get("http://google.com")->content; 220 221 index($elem) 222 This method returns the index number of its argument if the elem is in 223 the current pQuery object. Otherwise it returns -1. 169 224 170 225 UNDER CONSTRUCTION trunk/src/ingy/pQuery/lib/pQuery.pm
r347 r351 9 9 use base 'Exporter'; 10 10 11 our $VERSION = '0.0 2';12 13 our @EXPORT = qw(pQuery );11 our $VERSION = '0.03'; 12 13 our @EXPORT = qw(pQuery PQUERY); 14 14 15 15 our $document; … … 25 25 } 26 26 27 sub PQUERY { 28 return 'PQUERY'->new(@_); 29 } 30 31 ################################################################################ 32 # Playing around stuffs 33 ################################################################################ 34 sub url { 35 my $this = shift; 36 return $my->{$this}{url} 37 if $my->{$this}{url}; 38 while ($this = $my->{$this}{prevObject}) { 39 return $my->{$this}{url} 40 if $my->{$this}{url}; 41 } 42 return; 43 } 44 45 sub eq { 46 my ($this, $i) = @_; 47 return $this->_pushStack($this->[$i]); 48 } 49 50 51 ################################################################################ 52 # Truly ported from jQuery stuff 53 ################################################################################ 27 54 sub new { 28 55 my $class = shift; 29 my $ self= bless [], $class;30 $my->{$ self} = {};31 return $ self->_init(@_);56 my $this = bless [], $class; 57 $my->{$this} = {}; 58 return $this->_init(@_); 32 59 } 33 60 34 61 sub _init { 35 my ($ self, $selector, $context) = @_;36 37 $selector ||= $document or return $ self;62 my ($this, $selector, $context) = @_; 63 64 $selector ||= $document or return $this; 38 65 39 66 if (ref($selector) eq $dom_element_class) { 40 @$ self= $selector;41 return $ self;67 @$this = $selector; 68 return $this; 42 69 } 43 70 elsif (not ref($selector)) { … … 47 74 if ($1) { 48 75 $selector = [pQuery::DOM->fromHTML($1)]; 49 # $selector = $ self->_clean([$1], $context);76 # $selector = $this->_clean([$1], $context); 50 77 } 51 78 else { 52 79 my $elem = $document->getElementById($3); 53 80 if ($elem) { 54 @$ self= $elem;55 return $ self;81 @$this = $elem; 82 return $this; 56 83 } 57 84 else { … … 62 89 else { 63 90 if ($selector =~ /^\s*(https?|file):/) { 64 return $document = $self->_new_from_url($selector); 91 $my->{$this}{url} = $selector; 92 return $document = $this->_new_from_url($selector); 65 93 } 66 return pQuery($context)->find($selector); 94 elsif ($selector =~ /^\S+\.html?$/) { 95 $my->{$this}{file} = $selector; 96 open FILE, $selector; 97 my $html = do {local $/; <FILE>}; 98 close FILE; 99 $selector = [pQuery::DOM->fromHTML($html)]; 100 } 101 else { 102 return pQuery($context)->find($selector); 103 } 67 104 } 68 105 } 69 @$ self= (ref($selector) eq 'ARRAY' or ref($selector) eq 'pQuery')106 @$this = (ref($selector) eq 'ARRAY' or ref($selector) eq 'pQuery') 70 107 ? @$selector 71 108 : $selector; 72 return $self; 73 } 74 75 sub _new_from_url { 76 my $self = shift; 77 my $url = shift; 78 my $response = $self->get($url); 79 return $self 80 unless $response->is_success; 81 @$self = pQuery::DOM->fromHTML($response->content); 82 return $self; 83 } 109 return $this; 110 } 111 112 sub pquery { return $VERSION } 113 114 sub size { return $#{$_[0]} + 1 } 115 sub length { return $#{$_[0]} + 1 } 116 117 sub get { 118 my $this = shift; 119 120 # Get could be for Ajax URL or Object Member 121 return $this->_web_get(@_) 122 if @_ and $_[0] !~ /^\d+$/; 123 124 return @_ 125 ? $this->[$_[0]] 126 : wantarray ? (@$this) : $this->[0]; 127 } 128 129 sub _pushStack { 130 my ($this, $elems) = @_; 131 my $ret = pQuery($elems); 132 $ret->_prevObject($this); 133 return $ret; 134 } 135 136 sub _prevObject { 137 my $this = shift; 138 return @_ 139 ? ($my->{$this}{prevObject} = $_[0]) 140 : $my->{$this}{prevObject}; 141 } 142 143 # Not needed in Perl 144 # sub _setArray { 145 # my ($this, $elems) = @_; 146 # @$this = @$elems; 147 # return $this; 148 # } 149 150 sub each { 151 my ($this, $sub) = @_; 152 my $i = 0; 153 &$sub($i++) for @$this; 154 return $this; 155 } 156 157 # XXX Needs test 158 sub index { 159 my ($this, $elem) = @_; 160 my $ret = -1; 161 $this->each(sub { 162 $ret = shift 163 if (ref($_) && ref($elem)) ? ($_ == $elem) : ($_ eq $elem); 164 }); 165 return $ret; 166 } 167 168 # sub attr { 169 # } 84 170 85 171 sub html { 86 my $ self= shift;87 return unless @$ self;172 my $this = shift; 173 return unless @$this; 88 174 if (@_) { 89 for (@$ self) {175 for (@$this) { 90 176 next unless ref($_); 91 177 $_->innerHTML(@_); 92 178 } 93 return $ self;94 } 95 return $ self->[0]->innerHTML(@_);179 return $this; 180 } 181 return $this->[0]->innerHTML(@_); 96 182 } 97 183 98 184 sub toHtml { 99 my $ self= shift;100 return unless @$ self;101 return $ self->[0]->toHTML;185 my $this = shift; 186 return unless @$this; 187 return $this->[0]->toHTML; 102 188 } 103 189 104 190 sub text { 105 my $ self= shift;191 my $this = shift; 106 192 my $text = ''; 107 193 108 $ self->each(sub {194 $this->each(sub { 109 195 _to_text($_, \$text); 110 196 }); … … 116 202 } 117 203 118 sub each {119 my ($self, $sub) = @_;120 my $i = 0;121 &$sub($i++) for @$self;122 return $self;123 }124 125 204 sub find { 126 my $ self= shift;205 my $this = shift; 127 206 my $selector = shift or return; 128 207 my $elems = []; 129 $ self->each(sub {208 $this->each(sub { 130 209 _find_elems($_, $selector, $elems); 131 210 }); 132 return pQuery($elems);211 return $this->_pushStack($elems); 133 212 } 134 213 135 214 sub end { 136 my $self = shift; 137 die "not implemented yet"; 138 } 139 140 sub get { 141 my $self = shift; 215 my $this = shift; 216 return $this->_prevObject; 217 } 218 219 ################################################################################ 220 # Helper functions (not methods) 221 ################################################################################ 222 sub _new_from_url { 223 my $this = shift; 224 my $url = shift; 225 my $response = $this->get($url); 226 return $this 227 unless $response->is_success; 228 @$this = pQuery::DOM->fromHTML($response->content); 229 return $this; 230 } 231 232 sub _web_get { 233 my $this = shift; 142 234 my $url = shift; 143 235 require LWP::UserAgent; … … 149 241 } 150 242 151 # Helper functions (not methods)152 243 sub _to_text { 153 244 my ($elem, $text) = @_; … … 178 269 } 179 270 271 ################################################################################ 272 # THE AMAZING PQUERY 273 ################################################################################ 274 package PQUERY; 275 276 sub new { 277 my $class = shift; 278 my $this = bless [], $class; 279 @$this = map 'pQuery'->new($_), @_; 280 return $this; 281 } 282 283 sub AUTOLOAD { 284 (my $method = $PQUERY::AUTOLOAD) =~ s/.*:://; 285 my $this = shift; 286 my @args = @_; 287 $this->EACH(sub { 288 my $i = shift; 289 $this->[$i] = $_->$method(@args); 290 }); 291 return $this; 292 } 293 294 sub EACH { 295 my ($this, $sub) = @_; 296 my $index = 0; 297 &$sub($index++) for @$this; 298 return $this; 299 } 300 301 sub DESTROY {} 302 180 303 1; 181 304 … … 203 326 the same goal. 204 327 205 pQuery exports a single function called C<pQuery>. This function acts a 206 constructor and does different things depending on the arguments you 328 pQuery exports a single function called C<pQuery>. (Actually, it also 329 exports the special C<PQUERY> function. Read below.) This function acts 330 a constructor and does different things depending on the arguments you 207 331 give it. This is discussed in the L<CONSTRUCTORS> section below. 208 332 … … 220 344 described below. 221 345 346 =head1 THE ROYAL PQUERY 347 348 The power of jQuery is that single method calls can apply to many DOM 349 objects. pQuery does the exact same thing but can take this one step 350 further. A single PQUERY object can contain several DOMs! 351 352 Consider this example: 353 354 > perl -MpQuery -le 'PQUERY(\ 355 map "http://search.cpan.org/~$_/", qw(ingy gugod miyagawa))\ 356 ->find("table")->eq(1)->find("tr")\ 357 ->EACH(sub{\ 358 printf("%40s - %s Perl distributions\n", $_->url, $_->length - 1)\ 359 })' 360 http://search.cpan.org/~ingy/ - 88 Perl distributions 361 http://search.cpan.org/~gugod/ - 86 Perl distributions 362 http://search.cpan.org/~miyagawa/ - 138 Perl distributions 363 364 The power lies in C<PQUERY>, a special constructor that creates a 365 wrapper object for many pQuery objects, and applies all methods called 366 on it to all the pQuery objects it contains. 367 222 368 =head1 CONSTRUCTORS 223 369 … … 225 371 different things depending on the arguments you pass it. 226 372 227 =head2 AURL373 =head2 URL 228 374 229 375 If you pass pQuery a URL, it will attempt to get the page and use its … … 245 391 pQuery("<p>Hello <b>world</b>.</p>"); 246 392 393 =head2 FILE 394 395 If you pass pQuery a string that ends with .html and contains no 396 whitespace, pQuery will assume it is the name of a file containing html 397 and will read the contents and parse the HTML into a new DOM. 398 399 pQuery("my/webpage.html"); 400 247 401 =head2 Selector String 248 402 … … 282 436 my $html = pQuery->get("http://google.com")->content; 283 437 438 =head2 PQUERY(@list_of_pQuery_constructor_args) 439 440 The PQUERY constructor takes a list of any of the above pQuery forms and 441 creates a PQUERY object with one pQuery object per argument. 442 284 443 =head1 METHODS 285 444 286 445 This is a reference of all the methods you can call on a pQuery object. They 287 446 are almost entirely ported from jQuery. 447 448 =head2 pquery() 449 450 Returns the version number of the pQuery module. 451 452 =size() 453 454 Returns the number of elements in the pQuery object. 455 456 =length() 457 458 Also returns the number of elements in the pQuery object. 288 459 289 460 =head2 each($sub) … … 302 473 The C<each> method returns the pQuery object that called it. 303 474 475 =head2 EACH($sub) 476 477 This method can only be called on PQUERY objects. The sub is called once 478 for every pQuery object within the PQUERY object. If you call C<each()> 479 on a PQUERY object, it iterates on all the DOM objects of each pQuery 480 object (as you would expect). 481 304 482 =head2 find($selector) 305 483 … … 358 536 ->each(sub { ... }); # Do something with the tables 359 537 360 NOTE: Not implemented yet. :( 361 362 =head2 get($url) 538 =head2 get($index) get($url) 539 540 If this method is passed an integer, it will return that specific 541 element from the array of elements in the pQuery object. 363 542 364 543 This method will fetch the HTML content of the URL and return a … … 366 545 367 546 my $html = pQuery.get("http://google.com")->content; 547 548 =head2 index($elem) 549 550 This method returns the index number of its argument if the elem is in the 551 current pQuery object. Otherwise it returns -1. 368 552 369 553 =head1 UNDER CONSTRUCTION trunk/src/ingy/pQuery/lib/pQuery/DOM.pm
r347 r351 2 2 use strict; 3 3 use warnings; 4 use Carp; 4 5 5 6 use base 'HTML::TreeBuilder'; … … 254 255 255 256 ################################################################################ 257 # Common pQuery method mistakes 258 ################################################################################ 259 # sub text { 260 # confess "Invalid method 'text' called on pQuery::DOM object"; 261 # } 262 263 ################################################################################ 256 264 # Helper Functions 257 265 ################################################################################ trunk/src/ingy/pQuery/t/contructors.t
r347 r351 1 use Test::Moretests => 13;1 use t::TestpQuery tests => 13; 2 2 use strict; 3 3
