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

Documentation generated on Thu, 04 May 2006 19:47:50 -0600 by phpDocumentor 1.3.0RC4