1 package HTML::Zoom::ActionBuilder;
4 use warnings FATAL => 'all';
6 use HTML::Zoom::Parser::BuiltIn;
7 use HTML::Zoom::EventFilter;
12 my ($tb, $name, @args) = @_;
13 confess "Don't know how to build ${name} in ${tb}"
14 unless $tb->can("build_${name}");
16 return $tb->${\"build_${name}"}(@args);
19 sub build_add_attribute {
20 my ($tb, $name, $value) = @_;
22 my ($self, $evt) = @_;
23 delete @{$evt}{qw(raw raw_attrs)};
24 if (defined $evt->{attrs}{$name}) {
25 $evt->{attrs}{$name} .= ' '.$value;
27 $evt->{attrs}{$name} = $value;
32 sub build_set_attribute {
33 my ($tb, $name, $value) = @_;
35 my ($self, $evt) = @_;
36 delete @{$evt}{qw(raw raw_attrs)};
37 $evt->{attrs}{$name} = $value;
41 sub build_add_class { shift->build_add_attribute('class' => @_) }
42 sub build_set_class { shift->build_set_attribute('class' => @_) }
44 sub build_replace_content {
46 my $raw = HTML::Zoom::Parser::BuiltIn::_simple_escape($text);
47 $tb->build_replace_content_raw($raw);
50 sub build_replace_content_raw {
53 my ($self, $evt) = @_;
54 my $in_place_close = $evt->{is_in_place_close};
55 if ($in_place_close) {
57 $evt->{is_in_place_close} = 0;
59 $self->until_close_do_last(
62 delete $_[1]->{raw} if $in_place_close;
63 $_[0]->next({ type => 'TEXT', raw => $raw })
71 my $data = $args->{data};
73 my ($self, $to_repeat) = @_;
75 if ($to_repeat->[-1]->{type} eq 'TEXT') {
76 if ($to_repeat->[-1]->{raw} =~ s/(\s+)$//) {
80 foreach my $d (@$data) {
82 HTML::Zoom::EventFilter->build_selector_pair($_, $d->{$_})
84 my $sel = HTML::Zoom::EventFilter->selector_handler(\@pairs);
85 $sel->set_next($self->get_next);
86 $sel->call($_) for @$to_repeat;
88 if (defined $stole_last) {
89 $self->next({ type => 'TEXT', raw => $stole_last });
93 my ($self, $evt) = @_;
94 return if $evt->{is_in_place_close}; # no content to repeat
96 $self->until_close_do_last(
97 sub { push(@repeat, $_[1]) },
98 sub { $_[0]->$do_repeat(\@repeat) },