Changeset 347

Show
Ignore:
Timestamp:
03/08/08 14:47:58 (2 months ago)
Author:
ingy
Message:
0.02
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/ingy/pQuery/Changes

    r324 r347  
     1--- 
     2version: 0.02 
     3date:    Sat Mar  8 19:56:33 EET 2008 
     4changes: 
     5- Added a pQuery::DOM class. 
     6- Finished porting constructor from jQuery. 
     7 
    18--- 
    29version: 0.01 
  • trunk/src/ingy/pQuery/MANIFEST

    r328 r347  
    1717inc/Test/More.pm 
    1818lib/pQuery.pm 
     19lib/pQuery/DOM.pm 
    1920Makefile.PL 
    2021MANIFEST                        This list of files 
     
    2324t/contructors.t 
    2425t/document1.html 
     26t/dom.t 
    2527t/each.t 
    2628t/find.t 
  • trunk/src/ingy/pQuery/README

    r324 r347  
    66 
    77        pQuery("http://google.com/search?q=pquery") 
    8             ->find("h2.r") 
     8            ->find("h2") 
    99            ->each(sub { 
    1010                my $i = shift; 
    11                 print ($i + 1), ") ", pQuery($_)->text, "\n"; 
     11                print $i + 1, ") ", pQuery($_)->text, "\n"; 
    1212            }); 
    1313 
     
    2424 
    2525    A pQuery object acts like an array reference (because, in fact, it is). 
    26     Typically it is an array of HTML::DOM elements, but it can be an array 
     26    Typically it is an array of pQuery::DOM elements, but it can be an array 
    2727    of anything. 
     28 
     29    pQuery::DOM is roughly an attempt to duplicate JavaScript's DOM in Perl. 
     30    It subclasses HTML::TreeBuilder/HTML::Element so there are a few 
     31    differences to be aware of. See the pQuery::DOM documentation for 
     32    details. 
    2833 
    2934    Like jQuery, pQuery methods return a pQuery object; either the original 
     
    3136 
    3237CONSTRUCTORS 
    33     THe pQuery constructor is an exported function called "pQuery". It does 
     38    The pQuery constructor is an exported function called "pQuery". It does 
    3439    different things depending on the arguments you pass it. 
    3540 
    3641  A URL 
    3742    If you pass pQuery a URL, it will attempt to get the page and use its 
    38     HTML to create a HTML::DOM object. The pQuery object will contain the 
    39     top level HTML::DOM object. 
     43    HTML to create a pQuery::DOM object. The pQuery object will contain the 
     44    top level pQuery::DOM object. 
    4045 
    4146        pQuery("http://google.com"); 
    4247 
     48    It will also set the global variable $pQuery::document to the resulting 
     49    DOM object. Future calls to pQuery methods will use this document if 
     50    none other is supplied. 
     51 
    4352  HTML 
    4453    If you already have an HTML string, pass it to pQuery and it will create 
    45     a HTML::DOM object. The pQuery object will contain the top level 
    46     HTML::DOM object. 
     54    a pQuery::DOM object. The pQuery object will contain the top level 
     55    pQuery::DOM object. 
    4756 
    4857        pQuery("<p>Hello <b>world</b>.</p>"); 
     
    5059  Selector String 
    5160    You can create a pQuery object with a selector string just like in 
    52     jQuery. The problem is that Perl doesn't have a global DOM object lying 
    53     around like JavaScript does. You need to pass the DOM to select on as 
    54     the second parameter. (jQuery also has this second parameter). 
     61    jQuery. The problem is that Perl doesn't have a global document object 
     62    lying around like JavaScript does. 
     63 
     64    One thing you can do is set the global variable, $pQuery::document, to a 
     65    pQuery::DOM document. This will be used by future selectors. 
     66 
     67    Another thing you can do is pass the document to select on as the second 
     68    parameter. (jQuery also has this second, context parameter). 
    5569 
    5670        pQuery("table.mygrid > td:eq(7)", $dom); 
     
    6478  Array Reference 
    6579    You can create a pQuery object as an array of anything you want; not 
    66     just HTML::DOM elements. This can be useful to use the "each" method to 
    67     iterate over the array. 
     80    just pQuery::DOM elements. This can be useful to use the "each" method 
     81    to iterate over the array. 
    6882 
    6983        pQuery(\ @some_array); 
     
    7892METHODS 
    7993    This is a reference of all the methods you can call on a pQuery object. 
    80     They are all ported from jQuery. 
     94    They are almost entirely ported from jQuery. 
    8195 
    8296  each($sub) 
     
    95109 
    96110  find($selector) 
    97     This method will search all the HTML::DOM elements of the its caller fo
    98     all sub elements that match the selector string. It will return a new 
    99     pQuery object containing all the elements found. 
     111    This method will search all the pQuery::DOM elements of the its calle
     112    for all sub elements that match the selector string. It will return a 
     113    new pQuery object containing all the elements found. 
    100114 
    101115        my $pquery2 = $pquery1->find("h1,h2,h3"); 
     116 
     117  html() html($html) 
     118    This method is akin to the famous JavaScript/DOM function "innerHTML". 
     119 
     120    If called with no arguments, this will return the the inner HTML string 
     121    of the first DOM element in the pQuery object. 
     122 
     123    If called with an HTML string argument, this will set the inner HTML of 
     124    all the DOM elements in the pQuery object. 
     125 
     126  toHtml() 
     127    This extremely handy method is not ported from jQuery. Maybe jQuery will 
     128    port it back some day. :) 
     129 
     130    This function takes no arguments, and returns the outer HTML of the 
     131    first DOM object in the pQuery object. Outer HTML means the HTML of the 
     132    current object and its inner HTML. 
     133 
     134    For example: 
     135 
     136        pQuery('<p>I <b>like</b> pie</p>').HTML(); 
     137 
     138    returns: 
     139 
     140        <p>I <b>like</b> pie</p> 
     141 
     142    while: 
     143 
     144        pQuery('<p>I <b>like</b> pie</p>').html(); 
     145 
     146    returns: 
     147 
     148        I <b>like</b> pie 
    102149 
    103150  end() 
     
    112159            ->end()               # Go back to the tables selection 
    113160            ->each(sub { ... });  # Do something with the tables 
     161 
     162    NOTE: Not implemented yet. :( 
    114163 
    115164  get($url) 
     
    127176    only). 
    128177 
    129     There is still much more code to port. Stay tuned... 
     178    Version 0.02 added the pQuery::DOM class which is a huge improvement, 
     179    and should facilitate making the rest of the porting easy. 
     180 
     181    But there is still much more code to port. Stay tuned... 
    130182 
    131183AUTHOR 
  • trunk/src/ingy/pQuery/lib/pQuery.pm

    r344 r347  
    99use base 'Exporter'; 
    1010 
    11 our $VERSION = '0.01'; 
     11our $VERSION = '0.02'; 
    1212 
    1313our @EXPORT = qw(pQuery); 
    1414 
    15 our $DOM
     15our $document
    1616 
    1717my $my = {}; 
    1818my $lwp_user_agent; 
    19 my $quickExpr = qr/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; 
     19my $quickExpr = qr/^([^<]*<(.|\s)+>[^>]*)$|^#(\w+)$/; 
    2020my $isSimple = qr/^.[^:#\[\.]*$/; 
    2121my $dom_element_class = 'pQuery::DOM'; 
     
    3535    my ($self, $selector, $context) = @_; 
    3636 
    37     my $document = $DOM || $main::DOM || $main::DOM; 
    3837    $selector ||= $document or return $self; 
    3938 
     
    4746        if ($match and ($1 or not $context)) { 
    4847            if ($1) { 
    49                 $selector = $self->_clean([$1], $context); 
     48                $selector = [pQuery::DOM->fromHTML($1)]; 
     49#                 $selector = $self->_clean([$1], $context); 
    5050            } 
    5151            else { 
    52                 my $id = $3; 
    53                 my $elem = $document->getElementById($id); 
     52                my $elem = $document->getElementById($3); 
    5453                if ($elem) { 
    55                     if ($elem->id ne $id) { 
    56                         return pQuery->find($selector); 
    57                     } 
    58                     else { 
    59                         $self->[0] = $elem; 
    60                         $#$self = 0; 
    61                         return $self; 
    62                     } 
     54                    @$self = $elem; 
     55                    return $self; 
    6356                } 
    6457                else { 
     
    6659                } 
    6760            } 
    68  
    69  
    70  
    71             @$self = pQuery::DOM->fromHTML($selector); 
    72             return $self; 
    73  
    74  
    75  
    7661        } 
    7762        else { 
    78  
    79  
    8063            if ($selector =~ /^\s*(https?|file):/) { 
    81                 return $self->_new_from_url($selector); 
     64                return $document = $self->_new_from_url($selector); 
    8265            } 
    83             else { 
    84                 die "Can't create new pQuery object with these arguments:\n(@_)"; 
    85             } 
    86         } 
    87     } 
    88     elsif (ref($selector) eq 'ARRAY') { 
    89         @$self = @$selector; 
    90         return $self; 
    91     } 
     66            return pQuery($context)->find($selector); 
     67        } 
     68    } 
     69    @$self = (ref($selector) eq 'ARRAY' or ref($selector) eq 'pQuery') 
     70        ? @$selector 
     71        : $selector; 
    9272    return $self; 
    93 } 
    94  
    95 sub _clean { 
    96     my ($self, $html) = @_; 
    97     return $html->[0]; 
    9873} 
    9974 
     
    10277    my $url = shift; 
    10378    my $response = $self->get($url); 
    104     if (! $response->is_success) { 
     79    return $self 
     80        unless $response->is_success; 
     81    @$self = pQuery::DOM->fromHTML($response->content); 
     82    return $self; 
     83
     84 
     85sub html { 
     86    my $self = shift; 
     87    return unless @$self; 
     88    if (@_) { 
     89        for (@$self) { 
     90            next unless ref($_); 
     91            $_->innerHTML(@_); 
     92        } 
    10593        return $self; 
    10694    } 
    107     @$self = pQuery::DOM->fromHTML($response->content); 
    108 
    109  
    110 sub html { 
    111     my $self = shift; 
    112     if (@_) { 
    113         my $dom = $self->html_to_dom(@_); 
    114         die "XXX - need to insert dom here"; 
    115     } 
     95    return $self->[0]->innerHTML(@_); 
     96
     97 
     98sub toHtml { 
     99    my $self = shift; 
    116100    return unless @$self; 
    117  
    118     return $self->[0]->innerHTML; 
    119 } 
    120  
    121 sub toHtml { 
    122     my $self = shift; 
    123     if (@_) { 
    124         my $dom = $self->html_to_dom(@_); 
    125         die "XXX - need to insert dom here"; 
    126     } 
    127     return unless @$self; 
    128  
    129101    return $self->[0]->toHTML; 
    130102} 
     
    217189 
    218190    pQuery("http://google.com/search?q=pquery") 
    219         ->find("h2.r") 
     191        ->find("h2") 
    220192        ->each(sub { 
    221193            my $i = shift; 
    222             print ($i + 1), ") ", pQuery($_)->text, "\n"; 
     194            print $i + 1, ") ", pQuery($_)->text, "\n"; 
    223195        }); 
    224196 
     
    236208 
    237209A pQuery object acts like an array reference (because, in fact, it is). 
    238 Typically it is an array of HTML::DOM elements, but it can be an array 
     210Typically it is an array of pQuery::DOM elements, but it can be an array 
    239211of anything. 
     212 
     213pQuery::DOM is roughly an attempt to duplicate JavaScript's DOM in 
     214Perl. It subclasses HTML::TreeBuilder/HTML::Element so there are a 
     215few differences to be aware of. See the L<pQuery::DOM> documentation 
     216for details. 
    240217 
    241218Like jQuery, pQuery methods return a pQuery object; either the 
     
    245222=head1 CONSTRUCTORS 
    246223 
    247 THe pQuery constructor is an exported function called C<pQuery>. It does 
     224The pQuery constructor is an exported function called C<pQuery>. It does 
    248225different things depending on the arguments you pass it. 
    249226 
     
    251228 
    252229If you pass pQuery a URL, it will attempt to get the page and use its 
    253 HTML to create a HTML::DOM object. The pQuery object will contain the 
    254 top level HTML::DOM object. 
     230HTML to create a pQuery::DOM object. The pQuery object will contain the 
     231top level pQuery::DOM object. 
    255232 
    256233    pQuery("http://google.com"); 
    257234 
     235It will also set the global variable C<$pQuery::document> to the 
     236resulting DOM object. Future calls to pQuery methods will use this 
     237document if none other is supplied. 
     238 
    258239=head2 HTML 
    259240 
    260241If you already have an HTML string, pass it to pQuery and it will create 
    261 a HTML::DOM object. The pQuery object will contain the top level 
    262 HTML::DOM object. 
     242a pQuery::DOM object. The pQuery object will contain the top level 
     243pQuery::DOM object. 
    263244 
    264245    pQuery("<p>Hello <b>world</b>.</p>"); 
     
    267248 
    268249You can create a pQuery object with a selector string just like in 
    269 jQuery. The problem is that Perl doesn't have a global DOM object lying 
    270 around like JavaScript does. You need to pass the DOM to select on as 
    271 the second parameter. (jQuery also has this second parameter). 
     250jQuery. The problem is that Perl doesn't have a global document object 
     251lying around like JavaScript does. 
     252 
     253One thing you can do is set the global variable, C<$pQuery::document>, 
     254to a pQuery::DOM document. This will be used by future selectors. 
     255 
     256Another thing you can do is pass the document to select on as the second 
     257parameter. (jQuery also has this second, context parameter). 
    272258 
    273259    pQuery("table.mygrid > td:eq(7)", $dom); 
     
    283269 
    284270You can create a pQuery object as an array of anything you want; not 
    285 just HTML::DOM elements. This can be useful to use the C<each> method to 
     271just pQuery::DOM elements. This can be useful to use the C<each> method to 
    286272iterate over the array. 
    287273 
     
    299285 
    300286This is a reference of all the methods you can call on a pQuery object. They 
    301 are all ported from jQuery. 
     287are almost entirely ported from jQuery. 
    302288 
    303289=head2 each($sub) 
     
    318304=head2 find($selector) 
    319305 
    320 This method will search all the HTML::DOM elements of the its caller for 
     306This method will search all the pQuery::DOM elements of the its caller for 
    321307all sub elements that match the selector string. It will return a new 
    322308pQuery object containing all the elements found. 
     
    334320the DOM elements in the pQuery object. 
    335321 
    336 =head2 HTML() 
     322=head2 toHtml() 
     323 
     324This extremely handy method is not ported from jQuery. Maybe jQuery will 
     325port it back some day. :) 
    337326 
    338327This function takes no arguments, and returns the B<outer> HTML of the first 
     
    369358        ->each(sub { ... });  # Do something with the tables 
    370359 
     360NOTE: Not implemented yet. :( 
     361 
    371362=head2 get($url) 
    372363 
     
    385376only). 
    386377 
    387 There is still much more code to port. Stay tuned... 
     378Version 0.02 added the pQuery::DOM class which is a huge improvement, and 
     379should facilitate making the rest of the porting easy. 
     380 
     381But there is still much more code to port. Stay tuned... 
    388382 
    389383=head1 AUTHOR 
  • trunk/src/ingy/pQuery/lib/pQuery/DOM.pm

    r346 r347  
    9696sub fromHTML { 
    9797    my ($class, $html) = @_; 
    98     my $dom = $class->_builder->parse_content($html); 
    99     if ($html =~ /^\s*<html.*?>/) { 
     98    my $dom; 
     99    if ($html =~ /^\s*<html.*?>.*<\/html>\s*\z/s) { 
     100        $dom = $class->_builder->parse_content($html); 
    100101        return $dom; 
    101102    } 
     103    $dom = $class->_builder->parse_content('<dummy>' . $html . '</dummy>'); 
    102104    my @dom = map { 
    103105        if (ref($_)) { 
     
    319321 
    320322To deal with children, use the childNodes method which returns a list 
    321 of all the child nodes. Then you can you standard Perl idioms to 
     323of all the child nodes. Then you can use standard Perl idioms to 
    322324process them. 
    323325 
     
    342344=item createElement($tag) 
    343345 
    344 Create a new HTML Element node with the specified tag. This node will be empty 
    345 and have no attributes. 
     346Create a new HTML Element node with the specified tag. This node will be 
     347empty and have no attributes. 
    346348 
    347349=item createComment($text) 
  • trunk/src/ingy/pQuery/t/contructors.t

    r344 r347  
    1 use Test::More tests => 8; 
     1use Test::More tests => 13; 
     2use strict; 
    23 
    34use pQuery; 
    45 
    5 my $p1 = pQuery
     6my $pq
    67 
    7 is ref($p1), 'pQuery', 'Empty object created'; 
    8 is scalar(@$p1), 0, 'Empty object is empty'
     8is $pQuery::document, undef, '$pQuery::document is not defined by default'; 
     9$pq = pQuery
    910 
    10 my $p2 = pQuery([5..10]); 
     11is ref($pq), 'pQuery', 'Empty object created'; 
     12is scalar(@$pq), 0, 'Empty object is empty'; 
    1113 
    12 is ref($p2), 'pQuery', 'Array object created'
    13 is scalar(@$p2), 6, 'Object has six elements'; 
    14 is $p2->[2], 7, 'Check value of a element'; 
     14$pq = pQuery(pQuery::DOM->fromHTML('<div>'))
     15is ref($pq), 'pQuery', 'pQuery object created'; 
     16is scalar(@$pq), 1, 'Object has one element'; 
    1517 
    16 my $p3 = pQuery('<ul><li>one</li><li>two</li></ul>'); 
     18$pq = pQuery([pQuery::DOM->fromHTML('I <b>Like</b> <ul>Pie</ul>.')]); 
     19is ref($pq), 'pQuery', 'pQuery object created'; 
     20is scalar(@$pq), 5, 'Object has 5 elements'; 
    1721 
    18 is ref($p3), 'pQuery', 'HTML object created'; 
    19 is scalar(@$p3), 1, 'Object has six elements'; 
     22$pq = pQuery('<ul><li>one</li><li>two</li></ul>'); 
    2023 
    21 my $p4 = pQuery('<p>aaa</p>bbb<p>ccc</p>'); 
     24is ref($pq), 'pQuery', 'HTML object created'; 
     25is scalar(@$pq), 1, 'Object has six elements'; 
    2226 
    23 is scalar(@$p4), 3, 'Object has 3 elements'; 
     27$pq = pQuery('<p>aaa</p>bbb<p>ccc</p>'); 
     28 
     29is scalar(@$pq), 3, 'Object has 3 elements'; 
     30 
     31$pq = pQuery([5..10]); 
     32 
     33is ref($pq), 'pQuery', 'Array object created'; 
     34is scalar(@$pq), 6, 'Object has six elements'; 
     35is $pq->[2], 7, 'Check value of a element'; 
     36