| blib/lib/Mojolicious/Plugin/TagHelpers.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 132 | 132 | 100.0 |
| branch | 56 | 56 | 100.0 |
| condition | 22 | 23 | 95.6 |
| subroutine | 39 | 39 | 100.0 |
| pod | 1 | 1 | 100.0 |
| total | 250 | 251 | 99.6 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package Mojolicious::Plugin::TagHelpers; | ||||||
| 2 | 48 | 48 | 367 | use Mojo::Base 'Mojolicious::Plugin'; | |||
| 48 | 122 | ||||||
| 48 | 2670 | ||||||
| 3 | |||||||
| 4 | 48 | 48 | 350 | use Mojo::ByteStream; | |||
| 48 | 120 | ||||||
| 48 | 2126 | ||||||
| 5 | 48 | 48 | 375 | use Mojo::DOM::HTML qw(tag_to_html); | |||
| 48 | 298 | ||||||
| 48 | 3022 | ||||||
| 6 | 48 | 48 | 349 | use Scalar::Util qw(blessed); | |||
| 48 | 135 | ||||||
| 48 | 136912 | ||||||
| 7 | |||||||
| 8 | sub register { | ||||||
| 9 | 104 | 104 | 1 | 357 | my ($self, $app) = @_; | ||
| 10 | |||||||
| 11 | # Text field variations | ||||||
| 12 | 104 | 370 | my @time = qw(date month time week); | ||||
| 13 | 104 | 300 | for my $name (@time, qw(color email number range search tel text url)) { | ||||
| 14 | 1248 | 72 | 6442 | $app->helper("${name}_field" => sub { _input(@_, type => $name) }); | |||
| 72 | 261 | ||||||
| 15 | } | ||||||
| 16 | 104 | 2 | 775 | $app->helper(datetime_field => sub { _input(@_, type => 'datetime-local') }); | |||
| 2 | 18 | ||||||
| 17 | |||||||
| 18 | 104 | 512 | my @helpers = ( | ||||
| 19 | qw(asset_tag csrf_field form_for hidden_field javascript label_for link_to select_field stylesheet submit_button), | ||||||
| 20 | qw(tag_with_error text_area) | ||||||
| 21 | ); | ||||||
| 22 | 104 | 1201 | $app->helper($_ => __PACKAGE__->can("_$_")) for @helpers; | ||||
| 23 | |||||||
| 24 | 104 | 5 | 814 | $app->helper(button_to => sub { _button_to(0, @_) }); | |||
| 5 | 14 | ||||||
| 25 | 104 | 24 | 740 | $app->helper(check_box => sub { _input(@_, type => 'checkbox') }); | |||
| 24 | 52 | ||||||
| 26 | 104 | 9 | 729 | $app->helper(csrf_button_to => sub { _button_to(1, @_) }); | |||
| 9 | 33 | ||||||
| 27 | 104 | 6 | 801 | $app->helper(file_field => sub { _empty_field('file', @_) }); | |||
| 6 | 25 | ||||||
| 28 | 104 | 14 | 751 | $app->helper(image => sub { _tag('img', src => shift->url_for(shift), @_) }); | |||
| 14 | 55 | ||||||
| 29 | 104 | 11 | 672 | $app->helper(input_tag => sub { _input(@_) }); | |||
| 11 | 30 | ||||||
| 30 | 104 | 8 | 642 | $app->helper(password_field => sub { _empty_field('password', @_) }); | |||
| 8 | 30 | ||||||
| 31 | 104 | 6 | 732 | $app->helper(radio_button => sub { _input(@_, type => 'radio') }); | |||
| 6 | 19 | ||||||
| 32 | |||||||
| 33 | # "t" is just a shortcut for the "tag" helper | ||||||
| 34 | 104 | 139 | 761 | $app->helper($_ => sub { shift; _tag(@_) }) for qw(t tag); | |||
| 139 | 221 | ||||||
| 139 | 283 | ||||||
| 35 | } | ||||||
| 36 | |||||||
| 37 | sub _asset_tag { | ||||||
| 38 | 6 | 6 | 13 | my ($c, $target) = (shift, shift); | |||
| 39 | |||||||
| 40 | 6 | 24 | my $url = $c->url_for_asset($target); | ||||
| 41 | |||||||
| 42 | 6 | 100 | 42 | return $c->helpers->javascript($url, @_) if $target =~ /\.js$/; | |||
| 43 | 4 | 100 | 18 | return $c->helpers->stylesheet($url, @_) if $target =~ /\.css$/; | |||
| 44 | 2 | 10 | return $c->helpers->image($url, @_); | ||||
| 45 | } | ||||||
| 46 | |||||||
| 47 | sub _button_to { | ||||||
| 48 | 14 | 14 | 40 | my ($csrf, $c, $text) = (shift, shift, shift); | |||
| 49 | 14 | 100 | 44 | my $prefix = $csrf ? _csrf_field($c) : ''; | |||
| 50 | 14 | 14 | 97 | return _form_for($c, @_, sub { $prefix . _submit_button($c, $text) }); | |||
| 14 | 55 | ||||||
| 51 | } | ||||||
| 52 | |||||||
| 53 | sub _csrf_field { | ||||||
| 54 | 18 | 18 | 33 | my $c = shift; | |||
| 55 | 18 | 62 | return _hidden_field($c, csrf_token => $c->helpers->csrf_token, @_); | ||||
| 56 | } | ||||||
| 57 | |||||||
| 58 | sub _empty_field { | ||||||
| 59 | 14 | 14 | 44 | my ($type, $c, $name) = (shift, shift, shift); | |||
| 60 | 14 | 43 | return _validation($c, $name, 'input', name => $name, @_, type => $type); | ||||
| 61 | } | ||||||
| 62 | |||||||
| 63 | sub _form_for { | ||||||
| 64 | 65 | 65 | 203 | my ($c, @url) = (shift, shift); | |||
| 65 | 65 | 100 | 243 | push @url, shift if ref $_[0] eq 'HASH'; | |||
| 66 | |||||||
| 67 | # Method detection | ||||||
| 68 | 65 | 206 | my $r = $c->app->routes->lookup($url[0]); | ||||
| 69 | 65 | 100 | 282 | my $method = $r ? $r->suggested_method : 'GET'; | |||
| 70 | 65 | 100 | 676 | my @post = $method ne 'GET' ? (method => 'POST') : (); | |||
| 71 | |||||||
| 72 | 65 | 207 | my $url = $c->url_for(@url); | ||||
| 73 | 65 | 100 | 100 | 293 | $url->query({_method => $method}) if @post && $method ne 'POST'; | ||
| 74 | 65 | 211 | return _tag('form', action => $url, @post, @_); | ||||
| 75 | } | ||||||
| 76 | |||||||
| 77 | sub _hidden_field { | ||||||
| 78 | 76 | 76 | 270 | my ($c, $name, $value) = (shift, shift, shift); | |||
| 79 | 76 | 229 | return _tag('input', name => $name, value => $value, @_, type => 'hidden'); | ||||
| 80 | } | ||||||
| 81 | |||||||
| 82 | sub _input { | ||||||
| 83 | 115 | 115 | 289 | my ($c, $name) = (shift, shift); | |||
| 84 | 115 | 100 | 525 | my %attrs = @_ % 2 ? (value => shift, @_) : @_; | |||
| 85 | |||||||
| 86 | 115 | 100 | 227 | if (my @values = @{$c->every_param($name)}) { | |||
| 115 | 409 | ||||||
| 87 | |||||||
| 88 | # Checkbox or radiobutton | ||||||
| 89 | 45 | 100 | 143 | my $type = $attrs{type} || ''; | |||
| 90 | 45 | 100 | 100 | 165 | if ($type eq 'checkbox' || $type eq 'radio') { | ||
| 91 | 23 | 100 | 59 | my $value = $attrs{value} // 'on'; | |||
| 92 | 23 | 37 | delete $attrs{checked}; | ||||
| 93 | 23 | 100 | 58 | $attrs{checked} = undef if grep { $_ eq $value } @values; | |||
| 36 | 111 | ||||||
| 94 | } | ||||||
| 95 | |||||||
| 96 | # Others | ||||||
| 97 | 22 | 60 | else { $attrs{value} = $values[-1] } | ||||
| 98 | } | ||||||
| 99 | |||||||
| 100 | 115 | 502 | return _validation($c, $name, 'input', name => $name, %attrs); | ||||
| 101 | } | ||||||
| 102 | |||||||
| 103 | sub _javascript { | ||||||
| 104 | 120 | 120 | 234 | my $c = shift; | |||
| 105 | 120 | 100 | 356 | my $content = ref $_[-1] eq 'CODE' ? "//() . "\n//]]>" : ''; | |||
| 106 | 120 | 100 | 587 | my @src = @_ % 2 ? (src => $c->url_for(shift)) : (); | |||
| 107 | 120 | 120 | 731 | return _tag('script', @src, @_, sub {$content}); | |||
| 120 | 378 | ||||||
| 108 | } | ||||||
| 109 | |||||||
| 110 | sub _label_for { | ||||||
| 111 | 10 | 10 | 32 | my ($c, $name) = (shift, shift); | |||
| 112 | 10 | 100 | 34 | my $content = ref $_[-1] eq 'CODE' ? pop : shift; | |||
| 113 | 10 | 37 | return _validation($c, $name, 'label', for => $name, @_, $content); | ||||
| 114 | } | ||||||
| 115 | |||||||
| 116 | sub _link_to { | ||||||
| 117 | 41 | 41 | 139 | my ($c, $content) = (shift, shift); | |||
| 118 | 41 | 99 | my @url = ($content); | ||||
| 119 | |||||||
| 120 | # Content | ||||||
| 121 | 41 | 100 | 147 | unless (ref $_[-1] eq 'CODE') { | |||
| 122 | 27 | 65 | @url = (shift); | ||||
| 123 | 27 | 72 | push @_, $content; | ||||
| 124 | } | ||||||
| 125 | |||||||
| 126 | # Captures | ||||||
| 127 | 41 | 100 | 131 | push @url, shift if ref $_[0] eq 'HASH'; | |||
| 128 | |||||||
| 129 | 41 | 156 | return _tag('a', href => $c->url_for(@url), @_); | ||||
| 130 | } | ||||||
| 131 | |||||||
| 132 | sub _option { | ||||||
| 133 | 64 | 64 | 122 | my ($values, $pair) = @_; | |||
| 134 | |||||||
| 135 | 64 | 100 | 174 | $pair = [$pair => $pair] unless ref $pair eq 'ARRAY'; | |||
| 136 | 64 | 210 | my %attrs = (value => $pair->[1], @$pair[2 .. $#$pair]); | ||||
| 137 | 64 | 100 | 156 | delete $attrs{selected} if keys %$values; | |||
| 138 | 64 | 100 | 147 | $attrs{selected} = undef if $values->{$pair->[1]}; | |||
| 139 | |||||||
| 140 | 64 | 174 | return _tag('option', %attrs, $pair->[0]); | ||||
| 141 | } | ||||||
| 142 | |||||||
| 143 | sub _select_field { | ||||||
| 144 | 26 | 26 | 83 | my ($c, $name, $options, %attrs) = (shift, shift, shift, @_); | |||
| 145 | |||||||
| 146 | 26 | 49 | my %values = map { $_ => 1 } grep {defined} @{$c->every_param($name)}; | ||||
| 16 | 71 | ||||||
| 17 | 47 | ||||||
| 26 | 84 | ||||||
| 147 | |||||||
| 148 | 26 | 63 | my $groups = ''; | ||||
| 149 | 26 | 62 | for my $group (@$options) { | ||||
| 150 | |||||||
| 151 | # "optgroup" tag | ||||||
| 152 | 50 | 100 | 66 | 218 | if (blessed $group && $group->isa('Mojo::Collection')) { | ||
| 153 | 10 | 31 | my ($label, $values, %attrs) = @$group; | ||||
| 154 | 10 | 17 | my $content = join '', map { _option(\%values, $_) } @$values; | ||||
| 24 | 54 | ||||||
| 155 | 10 | 10 | 57 | $groups .= _tag('optgroup', label => $label, %attrs, sub {$content}); | |||
| 10 | 22 | ||||||
| 156 | } | ||||||
| 157 | |||||||
| 158 | # "option" tag | ||||||
| 159 | 40 | 95 | else { $groups .= _option(\%values, $group) } | ||||
| 160 | } | ||||||
| 161 | |||||||
| 162 | 26 | 26 | 166 | return _validation($c, $name, 'select', name => $name, %attrs, sub {$groups}); | |||
| 26 | 78 | ||||||
| 163 | } | ||||||
| 164 | |||||||
| 165 | sub _stylesheet { | ||||||
| 166 | 122 | 122 | 298 | my $c = shift; | |||
| 167 | 122 | 100 | 355 | my $content = ref $_[-1] eq 'CODE' ? "/*() . "\n/*]]>*/" : ''; | |||
| 168 | 122 | 100 | 2 | 351 | return _tag('style', @_, sub {$content}) unless @_ % 2; | ||
| 2 | 8 | ||||||
| 169 | 120 | 414 | return _tag('link', rel => 'stylesheet', href => $c->url_for(shift), @_); | ||||
| 170 | } | ||||||
| 171 | |||||||
| 172 | sub _submit_button { | ||||||
| 173 | 50 | 100 | 50 | 201 | my ($c, $value) = (shift, shift // 'Ok'); | ||
| 174 | 50 | 150 | return _tag('input', value => $value, @_, type => 'submit'); | ||||
| 175 | } | ||||||
| 176 | |||||||
| 177 | 876 | 876 | 2607 | sub _tag { Mojo::ByteStream->new(tag_to_html(@_)) } | |||
| 178 | |||||||
| 179 | sub _tag_with_error { | ||||||
| 180 | 8 | 8 | 22 | my ($c, $tag) = (shift, shift); | |||
| 181 | 8 | 100 | 54 | my ($content, %attrs) = (@_ % 2 ? pop : undef, @_); | |||
| 182 | 8 | 100 | 36 | $attrs{class} .= $attrs{class} ? ' field-with-error' : 'field-with-error'; | |||
| 183 | 8 | 100 | 36 | return _tag($tag, %attrs, defined $content ? $content : ()); | |||
| 184 | } | ||||||
| 185 | |||||||
| 186 | sub _text_area { | ||||||
| 187 | 13 | 13 | 37 | my ($c, $name) = (shift, shift); | |||
| 188 | |||||||
| 189 | 13 | 100 | 42 | my $cb = ref $_[-1] eq 'CODE' ? pop : undef; | |||
| 190 | 13 | 100 | 37 | my $content = @_ % 2 ? shift : undef; | |||
| 191 | 13 | 100 | 45 | $content = $c->param($name) // $content // $cb // ''; | |||
| 100 | |||||||
| 100 | |||||||
| 192 | |||||||
| 193 | 13 | 57 | return _validation($c, $name, 'textarea', name => $name, @_, $content); | ||||
| 194 | } | ||||||
| 195 | |||||||
| 196 | sub _validation { | ||||||
| 197 | 178 | 178 | 404 | my ($c, $name) = (shift, shift); | |||
| 198 | 178 | 100 | 587 | return _tag(@_) unless $c->helpers->validation->has_error($name); | |||
| 199 | 11 | 36 | return $c->helpers->tag_with_error(@_); | ||||
| 200 | } | ||||||
| 201 | |||||||
| 202 | 1; | ||||||
| 203 | |||||||
| 204 | =encoding utf8 | ||||||
| 205 | |||||||
| 206 | =head1 NAME | ||||||
| 207 | |||||||
| 208 | Mojolicious::Plugin::TagHelpers - Tag helpers plugin | ||||||
| 209 | |||||||
| 210 | =head1 SYNOPSIS | ||||||
| 211 | |||||||
| 212 | # Mojolicious | ||||||
| 213 | $app->plugin('TagHelpers'); | ||||||
| 214 | |||||||
| 215 | # Mojolicious::Lite | ||||||
| 216 | plugin 'TagHelpers'; | ||||||
| 217 | |||||||
| 218 | =head1 DESCRIPTION | ||||||
| 219 | |||||||
| 220 | L | ||||||
| 221 | Standard|https://html.spec.whatwg.org>. | ||||||
| 222 | |||||||
| 223 | Most form helpers can automatically pick up previous input values and will show them as default. You can also use | ||||||
| 224 | L |
||||||
| 225 | automatically. | ||||||
| 226 | |||||||
| 227 | % param country => 'germany' unless param 'country'; | ||||||
| 228 | <%= radio_button country => 'germany' %> Germany | ||||||
| 229 | <%= radio_button country => 'france' %> France | ||||||
| 230 | <%= radio_button country => 'uk' %> UK | ||||||
| 231 | |||||||
| 232 | For fields that failed validation with L |
||||||
| 233 | class will be automatically added through L"tag_with_error">, to make styling with CSS easier. | ||||||
| 234 | |||||||
| 235 | |||||||
| 236 | |||||||
| 237 | This is a core plugin, that means it is always enabled and its code a good example for learning how to build new | ||||||
| 238 | plugins, you're welcome to fork it. | ||||||
| 239 | |||||||
| 240 | See L |
||||||
| 241 | |||||||
| 242 | =head1 HELPERS | ||||||
| 243 | |||||||
| 244 | L |
||||||
| 245 | |||||||
| 246 | =head2 asset_tag | ||||||
| 247 | |||||||
| 248 | %= asset_tag '/app.js' | ||||||
| 249 | %= asset_tag '/app.js', async => 'async' | ||||||
| 250 | |||||||
| 251 | Generate C | ||||||
| 454 | |||||||
| 455 | |||||||
| 458 | |||||||
| 459 | =head2 label_for | ||||||
| 460 | |||||||
| 461 | %= label_for first_name => 'First name' | ||||||
| 462 | %= label_for first_name => 'First name', class => 'user' | ||||||
| 463 | %= label_for first_name => begin | ||||||
| 464 | First name | ||||||
| 465 | % end | ||||||
| 466 | %= label_for first_name => (class => 'user') => begin | ||||||
| 467 | First name | ||||||
| 468 | % end | ||||||
| 469 | |||||||
| 470 | Generate C | ||||||
| 471 | |||||||
| 472 | |||||||
| 473 | |||||||
| 474 | |||||||
| 475 | First name | ||||||
| 476 | |||||||
| 477 | |||||||
| 478 | First name | ||||||
| 479 | |||||||
| 480 | |||||||
| 481 | =head2 link_to | ||||||
| 482 | |||||||
| 483 | %= link_to Home => 'index' | ||||||
| 484 | %= link_to Home => 'index' => {format => 'txt'} => (class => 'menu') | ||||||
| 485 | %= link_to index => {format => 'txt'} => (class => 'menu') => begin | ||||||
| 486 | Home | ||||||
| 487 | % end | ||||||
| 488 | %= link_to Contact => 'mailto:sri@example.com' | ||||||
| 489 | <%= link_to index => begin %>Home<% end %> | ||||||
| 490 | <%= link_to '/file.txt' => begin %>File<% end %> | ||||||
| 491 | <%= link_to 'https://mojolicious.org' => begin %>Mojolicious<% end %> | ||||||
| 492 | <%= link_to url_for->query(foo => 'bar')->to_abs => begin %>Retry<% end %> | ||||||
| 493 | |||||||
| 494 | Generate portable C tag with L |
||||||
| 495 | content. | ||||||
| 496 | |||||||
| 497 | Home | ||||||
| 498 | Home | ||||||
| 499 | |||||||
| 500 | Home | ||||||
| 501 | |||||||
| 502 | Contact | ||||||
| 503 | Home | ||||||
| 504 | File | ||||||
| 505 | Mojolicious | ||||||
| 506 | Retry | ||||||
| 507 | |||||||
| 508 | The first argument to C |
||||||
| 509 | final argument is Perl code such as a template block (created with the | ||||||
| 510 | C |
||||||
| 511 | omitted at the start of the argument list, and the block will become | ||||||
| 512 | the link content. | ||||||
| 513 | |||||||
| 514 | =head2 month_field | ||||||
| 515 | |||||||
| 516 | %= month_field 'vacation' | ||||||
| 517 | %= month_field vacation => '2012-12' | ||||||
| 518 | %= month_field vacation => '2012-12', id => 'foo' | ||||||
| 519 | |||||||
| 520 | Generate C tag of type C |
||||||
| 521 | |||||||
| 522 | |||||||
| 523 | |||||||
| 524 | |||||||
| 525 | |||||||
| 526 | =head2 number_field | ||||||
| 527 | |||||||
| 528 | %= number_field 'age' | ||||||
| 529 | %= number_field age => 25 | ||||||
| 530 | %= number_field age => 25, id => 'foo', min => 0, max => 200 | ||||||
| 531 | |||||||
| 532 | Generate C tag of type C |
||||||
| 533 | |||||||
| 534 | |||||||
| 535 | |||||||
| 536 | |||||||
| 537 | |||||||
| 538 | =head2 password_field | ||||||
| 539 | |||||||
| 540 | %= password_field 'pass' | ||||||
| 541 | %= password_field 'pass', id => 'foo' | ||||||
| 542 | |||||||
| 543 | Generate C tag of type C |
||||||
| 544 | |||||||
| 545 | |||||||
| 546 | |||||||
| 547 | |||||||
| 548 | =head2 radio_button | ||||||
| 549 | |||||||
| 550 | %= radio_button 'test' | ||||||
| 551 | %= radio_button country => 'germany' | ||||||
| 552 | %= radio_button country => 'germany', checked => undef, id => 'foo' | ||||||
| 553 | |||||||
| 554 | Generate C tag of type C |
||||||
| 555 | |||||||
| 556 | |||||||
| 557 | |||||||
| 558 | |||||||
| 559 | |||||||
| 560 | =head2 range_field | ||||||
| 561 | |||||||
| 562 | %= range_field 'age' | ||||||
| 563 | %= range_field age => 25 | ||||||
| 564 | %= range_field age => 25, id => 'foo', min => 0, max => 200 | ||||||
| 565 | |||||||
| 566 | Generate C tag of type C |
||||||
| 567 | |||||||
| 568 | |||||||
| 569 | |||||||
| 570 | |||||||
| 571 | |||||||
| 572 | =head2 search_field | ||||||
| 573 | |||||||
| 574 | %= search_field 'q' | ||||||
| 575 | %= search_field q => 'perl' | ||||||
| 576 | %= search_field q => 'perl', id => 'foo' | ||||||
| 577 | |||||||
| 578 | Generate C tag of type C |
||||||
| 579 | |||||||
| 580 | |||||||
| 581 | |||||||
| 582 | |||||||
| 583 | |||||||
| 584 | =head2 select_field | ||||||
| 585 | |||||||
| 586 | %= select_field country => ['de', 'en'] | ||||||
| 587 | %= select_field country => [[Germany => 'de'], 'en'], id => 'eu' | ||||||
| 588 | %= select_field country => [[Germany => 'de', selected => 'selected'], 'en'] | ||||||
| 589 | %= select_field country => [c(EU => [[Germany => 'de'], 'en'], id => 'eu')] | ||||||
| 590 | %= select_field country => [c(EU => ['de', 'en']), c(Asia => ['cn', 'jp'])] | ||||||
| 591 | |||||||
| 592 | Generate C | ||||||
| 593 | Previous input values will automatically get picked up and shown as default. | ||||||
| 594 | |||||||
| 595 | |||||||
| 596 | |||||||
| 597 | |||||||
| 598 | |||||||
| 599 | |||||||
| 600 | |||||||
| 601 | |||||||
| 602 | |||||||
| 603 | |||||||
| 604 | |||||||
| 605 | |||||||
| 606 | |||||||
| 607 | |||||||
| 608 | |||||||
| 609 | |||||||
| 610 | |||||||
| 611 | |||||||
| 612 | |||||||
| 613 | |||||||
| 614 | |||||||
| 615 | |||||||
| 616 | |||||||
| 617 | |||||||
| 618 | |||||||
| 619 | |||||||
| 620 | |||||||
| 621 | |||||||
| 622 | |||||||
| 623 | |||||||
| 624 | =head2 stylesheet | ||||||
| 625 | |||||||
| 626 | %= stylesheet '/foo.css' | ||||||
| 627 | %= stylesheet '/foo.css', title => 'Foo style' | ||||||
| 628 | %= stylesheet begin | ||||||
| 629 | body {color: #000} | ||||||
| 630 | % end | ||||||
| 631 | |||||||
| 632 | Generate portable C | ||||||
| 639 | |||||||
| 640 | =head2 submit_button | ||||||
| 641 | |||||||
| 642 | %= submit_button | ||||||
| 643 | %= submit_button 'Ok!', id => 'foo' | ||||||
| 644 | |||||||
| 645 | Generate C tag of type C |
||||||
| 646 | |||||||
| 647 | |||||||
| 648 | |||||||
| 649 | |||||||
| 650 | =head2 t | ||||||
| 651 | |||||||
| 652 | %= t div => 'test & 123' | ||||||
| 653 | |||||||
| 654 | Alias for L"tag">. | ||||||
| 655 | |||||||
| 656 | test & 123 |
||||||
| 657 | |||||||
| 658 | =head2 tag | ||||||
| 659 | |||||||
| 660 | %= tag 'br' | ||||||
| 661 | %= tag 'div' | ||||||
| 662 | %= tag 'div', id => 'foo', hidden => undef | ||||||
| 663 | %= tag 'div', 'test & 123' | ||||||
| 664 | %= tag 'div', id => 'foo', 'test & 123' | ||||||
| 665 | %= tag 'div', data => {my_id => 1, Name => 'test'}, 'test & 123' | ||||||
| 666 | %= tag div => begin | ||||||
| 667 | test & 123 | ||||||
| 668 | % end | ||||||
| 669 | <%= tag div => (id => 'foo') => begin %>test & 123<% end %> | ||||||
| 670 | |||||||
| 671 | Alias for L |
||||||
| 672 | |||||||
| 673 | |
||||||
| 674 | |||||||
| 675 | |||||||
| 676 | test & 123 |
||||||
| 677 | test & 123 |
||||||
| 678 | test & 123 |
||||||
| 679 | |
||||||
| 680 | test & 123 | ||||||
| 681 | |||||||
| 682 | test & 123 |
||||||
| 683 | |||||||
| 684 | Very useful for reuse in more specific tag helpers. | ||||||
| 685 | |||||||
| 686 | my $output = $c->tag('meta'); | ||||||
| 687 | my $output = $c->tag('meta', charset => 'UTF-8'); | ||||||
| 688 | my $output = $c->tag('div', ' This will be escaped '); |
||||||
| 689 | my $output = $c->tag('div', sub { ' This will not be escaped ' }); |
||||||
| 690 | |||||||
| 691 | Results are automatically wrapped in L |
||||||
| 692 | templates. | ||||||
| 693 | |||||||
| 694 | =head2 tag_with_error | ||||||
| 695 | |||||||
| 696 | %= tag_with_error 'input', class => 'foo' | ||||||
| 697 | |||||||
| 698 | Same as L"tag">, but adds the class C |
||||||
| 699 | |||||||
| 700 | |||||||
| 701 | |||||||
| 702 | =head2 tel_field | ||||||
| 703 | |||||||
| 704 | %= tel_field 'work' | ||||||
| 705 | %= tel_field work => '123456789' | ||||||
| 706 | %= tel_field work => '123456789', id => 'foo' | ||||||
| 707 | |||||||
| 708 | Generate C tag of type C |
||||||
| 709 | |||||||
| 710 | |||||||
| 711 | |||||||
| 712 | |||||||
| 713 | |||||||
| 714 | =head2 text_area | ||||||
| 715 | |||||||
| 716 | %= text_area 'story' | ||||||
| 717 | %= text_area 'story', cols => 40 | ||||||
| 718 | %= text_area story => 'Default', cols => 40 | ||||||
| 719 | %= text_area story => (cols => 40) => begin | ||||||
| 720 | Default | ||||||
| 721 | % end | ||||||
| 722 | |||||||
| 723 | Generate C | ||||||
| 724 | |||||||
| 725 | |||||||
| 726 | |||||||
| 727 | |||||||
| 728 | |||||||
| 729 | Default | ||||||
| 730 | |||||||
| 731 | |||||||
| 732 | =head2 text_field | ||||||
| 733 | |||||||
| 734 | %= text_field 'first_name' | ||||||
| 735 | %= text_field first_name => 'Default' | ||||||
| 736 | %= text_field first_name => 'Default', class => 'user' | ||||||
| 737 | |||||||
| 738 | Generate C tag of type C |
||||||
| 739 | |||||||
| 740 | |||||||
| 741 | |||||||
| 742 | |||||||
| 743 | |||||||
| 744 | =head2 time_field | ||||||
| 745 | |||||||
| 746 | %= time_field 'start' | ||||||
| 747 | %= time_field start => '23:59:59' | ||||||
| 748 | %= time_field start => '23:59:59', id => 'foo' | ||||||
| 749 | |||||||
| 750 | Generate C tag of type C | ||||||
| 751 | |||||||
| 752 | |||||||
| 753 | |||||||
| 754 | |||||||
| 755 | |||||||
| 756 | =head2 url_field | ||||||
| 757 | |||||||
| 758 | %= url_field 'address' | ||||||
| 759 | %= url_field address => 'https://mojolicious.org' | ||||||
| 760 | %= url_field address => 'https://mojolicious.org', id => 'foo' | ||||||
| 761 | |||||||
| 762 | Generate C tag of type C |
||||||
| 763 | |||||||
| 764 | |||||||
| 765 | |||||||
| 766 | |||||||
| 767 | |||||||
| 768 | =head2 week_field | ||||||
| 769 | |||||||
| 770 | %= week_field 'vacation' | ||||||
| 771 | %= week_field vacation => '2012-W17' | ||||||
| 772 | %= week_field vacation => '2012-W17', id => 'foo' | ||||||
| 773 | |||||||
| 774 | Generate C tag of type C |
||||||
| 775 | |||||||
| 776 | |||||||
| 777 | |||||||
| 778 | |||||||
| 779 | |||||||
| 780 | =head1 METHODS | ||||||
| 781 | |||||||
| 782 | L |
||||||
| 783 | ones. | ||||||
| 784 | |||||||
| 785 | =head2 register | ||||||
| 786 | |||||||
| 787 | $plugin->register(Mojolicious->new); | ||||||
| 788 | |||||||
| 789 | Register helpers in L |
||||||
| 790 | |||||||
| 791 | =head1 SEE ALSO | ||||||
| 792 | |||||||
| 793 | L |
||||||
| 794 | |||||||
| 795 | =cut |