js.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: js_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 
00004 /**
00005  * Javascript Generator class file.
00006  *
00007  * PHP versions 4 and 5
00008  *
00009  * CakePHP :  Rapid Development Framework <http://www.cakephp.org/>
00010  * Copyright 2006-2008, Cake Software Foundation, Inc.
00011  *                              1785 E. Sahara Avenue, Suite 490-204
00012  *                              Las Vegas, Nevada 89104
00013  *
00014  * Licensed under The MIT License
00015  * Redistributions of files must retain the above copyright notice.
00016  *
00017  * @filesource
00018  * @copyright       Copyright 2006-2008, Cake Software Foundation, Inc.
00019  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
00020  * @package         cake
00021  * @subpackage      cake.cake.libs.view.helpers
00022  * @since           CakePHP v 1.2
00023  * @version         $Revision: 580 $
00024  * @modifiedby      $LastChangedBy: gwoo $
00025  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00026  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00027  */
00028 
00029 /**
00030  * Javascript Generator helper class for easy use of JavaScript.
00031  *
00032  * JsHelper provides an abstract interface for authoring JavaScript with a
00033  * given client-side library.
00034  *
00035  * @package     cake
00036  * @subpackage  cake.cake.libs.view.helpers
00037  */
00038 
00039 class JsHelper extends Overloadable2 {
00040 
00041     var $base = null;
00042     var $webroot = null;
00043     var $here = null;
00044     var $params = null;
00045     var $action = null;
00046     var $data = null;
00047     var $themeWeb = null;
00048     var $plugin = null;
00049 
00050     var $helpers = array();
00051 
00052     var $hook = null;
00053 
00054     var $__objects = array();
00055 
00056     var $effectMap = array(
00057         'Appear', 'Fade', 'Puff', 'BlindDown', 'BlindUp', 'SwitchOff', 'SlideDown', 'SlideUp',
00058         'DropOut', 'Shake', 'Pulsate', 'Squish', 'Fold', 'Grow', 'Shrink', 'Highlight', 'toggle'
00059     );
00060 
00061     var $output = false;
00062 
00063     function __construct() {
00064         $this->effectMap = array_combine(
00065             array_map('strtolower', $this->effectMap),
00066             $this->effectMap
00067         );
00068         parent::__construct();
00069     }
00070 
00071     function call__($method, $params) {
00072         if (is_object($this->hook) && method_exists($this->hook, $method)) {
00073 
00074         }
00075         if (method_exists($this, $method . '_')) {
00076             return call_user_func_array(array(&$this, $method . '_'), $params);
00077         }
00078     }
00079 
00080     function alert_($message) {
00081         return 'alert("' . $this->escape($message) . '");';
00082     }
00083 
00084     function if_($if, $then, $else = null, $elseif = array()) {
00085         $len = strlen($if) - 1;
00086         if ($if{$len} == ';') {
00087             $if{$len} = null;
00088         }
00089 
00090         $out = 'if (' . $if . ') { ' . $then . ' }';
00091 
00092         foreach ($elseif as $cond => $exec) {
00093             //$out .=
00094         }
00095 
00096         if (!empty($else)) {
00097             $out .= ' else { ' . $else . ' }';
00098         }
00099 
00100         return $out;
00101     }
00102 
00103     function confirm_($message) {
00104         return 'confirm("' . $this->escape($message) . '");';
00105     }
00106 
00107     function prompt_($message, $default = '') {
00108         return 'prompt("' . $this->escape($message) . '", "' . $this->escape($default) . '");';
00109     }
00110 /*
00111  * Tries a series of expressions, and executes after first successful completion.
00112  * (See Prototype's Try.these).
00113  *
00114  * @return string
00115  */
00116     function tryThese_($expr1, $expr2, $expr3) {
00117     }
00118 /**
00119  * Loads a remote URL
00120  *
00121  * @param  string $url
00122  * @param  array  $options
00123  * @return string
00124  */
00125     function load_($url = null, $options = array()) {
00126 
00127         if (isset($options['update'])) {
00128             if (!is_array($options['update'])) {
00129                 $func = "new Ajax.Updater('{$options['update']}',";
00130             } else {
00131                 $func = "new Ajax.Updater(document.createElement('div'),";
00132             }
00133             if (!isset($options['requestHeaders'])) {
00134                 $options['requestHeaders'] = array();
00135             }
00136             if (is_array($options['update'])) {
00137                 $options['update'] = join(' ', $options['update']);
00138             }
00139             $options['requestHeaders']['X-Update'] = $options['update'];
00140         } else {
00141             $func = "new Ajax.Request(";
00142         }
00143 
00144         $func .= "'" . Router::url($url) . "'";
00145         $ajax =& new AjaxHelper();
00146         $func .= ", " . $ajax->__optionsForAjax($options) . ")";
00147 
00148         if (isset($options['before'])) {
00149             $func = "{$options['before']}; $func";
00150         }
00151         if (isset($options['after'])) {
00152             $func = "$func; {$options['after']};";
00153         }
00154         if (isset($options['condition'])) {
00155             $func = "if ({$options['condition']}) { $func; }";
00156         }
00157         if (isset($options['confirm'])) {
00158             $func = "if (confirm('" . $this->Javascript->escapeString($options['confirm'])
00159                 . "')) { $func; } else { return false; }";
00160         }
00161         return $func;
00162     }
00163 /**
00164  * Redirects to a URL
00165  *
00166  * @param  mixed $url
00167  * @param  array  $options
00168  * @return string
00169  */
00170     function redirect_($url = null) {
00171         return 'window.location = "' . Router::url($url) . '";';
00172     }
00173 /**
00174  * Escape a string to be JavaScript friendly.
00175  *
00176  * List of escaped ellements:
00177  *  + "\r\n" => '\n'
00178  *  + "\r" => '\n'
00179  *  + "\n" => '\n'
00180  *  + '"' => '\"'
00181  *  + "'" => "\\'"
00182  *
00183  * @param  string $script String that needs to get escaped.
00184  * @return string Escaped string.
00185  */
00186     function escape($string) {
00187         $escape = array("\r\n" => '\n', "\r" => '\n', "\n" => '\n', '"' => '\"', "'" => "\\'");
00188         return str_replace(array_keys($escape), array_values($escape), $string);
00189     }
00190 
00191     function get__($name) {
00192         return $this->__object($name, 'id');
00193     }
00194 
00195     function select($pattern) {
00196         return $this->__object($pattern, 'pattern');
00197     }
00198 
00199     function real($var) {
00200         return $this->__object($var, 'real');
00201     }
00202 
00203     function __object($name, $var) {
00204         if (!isset($this->__objects[$name])) {
00205             $this->__objects[$name] = new JsHelperObject($this);
00206             $this->__objects[$name]->{$var} = $name;
00207         }
00208         return $this->__objects[$name];
00209     }
00210 /**
00211  * Generates a JavaScript object in JavaScript Object Notation (JSON)
00212  * from an array
00213  *
00214  * @param array $data Data to be converted
00215  * @param boolean $block Wraps return value in a <script/> block if true
00216  * @param string $prefix Prepends the string to the returned data
00217  * @param string $postfix Appends the string to the returned data
00218  * @param array $stringKeys A list of array keys to be treated as a string
00219  * @param boolean $quoteKeys If false, treats $stringKey as a list of keys *not* to be quoted
00220  * @param string $q The type of quote to use
00221  * @return string A JSON code block
00222  */
00223     function object($data = array(), $block = false, $prefix = '', $postfix = '', $stringKeys = array(), $quoteKeys = true, $q = "\"") {
00224         if (is_object($data)) {
00225             $data = get_object_vars($data);
00226         }
00227 
00228         $out = array();
00229         $key = array();
00230 
00231         if (is_array($data)) {
00232             $keys = array_keys($data);
00233         }
00234 
00235         $numeric = true;
00236 
00237         if (!empty($keys)) {
00238             foreach ($keys as $key) {
00239                 if (!is_numeric($key)) {
00240                     $numeric = false;
00241                     break;
00242                 }
00243             }
00244         }
00245 
00246         foreach ($data as $key => $val) {
00247             if (is_array($val) || is_object($val)) {
00248                 $val = $this->object($val, false, '', '', $stringKeys, $quoteKeys, $q);
00249             } else {
00250                 if ((!count($stringKeys) && !is_numeric($val) && !is_bool($val)) || ($quoteKeys && in_array($key, $stringKeys)) || (!$quoteKeys && !in_array($key, $stringKeys)) && $val !== null) {
00251                     $val = $q . $this->escapeString($val) . $q;
00252                 }
00253                 if ($val == null) {
00254                     $val = 'null';
00255                 }
00256             }
00257 
00258             if (!$numeric) {
00259                 $val = $q . $key . $q . ':' . $val;
00260             }
00261 
00262             $out[] = $val;
00263         }
00264 
00265         if (!$numeric) {
00266             $rt = '{' . join(', ', $out) . '}';
00267         } else {
00268             $rt = '[' . join(', ', $out) . ']';
00269         }
00270         $rt = $prefix . $rt . $postfix;
00271 
00272         if ($block) {
00273             $rt = $this->codeBlock($rt);
00274         }
00275 
00276         return $rt;
00277     }
00278 }
00279 
00280 class JsHelperObject {
00281 
00282     var $__parent = null;
00283 
00284     var $id = null;
00285 
00286     var $pattern = null;
00287 
00288     var $real = null;
00289 
00290     function __construct(&$parent) {
00291         if (is_object($parent)) {
00292             $this->setParent($parent);
00293         }
00294     }
00295 
00296     function toString() {
00297         return $this->__toString();
00298     }
00299 
00300     function __toString() {
00301         return $this->literal;
00302     }
00303 
00304     function ref($ref = null) {
00305         if ($ref == null) {
00306             foreach (array('id', 'pattern', 'real') as $ref) {
00307                 if ($this->{$ref} !== null) {
00308                     return $this->{$ref};
00309                 }
00310             }
00311         } else {
00312             return ($this->{$ref} !== null);
00313         }
00314         return null;
00315     }
00316 
00317     function literal($append = null) {
00318         if (!empty($this->id)) {
00319             $data = '$("' . $this->id . '")';
00320         }
00321         if (!empty($this->pattern)) {
00322             $data = '$$("' . $this->pattern . '")';
00323         }
00324         if (!empty($this->real)) {
00325             $data = $this->real;
00326         }
00327         if (!empty($append)) {
00328             $data .= '.' . $append;
00329         }
00330         return $data;
00331     }
00332 
00333     function __call($name, $args) {
00334         $data = '';
00335 
00336         if (isset($this->__parent->effectMap[strtolower($name)])) {
00337             array_unshift($args, $this->__parent->effectMap[strtolower($name)]);
00338             $name = 'effect';
00339         }
00340 
00341         switch ($name) {
00342             case 'effect':
00343             case 'visualEffect':
00344 
00345                 if (strpos($args[0], '_') || $args[0]{0} != strtoupper($args[0]{0})) {
00346                     $args[0] = Inflector::camelize($args[0]);
00347                 }
00348 
00349                 if (strtolower($args[0]) == 'highlight') {
00350                     $data .= 'new ';
00351                 }
00352                 if ($this->pattern == null) {
00353                     $data .= 'Effect.' . $args[0] . '(' . $this->literal();
00354                 } else {
00355                     $data .= 'Effect.' . $args[0] . '(item';
00356                 }
00357 
00358                 if (isset($args[1]) && is_array($args[1])) {
00359                     $data .= ', {' . $this->__options($args[1]) . '}';
00360                 }
00361                 $data .= ');';
00362 
00363                 if ($this->pattern !== null) {
00364                     $data = $this->each($data);
00365                 }
00366             break;
00367             case 'remove':
00368             case 'toggle':
00369             case 'show':
00370             case 'hide':
00371                 if (empty($args)) {
00372                     $obj = 'Element';
00373                     $params = '';
00374                 } else {
00375                     $obj = 'Effect';
00376                     $params = ', "' . $args[0] . '"';
00377                 }
00378 
00379                 if ($this->pattern != null) {
00380                     $data = $this->each($obj . ".{$name}(item);");
00381                 } else {
00382                     $data = $obj . ".{$name}(" . $this->literal() . ');';
00383                 }
00384             break;
00385             case 'visible':
00386                 $data = $this->literal() . '.visible();';
00387             break;
00388             case 'update':
00389                 $data = $this->literal() . ".update({$args[0]});";
00390             break;
00391             case 'load':
00392                 $data = 'new Ajax.Updater("' . $this->id . '", "' . $args[0] . '"';
00393                 if (isset($args[1]) && is_array($args[1])) {
00394                     $data .= ', {' . $this->__options($args[1]) . '}';
00395                 }
00396                 $data .= ');';
00397             break;
00398             case 'each':
00399             case 'all':
00400             case 'any':
00401             case 'detect':
00402             case 'findAll':
00403                 if ($this->pattern != null) {
00404                     $data = $this->__iterate($name, $args[0]);
00405                 }
00406             break;
00407             case 'addClass':
00408             case 'removeClass':
00409             case 'hasClass':
00410             case 'toggleClass':
00411                 $data = $this->literal() . ".{$name}Name(\"{$args[0]}\");";
00412             break;
00413             case 'clone':
00414             case 'inspect':
00415             case 'keys':
00416             case 'values':
00417                 $data = "Object.{$name}(" . $this->literal() . ");";
00418             break;
00419             case 'extend':
00420                 $data = "Object.extend(" . $this->literal() . ", {$args[0]});";
00421             break;
00422             case '...':
00423                 // Handle other methods here
00424                 // including interfaces to load other files on-the-fly
00425                 // that add support for additional methods/replacing existing methods
00426             break;
00427             default:
00428                 $data = $this->literal() . '.' . $name . '();';
00429             break;
00430         }
00431 
00432         if ($this->__parent->output) {
00433             echo $data;
00434         } else {
00435             return $data;
00436         }
00437     }
00438 
00439     function __iterate($method, $data) {
00440         return '$$("' . $this->pattern . '").' . $method . '(function(item) {' . $data . '});';
00441     }
00442 
00443     function setParent(&$parent) {
00444         $this->__parent =& $parent;
00445     }
00446 
00447     function __options($opts) {
00448         $options = array();
00449         foreach ($opts as $key => $val) {
00450             if (!is_int($val)) {
00451                 $val = '"' . $val . '"';
00452             }
00453             $options[] = $key . ':' . $val;
00454         }
00455         return join(', ', $options);
00456     }
00457 }
00458 
00459 ?>