1use strict;
2
3package HTML::FormFu::Element::Block;
4$HTML::FormFu::Element::Block::VERSION = '2.07';
5# ABSTRACT: Block element
6
7use Moose;
8use MooseX::Attribute::Chained;
9
10extends 'HTML::FormFu::Element';
11
12with 'HTML::FormFu::Role::CreateChildren',
13    'HTML::FormFu::Role::GetProcessors',
14    'HTML::FormFu::Role::ContainsElements',
15    'HTML::FormFu::Role::ContainsElementsSharedWithField',
16    'HTML::FormFu::Role::FormAndBlockMethods',
17    'HTML::FormFu::Role::FormBlockAndFieldMethods';
18
19use HTML::FormFu::Constants qw( $EMPTY_STR );
20use HTML::FormFu::Util qw( _get_elements xml_escape process_attrs );
21use Clone ();
22use List::Util 1.45 qw( uniq );
23use Carp qw( croak );
24
25has tag                  => ( is => 'rw', traits => ['Chained'] );
26has nested_name          => ( is => 'rw', traits => ['Chained'] );
27has original_nested_name => ( is => 'rw', traits => ['Chained'] );
28has auto_block_id        => ( is => 'rw', traits => ['Chained'] );
29
30has _elements => (
31    is      => 'rw',
32    default => sub { [] },
33    lazy    => 1,
34    isa     => 'ArrayRef',
35);
36
37__PACKAGE__->mk_output_accessors(qw( content ));
38
39*elements     = \&element;
40*constraints  = \&constraint;
41*deflators    = \&deflator;
42*filters      = \&filter;
43*inflators    = \&inflator;
44*validators   = \&validator;
45*transformers = \&transformer;
46*plugins      = \&plugin;
47
48after BUILD => sub {
49    my ( $self, $args ) = @_;
50
51    $self->filename('block');
52    $self->tag('div');
53    $self->is_block(1);
54
55    return;
56};
57
58sub _single_plugin {
59    my ( $self, $arg ) = @_;
60
61    if ( !ref $arg ) {
62        $arg = { type => $arg };
63    }
64    elsif ( ref $arg eq 'HASH' ) {
65        $arg = {%$arg};    # shallow clone
66    }
67    else {
68        croak 'invalid args';
69    }
70
71    my @names = map { ref $_ ? @$_ : $_ }
72        grep {defined} ( delete $arg->{name}, delete $arg->{names} );
73
74    if ( !@names ) {
75        @names = uniq
76            grep {defined}
77            map  { $_->nested_name } @{ $self->get_fields };
78    }
79
80    croak "no field names to add plugin to" if !@names;
81
82    my $type = delete $arg->{type};
83
84    my @return;
85
86    for my $x (@names) {
87        for my $field ( @{ $self->get_fields( { nested_name => $x } ) } ) {
88            my $new = $field->_require_plugin( $type, $arg );
89            push @{ $field->_plugins }, $new;
90            push @return, $new;
91        }
92    }
93
94    return @return;
95}
96
97sub pre_process {
98    my ($self) = @_;
99
100    map { $_->pre_process } @{ $self->_elements };
101
102    return;
103}
104
105sub process {
106    my ($self) = @_;
107
108    map { $_->process } @{ $self->_elements };
109
110    return;
111}
112
113sub post_process {
114    my ($self) = @_;
115
116    map { $_->post_process } @{ $self->_elements };
117
118    return;
119}
120
121sub render_data {
122    my $self = shift;
123
124    my $render = $self->render_data_non_recursive( { @_ ? %{ $_[0] } : () } );
125
126    $render->{elements} = [ map { $_->render_data } @{ $self->_elements } ];
127
128    return $render;
129}
130
131sub render_data_non_recursive {
132    my ( $self, $args ) = @_;
133
134    my $render = $self->SUPER::render_data_non_recursive(
135        {   tag     => $self->tag,
136            content => xml_escape( $self->content ),
137            $args ? %$args : (),
138        } );
139
140    return $render;
141}
142
143sub prepare_id {
144    my ( $self, $render ) = @_;
145
146    if (  !defined $render->{attributes}{id}
147        && defined $self->auto_block_id
148        && length $self->auto_block_id )
149    {
150        my $form_name
151            = defined $self->form->id
152            ? $self->form->id
153            : $EMPTY_STR;
154
155        my %string = ( f => $form_name, );
156
157        my $id = $self->auto_block_id;
158        $id =~ s/%([f])/$string{$1}/g;
159
160        if ( defined( my $count = $self->repeatable_count ) ) {
161            $id =~ s/%r/$count/g;
162        }
163
164        $render->{attributes}{id} = $id;
165    }
166
167    return;
168}
169
170sub string {
171    my ( $self, $args ) = @_;
172
173    $args ||= {};
174
175    my $render
176        = exists $args->{render_data}
177        ? $args->{render_data}
178        : $self->render_data_non_recursive;
179
180    # start_block template
181
182    my $html = '';
183
184    if ( defined $render->{tag} ) {
185        $html .= sprintf "<%s%s>",
186            $render->{tag},
187            process_attrs( $render->{attributes} ),
188            ;
189    }
190
191    if ( defined $render->{legend} ) {
192        $html .=
193            sprintf "\n<legend%s>%s</legend>",
194            defined( $render->{legend_attributes} )
195            ? process_attrs( $render->{legend_attributes} )
196            : '',
197            $render->{legend};
198    }
199
200    # block template
201
202    $html .= "\n";
203
204    if ( defined $render->{content} ) {
205        $html .= sprintf "%s\n", $render->{content};
206    }
207    else {
208        for my $elem ( @{ $self->get_elements } ) {
209
210            # call render, so that child elements can use a different renderer
211            my $elem_html = $elem->render;
212
213            # skip Blank fields
214            if ( length $elem_html ) {
215                $html .= $elem_html . "\n";
216            }
217        }
218    }
219
220    # end_block template
221
222    if ( defined $render->{tag} ) {
223        $html .= sprintf "</%s>", $render->{tag};
224    }
225
226    return $html;
227}
228
229sub start {
230    my ($self) = @_;
231
232    return $self->tt(
233        {   filename    => 'start_block',
234            render_data => $self->render_data_non_recursive,
235        } );
236}
237
238sub end {
239    my ($self) = @_;
240
241    return $self->tt(
242        {   filename    => 'end_block',
243            render_data => $self->render_data_non_recursive,
244        } );
245}
246
247sub clone {
248    my $self = shift;
249
250    my $clone = $self->SUPER::clone(@_);
251
252    $clone->_elements( [ map { $_->clone } @{ $self->_elements } ] );
253
254    map { $_->parent($clone) } @{ $clone->_elements };
255
256    $clone->default_args( Clone::clone( $self->default_args ) );
257
258    return $clone;
259}
260
261__PACKAGE__->meta->make_immutable;
262
2631;
264
265__END__
266
267=pod
268
269=encoding UTF-8
270
271=head1 NAME
272
273HTML::FormFu::Element::Block - Block element
274
275=head1 VERSION
276
277version 2.07
278
279=head1 SYNOPSIS
280
281    ---
282    elements:
283      - type: Block
284        elements:
285          - type: Text
286            name: foo
287
288      - type: Block
289        tag: span
290        content: Whatever
291
292=head1 DESCRIPTION
293
294Block element which may contain other elements.
295
296=head1 METHODS
297
298=head2 tag
299
300Specifies which tag name should be used to render the block.
301
302Default Value: 'div'
303
304=head2 content
305
306If L</content> is set, it is used as the block's contents, and any attached
307elements are ignored.
308
309=head2 content_xml
310
311Arguments: $string
312
313If you don't want the content to be XML-escaped, use the L</content_xml>
314method instead of L</content>.
315
316=head2 content_loc
317
318Arguments: $localization_key
319
320To set the content to a localized string, set L</content_loc> to a key in
321your L10N file instead of using L</content>.
322
323=head2 elements
324
325See L<HTML::FormFu/elements> for details.
326
327=head2 element
328
329See L<HTML::FormFu/element> for details.
330
331=head2 deflators
332
333See L<HTML::FormFu/deflators> for details.
334
335=head2 deflator
336
337See L<HTML::FormFu/deflator> for details.
338
339=head2 filters
340
341See L<HTML::FormFu/filters> for details.
342
343=head2 filter
344
345See L<HTML::FormFu/filter> for details.
346
347=head2 constraints
348
349See L<HTML::FormFu/constraints> for details.
350
351=head2 constraint
352
353See L<HTML::FormFu/constraint> for details.
354
355=head2 inflators
356
357See L<HTML::FormFu/inflators> for details.
358
359=head2 inflator
360
361See L<HTML::FormFu/inflator> for details.
362
363=head2 validators
364
365See L<HTML::FormFu/validators> for details.
366
367=head2 validator
368
369See L<HTML::FormFu/validator> for details.
370
371=head2 transformers
372
373See L<HTML::FormFu/transformers> for details.
374
375=head2 transformer
376
377See L<HTML::FormFu/transformer> for details.
378
379=head2 auto_datalist_id
380
381See L<HTML::FormFu/auto_datalist_id> for details.
382
383=head1 CSS CLASSES
384
385=head2 auto_id
386
387See L<HTML::FormFu/auto_id> for details.
388
389=head2 auto_block_id
390
391Arguments: [$string]
392
393If set, the Block will be given an auto-generated
394L<id|HTML::FormFu::Element/id> attribute, if it doesn't have one already.
395
396The following character substitution will be performed: C<%f> will be
397replaced by L<< $form->id|/id >>, C<%r> will be replaced by
398L<< $block->repeatable_count|HTML::FormFu::Element::Repeatable/repeatable_count >>.
399
400Default Value: not defined
401
402Unlike most other auto_* methods, this is not an 'inherited accessor'.
403
404=head2 auto_label
405
406See L<HTML::FormFu/auto_label> for details.
407
408=head2 auto_error_field_class
409
410See L<HTML::FormFu/auto_error_field_class> for details.
411
412=head2 auto_error_class
413
414See L<HTML::FormFu/auto_error_class> for details.
415
416=head2 auto_error_message
417
418See L<HTML::FormFu/auto_error_message> for details.
419
420=head2 auto_constraint_class
421
422See L<HTML::FormFu/auto_constraint_class> for details.
423
424=head2 auto_inflator_class
425
426See L<HTML::FormFu/auto_inflator_class> for details.
427
428=head2 auto_validator_class
429
430See L<HTML::FormFu/auto_validator_class> for details.
431
432=head2 auto_transformer_class
433
434See L<HTML::FormFu/auto_transformer_class> for details.
435
436=head2 default_args
437
438See L<HTML::FormFu/default_args> for details.
439
440=head1 RENDERING
441
442=head2 start
443
444=head2 end
445
446=head1 INTROSPECTION
447
448=head2 get_elements
449
450See L<HTML::FormFu/get_elements> for details.
451
452=head2 get_element
453
454See L<HTML::FormFu/get_element> for details.
455
456=head2 get_all_elements
457
458See L<HTML::FormFu/get_all_elements> for details.
459
460=head2 get_fields
461
462See L<HTML::FormFu/get_fields> for details.
463
464=head2 get_field
465
466See L<HTML::FormFu/get_field> for details.
467
468=head2 get_deflators
469
470See L<HTML::FormFu/get_deflators> for details.
471
472=head2 get_deflator
473
474See L<HTML::FormFu/get_deflator> for details.
475
476=head2 get_filters
477
478See L<HTML::FormFu/get_filters> for details.
479
480=head2 get_filter
481
482See L<HTML::FormFu/get_filter> for details.
483
484=head2 get_constraints
485
486See L<HTML::FormFu/get_constraints> for details.
487
488=head2 get_constraint
489
490See L<HTML::FormFu/get_constraint> for details.
491
492=head2 get_inflators
493
494See L<HTML::FormFu/get_inflators> for details.
495
496=head2 get_inflator
497
498See L<HTML::FormFu/get_inflator> for details.
499
500=head2 get_validators
501
502See L<HTML::FormFu/get_validators> for details.
503
504=head2 get_validator
505
506See L<HTML::FormFu/get_validator> for details.
507
508=head2 get_transformers
509
510See L<HTML::FormFu/get_transformers> for details.
511
512=head2 get_transformer
513
514See L<HTML::FormFu/get_transformer> for details.
515
516=head2 get_errors
517
518See L<HTML::FormFu/get_errors> for details.
519
520=head2 clear_errors
521
522See L<HTML::FormFu/clear_errors> for details.
523
524=head1 SEE ALSO
525
526Base-class for L<HTML::FormFu::Element::Fieldset>.
527
528Is a sub-class of, and inherits methods from L<HTML::FormFu::Element>
529
530L<HTML::FormFu>
531
532=head1 REMOVED METHODS
533
534=head2 element_defaults
535
536Has been removed; use L</default_args> instead.
537
538=head1 AUTHOR
539
540Carl Franks, C<cfranks@cpan.org>
541
542=head1 LICENSE
543
544This library is free software, you can redistribute it and/or modify it under
545the same terms as Perl itself.
546
547=head1 AUTHOR
548
549Carl Franks <cpan@fireartist.com>
550
551=head1 COPYRIGHT AND LICENSE
552
553This software is copyright (c) 2018 by Carl Franks.
554
555This is free software; you can redistribute it and/or modify it under
556the same terms as the Perl 5 programming language system itself.
557
558=cut
559