use Carp qw(confess);
use Data::Dumper;
use HTML::Element;
+use List::Util qw(first);
use List::MoreUtils qw/:all/;
use Params::Validate qw(:all);
use Scalar::Listify;
$p->content_list;
}
+sub HTML::Element::hash_map {
+ my $container = shift;
+
+ my %p = validate(@_, {
+ hash => { type => HASHREF },
+ to_attr => 1,
+ excluding => { type => ARRAYREF , default => [] },
+ debug => { default => 0 },
+ });
+
+ warn 'The container tag is ', $container->tag if $p{debug} ;
+ warn 'hash' . Dumper($p{hash}) if $p{debug} ;
+ warn 'at_under' . Dumper(\@_);
+
+ my @same_as = $container->look_down( $p{to_attr} => qr/.+/ ) ;
+
+ warn 'Found ' . scalar(@same_as) . ' nodes' if $p{debug} ;
+
+
+ for my $same_as (@same_as) {
+ my $attr_val = $same_as->attr($p{to_attr}) ;
+ if (first { $attr_val eq $_ } @{$p{excluding}}) {
+ warn "excluding $attr_val" if $p{debug} ;
+ next;
+ }
+ warn "processing $attr_val" if $p{debug} ;
+ $same_as->replace_content( $p{hash}->{$attr_val} ) ;
+ }
+
+}
+
+
sub HTML::Element::passover {
my ($tree, $child_id) = @_;
- #warn "ARGS: my ($tree, $child)";
+ warn "ARGS: my ($tree, $child_id)" if $DEBUG;
+ warn $tree->as_HTML(undef, ' ') if $DEBUG;
my $exodus = $tree->look_down(id => $child_id);
- my @s = HTML::Element::siblings($exodus);
+ warn "E: $exodus" if $DEBUG;
- warn "sibling count", scalar @s;
- warn "siblings", join ':', @s;
+ my @s = HTML::Element::siblings($exodus);
for my $s (@s) {
- warn "SIBLING: $s";
- warn "ref sib", ref $s;
next unless ref $s;
if ($s->attr('id') eq $child_id) {
;
sub HTML::Element::content_handler {
- my ($tree, $id_name, $content) = @_;
+ my ($tree, %content_hash) = @_;
+
+ for my $k (keys %content_hash) {
+ $tree->set_child_content(id => $k, $content_hash{$k});
+ }
- $tree->set_child_content(id => $id_name, $content);
}
warn "wrapper_data: " . Dumper $p{wrapper_data} if $p{debug} ;
my $container = ref_or_ld($tree, $p{wrapper_ld});
+ warn "container: " . $container if $p{debug} ;
warn "wrapper_(preproc): " . $container->as_HTML if $p{debug} ;
$p{wrapper_proc}->($container) if defined $p{wrapper_proc} ;
warn "wrapper_(postproc): " . $container->as_HTML if $p{debug} ;
# ++$DEBUG if $table{debug} ;
# Get the table element
- warn 1;
+ #warn 1;
$table->{table_node} = ref_or_ld( $tree, $p{table_ld} ) ;
- warn 2;
+ #warn 2;
$table->{table_node} or confess
"table tag not found via " . Dumper($p{table_ld}) ;
if defined $p{tr_proc};
warn "data row redux: " . Dumper $row if $p{debug};
- warn 3.3;
+ #warn 3.3;
$p{td_proc}->($new_tr_node, $row);
push @table_rows, $new_tr_node;
- warn 4.4;
+ #warn 4.4;
redo;
}
my $select = {};
my $select_node = $s->look_down(id => $select{select_label});
+ warn "Select Node: " . $select_node if $select{debug};
- my $option = $select_node->look_down('_tag' => 'option');
+ unless ($select{append}) {
+ for my $option ($select_node->look_down('_tag' => 'option')) {
+ $option->delete;
+ }
+ }
-# warn $option;
+ my $option = HTML::Element->new('option');
+ warn "Option Node: " . $option if $select{debug};
$option->detach;
while (my $row = $select{data_iter}->($select{data}))
{
-# warn Dumper($row);
- my $o = $option->clone;
- $o->attr('value', $select{option_value}->($row));
- $o->attr('SELECTED', 1) if ($select{option_selected}->($row)) ;
-
- $o->replace_content($select{option_content}->($row));
- $select_node->push_content($o);
+ warn "Data Row:" . Dumper($row) if $select{debug};
+ my $o = $option->clone;
+ $o->attr('value', $select{option_value}->($row));
+ $o->attr('SELECTED', 1) if (exists $select{option_selected} and $select{option_selected}->($row)) ;
+
+ $o->replace_content($select{option_content}->($row));
+ $select_node->push_content($o);
+ warn $o->as_HTML if $select{debug};
}
=head2 Tree Rewriting Methods
+=head3 $elem->hash_map(hash => \%h, to_attr => $attr, excluding => \@excluded)
+
+This method is designed to take a hashref and populate a series of elements. For example:
+
+
+ <table>
+ <tr sclass="tr" class="alt" align="left" valign="top">
+ <td smap="people_id">1</td>
+ <td smap="phone">(877) 255-3239</td>
+ <td smap="password">*********</td>
+ </tr>
+ </table>
+
+In the table above, there are several attributes named C<< smap >>. If we have a hashref whose keys are the same:
+
+ my %data = (people_id => 888, phone => '444-4444', password => 'dont-you-dare-render');
+
+Then a single API call allows us to populate the HTML while excluding those ones we dont:
+
+ $tree->hash_map(hash => \%data, to_attr => 'sid', excluding => ['password']);
+
+Of course, the other way to prevent rendering some of the hash mapping is to not give that element the attr
+you plan to use for hash mapping.
+
+
=head3 $elem->replace_content(@new_elem)
Replaces all of C<$elem>'s content with C<@new_elem>.
After finding the node, it detaches the node's content and pushes $content as the node's content.
-=head3 $tree->content_handler($sid_value , $content)
+=head3 $tree->content_handler(%id_content)
This is a convenience method. Because the look_down criteria will often simply be:
$elem->set_child_content(sid => 'fixme', 'new text')
+PLEASE NOTE: you can pass a hash whose keys are C<id>s and whose values are the content you want there and it will perform the replacement on each hash member:
+
+ my %id_content = (name => "Terrence Brannon",
+ email => 'tbrannon@in.com',
+ balance => 666,
+ content => $main_content);
+
+ $tree->content_handler(%id_content);
+
=head3 $tree->highlander($subtree_span_id, $conditionals, @conditionals_args)
This allows for "if-then-else" style processing. Highlander was a movie in
remains.
Otherwise our "else" condition fires and the child with id C<welcome> remains.
+=head3 $tree->passover($id_of_element)
+
+In some cases, you know exactly which element should survive. In this case,
+you can simply call C<passover> to remove it's siblings. For the HTML
+above, you could delete C<under10> and C<welcome> by simply calling:
+
+ $tree->passover('under18');
+
=head3 $tree->highlander2($tree, $conditionals, @conditionals_args)
Right around the same time that C<table2()> came into being, Seamstress
-=head2 Tree-Building Methods: Unrolling an array via a single sample element (<ul> container)
+=head2 Tree-Building Methods
+
+
+
+=head3 Unrolling an array via a single sample element (<ul> container)
This is best described by example. Given this HTML:
</body>
</html>
-=head2 Tree-Building Methods: Unrolling an array via n sample elements (<dl> container)
+=head3 Unrolling an array via n sample elements (<dl> container)
C<iter()> was fine for awhile, but some things
(e.g. definition lists) need a more general function to make them easy to
);
-=head2 Tree-Building Methods: Select Unrolling
+
+
+=head3 Select Unrolling
The C<unroll_select> method has this API:
option_selected => $closure, # boolean to decide if SELECTED
data => $data # the data to be put into the SELECT
data_iter => $closure # the thing that will get a row of data
+ debug => $boolean,
+ append => $boolean, # remove the sample <OPTION> data or append?
);
Here's an example:
option_content => sub { my $row = shift; $row->clan_name },
option_selected => sub { my $row = shift; $row->selected },
data => \@query_results,
- data_iter => sub { my $data = shift; $data->next }
- )
+ data_iter => sub { my $data = shift; $data->next },
+ append => 0,
+ debug => 0
+ );