PHPonTrax
[ class tree: PHPonTrax ] [ index: PHPonTrax ] [ all elements ]

Source for file javascript_helper.php

Documentation is available at javascript_helper.php

  1. <?php
  2. /**
  3.  *  File containing the JavaScriptHelper class and support functions
  4.  *
  5.  *  (PHP 5)
  6.  *
  7.  *  @package PHPonTrax
  8.  *  @version $Id: javascript_helper.php 282 2007-02-15 02:18:23Z john $
  9.  *  @copyright (c) 2005 John Peterson
  10.  *
  11.  *   Permission is hereby granted, free of charge, to any person obtaining
  12.  *   a copy of this software and associated documentation files (the
  13.  *   "Software"), to deal in the Software without restriction, including
  14.  *   without limitation the rights to use, copy, modify, merge, publish,
  15.  *   distribute, sublicense, and/or sell copies of the Software, and to
  16.  *   permit persons to whom the Software is furnished to do so, subject to
  17.  *   the following conditions:
  18.  *
  19.  *   The above copyright notice and this permission notice shall be
  20.  *   included in all copies or substantial portions of the Software.
  21.  *
  22.  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23.  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24.  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25.  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26.  *   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27.  *   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28.  *   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29.  */
  30.  
  31. /**
  32.  *  @todo Document this class
  33.  *  @package PHPonTrax
  34.  */
  35. class JavaScriptHelper extends Helpers {
  36.  
  37.     /**
  38.      * 
  39.      *
  40.      */
  41.     function __construct({
  42.         parent::__construct();
  43.         $this->javascript_callbacks is_array($GLOBALS['JAVASCRIPT_CALLBACKS']$GLOBALS['JAVASCRIPT_CALLBACKS'array('uninitialized''loading''loaded''interactive''complete''failure''success');    
  44.         $this->ajax_options array_merge(array('before''after''condition''url''asynchronous''method''insertion''position''form''with''update''script')$this->javascript_callbacks);
  45.         $this->javascript_path dirname(__FILE__).'/javascripts';
  46.  
  47.     }
  48.  
  49.     protected function options_for_javascript($options{
  50.         $javascript array();
  51.         if(is_array($options)) {
  52.             $javascript array_map(create_function('$k, $v''return "{$k}:{$v}";')array_keys($options)array_values($options));
  53.             sort($javascript);
  54.         }
  55.         return '{' implode(', '$javascript'}';
  56.     }
  57.     
  58.     private function array_or_string_for_javascript($option{
  59.         if(is_array($option)) {
  60.             $js_option "['" implode('\',\''$option"']";
  61.         elseif (!is_null($option)) {
  62.             $js_option "'{$option}'";
  63.         }
  64.         return $js_option;
  65.     }
  66.     
  67.     private function options_for_ajax($options{
  68.         $js_options $this->build_callbacks($options);    
  69.         $js_options['asynchronous'($options['type'!= 'synchronous'"true" "false";
  70.         if($options['method']{
  71.             $js_options['method'$this->method_option_to_s($options['method']);
  72.         }
  73.         if($options['position']{
  74.             $js_options['insertion'"Insertion." Inflector::camelize($options['position']);
  75.         }
  76.         $js_options['evalScripts'$options['script'$options['script'"true";
  77.         
  78.         if($options['form']{
  79.             $js_options['parameters'"Form.serialize(this)";
  80.         elseif($options['submit']{
  81.             $js_options['parameters'"Form.serialize(document.getElementById('{$options['submit']}'))";
  82.         elseif($options['with']{
  83.             $js_options['parameters'$options['with'];
  84.         }
  85.         return $this->options_for_javascript($js_options);
  86.     }
  87.     
  88.     private function method_option_to_s($method{
  89.         return ((is_string($method&& !strstr($method"'")) "'{$method}'$method);
  90.     }
  91.     
  92.     private function build_observer($klass$name$options array()) {
  93.         if($options['update']{
  94.             if(!$options['with']{
  95.                 #$options['with'] = 'value';
  96.         $options['with'"'value=' + value";
  97.             }
  98.         }
  99.         $callback $this->remote_function($options);
  100.         $javascript  "new {$klass}('{$name}', ";
  101.         if($options['frequency']{
  102.             $javascript .= "{$options['frequency']}";
  103.         }
  104.         $javascript .= "function(element, value) {";
  105.         $javascript .= "{$callback}})";
  106.         return $this->javascript_tag($javascript);
  107.     }
  108.     
  109.     private function build_callbacks($options{
  110.         $callbacks array();
  111.         foreach($options as $callback => $code{
  112.             if(in_array($callback$this->javascript_callbacks)) {
  113.                 $name 'on' Inflector::capitalize($callback);
  114.                 $callbacks[$name"function(request){{$code}}";
  115.             }
  116.         }
  117.         return $callbacks;
  118.     }
  119.     
  120.     private function remove_ajax_options($options{
  121.         if(is_array($options)) {
  122.             $GLOBALS['ajax_options'$this->ajax_options;
  123.             foreach($options as $option_key => $option_value{
  124.                 if(!in_array($option_key$this->ajax_options)) {
  125.                     $new_options[$option_key$option_value;  
  126.                 }  
  127.             
  128.             if(is_array($new_options)) {
  129.                 $options $new_options
  130.             }           
  131.         }    
  132.         return $options;    
  133.     }
  134.        
  135.     # Returns a link that'll trigger a javascript $function using the 
  136.     # onclick handler and return false after the fact.
  137.     #
  138.     # Examples:
  139.     #   link_to_function("Greeting", "alert('Hello world!')")
  140.     #   link_to_function(image_tag("delete"), "if confirm('Really?'){ do_delete(); }")
  141.     function link_to_function($name$function$html_options array()) {
  142.         return $this->content_tag("a"$namearray_merge(array('href' => "#"'onclick' => "{$function}return false;")$html_options));
  143.     }
  144.     
  145.     # Returns a link to a remote action defined by <tt>$options['url']</tt> 
  146.     # (using the url_for() format) that's called in the background using 
  147.     # XMLHttpRequest. The result of that request can then be inserted into a
  148.     # DOM object whose id can be specified with <tt>$options['update']</tt>. 
  149.     # Usually, the result would be a partial prepared by the controller with
  150.     # render_partial. 
  151.     #
  152.     # Examples:
  153.     #  link_to_remote("Delete this post", array("update" => "posts", array("url" => array(":action" => "destroy", ":id" => $post->id)))
  154.     #  link_to_remote(image_tag("refresh"), array("update" => "emails", "url" => array(":action" => "list_emails")))
  155.     #  link_to_remote(image_tag("refresh"), array("update" => "emails", "url" => "/posts/list_emails"))
  156.     #
  157.     # You can also specify a hash for <tt>$options['update']</tt> to allow for
  158.     # easy redirection of output to an other DOM element if a server-side error occurs:
  159.     #
  160.     # Example:
  161.     #  link_to_remote("Delete this post", array(
  162.     #      "url" => array(":action" => "destroy", ":id" => $post->id),
  163.     #      "update" => array("success" => "posts", "failure" => "error")
  164.     #      ))
  165.     #
  166.     # Optionally, you can use the <tt>$options['position']</tt> parameter to influence
  167.     # how the target DOM element is updated. It must be one of 
  168.     # <tt>before</tt>, <tt>top</tt>, <tt>bottom</tt>, or <tt>after</tt>.
  169.     #
  170.     # By default, these remote requests are processed asynchronous during 
  171.     # which various JavaScript callbacks can be triggered (for progress indicators and
  172.     # the likes). All callbacks get access to the <tt>request</tt> object,
  173.     # which holds the underlying XMLHttpRequest. 
  174.     #
  175.     # To access the server response, use <tt>request.responseText</tt>, to
  176.     # find out the HTTP status, use <tt>request.status</tt>.
  177.     #
  178.     # Example:
  179.     #   link_to_remote($word, array(
  180.     #       "url" => array(":action" => "undo", "n" => $word_counter ),
  181.     #       "complete" => "undoRequestCompleted(request)"))
  182.     #
  183.     # The callbacks that may be specified are (in order):
  184.     #
  185.     # <tt>loading</tt>::       Called when the remote document is being 
  186.     #                           loaded with data by the browser.
  187.     # <tt>loaded</tt>::        Called when the browser has finished loading
  188.     #                           the remote document.
  189.     # <tt>interactive</tt>::   Called when the user can interact with the 
  190.     #                           remote document, even though it has not 
  191.     #                           finished loading.
  192.     # <tt>success</tt>::       Called when the XMLHttpRequest is completed,
  193.     #                           and the HTTP status code is in the 2XX range.
  194.     # <tt>failure</tt>::       Called when the XMLHttpRequest is completed,
  195.     #                           and the HTTP status code is not in the 2XX
  196.     #                           range.
  197.     # <tt>complete</tt>::      Called when the XMLHttpRequest is complete 
  198.     #                           (fires after success/failure if they are present).,
  199.     #                     
  200.     # You can further refine <tt>success</tt> and <tt>failure</tt> by adding additional 
  201.     # callbacks for specific status codes:
  202.     #
  203.     # Example:
  204.     #   link_to_remote($word,
  205.     #       "url" => array(":action" => "action"),
  206.     #       "failure" => "alert('HTTP Error ' + request.status + '!')")
  207.     #
  208.     # A status code callback overrides the success/failure handlers if present.
  209.     #
  210.     # If you for some reason or another need synchronous processing (that'll
  211.     # block the browser while the request is happening), you can specify 
  212.     # <tt>$options['type'] = "synchronous"</tt>.
  213.     #
  214.     # You can customize further browser side call logic by passing
  215.     # in JavaScript code snippets via some optional parameters. In
  216.     # their order of use these are:
  217.     #
  218.     # <tt>confirm</tt>::      Adds confirmation dialog.
  219.     # <tt>condition</tt>::    Perform remote request conditionally
  220.     #                          by this expression. Use this to
  221.     #                          describe browser-side conditions when
  222.     #                          request should not be initiated.
  223.     # <tt>before</tt>::       Called before request is initiated.
  224.     # <tt>after</tt>::        Called immediately after request was
  225.     #                          initiated and before <tt>:loading</tt>.
  226.     # <tt>submit</tt>::       Specifies the DOM element ID that's used
  227.     #                          as the parent of the form elements. By 
  228.     #                          default this is the current form, but
  229.     #                          it could just as well be the ID of a
  230.     #                          table row or any other DOM element.
  231.     function link_to_remote($name$options array()$html_options array()) {
  232.         return $this->link_to_function($name$this->remote_function($options)$html_options);
  233.     }
  234.     
  235.     # Periodically calls the specified url (<tt>$options['url']</tt>) every <tt>options[:frequency]</tt> seconds (default is 10).
  236.     # Usually used to update a specified div (<tt>$options['update']</tt>) with the results of the remote call.
  237.     # The options for specifying the target with 'url' and defining callbacks is the same as link_to_remote().
  238.     function periodically_call_remote($options array()) {
  239.         $frequency $options['frequency'$options['frequency'10# every ten seconds by default
  240.         $code "new PeriodicalExecuter(function() {" $this->remote_function($options"}, {$frequency})";
  241.         return $this->javascript_tag($code);
  242.     }
  243.     
  244.     # Returns a form tag that will submit using XMLHttpRequest in the background instead of the regular 
  245.     # reloading POST arrangement. Even though it's using JavaScript to serialize the form elements, the form submission 
  246.     # will work just like a regular submission as viewed by the receiving side (all elements available in $_REQUEST).
  247.     # The options for specifying the target with :url and defining callbacks is the same as link_to_remote().
  248.     #
  249.     # A "fall-through" target for browsers that doesn't do JavaScript can be specified with the :action/:method options on :html
  250.     #
  251.     #   form_remote_tag("html" => array("action" => url_for(":controller" => "some", ":action" => "place")))
  252.     # The Hash passed to the 'html' key is equivalent to the options (2nd) argument in the FormTagHelper::form_tag() method.
  253.     #
  254.     # By default the fall-through action is the same as the one specified in the 'url' (and the default method is 'post').
  255.     function form_remote_tag($options array()) {
  256.         $options['form'true;       
  257.         if (!$options['html']{
  258.             $options['html'array();
  259.         }
  260.         $options['html']['onsubmit'$this->remote_function($options"; return false;";
  261.         if($options['html']['action']{
  262.             $url_for_options $options['html']['action'];
  263.         else {
  264.             $url_for_options url_for($options['url']);    
  265.         }
  266.         if(!$options['html']['method']{
  267.             $options['html']['method'"post";
  268.         }
  269.         return $this->tag("form"$options['html']true);
  270.     }
  271.         
  272.     # Returns a button input tag that will submit form using XMLHttpRequest in the background instead of regular
  273.     # reloading POST arrangement. <tt>$options</tt> argument is the same as in <tt>form_remote_tag()</tt>
  274.     function submit_to_remote($name$value$options array()) {
  275.         if(!isset($options['with'])) {
  276.             $options['with''Form.serialize(this.form)';
  277.         }
  278.         if(!$options['html']{
  279.             $options['html'array();
  280.         }
  281.         $options['html']['type''button';
  282.         $options['html']['onclick'$this->remote_function($options"; return false;";
  283.         $options['html']['name'$name;
  284.         $options['html']['value'$value;      
  285.         return $this->tag("input"$options['html']);
  286.     }
  287.     
  288.     # Returns a Javascript function (or expression) that'll update a DOM element according to the options passed.
  289.     #
  290.     # * <tt>content</tt>: The content to use for updating. Can be left out if using block, see example.
  291.     # * <tt>action</tt>: Valid options are :update (assumed by default), :empty, :remove
  292.     # * <tt>position</tt> If the :action is :update, you can optionally specify one of the following positions: :before, :top, :bottom, :after.
  293.     #
  294.     # Examples:
  295.     #   javascript_tag(update_element_function(
  296.     #         "products", :position => :bottom, :content => "<p>New product!</p>")) 
  297.     #
  298.     #    replacement_function = update_element_function("products") do 
  299.     #     <p>Product 1</p>
  300.     #     <p>Product 2</p>
  301.     #    end 
  302.     #   javascript_tag(replacement_function) 
  303.     #
  304.     # This method can also be used in combination with remote method call where the result is evaluated afterwards to cause
  305.     # multiple updates on a page. Example:
  306.     #
  307.     #   # Calling view
  308.     #    form_remote_tag(array("url" => array(":action" => "buy"), "complete" => evaluate_remote_response())) 
  309.     #    all the inputs here...
  310.     #
  311.     #   # Controller action
  312.     #   function buy() {
  313.     #       $product = new Product;
  314.     #       $this->product = $product->find(1);
  315.     #   }
  316.     #
  317.     #   # Returning view
  318.     #    update_element_function(
  319.     #         "cart", array(":action" => "update", "position" => "bottom", 
  320.     #         "content" => "<p>New Product: #{$product->name}</p>")) 
  321.     #    update_element_function("status", array("binding" => $binding) do 
  322.     #     You've bought a new product!
  323.     #    end 
  324.     #
  325.     function update_element_function($element_id$options array()$block null{   
  326.         $content $this->escape_javascript(($options['content'$options['content'null));
  327.         if(!is_null($block)) {
  328.             $content $this->escape_javascript($this->capture($block));
  329.         }
  330.         switch((isset($options['action']$options['action''update')) {
  331.             case 'update':
  332.                 if($options['position']{
  333.                     $javascript_function "new Insertion." Inflector::camelize($options['position']"('{$element_id}','{$content}')";
  334.                 else {
  335.                     $javascript_function "$('{$element_id}').innerHTML = '{$content}'";
  336.                 }
  337.                 break;
  338.             case 'empty':
  339.                 $javascript_function "$('{$element_id}').innerHTML = ''";
  340.                 break;
  341.             case 'remove':
  342.                 $javascript_function "Element.remove('{$element_id}')";
  343.                 break;
  344.             default:
  345.                 $this->controller_object->raise("Invalid action, choose one of 'update', 'remove', 'empty'""ArgumentError");
  346.         }       
  347.         $javascript_function .= ";\n";
  348.         return ($options['binding'$javascript_function $options['binding'$javascript_function);
  349.     }
  350.     
  351.     # Returns 'eval(request.responseText)' which is the Javascript function that form_remote_tag can call in :complete to
  352.     # evaluate a multiple update return document using update_element_function calls.
  353.     function evaluate_remote_response({
  354.         return "eval(request.responseText)";
  355.     }
  356.     
  357.     
  358.     /*
  359.     # Returns the javascript needed for a remote function.
  360.     # Takes the same arguments as link_to_remote.
  361.     # 
  362.     # Example:
  363.     #   <select id="options" onchange="<?= remote_function(array("update" => "options", "url" => array(":action" => "update_options"))) ?>">
  364.     #     <option value="0">Hello</option>
  365.     #     <option value="1">World</option>
  366.     #   </select>
  367.     */
  368.     function remote_function($options{
  369.         $javascript_options $this->options_for_ajax($options);       
  370.         $update '';
  371.         if(is_array($options['update'])) {
  372.             $update  array();
  373.             if(isset($options['update']['success'])) {
  374.                 $update["success:'{$options['update']['success']}'";
  375.             }
  376.             if($options['update']['failure']{
  377.                 $update["failure:'{$options['update']['failure']}'";
  378.             }
  379.             $update '{' implode(','$update'}';
  380.         elseif($options['update']{
  381.             $update .= "'{$options['update']}'";
  382.         }   
  383.             
  384.         $function  empty($update"new Ajax.Request(" "new Ajax.Updater({$update}";
  385.         $function .= "'" url_for($options['url']"'";
  386.         $function .= ", " $javascript_options ")";
  387.         
  388.         if($options['before']{
  389.             $function "{$options['before']}; {$function}";
  390.         }
  391.         if($options['after']
  392.             $function "{$function}; {$options['after']}";
  393.         }
  394.         if($options['condition']{
  395.             $function "if ({$options['condition']}{ {$function}}";
  396.         }
  397.         if($options['confirm']{
  398.             $function "if (confirm('" $this->escape_javascript($options['confirm']"')) { {$function}}";
  399.         }
  400.         return $function;
  401.     }
  402.     
  403.     # Includes the Action Pack JavaScript libraries inside a single <script> 
  404.     # tag. The function first includes prototype.js and then its core extensions,
  405.     # (determined by filenames starting with "prototype").
  406.     # Afterwards, any additional scripts will be included in random order.
  407.     #
  408.     # Note: The recommended approach is to copy the contents of
  409.     # action_view/helpers/javascripts/ into your application's
  410.     # public/javascripts/ directory, and use javascript_include_tag() to 
  411.     # create remote <script> links.
  412.     function define_javascript_functions({
  413.         $javascript '<script type="text/javascript">';
  414.         
  415.         # load prototype.js and all .js files
  416.         $prototype_libs glob($this->javascript_path.'/*.js');
  417.         if(count($prototype_libs)) {
  418.             rsort($prototype_libs);
  419.             foreach($prototype_libs as $filename
  420.                 $javascript .= "\n" file_get_contents($filename);
  421.             }
  422.         }
  423.         
  424.         return $javascript '</script>';
  425.     }
  426.     
  427.     # Observes the field with the DOM ID specified by +field_id+ and makes
  428.     # an AJAX call when its contents have changed.
  429.     
  430.     # Required $options are:
  431.     # <tt>url</tt>::       +url_for+-style options for the action to call
  432.     #                       when the field has changed.
  433.     
  434.     # Additional options are:
  435.     # <tt>frequency</tt>:: The frequency (in seconds) at which changes to
  436.     #                       this field will be detected. Not setting this
  437.     #                       option at all or to a value equal to or less than
  438.     #                       zero will use event based observation instead of
  439.     #                       time based observation.
  440.     # <tt>update</tt>::    Specifies the DOM ID of the element whose 
  441.     #                       innerHTML should be updated with the
  442.     #                       XMLHttpRequest response text.
  443.     # <tt>with</tt>::      A JavaScript expression specifying the
  444.     #                       parameters for the XMLHttpRequest. This defaults
  445.     #                       to 'value', which in the evaluated context 
  446.     #                       refers to the new field value.
  447.     #
  448.     # Additionally, you may specify any of the options documented in
  449.     # link_to_remote().
  450.     function observe_field($field_id$options array()) {
  451.         if($options['frequency'0{
  452.             return $this->build_observer('Form.Element.Observer'$field_id$options);
  453.         else {
  454.             return $this->build_observer('Form.Element.EventObserver'$field_id$options);
  455.         }
  456.     }
  457.     
  458.     # Like observe_field(), but operates on an entire form identified by the
  459.     # DOM ID $form_id. $options are the same as observe_field(), except 
  460.     # the default value of the <tt>with</tt> option evaluates to the
  461.     # serialized (request string) value of the form.
  462.     function observe_form($form_id$options array()) {
  463.         if($options['frequency']{
  464.             return $this->build_observer('Form.Observer'$form_id$options);
  465.         else {
  466.             return $this->build_observer('Form.EventObserver'$form_id$options);
  467.         }
  468.     }
  469.     
  470.     # Returns a JavaScript snippet to be used on the AJAX callbacks for starting
  471.     # visual effects.
  472.     #
  473.     # This method requires the inclusion of the script.aculo.us JavaScript library.
  474.     #
  475.     # Example:
  476.     #   link_to_remote("Reload", array("update" => "posts", 
  477.     #         "url" => array(":action" => "reload"), 
  478.     #         "complete" => visual_effect("highlight", "posts", array("duration" => 0.5)))
  479.     #
  480.     # If no element_id is given, it assumes "element" which should be a local
  481.     # variable in the generated JavaScript execution context. This can be used
  482.     # for example with drop_receiving_element:
  483.     #
  484.     #   drop_receving_element (...), "loading" => visual_effect("fade")
  485.     #
  486.     # This would fade the element that was dropped on the drop receiving element.
  487.     #
  488.     # You can change the behaviour with various options, see
  489.     # http://script.aculo.us for more documentation.
  490.     function visual_effect($name$element_id false$js_options array()) {
  491.         $element ($element_id "'{$element_id}'"element");
  492.         if($js_options['queue']{
  493.             $js_options['queue'"'{$js_options['queue']}'";
  494.         }
  495.         return "new Effect." Inflector::camelize($name"({$element},$this->options_for_javascript($js_options");";
  496.     }
  497.     
  498.     # Makes the element with the DOM ID specified by +element_id+ sortable
  499.     # by drag-and-drop and make an AJAX call whenever the sort order has
  500.     # changed. By default, the action called gets the serialized sortable
  501.     # element as parameters.
  502.     #
  503.     # This method requires the inclusion of the script.aculo.us JavaScript library.
  504.     #
  505.     # Example:
  506.     #    sortable_element("my_list", array("url" => array(":action" => "order"))) 
  507.     #
  508.     # In the example, the action gets a "my_list" array parameter 
  509.     # containing the values of the ids of elements the sortable consists 
  510.     # of, in the current order.
  511.     #
  512.     # You can change the behaviour with various options, see
  513.     # http://script.aculo.us for more documentation.
  514.     function sortable_element($element_id$options array()) {
  515.         if(!$options['with']{
  516.             $options['with'"Sortable.serialize('{$element_id}')";
  517.         }
  518.         if(!$options['onUpdate']{
  519.             $options['onUpdate'"function(){" $this->remote_function($options"}";
  520.         }
  521.         $options $this->remove_ajax_options($options);
  522.         foreach(array('tag''overlap''constraint''handle'as $option{
  523.             if($options[$option]{
  524.                 $options[$option"'{$options[$option]}'";
  525.             }
  526.         }
  527.         
  528.         if($options['containment']{
  529.             $options['containment'$this->array_or_string_for_javascript($options['containment']);
  530.         }
  531.         if($options['only']{
  532.             $options['only'$this->array_or_string_for_javascript($options['only']);
  533.         }
  534.         return $this->javascript_tag("Sortable.create('{$element_id}', $this->options_for_javascript($options")");
  535.     }
  536.     
  537.     # Makes the element with the DOM ID specified by $element_id draggable.
  538.     #
  539.     # This method requires the inclusion of the script.aculo.us JavaScript library.
  540.     #
  541.     # Example:
  542.     #    draggable_element("my_image", array("revert" => true))
  543.     
  544.     # You can change the behaviour with various options, see
  545.     # http://script.aculo.us for more documentation. 
  546.     function draggable_element($element_id$options array()) {
  547.         return $this->javascript_tag("new Draggable('{$element_id}', $this->options_for_javascript($options")");
  548.     }
  549.     
  550.     # Makes the element with the DOM ID specified by $element_id receive
  551.     # dropped draggable elements (created by draggable_element).
  552.     # and make an AJAX call  By default, the action called gets the DOM ID of the
  553.     # element as parameter.
  554.     #
  555.     # This method requires the inclusion of the script.aculo.us JavaScript library.
  556.     #
  557.     # Example:
  558.     #    drop_receiving_element("my_cart", array("url" => array(":controller" => "cart", ":action" => "add"))) 
  559.     #
  560.     # You can change the behaviour with various options, see
  561.     # http://script.aculo.us for more documentation.
  562.     function drop_receiving_element($element_id$options array()) {
  563.         if(!$options['with']{
  564.             $options['with'"'id=' + encodeURIComponent(element.id)";
  565.         }
  566.         if(!$options['onUpdate']{
  567.             $options['onUpdate'"function(element){" $this->remote_function($options"}";
  568.         }
  569.         $options $this->remove_ajax_options($options);
  570.         if($options['accept']{
  571.             $options['accept'$this->array_or_string_for_javascript($options['accept']);  
  572.         }  
  573.         if($options['hoverclass']{
  574.             $options['hoverclass'"'{$options['hoverclass']}'";
  575.         }
  576.         return $this->javascript_tag("Droppables.add('{$element_id}', $this->options_for_javascript($options")");
  577.     }
  578.     
  579.     # Escape carrier returns and single and double quotes for JavaScript segments.
  580.     function escape_javascript($javascript{
  581.         $escape array(
  582.             "\r\n"  => '\n',
  583.             "\r"    => '\n',
  584.             "\n"    => '\n',
  585.             '"'     => '\"',
  586.             "'"     => "\\'"
  587.         );
  588.         return str_replace(array_keys($escape)array_values($escape)$javascript)
  589.         #return preg_replace('/\r\n|\n|\r/', "\\n",
  590.         #       preg_replace_callback('/["\']/', create_function('$m', 'return "\\{$m}";'),
  591.         #       (!is_null($javascript) ? $javascript : '')));
  592.     }
  593.     
  594.     # Returns a JavaScript tag with the $content inside. Example:
  595.     #   javascript_tag("alert('All is good')") => <script type="text/javascript">alert('All is good')</script>
  596.     function javascript_tag($content{
  597.         return $this->content_tag("script"$this->javascript_cdata_section($content)array('type' => "text/javascript"));
  598.     }
  599.     
  600.     function javascript_cdata_section($content{
  601.         return "\n//" $this->cdata_section("\n{$content}\n//""\n";
  602.     }
  603.     
  604. }
  605.  
  606.  
  607. /**
  608.   *  Avialble functions for use in views
  609.   *  link_to_remote($name, $options = array(), $html_options = array())
  610.   */
  611. function link_to_remote({
  612.     $javascript_helper new JavaScriptHelper();
  613.     $args func_get_args();
  614.     return call_user_func_array(array($javascript_helper'link_to_remote')$args);
  615. }
  616.  
  617. /**
  618.   *  link_to_function($name, $function, $html_options = array())
  619.   */
  620. function link_to_function({
  621.     $javascript_helper new JavaScriptHelper();
  622.     $args func_get_args();
  623.     return call_user_func_array(array($javascript_helper'link_to_function')$args);
  624. }
  625.  
  626.  
  627. /**
  628.   *  periodically_call_remote($options = array())
  629.   */
  630.     $javascript_helper new JavaScriptHelper();
  631.     $args func_get_args();
  632.     return call_user_func_array(array($javascript_helper'periodically_call_remote')$args);
  633. }
  634.  
  635. /**
  636.   *  form_remote_tag($options = array())
  637.   */
  638. function form_remote_tag({
  639.     $javascript_helper new JavaScriptHelper();
  640.     $args func_get_args();
  641.     return call_user_func_array(array($javascript_helper'form_remote_tag')$args);
  642.  
  643. /**
  644.   *  submit_to_remote($name, $value, $options = array())
  645.   */
  646. function submit_to_remote({
  647.     $javascript_helper new JavaScriptHelper();
  648.     $args func_get_args();
  649.     return call_user_func_array(array($javascript_helper'submit_to_remote')$args);
  650.  
  651. /**
  652.   *  update_element_function($element_id, $options = array(), $block = null)
  653.   */
  654.     $javascript_helper new JavaScriptHelper();
  655.     $args func_get_args();
  656.     return call_user_func_array(array($javascript_helper'update_element_function')$args);
  657.  
  658. /**
  659.   *  evaluate_remote_response()
  660.   */
  661.     $javascript_helper new JavaScriptHelper();
  662.     $args func_get_args();
  663.     return call_user_func_array(array($javascript_helper'evaluate_remote_response')$args);
  664.  
  665. /**
  666.   *  remote_function($options)
  667.   */
  668. function remote_function({
  669.     $javascript_helper new JavaScriptHelper();
  670.     $args func_get_args();
  671.     return call_user_func_array(array($javascript_helper'remote_function')$args);
  672.  
  673. /**
  674.   *  observe_field($field_id, $options = array())
  675.   */
  676. function observe_field({
  677.     $javascript_helper new JavaScriptHelper();
  678.     $args func_get_args();
  679.     return call_user_func_array(array($javascript_helper'observe_field')$args);
  680.  
  681. /**
  682.   *  observe_form($form_id, $options = array())
  683.   */
  684. function observe_form({
  685.     $javascript_helper new JavaScriptHelper();
  686.     $args func_get_args();
  687.     return call_user_func_array(array($javascript_helper'observe_form')$args);
  688.  
  689. /**
  690.   *  visual_effect($name, $element_id = false, $js_options = array())
  691.   */
  692. function visual_effect({
  693.     $javascript_helper new JavaScriptHelper();
  694.     $args func_get_args();
  695.     return call_user_func_array(array($javascript_helper'visual_effect')$args);
  696.  
  697. /**
  698.   *  sortable_element($element_id, $options = array())
  699.   */
  700. function sortable_element({
  701.     $javascript_helper new JavaScriptHelper();
  702.     $args func_get_args();
  703.     return call_user_func_array(array($javascript_helper'sortable_element')$args);
  704.  
  705. /**
  706.   *  draggable_element($element_id, $options = array())
  707.   */
  708. function draggable_element({
  709.     $javascript_helper new JavaScriptHelper();
  710.     $args func_get_args();
  711.     return call_user_func_array(array($javascript_helper'draggable_element')$args);
  712. }
  713.  
  714. /**
  715.   *  drop_receiving_element($element_id, $options = array())
  716.   */
  717. function drop_receiving_element({
  718.     $javascript_helper new JavaScriptHelper();
  719.     $args func_get_args();
  720.     return call_user_func_array(array($javascript_helper'drop_receiving_element')$args);
  721. }
  722.  
  723. /**
  724.   *  escape_javascript($javascript)
  725.   */
  726. function escape_javascript({
  727.     $javascript_helper new JavaScriptHelper();
  728.     $args func_get_args();
  729.     return call_user_func_array(array($javascript_helper'escape_javascript')$args);
  730. }
  731.  
  732. /**
  733.   *  javascript_tag($content)
  734.   */
  735. function javascript_tag({
  736.     $javascript_helper new JavaScriptHelper();
  737.     $args func_get_args();
  738.     return call_user_func_array(array($javascript_helper'javascript_tag')$args);
  739. }
  740.  
  741. /**
  742.   *  javascript_cdata_section($content)
  743.   */
  744.     $javascript_helper new JavaScriptHelper();
  745.     $args func_get_args();
  746.     return call_user_func_array(array($javascript_helper'javascript_cdata_section')$args);
  747. }
  748.  
  749. ?>

Documentation generated on Mon, 21 May 2007 22:28:43 -0600 by phpDocumentor 1.3.2