Development

/plugins/sfJqueryReloadedPlugin/1.2/trunk/lib/helper/jQueryHelper.php

You must first sign up to be able to contribute.

root/plugins/sfJqueryReloadedPlugin/1.2/trunk/lib/helper/jQueryHelper.php

Revision 33195, 29.2 kB (checked in by boutell, 6 years ago)

Setting sf_jquery_core to false now prevents jquery itself from being loaded by the plugin so that it can be loaded by other means in your project without conflicts

Line 
1 <?php
2
3 require_once(sfConfig::get('sf_symfony_lib_dir') . '/helper/JavascriptBaseHelper.php');
4
5 /**
6  * @desc  Load jquery library in header
7  * tom@punkave.com: sfJqueryReloadedPlugin not sfJqueryPlugin.
8  * Also, sf_jquery_web_dir wasn't being treated as a directory.
9  *
10  * tom@punkave.com 20090413: be consistent with the way global
11  * settings.yml files work, it should always be the webdir, not the /js/
12  * subfolder of the webdir.
13  *
14  * tom@punkave.com 20111109: if sf_jquery_core is explicitly set to false,
15  * don't try to load jquery at all - some other version of jquery is already
16  * in the project by other means.
17  */
18
19 if (sfConfig::get('sf_jquery_core', null) !== false)
20 {
21   if (!$jq_path = sfConfig::get('sf_jquery_path'))
22   {
23     $jq_path = sfConfig::get('sf_jquery_web_dir', '/sfJqueryReloadedPlugin') .
24       '/js/' . sfConfig::get('sf_jquery_core', 'jquery-1.4.2.min.js');
25   }
26   sfContext::getInstance()->getResponse()->addJavascript($jq_path, 'first');
27 }
28
29 /**
30  * Add jQuery plugins by name rather than by filename so that you don't have
31  * to worry about what the current version is. Currently supported:
32  *
33  * sortable
34  * autocomplete
35  *
36  * This is useful to app developers when the normal "just in time" approach
37  * doesn't work. For instance, if you are making helper calls in layout.php (or
38  * components invoked by it...) and you have already called get_javascripts,
39  * it's too late to rely on the automatic calls to jq_add_plugin in the
40  * various helpers. So call this early instead, right after use_helper.
41  *
42  * Example:
43  *   <?php echo jq_add_plugins_by_name(array('sortable', 'autocomplete')) ?>
44  *
45  */
46
47 function jq_add_plugins_by_name($args = array()) {
48   /*
49    * When adding the capability to use a new plugin you must
50    * extend this array, and keep it up to date when you update to
51    * a new version. You must also update the plugin's
52    * default config/settings.yml file
53    */
54
55   $plugins = array(
56     // Backwards compatibility
57     'sortable' => 'jquery-ui-1.7.3.custom.min.js',
58     'ui' => 'jquery-ui-1.7.3.custom.min.js',
59     'autocomplete' => 'jquery.autocomplete.min.js'
60   );
61
62   $pluginPaths = sfConfig::get('sf_jquery_plugin_paths');
63   foreach ($args as $name)
64   {
65     if (!isset($plugins[$name]))
66     {
67       throw new Exception("Unknown jQuery plugin name $name");
68     }
69     if (!isset($pluginPaths[$name]))
70     {
71       $filename = sfConfig::get("sf_jquery_$name", $plugins[$name]);
72       $filename = sfConfig::get('sf_jquery_web_dir', '/sfJqueryReloadedPlugin') . "/js/plugins/$filename";
73     } else {
74       $filename = $pluginPaths[$name];
75     }
76     sfContext::getInstance()->getResponse()->addJavascript($filename);
77   }
78 }
79
80
81 /*
82  * Backwards compatibility only. Don't use this.
83  */
84
85 function jq_add_plugin($options = array()) {
86     // tom@punkave.com: with a singular name (jq_add_plugin), this function
87     // really should accept a non-array argument
88     if (!is_array($options))
89     {
90         $options = array($options);
91     }
92     foreach ( $options as $o ) {
93     $file = sfConfig::get('sf_jquery_web_dir', '/sfJqueryReloadedPlugin') . "/js/plugins/$o";
94         sfContext::getInstance ()->getResponse ()->addJavascript ($file);
95     }
96 }
97
98
99 /**
100  * Periodically calls the specified url ('url') every 'frequency' seconds (default is 10).
101  * Usually used to update a specified div ('update') with the results of the remote call.
102  * The options for specifying the target with 'url' and defining callbacks is the same as 'link_to_remote()'.
103  */
104 function jq_periodically_call_remote($options = array())
105 {
106     $frequency = isset($options['frequency']) ? $options['frequency'] : 10; // every ten seconds by default
107     $code = 'setInterval(function() {'.jq_remote_function($options).'}, '.($frequency * 1000).')';
108
109     return javascript_tag($code);
110 }
111
112 /**
113  * Returns an html button to a remote action defined by 'url' (using the
114  * 'url_for()' format) that's called in the background using XMLHttpRequest.
115  *
116  * See link_to_remote() for details.
117  *
118  */
119 function jq_button_to_remote($name, $options = array(), $html_options = array())
120 {
121     return jq_button_to_function($name, jq_remote_function($options), $html_options);
122 }
123
124
125 /**
126  * Returns a link to a remote action defined by 'url'
127  * (using the 'url_for()' format) that's called in the background using
128  * XMLHttpRequest. The result of that request can then be inserted into a
129  * DOM object whose id can be specified with 'update'.
130  * Usually, the result would be a partial prepared by the controller with
131  * either 'render_partial()'.
132  *
133  * Examples:
134  *  <?php echo link_to_remote('Delete this post'), array(
135  *    'update' => 'posts',
136  *    'url'    => 'destroy?id='.$post.id,
137  *  )) ?>
138  *  <?php echo link_to_remote(image_tag('refresh'), array(
139  *    'update' => 'emails',
140  *    'url'    => '@list_emails',
141  *  )) ?>
142  *
143  * You can also specify a hash for 'update' to allow for
144  * easy redirection of output to an other DOM element if a server-side error occurs:
145  *
146  * Example:
147  *  <?php echo link_to_remote('Delete this post', array(
148  *      'update' => array('success' => 'posts', 'failure' => 'error'),
149  *      'url'    => 'destroy?id='.$post.id,
150  *  )) ?>
151  *
152  * Optionally, you can use the 'position' parameter to influence
153  * how the target DOM element is updated. It must be one of
154  * 'before', 'top', 'bottom', or 'after'.
155  *
156  * By default, these remote requests are processed asynchronous during
157  * which various JavaScript callbacks can be triggered (for progress indicators and
158  * the likes). All callbacks get access to the 'request' object,
159  * which holds the underlying XMLHttpRequest.
160  *
161  * To access the server response, use 'request.responseText', to
162  * find out the HTTP status, use 'request.status'.
163  *
164  * If you are using JSON, you can access it via the 'data' parameter
165  *
166  * Example:
167  *  <?php echo jq_link_to_remote($word, array(
168  *    'url'      => '@undo?n='.$word_counter,
169  *    'complete' => 'undoRequestCompleted(request)'
170  *  )) ?>
171  *
172  * The callbacks that may be specified are (in order):
173  *
174  * 'loading'                 Called when the remote document is being
175  *                           loaded with data by the browser.
176  * 'loaded'                  Called when the browser has finished loading
177  *                           the remote document.
178  * 'interactive'             Called when the user can interact with the
179  *                           remote document, even though it has not
180  *                           finished loading.
181  * 'success'                 Called when the XMLHttpRequest is completed,
182  *                           and the HTTP status code is in the 2XX range.
183  * 'failure'                 Called when the XMLHttpRequest is completed,
184  *                           and the HTTP status code is not in the 2XX
185  *                           range.
186  * 'complete'                Called when the XMLHttpRequest is complete
187  *                           (fires after success/failure if they are present).,
188  *
189  * You can further refine 'success' and 'failure' by adding additional
190  * callbacks for specific status codes:
191  *
192  * Example:
193  *  <?php echo jq_link_to_remote($word, array(
194  *       'url'     => '@rule',
195  *       '404'     => "alert('Not found...? Wrong URL...?')",
196  *       'failure' => "alert('HTTP Error ' + request.status + '!')",
197  *  )) ?>
198  *
199  * A status code callback overrides the success/failure handlers if present.
200  *
201  * If you for some reason or another need synchronous processing (that'll
202  * block the browser while the request is happening), you can specify
203  * 'type' => 'synchronous'.
204  *
205  * You can customize further browser side call logic by passing
206  * in JavaScript code snippets via some optional parameters. In
207  * their order of use these are:
208  *
209  * 'confirm'             Adds confirmation dialog.
210  * 'condition'           Perform remote request conditionally
211  *                       by this expression. Use this to
212  *                       describe browser-side conditions when
213  *                       request should not be initiated.
214  * 'before'              Called before request is initiated.
215  * 'after'               Called immediately after request was
216  *                       initiated and before 'loading'.
217  * 'submit'              Specifies the DOM element ID that's used
218  *                       as the parent of the form elements. By
219  *                       default this is the current form, but
220  *                       it could just as well be the ID of a
221  *                       table row or any other DOM element.
222  */
223 function jq_link_to_remote($name, $options = array(), $html_options = array())
224 {
225     return jq_link_to_function($name, jq_remote_function($options), $html_options);
226 }
227
228 /**
229  * Returns a Javascript function (or expression) that will update a DOM element '$element_id'
230  * according to the '$options' passed.
231  *
232  * Possible '$options' are:
233  * 'content'            The content to use for updating. Can be left out if using block, see example.
234  * 'action'             Valid options are 'update' (assumed by default), 'empty', 'remove'
235  * 'position'           If the 'action' is 'update', you can optionally specify one of the following positions:
236  *                      'before', 'top', 'bottom', 'after'.
237  *
238  * Example:
239  *   <?php echo javascript_tag(
240  *      update_element_function('products', array(
241  *            'position' => 'bottom',
242  *            'content'  => "<p>New product!</p>",
243  *      ))
244  *   ) ?>
245  */
246
247 function jq_update_element_function($element_id, $options = array())
248 {
249
250
251     $content = escape_javascript(isset($options['content']) ? $options['content'] : '');
252
253     $value = isset($options['action']) ? $options['action'] : 'update';
254     switch ($value)
255     {
256         case 'update':
257             $updateMethod = _update_method(isset($options['position']) ? $options['position'] : '');
258             $javascript_function = "jQuery('#$element_id').$updateMethod('$content')";
259             break;
260
261         case 'empty':
262             $javascript_function = "jQuery('#$element_id').empty()";
263             break;
264
265         case 'remove':
266             $javascript_function = "jQuery('#$element_id').remove()";
267             break;
268
269         default:
270             throw new sfException('Invalid action, choose one of update, remove, empty');
271     }
272
273     $javascript_function .= ";\n";
274
275     return (isset($options['binding']) ? $javascript_function.$options['binding'] : $javascript_function);
276 }
277
278 /**
279  * Returns the javascript needed for a remote function.
280  * Takes the same arguments as 'link_to_remote()'.
281  *
282  * Example:
283  *   <select id="options" onchange="<?php echo remote_function(array('update' => 'options', 'url' => '@update_options')) ?>">
284  *     <option value="0">Hello</option>
285  *     <option value="1">World</option>
286  *   </select>
287  */
288 function jq_remote_function($options)
289 {
290     // Defining elements to update
291     if (isset($options['update']) && is_array($options['update']))
292     {
293         // On success, update the element with returned data
294         if (isset($options['update']['success'])) $update_success = "#".$options['update']['success'];
295
296         // On failure, execute a client-side function
297         if (isset($options['update']['failure'])) $update_failure = $options['update']['failure'];
298     }
299     else if (isset($options['update'])) $update_success = "#".$options['update'];
300
301     // Update method
302     $updateMethod = _update_method(isset($options['position']) ? $options['position'] : '');
303
304     // Callbacks
305     if (isset($options['loading'])) $callback_loading = $options['loading'];
306     if (isset($options['complete'])) $callback_complete = $options['complete'];
307     if (isset($options['success'])) $callback_success = $options['success'];
308     
309     if (isset($options['cache'])) {
310         if($options['cache']){
311             $cache = 'true';
312         } else {
313             $cache = 'false';
314         }
315     }
316     $execute = 'false';
317     if ((isset($options['script'])) && ($options['script'] == '1')) $execute = 'true';
318
319     // Data Type
320     if (isset($options['dataType']))
321     {
322         $dataType = $options['dataType'];
323     }
324     elseif ($execute)
325     {
326         $dataType = 'html';
327     }
328     else
329     {
330         $dataType = 'text';
331     }
332
333     // POST or GET ?
334     $method = 'POST';
335     if ((isset($options['method'])) && (strtoupper($options['method']) == 'GET')) $method = $options['method'];
336
337     // async or sync, async is default
338     if ((isset($options['type'])) && ($options['type'] == 'synchronous')) $type = 'false';
339
340     // Is it a form submitting
341     if (isset($options['form'])) $formData = 'jQuery(this).serialize()';
342     elseif (isset($options['submit'])) $formData = '{\'#'.$options['submit'].'\'}.serialize()';
343     // boutell and JoeZ99: 'with' should not be quoted, it's not useful
344     // that way, see the Symfony documentation for the original remote_function
345     elseif (isset($options['with'])) $formData = $options['with'];
346     // Is it a link with csrf protection
347     elseif(isset($options['csrf']) && $options['csrf'] == '1')
348     {
349       // Symfony 1.4 form should be BaseForm, not sfForm. Also this means
350       // CSRF works properly according to Jose Fernando Castillo Rosas
351         $form = new BaseForm();
352         if ($form->isCSRFProtected())
353         {
354             $formData = '{'.$form->getCSRFFieldName().': \''.$form->getCSRFToken().'\'}';
355         }
356     }
357
358     // build the function
359     $function = "jQuery.ajax({";
360     $function .= 'type:\''.$method.'\'';
361     $function .= ',dataType:\'' . $dataType . '\'';
362     if (isset($type)) $function .= ',async:'.$type;
363     if (isset($cache)) $function .= ',cache:'.$cache;
364     if (isset($formData)) $function .= ',data:'.$formData;
365     if (isset($update_success) and !isset($callback_success)) $function .= ',success:function(data, textStatus){jQuery(\''.$update_success.'\').'.$updateMethod.'(data);}';
366     if (isset($update_failure)) $function .= ',error:function(XMLHttpRequest, textStatus, errorThrown){'.$update_failure.'}';
367     if (isset($callback_loading)) $function .= ',beforeSend:function(XMLHttpRequest){'.$callback_loading.'}';
368     if (isset($callback_complete)) $function .= ',complete:function(XMLHttpRequest, textStatus){'.$callback_complete.'}';
369     if (isset($callback_success)) $function .= ',success:function(data, textStatus){'.$callback_success.'}';
370     $function .= ',url:\''.url_for($options['url']).'\'';
371     $function .= '})';
372
373     if (isset($options['before']))
374     {
375         $function = $options['before'].'; '.$function;
376     }
377     if (isset($options['after']))
378     {
379         $function = $function.'; '.$options['after'];
380     }
381     if (isset($options['condition']))
382     {
383         $function = 'if ('.$options['condition'].') { '.$function.'; }';
384     }
385     if (isset($options['confirm']))
386     {
387         $function = "if (confirm('".escape_javascript($options['confirm'])."')) { $function; }";
388         if (isset($options['cancel']))
389         {
390             $function = $function.' else { '.$options['cancel'].' }';
391         }
392     }
393
394     return $function.( (isset($options['stop_propagation']) && $options['stop_propagation']) ? '; if(event && event.stopPropagation) {event.stopPropagation();} else {window.event.cancelBubble = true;}' : '');
395 }
396
397 /**
398  * Returns a form tag that will submit using XMLHttpRequest in the background instead of the regular
399  * reloading POST arrangement. Even though it's using JavaScript to serialize the form elements, the form submission
400  * will work just like a regular submission as viewed by the receiving side (all elements available in 'params').
401  * The options for specifying the target with 'url' and defining callbacks are the same as 'link_to_remote()'.
402  *
403  * A "fall-through" target for browsers that don't do JavaScript can be specified
404  * with the 'action'/'method' options on '$options_html'
405  *
406  * Example:
407  *  <?php echo form_remote_tag(array(
408  *    'url'      => '@tag_add',
409  *    'update'   => 'question_tags',
410  *    'loading'  => "Element.show('indicator'); \$('tag').value = ''",
411  *    'complete' => "Element.hide('indicator');".visual_effect('highlight', 'question_tags'),
412  *  )) ?>
413  *
414  * The hash passed as a second argument is equivalent to the options (2nd) argument in the form_tag() helper.
415  *
416  * By default the fall-through action is the same as the one specified in the 'url'
417  * (and the default method is 'post').
418  */
419 function jq_form_remote_tag($options = array(), $options_html = array())
420 {
421     $options = _parse_attributes($options);
422     $options_html = _parse_attributes($options_html);
423
424     $options['form'] = true;
425
426     $options_html['onsubmit'] = jq_remote_function($options).'; return false;';
427     $options_html['action'] = isset($options_html['action']) ? $options_html['action'] : url_for($options['url']);
428     $options_html['method'] = isset($options_html['method']) ? $options_html['method'] : 'post';
429
430     return tag('form', $options_html, true);
431 }
432
433
434
435
436
437 /**
438  * Returns a JavaScript snippet to be used on the AJAX callbacks for starting
439  * visual effects.
440  *
441  *
442  * Visual effect support 3 optionnal options :  callback,  speed, opacity.  Not all effect does support all options.
443  *
444  * List of effects (options that supported by this effect)
445  * Effects:
446  *         - hide(speed, callback)
447  *         - show(speed, callback)
448  *         - slideDown(speed, callback)
449  *         - slideUp(speed, callback)
450  *         - slideToggle(speed, callback)
451  *         - fadeIn(speed, callback)
452  *         - fadeOut(speed, callback)
453  *         - fadeTo(speed, opacity, callback)
454  *         - toggle
455  *
456  *
457  *
458  * Example of effect that support speed + callback:
459  *  <?php echo link_to_remote('Reload', array(
460  *        'update'  => 'posts',
461  *        'url'     => '@reload',
462  *        'complete => visual_effect('fade', '#posts', array('speed' => 'slow', 'callback' => 'function(){$("post_content").css("background", "yellow")}' )),
463  *  )) ?>
464  *
465  * Speed support 4 arguments : 'fast', 'normal', 'slow', number_in_miliseconds
466  *
467  *
468  *
469  * Example of effect that support speed + opacity + callback:
470  *  <?php echo link_to_remote('Reload', array(
471  *        'update'  => 'posts',
472  *        'url'     => '@reload',
473  *        'complete => visual_effect('fadeTo', '#posts', array('speed' => 'slow', 'opacity' => '0.33', 'callback' => 'function(){$("post_content").css("background", "yellow")}' )),
474  *  )) ?>
475  *
476  * Opacity must be between 0 and 1, if none are specify or not between 0 and 1m, it assumes 0.5(default value)
477  *
478  *
479  *
480  *  Element is optional so if you dont specify it assumes current element
481  *  Example
482  *  <?php echo form_to_remote(array(
483  *        'update'  => 'posts',
484  *        'url'     => '@reload',
485  *        'complete => visual_effect('hide'),
486  *  )) ?>
487  *
488  * This would hide the form when request is completed
489  *
490  *
491  *
492  * Fore more information check the jquery doc
493  * http://http://docs.jquery.com/Effects.
494  */
495 function jq_visual_effect($effect, $element_id = false, $js_options = array())
496 {
497
498     //format slide /fade effect name correctly.
499     if(preg_match("/^(slide|fade)/i", $effect, $matches))
500     {
501         $count = strtolower($matches[1]) == 'fade'? 3 : 4;
502         $effect = preg_replace("/(^|_|-)+(.)/e", '', $effect); //remove non alpha char
503         $effect = preg_replace('/\ +/', '', $effect);  //remove space
504             
505
506             
507         $effect = trim(strtolower($matches[1]).ucfirst(strtolower(substr($effect, $count))));
508     }
509     else
510     {
511         $effect = trim(strtolower($effect));
512     }
513
514     $element = $element_id ? "'$element_id'" : 'this';
515
516     //Building speed
517     $speed = isset($js_options['speed'])? is_numeric($js_options['speed'] )?$js_options['speed'] : "'". $js_options['speed'] ."'": "'normal'";
518
519     //Building opacty
520     $opacity = isset($js_options['opacity']) && is_numeric($js_options['opacity'] )?$js_options['opacity'] >= 0 && $js_options['opacity'] <= 1?$js_options['opacity'] :0.5:0.5;
521
522     //Building callback
523     $callback =  isset($js_options['callback']) ? ", "$js_options['callback'] :null;
524
525
526
527     if(in_array($effect, array('hide', 'show','slideDown', 'slideUp', 'slideToggle', 'fadeIn', 'fadeOut')))
528     {
529         return  sprintf("jQuery(%s).%s(%s %s );", $element, $effect, $speed, $callback);
530     }
531     elseif($effect == "fadeTo")
532     {
533         return  sprintf("jQuery(%s).%s(%s, %s %s);", $element, $effect, $speed, $opacity, $callback);
534     }
535     else
536     {
537         return  sprintf("jQuery(%s).%s();", $element, $effect);
538     }
539 }
540
541
542 /**
543  *  Returns a button input tag that will submit form using XMLHttpRequest in the background instead of regular
544  *  reloading POST arrangement. The '$options' argument is the same as in 'form_remote_tag()'.
545  */
546 function jq_submit_to_remote($name, $value, $options = array(), $options_html = array())
547 {
548     $options = _parse_attributes($options);
549     $options_html = _parse_attributes($options_html);
550
551     if (!isset($options['with']))
552     {
553         $options['with'] = 'jQuery(this.form.elements).serialize()';
554     }
555
556     $options_html['type'] = 'button';
557     $options_html['onclick'] = jq_remote_function($options).'; return false;';
558     $options_html['name'] = $name;
559     $options_html['value'] = $value;
560
561     return tag('input', $options_html, false);
562 }
563
564
565 /**
566  *  Returns a image submit tag that will submit form using XMLHttpRequest in the background instead of regular
567  *  reloading POST arrangement. The '$options' argument is the same as in 'form_remote_tag()'.
568  */
569 function jq_submit_image_to_remote($name, $source, $options = array(), $options_html = array())
570 {
571     $options = _parse_attributes($options);
572     $options_html = _parse_attributes($options_html);
573
574     if (!isset($options['with']))
575     {
576         $options['with'] = 'jQuery(this.form.elements).serialize()';
577     }
578
579     $options_html['type'] = 'image';
580     $options_html['onclick'] = jq_remote_function($options).'; return false;';
581     $options_html['name'] = $name;
582     $options_html['src'] = image_path($source);
583
584     if (!isset($options_html['alt']))
585     {
586         $path_pos = strrpos($source, '/');
587         $dot_pos = strrpos($source, '.');
588         $begin = $path_pos ? $path_pos + 1 : 0;
589         $nb_str = ($dot_pos ? $dot_pos : strlen($source)) - $begin;
590         $options_html['alt'] = ucfirst(substr($source, $begin, $nb_str));
591     }
592
593     return tag('input', $options_html, false);
594 }
595
596 /**
597  * Makes the elements matching the jQuery selector '$selector'
598  * sortable by drag-and-drop and makes an AJAX call whenever the sort order
599  * has changed. By default, the action called gets the serialized sortable
600  * element as parameters.
601  *
602  * Example:
603  *   <php echo sortable_element("#foo", array(
604  *      'url' => '@order',
605  *   )) ?>
606  *
607  * In the example, the action gets a 'foo' array parameter
608  * containing the values of the ids of elements the sortable consists
609  * of, in the current order.
610  *
611  * Additional options can be passed in the $options associative array
612  * and will be sent to jquery as parameters. For example:
613  * 'handle' => 'span' specifies that span elements within the
614  * sortable element are the element the user actually clicks on
615  *  (although entire first-generation child elements of the
616  * sortable element get reordered as a result).
617  *
618  * Added by tom@punkave.com.
619  */
620 function jq_sortable_element($selector, $options = array())
621 {
622     // We need ui for this trick. It's now just ui, not sortable; for simplicity
623     // we have a catch-all ui package, which is minimized to contain only the
624     // features that actually get used by the plugin. If you want fewer features,
625     // or more features, from jQuery ui then get your own minimized package download
626     // from the jquery ui site
627   jq_add_plugins_by_name(array("ui"));
628     $options = _parse_attributes($options);
629     $options['url'] = url_for($options['url']);
630   $options['type'] = 'POST';
631   $selector = json_encode($selector);
632   $options = json_encode($options);   
633     
634     $result = <<<EOM
635 $(document).ready(
636   function()
637   {
638     $($selector).sortable(
639     {
640       update: function(e, ui)
641       {
642         var serial = jQuery($selector).sortable('serialize', {});
643         var options = $options;
644         options['data'] = serial;
645         $.ajax(options);
646       }
647     } );
648   });
649 EOM;
650   return javascript_tag($result);
651 }
652
653
654 /**
655  * wrapper for script.aculo.us/prototype Ajax.Autocompleter.
656  * @author Bruno Adele <bruno.adele@jesuislibre.org>
657  * @param string name value of input field
658  * @param string default value for input field
659  * @param array input tag options. (size, autocomplete, etc...)
660  * @param array completion options. (use_style, etc...)
661  *
662  * Example:
663  * echo jq_input_auto_complete_tag('q','', 'search/index',array(
664  *         'size' => 15),array(
665  *                 'use_style' => false,
666  *                 'scrollHeight' => 480,
667  *                 'scroll' => false,
668  *                 'highlight' => false,
669  *        ) ) ?>
670  *
671  * @return string input field tag, div for completion results, and
672  *                 auto complete javascript tags
673  */
674 function jq_input_auto_complete_tag($name, $value, $url, $tag_options = array(), $completion_options = array()) {
675     // We need ui.autocomplete for this trick
676   jq_add_plugins_by_name(array("autocomplete"));
677
678     $tag_options = _convert_options($tag_options);
679     $comp_options = _convert_options($completion_options);
680
681     // Convert to JSON parameters
682     $jsonOptions = '';
683     foreach ($comp_options as $key => $val)
684     {
685         if ($jsonOptions!='')
686         {
687             $jsonOptions .= ', ';
688         }
689         switch($key) {
690             case 'formatItem':
691             case 'formatResult':
692                 $jsonOptions .= "$key: " . $val;
693                 break;
694             default:
695                 $jsonOptions .= "$key: " . json_encode($val);
696                 break;
697         }
698     }
699
700     // Get Stylesheet
701     $context = sfContext::getInstance();
702     $response = $context->getResponse();
703     $comp_options = _convert_options($completion_options);
704     if (isset($comp_options['use_style']) && $comp_options['use_style'] == true)
705     {
706         $response->addStylesheet(sfConfig::get('sf_jquery_web_dir').'/css/JqueryAutocomplete');
707     }
708
709     // Get Id from name attribute
710     $tag_options['id'] = get_id_from_name(isset($tag_options['id']) ? $tag_options['id'] : $name);
711
712     // Add input form
713     $javascript  = tag('input', array_merge(array('type' => 'text', 'name' => $name, 'value' => $value), _convert_options($tag_options)));
714
715     // Calc JQuery Javascript code
716     $autocomplete_script = sprintf('$("#%s").autocomplete("%s",{ %s    });',$name,$url,$jsonOptions);
717     $javascript .=    javascript_tag($autocomplete_script);
718
719     return $javascript;
720 }
721
722 /**
723  * Makes the elements matching the selector $selector draggable.
724  *
725  * Example:
726  *   <?php echo jq_draggable_element('ul.mydraggables li', array(
727  *      'revert' => true,
728  *   )) ?>
729  *
730  * You can change the behaviour with various options, see
731  * http://script.aculo.us for more documentation.
732  */
733 function jq_draggable_element($selector, $options = array())
734 {
735     // We need ui for this trick
736   jq_add_plugins_by_name(array("ui"));
737     $options = json_encode(_parse_attributes($options)); 
738     $selector = json_encode($selector);
739   return javascript_tag("jQuery($selector).draggable($options)");
740 }
741
742 /**
743  * Makes the element with the DOM ID specified by '$element_id' receive
744  * dropped draggable elements (created by 'draggable_element()') and make an AJAX call.
745  * By default, the action called gets the DOM ID of the element as parameter.
746  *
747  * Example:
748  *   <?php drop_receiving_element('my_cart', array(
749  *      'url' => 'cart/add',
750  *   )) ?>
751  *
752  * You can change the behaviour with various options, see
753  * http://script.aculo.us for more documentation.
754  */
755 function jq_drop_receiving_element($selector, $options = array())
756 {
757   jq_add_plugins_by_name(array("ui"));
758   if (!isset($options['with']))
759   {
760     $options['with'] = "'id=' + encodeURIComponent(element.id)";
761   }
762   if (!isset($options['drop']))
763   {
764     $options['drop'] = "function(element){".jq_remote_function($options)."}";
765   }
766
767   // For backwards compatibility with prototype
768   if (isset($options['hoverclass']))
769   {
770     $options['hoverClass'] = $options['hoverclass'];
771   }
772   $options['hoverClass'] = json_encode('hoverclass');
773  
774   foreach (jq_get_ajax_options() as $key)
775   {
776     unset($options[$key]);
777   }
778
779   if (isset($options['accept']))
780   {
781     $options['accept'] = json_encode($options['accept']);
782   }
783   $options = jq_options_for_javascript($options);
784   $selector = json_encode($selector);
785   return javascript_tag("jQuery($selector).droppable($options);");
786 }
787
788 function _update_method($position) {
789     // Updating method
790     $updateMethod = 'html';
791     switch ($position) {
792         case 'before':$updateMethod='before';break;
793         case 'after':$updateMethod='after';break;
794         case 'top':$updateMethod='prepend';break;
795         case 'bottom':$updateMethod='append';break;
796     }
797
798     return $updateMethod;
799 }
800
801 /***  This should be just a wrapper for the JavascriptBaseHelper link_to_function call,
802     but right now it is a copy that contains correct support for 'confirm' that
803     doesn't break IE or produce invalid HTML. It will make sense to turn this back
804     into a simple wrapper once it is fixed in a Symfony release. See:
805     
806     http://trac.symfony-project.org/ticket/4152 ***/
807     
808 function jq_link_to_function($name, $function, $html_options = array())
809 {
810   $html_options = _parse_attributes($html_options);
811
812   $html_options['href'] = isset($html_options['href']) ? $html_options['href'] : '#';
813   if ( isset($html_options['confirm']) )
814   {
815     $confirm = escape_javascript($html_options['confirm']);
816     $html_options['onclick'] = "if(confirm('$confirm')){ $function;}; return false;";
817     // tom@punkave.com: without this we get a confirm attribute, which breaks confirm() in IE
818     // (we could call window.confirm, but there is no reason to have the
819     // nonstandard confirm attribute)
820     unset($html_options['confirm']);
821   }
822   else
823   {
824     $html_options['onclick'] = $function.'; return false;';
825   }
826
827   return content_tag('a', $name, $html_options);
828 }
829     
830 /***  This is a wrapper for the JavascriptHelper function  ***/
831 function jq_button_to_function($name, $function, $html_options = array())
832 {
833     return button_to_function($name, $function, $html_options);
834 }
835
836
837 /***  This is a wrapper for the JavascriptHelper function  ***/
838 function jq_javascript_tag($content = null)
839 {
840     return javascript_tag($content);
841 }
842
843
844
845 /***  This is a wrapper for the JavascriptHelper function  ***/
846 function jq_javascript_cdata_section($content)
847 {
848     return javascript_cdata_section($content);
849 }
850
851
852 /***  This is a wrapper for the JavascriptHelper function  ***/
853 function jq_if_javascript()
854 {
855     return if_javascript();
856 }
857
858
859 /***  This is a wrapper for the JavascriptHelper function  ***/
860 function jq_end_javascript_tag()
861 {
862     return end_javascript_tag();
863 }
864
865 function _options_for_javascript($options)
866 {
867   $opts = array();
868   foreach ($options as $key => $value)
869   {
870     $opts[] = "$key:$value";
871   }
872   sort($opts);
873
874   return '{'.join(', ', $opts).'}';
875 }
Note: See TracBrowser for help on using the browser.