pictcode / lib / Cake / View / Helper / JsHelper.php @ 9d2f0219
履歴 | 表示 | アノテート | ダウンロード (14.529 KB)
| 1 | 635eef61 | spyder1211 | <?php
|
|---|---|---|---|
| 2 | /**
|
||
| 3 | * Javascript Generator class file.
|
||
| 4 | *
|
||
| 5 | * CakePHP : Rapid Development Framework (http://cakephp.org)
|
||
| 6 | * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 7 | *
|
||
| 8 | * Licensed under The MIT License
|
||
| 9 | * For full copyright and license information, please see the LICENSE.txt
|
||
| 10 | * Redistributions of files must retain the above copyright notice.
|
||
| 11 | *
|
||
| 12 | * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 13 | * @link http://cakephp.org CakePHP(tm) Project
|
||
| 14 | * @package Cake.View.Helper
|
||
| 15 | * @since CakePHP(tm) v 1.2
|
||
| 16 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||
| 17 | */
|
||
| 18 | |||
| 19 | App::uses('AppHelper', 'View/Helper'); |
||
| 20 | App::uses('JsBaseEngineHelper', 'View/Helper'); |
||
| 21 | App::uses('Multibyte', 'I18n'); |
||
| 22 | |||
| 23 | /**
|
||
| 24 | * Javascript Generator helper class for easy use of JavaScript.
|
||
| 25 | *
|
||
| 26 | * JsHelper provides an abstract interface for authoring JavaScript with a
|
||
| 27 | * given client-side library.
|
||
| 28 | *
|
||
| 29 | * @package Cake.View.Helper
|
||
| 30 | * @property HtmlHelper $Html
|
||
| 31 | * @property FormHelper $Form
|
||
| 32 | */
|
||
| 33 | class JsHelper extends AppHelper { |
||
| 34 | |||
| 35 | /**
|
||
| 36 | * Whether or not you want scripts to be buffered or output.
|
||
| 37 | *
|
||
| 38 | * @var bool
|
||
| 39 | */
|
||
| 40 | public $bufferScripts = true; |
||
| 41 | |||
| 42 | /**
|
||
| 43 | * Helper dependencies
|
||
| 44 | *
|
||
| 45 | * @var array
|
||
| 46 | */
|
||
| 47 | public $helpers = array('Html', 'Form'); |
||
| 48 | |||
| 49 | /**
|
||
| 50 | * Variables to pass to Javascript.
|
||
| 51 | *
|
||
| 52 | * @var array
|
||
| 53 | * @see JsHelper::set()
|
||
| 54 | */
|
||
| 55 | protected $_jsVars = array(); |
||
| 56 | |||
| 57 | /**
|
||
| 58 | * Scripts that are queued for output
|
||
| 59 | *
|
||
| 60 | * @var array
|
||
| 61 | * @see JsHelper::buffer()
|
||
| 62 | */
|
||
| 63 | protected $_bufferedScripts = array(); |
||
| 64 | |||
| 65 | /**
|
||
| 66 | * Current Javascript Engine that is being used
|
||
| 67 | *
|
||
| 68 | * @var string
|
||
| 69 | */
|
||
| 70 | protected $_engineName; |
||
| 71 | |||
| 72 | /**
|
||
| 73 | * The javascript variable created by set() variables.
|
||
| 74 | *
|
||
| 75 | * @var string
|
||
| 76 | */
|
||
| 77 | public $setVariable = 'app'; |
||
| 78 | |||
| 79 | /**
|
||
| 80 | * Constructor - determines engine helper
|
||
| 81 | *
|
||
| 82 | * @param View $View the view object the helper is attached to.
|
||
| 83 | * @param string|array $settings Settings array contains name of engine helper.
|
||
| 84 | */
|
||
| 85 | public function __construct(View $View, $settings = array()) { |
||
| 86 | $className = 'Jquery'; |
||
| 87 | if (is_array($settings) && isset($settings[0])) { |
||
| 88 | $className = $settings[0]; |
||
| 89 | } elseif (is_string($settings)) { |
||
| 90 | $className = $settings; |
||
| 91 | } |
||
| 92 | $engineName = $className; |
||
| 93 | list(, $className) = pluginSplit($className); |
||
| 94 | |||
| 95 | $this->_engineName = $className . 'Engine'; |
||
| 96 | $engineClass = $engineName . 'Engine'; |
||
| 97 | $this->helpers[] = $engineClass; |
||
| 98 | parent::__construct($View, $settings); |
||
| 99 | } |
||
| 100 | |||
| 101 | /**
|
||
| 102 | * call__ Allows for dispatching of methods to the Engine Helper.
|
||
| 103 | * methods in the Engines bufferedMethods list will be automatically buffered.
|
||
| 104 | * You can control buffering with the buffer param as well. By setting the last parameter to
|
||
| 105 | * any engine method to a boolean you can force or disable buffering.
|
||
| 106 | *
|
||
| 107 | * e.g. `$js->get('#foo')->effect('fadeIn', array('speed' => 'slow'), true);`
|
||
| 108 | *
|
||
| 109 | * Will force buffering for the effect method. If the method takes an options array you may also add
|
||
| 110 | * a 'buffer' param to the options array and control buffering there as well.
|
||
| 111 | *
|
||
| 112 | * e.g. `$js->get('#foo')->event('click', $functionContents, array('buffer' => true));`
|
||
| 113 | *
|
||
| 114 | * The buffer parameter will not be passed onto the EngineHelper.
|
||
| 115 | *
|
||
| 116 | * @param string $method Method to be called
|
||
| 117 | * @param array $params Parameters for the method being called.
|
||
| 118 | * @return mixed Depends on the return of the dispatched method, or it could be an instance of the EngineHelper
|
||
| 119 | */
|
||
| 120 | public function __call($method, $params) { |
||
| 121 | if ($this->{$this->_engineName} && method_exists($this->{$this->_engineName}, $method)) { |
||
| 122 | $buffer = false; |
||
| 123 | $engineHelper = $this->{$this->_engineName}; |
||
| 124 | if (in_array(strtolower($method), $engineHelper->bufferedMethods)) { |
||
| 125 | $buffer = true; |
||
| 126 | } |
||
| 127 | if (count($params) > 0) { |
||
| 128 | $lastParam = $params[count($params) - 1]; |
||
| 129 | $hasBufferParam = (is_bool($lastParam) || is_array($lastParam) && isset($lastParam['buffer'])); |
||
| 130 | if ($hasBufferParam && is_bool($lastParam)) { |
||
| 131 | $buffer = $lastParam; |
||
| 132 | unset($params[count($params) - 1]); |
||
| 133 | } elseif ($hasBufferParam && is_array($lastParam)) { |
||
| 134 | $buffer = $lastParam['buffer']; |
||
| 135 | unset($params['buffer']); |
||
| 136 | } |
||
| 137 | } |
||
| 138 | |||
| 139 | $out = call_user_func_array(array(&$engineHelper, $method), $params); |
||
| 140 | if ($this->bufferScripts && $buffer && is_string($out)) { |
||
| 141 | $this->buffer($out); |
||
| 142 | return null; |
||
| 143 | } |
||
| 144 | if (is_object($out) && $out instanceof JsBaseEngineHelper) { |
||
| 145 | return $this; |
||
| 146 | } |
||
| 147 | return $out; |
||
| 148 | } |
||
| 149 | if (method_exists($this, $method . '_')) { |
||
| 150 | return call_user_func(array(&$this, $method . '_'), $params); |
||
| 151 | } |
||
| 152 | trigger_error(__d('cake_dev', 'JsHelper:: Missing Method %s is undefined', $method), E_USER_WARNING); |
||
| 153 | } |
||
| 154 | |||
| 155 | /**
|
||
| 156 | * Overwrite inherited Helper::value()
|
||
| 157 | * See JsBaseEngineHelper::value() for more information on this method.
|
||
| 158 | *
|
||
| 159 | * @param mixed $val A PHP variable to be converted to JSON
|
||
| 160 | * @param bool $quoteString If false, leaves string values unquoted
|
||
| 161 | * @param string $key Key name.
|
||
| 162 | * @return string a JavaScript-safe/JSON representation of $val
|
||
| 163 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::value
|
||
| 164 | */
|
||
| 165 | public function value($val = array(), $quoteString = null, $key = 'value') { |
||
| 166 | if ($quoteString === null) { |
||
| 167 | $quoteString = true; |
||
| 168 | } |
||
| 169 | return $this->{$this->_engineName}->value($val, $quoteString); |
||
| 170 | } |
||
| 171 | |||
| 172 | /**
|
||
| 173 | * Writes all Javascript generated so far to a code block or
|
||
| 174 | * caches them to a file and returns a linked script. If no scripts have been
|
||
| 175 | * buffered this method will return null. If the request is an XHR(ajax) request
|
||
| 176 | * onDomReady will be set to false. As the dom is already 'ready'.
|
||
| 177 | *
|
||
| 178 | * ### Options
|
||
| 179 | *
|
||
| 180 | * - `inline` - Set to true to have scripts output as a script block inline
|
||
| 181 | * if `cache` is also true, a script link tag will be generated. (default true)
|
||
| 182 | * - `cache` - Set to true to have scripts cached to a file and linked in (default false)
|
||
| 183 | * - `clear` - Set to false to prevent script cache from being cleared (default true)
|
||
| 184 | * - `onDomReady` - wrap cached scripts in domready event (default true)
|
||
| 185 | * - `safe` - if an inline block is generated should it be wrapped in <![CDATA[ ... ]]> (default true)
|
||
| 186 | *
|
||
| 187 | * @param array $options options for the code block
|
||
| 188 | * @return mixed Completed javascript tag if there are scripts, if there are no buffered
|
||
| 189 | * scripts null will be returned.
|
||
| 190 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::writeBuffer
|
||
| 191 | */
|
||
| 192 | public function writeBuffer($options = array()) { |
||
| 193 | $domReady = !$this->request->is('ajax'); |
||
| 194 | $defaults = array( |
||
| 195 | 'onDomReady' => $domReady, 'inline' => true, |
||
| 196 | 'cache' => false, 'clear' => true, 'safe' => true |
||
| 197 | ); |
||
| 198 | $options += $defaults; |
||
| 199 | $script = implode("\n", $this->getBuffer($options['clear'])); |
||
| 200 | |||
| 201 | if (empty($script)) { |
||
| 202 | return null; |
||
| 203 | } |
||
| 204 | |||
| 205 | if ($options['onDomReady']) { |
||
| 206 | $script = $this->{$this->_engineName}->domReady($script); |
||
| 207 | } |
||
| 208 | $opts = $options; |
||
| 209 | unset($opts['onDomReady'], $opts['cache'], $opts['clear']); |
||
| 210 | |||
| 211 | if ($options['cache'] && $options['inline']) { |
||
| 212 | $filename = md5($script); |
||
| 213 | $path = WWW_ROOT . Configure::read('App.jsBaseUrl'); |
||
| 214 | if (file_exists($path . $filename . '.js') |
||
| 215 | || cache(str_replace(WWW_ROOT, '', $path) . $filename . '.js', $script, '+999 days', 'public') |
||
| 216 | ) {
|
||
| 217 | return $this->Html->script($filename); |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | $return = $this->Html->scriptBlock($script, $opts); |
||
| 222 | if ($options['inline']) { |
||
| 223 | return $return; |
||
| 224 | } |
||
| 225 | return null; |
||
| 226 | } |
||
| 227 | |||
| 228 | /**
|
||
| 229 | * Write a script to the buffered scripts.
|
||
| 230 | *
|
||
| 231 | * @param string $script Script string to add to the buffer.
|
||
| 232 | * @param bool $top If true the script will be added to the top of the
|
||
| 233 | * buffered scripts array. If false the bottom.
|
||
| 234 | * @return void
|
||
| 235 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::buffer
|
||
| 236 | */
|
||
| 237 | public function buffer($script, $top = false) { |
||
| 238 | if ($top) { |
||
| 239 | array_unshift($this->_bufferedScripts, $script); |
||
| 240 | } else {
|
||
| 241 | $this->_bufferedScripts[] = $script; |
||
| 242 | } |
||
| 243 | } |
||
| 244 | |||
| 245 | /**
|
||
| 246 | * Get all the buffered scripts
|
||
| 247 | *
|
||
| 248 | * @param bool $clear Whether or not to clear the script caches (default true)
|
||
| 249 | * @return array Array of scripts added to the request.
|
||
| 250 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::getBuffer
|
||
| 251 | */
|
||
| 252 | public function getBuffer($clear = true) { |
||
| 253 | $this->_createVars();
|
||
| 254 | $scripts = $this->_bufferedScripts; |
||
| 255 | if ($clear) { |
||
| 256 | $this->_bufferedScripts = array(); |
||
| 257 | $this->_jsVars = array(); |
||
| 258 | } |
||
| 259 | return $scripts; |
||
| 260 | } |
||
| 261 | |||
| 262 | /**
|
||
| 263 | * Generates the object string for variables passed to javascript and adds to buffer
|
||
| 264 | *
|
||
| 265 | * @return void
|
||
| 266 | */
|
||
| 267 | protected function _createVars() { |
||
| 268 | if (!empty($this->_jsVars)) { |
||
| 269 | $setVar = (strpos($this->setVariable, '.')) ? $this->setVariable : 'window.' . $this->setVariable; |
||
| 270 | $this->buffer($setVar . ' = ' . $this->object($this->_jsVars) . ';', true); |
||
| 271 | } |
||
| 272 | } |
||
| 273 | |||
| 274 | /**
|
||
| 275 | * Generate an 'Ajax' link. Uses the selected JS engine to create a link
|
||
| 276 | * element that is enhanced with Javascript. Options can include
|
||
| 277 | * both those for HtmlHelper::link() and JsBaseEngine::request(), JsBaseEngine::event();
|
||
| 278 | *
|
||
| 279 | * ### Options
|
||
| 280 | *
|
||
| 281 | * - `confirm` - Generate a confirm() dialog before sending the event.
|
||
| 282 | * - `id` - use a custom id.
|
||
| 283 | * - `htmlAttributes` - additional non-standard htmlAttributes. Standard attributes are class, id,
|
||
| 284 | * rel, title, escape, onblur and onfocus.
|
||
| 285 | * - `buffer` - Disable the buffering and return a script tag in addition to the link.
|
||
| 286 | *
|
||
| 287 | * @param string $title Title for the link.
|
||
| 288 | * @param string|array $url Mixed either a string URL or a CakePHP URL array.
|
||
| 289 | * @param array $options Options for both the HTML element and Js::request()
|
||
| 290 | * @return string Completed link. If buffering is disabled a script tag will be returned as well.
|
||
| 291 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::link
|
||
| 292 | */
|
||
| 293 | public function link($title, $url = null, $options = array()) { |
||
| 294 | if (!isset($options['id'])) { |
||
| 295 | $options['id'] = 'link-' . (int)mt_rand(); |
||
| 296 | } |
||
| 297 | list($options, $htmlOptions) = $this->_getHtmlOptions($options); |
||
| 298 | $out = $this->Html->link($title, $url, $htmlOptions); |
||
| 299 | $this->get('#' . $htmlOptions['id']); |
||
| 300 | $requestString = $event = ''; |
||
| 301 | if (isset($options['confirm'])) { |
||
| 302 | $requestString = $this->confirmReturn($options['confirm']); |
||
| 303 | unset($options['confirm']); |
||
| 304 | } |
||
| 305 | $buffer = isset($options['buffer']) ? $options['buffer'] : null; |
||
| 306 | $safe = isset($options['safe']) ? $options['safe'] : true; |
||
| 307 | unset($options['buffer'], $options['safe']); |
||
| 308 | |||
| 309 | $requestString .= $this->request($url, $options); |
||
| 310 | |||
| 311 | if (!empty($requestString)) { |
||
| 312 | $event = $this->event('click', $requestString, $options + array('buffer' => $buffer)); |
||
| 313 | } |
||
| 314 | if (isset($buffer) && !$buffer) { |
||
| 315 | $opts = array('safe' => $safe); |
||
| 316 | $out .= $this->Html->scriptBlock($event, $opts); |
||
| 317 | } |
||
| 318 | return $out; |
||
| 319 | } |
||
| 320 | |||
| 321 | /**
|
||
| 322 | * Pass variables into Javascript. Allows you to set variables that will be
|
||
| 323 | * output when the buffer is fetched with `JsHelper::getBuffer()` or `JsHelper::writeBuffer()`
|
||
| 324 | * The Javascript variable used to output set variables can be controlled with `JsHelper::$setVariable`
|
||
| 325 | *
|
||
| 326 | * @param string|array $one Either an array of variables to set, or the name of the variable to set.
|
||
| 327 | * @param string|array $two If $one is a string, $two is the value for that key.
|
||
| 328 | * @return void
|
||
| 329 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::set
|
||
| 330 | */
|
||
| 331 | public function set($one, $two = null) { |
||
| 332 | $data = null; |
||
| 333 | if (is_array($one)) { |
||
| 334 | if (is_array($two)) { |
||
| 335 | $data = array_combine($one, $two); |
||
| 336 | } else {
|
||
| 337 | $data = $one; |
||
| 338 | } |
||
| 339 | } else {
|
||
| 340 | $data = array($one => $two); |
||
| 341 | } |
||
| 342 | if (!$data) { |
||
| 343 | return false; |
||
| 344 | } |
||
| 345 | $this->_jsVars = array_merge($this->_jsVars, $data); |
||
| 346 | } |
||
| 347 | |||
| 348 | /**
|
||
| 349 | * Uses the selected JS engine to create a submit input
|
||
| 350 | * element that is enhanced with Javascript. Options can include
|
||
| 351 | * both those for FormHelper::submit() and JsBaseEngine::request(), JsBaseEngine::event();
|
||
| 352 | *
|
||
| 353 | * Forms submitting with this method, cannot send files. Files do not transfer over XmlHttpRequest
|
||
| 354 | * and require an iframe or flash.
|
||
| 355 | *
|
||
| 356 | * ### Options
|
||
| 357 | *
|
||
| 358 | * - `url` The url you wish the XHR request to submit to.
|
||
| 359 | * - `confirm` A string to use for a confirm() message prior to submitting the request.
|
||
| 360 | * - `method` The method you wish the form to send by, defaults to POST
|
||
| 361 | * - `buffer` Whether or not you wish the script code to be buffered, defaults to true.
|
||
| 362 | * - Also see options for JsHelper::request() and JsHelper::event()
|
||
| 363 | *
|
||
| 364 | * @param string $caption The display text of the submit button.
|
||
| 365 | * @param array $options Array of options to use. See the options for the above mentioned methods.
|
||
| 366 | * @return string Completed submit button.
|
||
| 367 | * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#JsHelper::submit
|
||
| 368 | */
|
||
| 369 | public function submit($caption = null, $options = array()) { |
||
| 370 | if (!isset($options['id'])) { |
||
| 371 | $options['id'] = 'submit-' . (int)mt_rand(); |
||
| 372 | } |
||
| 373 | $formOptions = array('div'); |
||
| 374 | list($options, $htmlOptions) = $this->_getHtmlOptions($options, $formOptions); |
||
| 375 | $out = $this->Form->submit($caption, $htmlOptions); |
||
| 376 | |||
| 377 | $this->get('#' . $htmlOptions['id']); |
||
| 378 | |||
| 379 | $options['data'] = $this->serializeForm(array('isForm' => false, 'inline' => true)); |
||
| 380 | $requestString = $url = ''; |
||
| 381 | if (isset($options['confirm'])) { |
||
| 382 | $requestString = $this->confirmReturn($options['confirm']); |
||
| 383 | unset($options['confirm']); |
||
| 384 | } |
||
| 385 | if (isset($options['url'])) { |
||
| 386 | $url = $options['url']; |
||
| 387 | unset($options['url']); |
||
| 388 | } |
||
| 389 | if (!isset($options['method'])) { |
||
| 390 | $options['method'] = 'post'; |
||
| 391 | } |
||
| 392 | $options['dataExpression'] = true; |
||
| 393 | |||
| 394 | $buffer = isset($options['buffer']) ? $options['buffer'] : null; |
||
| 395 | $safe = isset($options['safe']) ? $options['safe'] : true; |
||
| 396 | unset($options['buffer'], $options['safe']); |
||
| 397 | |||
| 398 | $requestString .= $this->request($url, $options); |
||
| 399 | if (!empty($requestString)) { |
||
| 400 | $event = $this->event('click', $requestString, $options + array('buffer' => $buffer)); |
||
| 401 | } |
||
| 402 | if (isset($buffer) && !$buffer) { |
||
| 403 | $opts = array('safe' => $safe); |
||
| 404 | $out .= $this->Html->scriptBlock($event, $opts); |
||
| 405 | } |
||
| 406 | return $out; |
||
| 407 | } |
||
| 408 | |||
| 409 | /**
|
||
| 410 | * Parse a set of Options and extract the Html options.
|
||
| 411 | * Extracted Html Options are removed from the $options param.
|
||
| 412 | *
|
||
| 413 | * @param array $options Options to filter.
|
||
| 414 | * @param array $additional Array of additional keys to extract and include in the return options array.
|
||
| 415 | * @return array Array of js options and Htmloptions
|
||
| 416 | */
|
||
| 417 | protected function _getHtmlOptions($options, $additional = array()) { |
||
| 418 | $htmlKeys = array_merge( |
||
| 419 | array('class', 'id', 'escape', 'onblur', 'onfocus', 'rel', 'title', 'style'), |
||
| 420 | $additional
|
||
| 421 | ); |
||
| 422 | $htmlOptions = array(); |
||
| 423 | foreach ($htmlKeys as $key) { |
||
| 424 | if (isset($options[$key])) { |
||
| 425 | $htmlOptions[$key] = $options[$key]; |
||
| 426 | } |
||
| 427 | unset($options[$key]); |
||
| 428 | } |
||
| 429 | if (isset($options['htmlAttributes'])) { |
||
| 430 | $htmlOptions = array_merge($htmlOptions, $options['htmlAttributes']); |
||
| 431 | unset($options['htmlAttributes']); |
||
| 432 | } |
||
| 433 | return array($options, $htmlOptions); |
||
| 434 | } |
||
| 435 | |||
| 436 | } |