From dbfa87a3950d2074807fee15619ae6c2a6cf8a67 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sat, 25 Jun 2016 22:33:52 +0100 Subject: [PATCH] Add itercb, fid, fclass methods --- MANIFEST | 2 + lib/HTML/Element/Library.pm | 104 ++++++++++++++++++++++++++++++++++++ t/html/itercb-exp.html | 8 +++ t/html/itercb.html | 6 +++ t/misc.t | 21 +++++++- 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 t/html/itercb-exp.html create mode 100644 t/html/itercb.html diff --git a/MANIFEST b/MANIFEST index ebcb91e..dc1dee2 100644 --- a/MANIFEST +++ b/MANIFEST @@ -25,6 +25,8 @@ t/html/highlander-5-exp.html t/html/highlander.html t/html/iter2-exp.html t/html/iter2.html +t/html/itercb-exp.html +t/html/itercb.html t/html/iter-exp.html t/html/iter.html t/html/position.html diff --git a/lib/HTML/Element/Library.pm b/lib/HTML/Element/Library.pm index 2ebc43e..928707c 100644 --- a/lib/HTML/Element/Library.pm +++ b/lib/HTML/Element/Library.pm @@ -246,6 +246,19 @@ sub HTML::Element::iter { $p->replace_with(@item); } +sub HTML::Element::itercb { + my ($self, $data, $code) = @_; + my $orig = $self; + my $prev = $orig; + for my $el (@$data) { + my $current = $orig->clone; + $code->($el, $current); + $prev->postinsert($current); + $prev = $current; + } + $orig->detach; +} + sub HTML::Element::iter2 { ## no critic (RequireArgUnpacking) my $tree = shift; @@ -681,6 +694,9 @@ sub HTML::TreeBuilder::parse_string { HTML::TreeBuilder->parse($string); } +sub HTML::Element::fid { shift->look_down(id => $_[0]) } +sub HTML::Element::fclass { shift->look_down(class => qr/\b$_[0]\b/s) } + 1; __END__ @@ -701,6 +717,22 @@ HTML:::Element::Library provides extra methods for HTML::Element. =head1 METHODS +=head2 Aliases + +These are short aliases for common operations: + +=over + +=item I<$el>->B(I<$id>) + +Finds an element given its id. Equivalent to C<< $el->look_down(id => $id) >>. + +=item I<$el>->B(I<$class>) + +Finds one or more elements given one of their classes. Equivalent to C<< $el->look_down(class => qr/\b$class\b/s) >> + +=back + =head2 Positional Querying Methods =head3 $elem->siblings @@ -1187,6 +1219,78 @@ instead of: and there is no good answer. The latter would be more concise and it is what I should have done. +=head3 Unrolling an array via a single sample element and a callback (
    container) + +This is a more advanced version of the previous method. Instead of +cloning the sample element several times and calling +C on the clone with the array element, a custom +callback is called with the clone and array element. + +Here is the example from before. + + Here are the things I need from the store: +
      +
    • Sample item
    • +
    + +Code: + + sub cb { + my ($data, $li) = @_; + $li->replace_content($data); + } + + my $li = $tree->look_down(class => 'store_items'); + my @items = qw(bread butter vodka); + $li->itercb(\@items, \&cb); + +Output is as before: + + + + Here are the things I need from the store: +
      +
    • bread
    • +
    • butter
    • +
    • vodka
    • +
    + + + +Here is a more complex example (unrolling a table). HTML: + + + +
    First NameLast NameOption
    FirstLast1 +
    + +Code: + + sub tr_cb { + my ($data, $tr) = @_; + $tr->look_down(class => 'first')->replace_content($data->{first}); + $tr->look_down(class => 'last')->replace_content($data->{last}); + $tr->look_down(class => 'option')->replace_content($data->{option}); + } + + my @data = ( + {first => 'Foo', last => 'Bar', option => 2}, + {first => 'Bar', last => 'Bar', option => 3}, + {first => 'Baz', last => 'Bar', option => 4}, + ); + + my $tr = $tree->find('table')->find('tbody')->find('tr'); + $tr->itercb(\@data, \&tr_cb); + +Produces: + + + +
    First NameLast NameOption
    FooBar2 +
    BarBar3 +
    BazBar4 +
    + =head3 Unrolling an array via n sample elements (
    container) C was fine for awhile, but some things (e.g. definition lists) diff --git a/t/html/itercb-exp.html b/t/html/itercb-exp.html new file mode 100644 index 0000000..e6267f8 --- /dev/null +++ b/t/html/itercb-exp.html @@ -0,0 +1,8 @@ + + + + + + +
    First NameLast NameOption
    FooBar2
    BarBar3
    BazBar4
    + diff --git a/t/html/itercb.html b/t/html/itercb.html new file mode 100644 index 0000000..386c958 --- /dev/null +++ b/t/html/itercb.html @@ -0,0 +1,6 @@ + + + + +
    First NameLast NameOption
    FirstLast1
    + diff --git a/t/misc.t b/t/misc.t index a0ae26c..2af0efc 100644 --- a/t/misc.t +++ b/t/misc.t @@ -1,6 +1,6 @@ #!/usr/bin/perl -T use lib '.'; -use t::lib tests => 26; +use t::lib tests => 27; ################################################## # Short tests based on mklol @@ -123,6 +123,25 @@ isxml $tree, 't/html/dual_iter-exp.html', 'dual_iter'; ### +sub cb { + my ($data, $tr) = @_; + $tr->look_down(class => 'first')->replace_content($data->{first}); + $tr->look_down(class => 'last')->replace_content($data->{last}); + $tr->look_down(class => 'option')->replace_content($data->{option}); +} + +my @cbdata = ( + {first => 'Foo', last => 'Bar', option => 2}, + {first => 'Bar', last => 'Bar', option => 3}, + {first => 'Baz', last => 'Bar', option => 4}, +); + +$tree = mktree 't/html/itercb.html'; +$tree->find('table')->find('tbody')->find('tr')->itercb(\@cbdata, \&cb); +isxml $tree, 't/html/itercb-exp.html', 'itercb'; + +### + for my $age (qw/5 15 50/) { $tree = mktree 't/html/highlander.html'; $tree->highlander( -- 2.39.2