File Coverage

blib/lib/HTML/FormHandler/Render/RepeatableJs.pm
Criterion Covered Total %
statement 20 20 100.0
branch 1 2 50.0
condition n/a
subroutine 3 3 100.0
pod 0 1 0.0
total 24 26 92.3


line stmt bran cond sub pod time code
1             package HTML::FormHandler::Render::RepeatableJs;
2             # ABSTRACT: role providing method to construct repeatable javascript
3             $HTML::FormHandler::Render::RepeatableJs::VERSION = '0.40068';
4 1     1   2097 use Moose::Role;
  1         4  
  1         12  
5              
6 1     1   5426 use JSON::MaybeXS ('encode_json');
  1         2  
  1         284  
7              
8              
9             sub render_repeatable_js {
10 1     1 0 3 my $self = shift;
11 1 50       50 return '' unless $self->has_for_js;
12              
13 1         38 my $for_js = $self->for_js;
14 1         4 my %index;
15             my %html;
16 1         0 my %level;
17 1         4 foreach my $key ( keys %$for_js ) {
18 1         4 $index{$key} = $for_js->{$key}->{index};
19 1         3 $html{$key} = $for_js->{$key}->{html};
20 1         9 $level{$key} = $for_js->{$key}->{level};
21             }
22 1         19 my $index_str = encode_json( \%index );
23 1         11 my $html_str = encode_json( \%html );
24 1         12 my $level_str = encode_json( \%level );
25 1         9 my $js = <<EOS;
26             <script>
27             \$(document).ready(function() {
28             var rep_index = $index_str;
29             var rep_html = $html_str;
30             var rep_level = $level_str;
31             \$('.add_element').click(function() {
32             // get the repeatable id
33             var data_rep_id = \$(this).attr('data-rep-id');
34             // create a regex out of index placeholder
35             var level = rep_level[data_rep_id]
36             var re = new RegExp('\{index-' + level + '\}',"g");
37             // replace the placeholder in the html with the index
38             var index = rep_index[data_rep_id];
39             var html = rep_html[data_rep_id];
40             html = html.replace(re, index);
41             // escape dots in element id
42             var esc_rep_id = data_rep_id.replace(/[.]/g, '\\\\.');
43             // append new element in the 'controls' div of the repeatable
44             var rep_controls = \$('#' + esc_rep_id + ' > .controls');
45             rep_controls.append(html);
46             // increment index of repeatable fields
47             index++;
48             rep_index[data_rep_id] = index;
49             });
50              
51             \$(document).on('click', '.rm_element', function(event) {
52             cont = confirm('Remove?');
53             if (cont) {
54             var id = \$(this).attr('data-rep-elem-id');
55             var esc_id = id.replace(/[.]/g, '\\\\.');
56             var rm_elem = \$('#' + esc_id);
57             rm_elem.remove();
58             }
59             event.preventDefault();
60             });
61              
62             });
63             </script>
64             EOS
65 1         9 return $js;
66             }
67              
68              
69             1;
70              
71             __END__
72              
73             =pod
74              
75             =encoding UTF-8
76              
77             =head1 NAME
78              
79             HTML::FormHandler::Render::RepeatableJs - role providing method to construct repeatable javascript
80              
81             =head1 VERSION
82              
83             version 0.40068
84              
85             =head1 SYNOPSIS
86              
87             Creates jQuery javascript to add and delete repeatable
88             elements.
89              
90             Note: This is still EXPERIMENTAL.
91             This is an EXAMPLE.
92             Changes are very likely to occur.
93             Javascript is not guaranteed to be best practice.
94             It will not work on all rendered repeatables (requires wrapper with id).
95             It is strongly suggested that you make your own role if you use it.
96             Then you can modify it as needed.
97             Or just write out the rep_ data to javascript variables, and write the
98             function in javascript.
99             This function uses a plain javascript confirmation dialog.
100             You almost certainly want to do something else.
101             This javascript depends on the Repeatable field having a 'controls' div class
102             in order to position the new elements. Use the Bootstrap wrapper or the
103             'controls_div' tag on the Simple wrapper.
104              
105             A role to be used in a Form Class:
106              
107             package MyApp::Form::Test;
108             use HTML::FormHandler::Moose;
109             extends 'HTML::FormHandler';
110             with 'HTML::FormHandler::Render::RepeatableJs';
111             ...
112              
113             =head2 DESCRIPTION
114              
115             This contains one method, 'render_repeatable_js'. It's designed to be
116             used in a template, something like:
117              
118             [% WRAPPER "wrapper.tt" %]
119             [% form.render_repeatable_js %]
120             <h1>Editing Object .... </h1>
121             [% form.render %]
122             [% END -%]
123              
124             It will render javascript which can be used with the AddElement field,
125             and setting the 'setup_for_js' flag in the Repeatable field to add
126             the ability to dynamically add a new repeatable element in a form.
127              
128             Note: this code is provided as an example. You may need to write your
129             own javascript function if your situation is different.
130              
131             Some of the extra information (level) in this function is in preparation for
132             handling nested repeatables, but it's not supported yet.
133              
134             This function operates on HTML elements that have the id of the
135             repeatable element. That requires that the wrapper have the repeatable
136             instance ID (now rendered by default). If you don't have wrappers around
137             your repeatable elements, this won't work.
138              
139             See L<HTML::FormHandler::Field::AddElement> for an example of rendering
140             an HTML element that can be used to provide the AddElement button.
141             See that field for the requirements for the add HTML.
142              
143             See L<HTML::FormHandler::Field::RmElement> for an example of rendering
144             an HTML element that can be used to provide a 'remove' button.
145             See that field for the requirements for the remove HTML.
146              
147             =head1 NAME
148              
149             HTML::FormHandler::Render::RepeatableJs
150              
151             =head1 AUTHOR
152              
153             FormHandler Contributors - see HTML::FormHandler
154              
155             =head1 COPYRIGHT AND LICENSE
156              
157             This software is copyright (c) 2017 by Gerda Shank.
158              
159             This is free software; you can redistribute it and/or modify it under
160             the same terms as the Perl 5 programming language system itself.
161              
162             =cut