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