File Coverage

blib/lib/HTML/Prototype.pm
Criterion Covered Total %
statement 27 257 10.5
branch 0 76 0.0
condition 0 83 0.0
subroutine 9 43 20.9
pod 25 25 100.0
total 61 484 12.6


line stmt bran cond sub pod time code
1             package HTML::Prototype;
2            
3 1     1   1331 use strict;
  1         2  
  1         37  
4 1     1   7 use base qw/Class::Accessor::Fast/;
  1         2  
  1         107  
5 1     1   6 use vars qw/$VERSION $prototype $controls $dragdrop $effects/;
  1         3  
  1         102  
6            
7             $VERSION = '1.48';
8            
9 1     1   1475 use HTML::Element;
  1         579036  
  1         10  
10 1     1   1347 use HTML::Prototype::Js;
  1         3  
  1         37  
11 1     1   736 use HTML::Prototype::Controls;
  1         3  
  1         29  
12 1     1   629 use HTML::Prototype::DragDrop;
  1         3  
  1         28  
13 1     1   694 use HTML::Prototype::Effects;
  1         2  
  1         26  
14 1     1   5 use HTML::Prototype::Helper;
  1         2  
  1         4577  
15            
16             {
17             local $/;
18             $prototype = ;
19             close HTML::Prototype::Js::DATA;
20             $controls = ;
21             close HTML::Prototype::Controls::DATA;
22             $dragdrop = ;
23             close HTML::Prototype::DragDrop::DATA;
24             $effects = ;
25             close HTML::Prototype::Effects::DATA;
26             }
27            
28             my $callbacks = [qw/uninitialized loading loaded interactive complete/];
29             my $ajax_options = [qw/url asynchronous method insertion form with/];
30            
31             =head1 NAME
32            
33             HTML::Prototype - Generate HTML and Javascript for the Prototype library
34            
35             =head1 SYNOPSIS
36            
37             use HTML::Prototype;
38            
39             my $prototype = HTML::Prototype->new;
40             print $prototype->auto_complete_field(...);
41             print $prototype->auto_complete_result(...);
42             print $prototype->auto_complete_stylesheet(...);
43             print $prototype->content_tag(...);
44             print $prototype->define_javascript_functions;
45             print $prototype->draggable_element(...);
46             print $prototype->drop_receiving_element(...);
47             print $prototype->evaluate_remote_response(...);
48             print $prototype->form_remote_tag(...);
49             print $prototype->in_place_editor(...);
50             print $prototype->in_place_editor_field(...);
51             print $prototype->in_place_editor_stylesheet(...);
52             print $prototype->javascript_tag(...);
53             print $prototype->link_to_function(...);
54             print $prototype->link_to_remote(...);
55             print $prototype->observe_field(...);
56             print $prototype->observe_form(...);
57             print $prototype->periodically_call_remote(...);
58             print $prototype->sortable_element(...);
59             print $prototype->submit_to_remote(...);
60             print $prototype->tag(...);
61             print $prototype->text_field_with_auto_complete(...);
62             print $prototype->update_element_function(...);
63             print $prototype->visual_effect(...);
64            
65             =head1 DESCRIPTION
66            
67             The module contains some code generators for Prototype, the famous JavaScript
68             OO library and the script.aculous extensions.
69            
70             The Prototype library (http://prototype.conio.net/) is designed to make
71             AJAX easy. Catalyst::Plugin::Prototype makes it easy to connect to the
72             Prototype library.
73            
74             This is mostly a port of the Ruby on Rails helper tags for JavaScript
75             for use in L.
76            
77             =head2 METHODS
78            
79             =over 4
80            
81             =item $prototype->in_place_editor( $field_id, \%options )
82            
83             Makes an HTML element specified by the DOM ID C<$field_id> become an in-place
84             editor of a property.
85            
86             A form is automatically created and displayed when the user clicks the element,
87             something like this:
88            
89            
90            
91            
92             cancel
93            
94            
95             The form is serialized and sent to the server using an Ajax call, the action
96             on the server should process the value and return the updated value in the
97             body of the reponse. The element will automatically be updated with the
98             changed value (as returned from the server).
99            
100             Required options are:
101            
102             C: Specifies the url where the updated value should be sent after the
103             user presses "ok".
104            
105             Addtional options are:
106            
107             C: Number of rows (more than 1 will use a TEXTAREA)
108            
109             C: The number of columns the text area should span (works for both single line or multi line).
110            
111             C: Synonym for ‘cols’ when using single-line (rows=1) input
112            
113             C: The text on the cancel link. (default: "cancel")
114            
115             C: CSS class used for the in place edit form. (default: "inplaceeditor-form")
116            
117             C: The text on the save link. (default: "ok")
118            
119             C: CSS class added to the element while displaying "Saving..."
120             (removed when server responds). (default: "inplaceeditor-saving")
121            
122             C: Will cause the text to be loaded from the server (useful if
123             your text is actually textile and formatted on the server)
124            
125             C: If the C option is specified then this text is
126             displayed while the text is being loaded from the server. (default: "Loading...")
127            
128             C: The text on the click-to-edit link. (default: "click to edit")
129            
130             C: The id of an external control used to enter edit mode.
131            
132             C: Pass through options to the AJAX call (see prototype's Ajax.Updater)
133            
134             C: JavaScript snippet that should return what is to be sent in the
135             Ajax call, C
and C are implicit parameters
136            
137             =cut
138            
139             sub in_place_editor {
140 0     0 1   my ( $self, $id, $options ) = @_;
141            
142 0           my %to_options = (
143             'cancel_text' => \'cancelText',
144             'save_text' => \'okText',
145             'rows' => 'rows',
146             'external_control' => \'externalControl',
147             'ajax_options' => 'ajaxOptions',
148             'saving_text' => \'savingText',
149             'saving_class_name' => \'savingClassName',
150             'form_id' => \'formId',
151             'cols' => 'cols',
152             'size' => 'size',
153             'load_text_url' => \'loadTextURL',
154             'loading_text' => \'loadingText',
155             'form_class_name' => \'formClassName',
156             'click_to_edit_text' => \'clickToEditText',
157             );
158            
159 0           my $function = "new Ajax.InPlaceEditor( '$id', '" . $options->{url} . "'";
160            
161 0           my $js_options = _options_to_js_options( \%to_options, $options );
162 0 0         $js_options->{callback} =
163             ( 'function ( form, value ) { return ' . $options->{with} . ' }' )
164             if $options->{with};
165            
166 0           $function .= ',' . _options_for_javascript($js_options)
167 0 0         if keys %{$js_options};
168 0           $function .= ')';
169            
170 0           return $self->javascript_tag($function);
171             }
172            
173             =item $prototype->in_place_editor_field( $object, $method, \%tag_options, \%in_place_editor_options )
174            
175             Renders the value of the specified object and method with in-place editing capabilities.
176            
177             =cut
178            
179             sub in_place_editor_field {
180 0     0 1   my ( $self, $object, $method, $tag_options, $in_place_editor_options ) = @_;
181            
182 0   0       $tag_options ||= {};
183 0   0       $in_place_editor_options ||= {};
184            
185 0           my $tag = HTML::Prototype::Helper::Tag->new( $object, $method, $self );
186 0           $tag_options = {
187             tag => 'span',
188             id => "$object\_$method\_" . $tag->object->id . '_in_place_editor',
189             class => 'in_place_editor_field',
190 0           %{$tag_options},
191             };
192            
193 0           return $tag->to_content_tag( delete $tag_options->{tag}, $tag_options )
194             . $self->in_place_editor( $tag_options->{id}, $in_place_editor_options );
195             }
196            
197             =item $prototype->in_place_editor_stylesheet
198            
199             Returns the in_place_editor stylesheet.
200            
201             =cut
202            
203             sub in_place_editor_stylesheet {
204 0     0 1   my $self = shift;
205 0           return $self->content_tag( 'style', <<"");
206             .inplaceeditor-saving {
207             background: url(wait.gif) bottom right no-repeat;
208             }
209            
210             }
211            
212             =item $prototype->auto_complete_field( $field_id, \%options )
213            
214             Adds Ajax autocomplete functionality to the text input field with the
215             DOM ID specified by C<$field_id>.
216            
217             This function expects that the called action returns a HTML
    list,
218             or nothing if no entries should be displayed for autocompletion.
219            
220             Required options are:
221            
222             C: Specifies the URL to be used in the AJAX call.
223            
224            
225             Addtional options are:
226            
227             C: Specifies the DOM ID of the element whose innerHTML should
228             be updated with the autocomplete entries returned by the Ajax request.
229             Defaults to field_id + '_auto_complete'.
230            
231             C: A Javascript expression specifying the parameters for the
232             XMLHttpRequest.
233             This defaults to 'value', which in the evaluated context refers to the
234             new field value.
235            
236             C: Specifies the DOM ID of an elment which will be displayed
237             Here's an example using L with an indicator against the auto_complete_result example below on the server side. Notice the 'style="display:none"' in the indicator .
238            
239             <% $c->prototype->define_javascript_functions %>
240            
241            
242            
243             Type search terms
244            
245            
246            
247            
248            
249            
250            
251            
252             <% $c->prototype->auto_complete_field( 'acomp', { url => '/autocomplete', indicator => 'acomp_stat' } ) %>
253            
254             while autocomplete is running.
255            
256             C: A string or an array of strings containing separator tokens for
257             tokenized incremental autocompletion. Example: C< ','>> would
258             allow multiple autocompletion entries, separated by commas.
259            
260             C: The minimum number of characters that should be in the input
261             field before an Ajax call is made to the server.
262            
263             C: A Javascript expression that is called when the autocompletion
264             div is hidden. The expression should take two variables: element and update.
265             Element is a DOM element for the field, update is a DOM element for the div
266             from which the innerHTML is replaced.
267            
268             C: Like on_hide, only now the expression is called then the div
269             is shown.
270            
271             C
272             insertion should be extracted. If this is not specified,
273             the entire element is used
274            
275            
276             =cut
277            
278             sub auto_complete_field {
279 0     0 1   my ( $self, $id, $options ) = @_;
280            
281 0           my %to_options = (
282             'on_show' => 'onShow',
283             'on_hide' => 'onHide',
284             'min_chars' => 'minChars',
285             'indicator' => \'indicator',
286             'select' => \'select',
287             );
288 0   0       $options ||= {};
289 0   0       my $update = ( $options->{update} || "$id" ) . '_auto_complete';
290 0   0       my $function =
291             "new Ajax.Autocompleter( '$id', '$update', '"
292             . ( $options->{url} || '' ) . "'";
293            
294 0           my $js_options = _options_to_js_options( \%to_options, $options );
295 0 0         $js_options->{tokens} =
296             _array_or_string_for_javascript( $options->{tokens} )
297             if $options->{tokens};
298 0 0         $js_options->{callback} =
299             ( 'function ( element, value ) { return ' . $options->{with} . ' }' )
300             if $options->{with};
301            
302 0           $function .= ', ' . _options_for_javascript($js_options)
303 0 0         if keys %{$js_options};
304 0           $function .= ' )';
305            
306 0           return $self->javascript_tag($function);
307             }
308            
309             =item $prototype->auto_complete_result(\@items, $fieldname, [$phrase])
310            
311             Returns a list, to communcate with the Autocompleter.
312            
313             Here's an example for L:
314            
315             sub autocomplete : Global {
316             my ( $self, $c ) = @_;
317             my @items = qw/foo bar baz/;
318             $c->res->body( $c->prototype->auto_complete_result(\@items) );
319             }
320            
321             =cut
322            
323             sub auto_complete_result {
324 0     0 1   my ( $self, $entries, $field, $phrase ) = @_;
325 0           my @elements;
326 0           for my $entry ( @{$entries} ) {
  0            
327 0           my $item;
328 0 0         if ( ref($entry) eq 'HASH' ) {
329 0           my $e = $entry->{$field};
330 0 0         $item = $phrase ? _highlight( $e, $phrase ) : $e;
331             }
332             else {
333 0           $item = $entry;
334             }
335 0           push @elements, HTML::Element->new('li')->push_content($item);
336             }
337            
338 0           @elements = _unique(@elements);
339            
340 0           return $self->content_tag( 'ul', \@elements );
341             }
342            
343             =item $prototype->text_field_with_auto_complete($method, [\%tag_options], [\%completion_options])
344            
345             Wrapper for text_field with added Ajax autocompletion functionality.
346            
347             In your controller, you'll need to define an action called
348             auto_complete_for_object_method to respond the AJAX calls,
349            
350             =cut
351            
352             sub text_field_with_auto_complete {
353 0     0 1   my ( $self, $object, $method, $tag_options, $completion_options ) = @_;
354            
355 0   0       $tag_options ||= {};
356 0   0       $completion_options ||= {};
357            
358 0 0         my $style =
359             $completion_options->{skip_style}
360             ? ''
361             : $self->auto_complete_stylesheet();
362 0           my $text_field = $self->text_field( $object, $method, $tag_options );
363 0           my $content_tag =
364             $self->content_tag( 'div', '',
365             { id => "$object\_$method\_auto_complete", class => 'auto_complete' } );
366 0           my $auto_complete_field = $self->auto_complete_field(
367             "$object\_$method",
368             {
369             url => { action => "auto_complete_for_$object\_$method" },
370 0           %{$completion_options}
371             }
372             );
373            
374 0           return $style . $text_field . $content_tag . $auto_complete_field;
375             }
376            
377             =item $prototype->auto_complete_stylesheet
378            
379             Returns the auto_complete stylesheet.
380            
381             =cut
382            
383             sub auto_complete_stylesheet {
384 0     0 1   my $self = shift;
385 0           return $self->content_tag( 'style', <<"");
386             div.auto_complete {
387             width: 350px;
388             background: #fff;
389             }
390             div.auto_complete ul {
391             border:1px solid #888;
392             margin:0;
393             padding:0;
394             width:100%;
395             list-style-type:none;
396             }
397             div.auto_complete ul li {
398             margin:0;
399             padding:3px;
400             }
401             div.auto_complete ul li.selected {
402             background-color: #ffb;
403             }
404             div.auto_complete ul strong.highlight {
405             color: #800;
406             margin:0;
407             padding:0;
408             }
409            
410             }
411            
412             =item $prototype->content_tag( $name, $content, \%html_options )
413            
414             Returns a block with opening tag, content, and ending tag. Useful for
415             autogenerating tags like B<Catalyst
416             Homepage>. The first parameter is the tag name, i.e. B<'a'> or
417             B<'img'>.
418            
419             =cut
420            
421             sub content_tag {
422 0     0 1   my ( $self, $name, $content, $html_options ) = @_;
423            
424 0           return HTML::Prototype::Helper::Tag->_content_tag( $name, $content,
425             $html_options );
426             }
427            
428             =item $prototype->text_field( $name, $method, $html_options )
429            
430             Returns an input tag of the "text" type tailored for accessing a specified
431             attribute (identified by I<$method>) on an object assigned to the template
432             (identified by I<$object>). Additional options on the input tag can be passed
433             as a hash ref with I<$html_options>.
434            
435             =cut
436            
437             sub text_field {
438 0     0 1   my ( $self, $object_name, $method, $html_options ) = @_;
439 0   0       $html_options ||= {};
440 0           return HTML::Prototype::Helper::Tag->new( $object_name, $method, $self,
441             undef, delete $html_options->{object} )
442             ->to_input_field_tag( "input", $html_options );
443             }
444            
445             =item $prototype->define_javascript_functions
446            
447             Returns the library of JavaScript functions and objects, in a script block.
448            
449             Notes for L users:
450            
451             You can use C