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
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
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
Search:
245
246
Searching...
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: Pick the class of the element from which the value for
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