Subversion-Projekte lars-tiefland.cakephp

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* SVN FILE: $Id: js.php 7945 2008-12-19 02:16:01Z gwoo $ */
3
/**
4
 * Javascript Generator class file.
5
 *
6
 * PHP versions 4 and 5
7
 *
8
 * CakePHP :  Rapid Development Framework (http://www.cakephp.org)
9
 * Copyright 2006-2008, Cake Software Foundation, Inc.
10
 *
11
 * Licensed under The MIT License
12
 * Redistributions of files must retain the above copyright notice.
13
 *
14
 * @filesource
15
 * @copyright     Copyright 2006-2008, Cake Software Foundation, Inc.
16
 * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
17
 * @package       cake
18
 * @subpackage    cake.cake.libs.view.helpers
19
 * @since         CakePHP v 1.2
20
 * @version       $Revision: 7945 $
21
 * @modifiedby    $LastChangedBy: gwoo $
22
 * @lastmodified  $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
23
 * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
24
 */
25
/**
26
 * Javascript Generator helper class for easy use of JavaScript.
27
 *
28
 * JsHelper provides an abstract interface for authoring JavaScript with a
29
 * given client-side library.
30
 *
31
 * @package       cake
32
 * @subpackage    cake.cake.libs.view.helpers
33
 */
34
class JsHelper extends Overloadable2 {
35
	var $base = null;
36
	var $webroot = null;
37
	var $here = null;
38
	var $params = null;
39
	var $action = null;
40
	var $data = null;
41
	var $themeWeb = null;
42
	var $plugin = null;
43
 
44
	var $helpers = array();
45
 
46
	var $hook = null;
47
 
48
	var $__objects = array();
49
 
50
	var $effectMap = array(
51
		'Appear', 'Fade', 'Puff', 'BlindDown', 'BlindUp', 'SwitchOff', 'SlideDown', 'SlideUp',
52
		'DropOut', 'Shake', 'Pulsate', 'Squish', 'Fold', 'Grow', 'Shrink', 'Highlight', 'toggle'
53
	);
54
 
55
	var $output = false;
56
 
57
	function __construct() {
58
		$this->effectMap = array_combine(
59
			array_map('strtolower', $this->effectMap),
60
			$this->effectMap
61
		);
62
		parent::__construct();
63
	}
64
 
65
	function call__($method, $params) {
66
		if (is_object($this->hook) && method_exists($this->hook, $method)) {
67
			$this->hook->dispatchMethod($method . '_', $params);
68
		}
69
		if (method_exists($this, $method . '_')) {
70
			return $this->dispatchMethod($method . '_', $params);
71
		}
72
	}
73
 
74
	function alert_($message) {
75
		return 'alert("' . $this->escape($message) . '");';
76
	}
77
 
78
	function if_($if, $then, $else = null, $elseIf = array()) {
79
		$len = strlen($if) - 1;
80
		if ($if{$len} == ';') {
81
			$if{$len} = null;
82
		}
83
 
84
		$out = 'if (' . $if . ') { ' . $then . ' }';
85
 
86
		foreach ($elseIf as $cond => $exec) {
87
			//$out .=
88
		}
89
 
90
		if (!empty($else)) {
91
			$out .= ' else { ' . $else . ' }';
92
		}
93
 
94
		return $out;
95
	}
96
 
97
	function confirm_($message) {
98
		return 'confirm("' . $this->escape($message) . '");';
99
	}
100
 
101
	function prompt_($message, $default = '') {
102
		return 'prompt("' . $this->escape($message) . '", "' . $this->escape($default) . '");';
103
	}
104
/*
105
 * Tries a series of expressions, and executes after first successful completion.
106
 * (See Prototype's Try.these).
107
 *
108
 * @return string
109
 */
110
	function tryThese_($expr1, $expr2, $expr3) {
111
	}
112
/**
113
 * Loads a remote URL
114
 *
115
 * @param  string $url
116
 * @param  array  $options
117
 * @return string
118
 */
119
	function load_($url = null, $options = array()) {
120
 
121
		if (isset($options['update'])) {
122
			if (!is_array($options['update'])) {
123
				$func = "new Ajax.Updater('{$options['update']}',";
124
			} else {
125
				$func = "new Ajax.Updater(document.createElement('div'),";
126
			}
127
			if (!isset($options['requestHeaders'])) {
128
				$options['requestHeaders'] = array();
129
			}
130
			if (is_array($options['update'])) {
131
				$options['update'] = join(' ', $options['update']);
132
			}
133
			$options['requestHeaders']['X-Update'] = $options['update'];
134
		} else {
135
			$func = "new Ajax.Request(";
136
		}
137
 
138
		$func .= "'" . Router::url($url) . "'";
139
		$ajax =& new AjaxHelper();
140
		$func .= ", " . $ajax->__optionsForAjax($options) . ")";
141
 
142
		if (isset($options['before'])) {
143
			$func = "{$options['before']}; $func";
144
		}
145
		if (isset($options['after'])) {
146
			$func = "$func; {$options['after']};";
147
		}
148
		if (isset($options['condition'])) {
149
			$func = "if ({$options['condition']}) { $func; }";
150
		}
151
		if (isset($options['confirm'])) {
152
			$func = "if (confirm('" . $this->Javascript->escapeString($options['confirm'])
153
				. "')) { $func; } else { return false; }";
154
		}
155
		return $func;
156
	}
157
/**
158
 * Redirects to a URL
159
 *
160
 * @param  mixed $url
161
 * @param  array  $options
162
 * @return string
163
 */
164
	function redirect_($url = null) {
165
		return 'window.location = "' . Router::url($url) . '";';
166
	}
167
/**
168
 * Escape a string to be JavaScript friendly.
169
 *
170
 * List of escaped ellements:
171
 *	+ "\r\n" => '\n'
172
 *	+ "\r" => '\n'
173
 *	+ "\n" => '\n'
174
 *	+ '"' => '\"'
175
 *	+ "'" => "\\'"
176
 *
177
 * @param  string $script String that needs to get escaped.
178
 * @return string Escaped string.
179
 */
180
	function escape($string) {
181
		$escape = array("\r\n" => '\n', "\r" => '\n', "\n" => '\n', '"' => '\"', "'" => "\\'");
182
		return str_replace(array_keys($escape), array_values($escape), $string);
183
	}
184
 
185
	function get__($name) {
186
		return $this->__object($name, 'id');
187
	}
188
 
189
	function select($pattern) {
190
		return $this->__object($pattern, 'pattern');
191
	}
192
 
193
	function real($var) {
194
		return $this->__object($var, 'real');
195
	}
196
 
197
	function __object($name, $var) {
198
		if (!isset($this->__objects[$name])) {
199
			$this->__objects[$name] = new JsHelperObject($this);
200
			$this->__objects[$name]->{$var} = $name;
201
		}
202
		return $this->__objects[$name];
203
	}
204
/**
205
 * Generates a JavaScript object in JavaScript Object Notation (JSON)
206
 * from an array
207
 *
208
 * @param array $data Data to be converted
209
 * @param boolean $block Wraps return value in a <script/> block if true
210
 * @param string $prefix Prepends the string to the returned data
211
 * @param string $postfix Appends the string to the returned data
212
 * @param array $stringKeys A list of array keys to be treated as a string
213
 * @param boolean $quoteKeys If false, treats $stringKey as a list of keys *not* to be quoted
214
 * @param string $q The type of quote to use
215
 * @return string A JSON code block
216
 */
217
	function object($data = array(), $block = false, $prefix = '', $postfix = '', $stringKeys = array(), $quoteKeys = true, $q = "\"") {
218
		if (is_object($data)) {
219
			$data = get_object_vars($data);
220
		}
221
 
222
		$out = array();
223
		$key = array();
224
 
225
		if (is_array($data)) {
226
			$keys = array_keys($data);
227
		}
228
 
229
		$numeric = true;
230
 
231
		if (!empty($keys)) {
232
			foreach ($keys as $key) {
233
				if (!is_numeric($key)) {
234
					$numeric = false;
235
					break;
236
				}
237
			}
238
		}
239
 
240
		foreach ($data as $key => $val) {
241
			if (is_array($val) || is_object($val)) {
242
				$val = $this->object($val, false, '', '', $stringKeys, $quoteKeys, $q);
243
			} else {
244
				if ((!count($stringKeys) && !is_numeric($val) && !is_bool($val)) || ($quoteKeys && in_array($key, $stringKeys)) || (!$quoteKeys && !in_array($key, $stringKeys)) && $val !== null) {
245
					$val = $q . $this->escapeString($val) . $q;
246
				}
247
				if ($val == null) {
248
					$val = 'null';
249
				}
250
			}
251
 
252
			if (!$numeric) {
253
				$val = $q . $key . $q . ':' . $val;
254
			}
255
 
256
			$out[] = $val;
257
		}
258
 
259
		if (!$numeric) {
260
			$rt = '{' . join(', ', $out) . '}';
261
		} else {
262
			$rt = '[' . join(', ', $out) . ']';
263
		}
264
		$rt = $prefix . $rt . $postfix;
265
 
266
		if ($block) {
267
			$rt = $this->codeBlock($rt);
268
		}
269
 
270
		return $rt;
271
	}
272
}
273
 
274
class JsHelperObject {
275
	var $__parent = null;
276
 
277
	var $id = null;
278
 
279
	var $pattern = null;
280
 
281
	var $real = null;
282
 
283
	function __construct(&$parent) {
284
		if (is_object($parent)) {
285
			$this->setParent($parent);
286
		}
287
	}
288
 
289
	function toString() {
290
		return $this->__toString();
291
	}
292
 
293
	function __toString() {
294
		return $this->literal;
295
	}
296
 
297
	function ref($ref = null) {
298
		if ($ref == null) {
299
			foreach (array('id', 'pattern', 'real') as $ref) {
300
				if ($this->{$ref} !== null) {
301
					return $this->{$ref};
302
				}
303
			}
304
		} else {
305
			return ($this->{$ref} !== null);
306
		}
307
		return null;
308
	}
309
 
310
	function literal($append = null) {
311
		if (!empty($this->id)) {
312
			$data = '$("' . $this->id . '")';
313
		}
314
		if (!empty($this->pattern)) {
315
			$data = '$$("' . $this->pattern . '")';
316
		}
317
		if (!empty($this->real)) {
318
			$data = $this->real;
319
		}
320
		if (!empty($append)) {
321
			$data .= '.' . $append;
322
		}
323
		return $data;
324
	}
325
 
326
	function __call($name, $args) {
327
		$data = '';
328
 
329
		if (isset($this->__parent->effectMap[strtolower($name)])) {
330
			array_unshift($args, $this->__parent->effectMap[strtolower($name)]);
331
			$name = 'effect';
332
		}
333
 
334
		switch ($name) {
335
			case 'effect':
336
			case 'visualEffect':
337
 
338
				if (strpos($args[0], '_') || $args[0]{0} != strtoupper($args[0]{0})) {
339
					$args[0] = Inflector::camelize($args[0]);
340
				}
341
 
342
				if (strtolower($args[0]) == 'highlight') {
343
					$data .= 'new ';
344
				}
345
				if ($this->pattern == null) {
346
					$data .= 'Effect.' . $args[0] . '(' . $this->literal();
347
				} else {
348
					$data .= 'Effect.' . $args[0] . '(item';
349
				}
350
 
351
				if (isset($args[1]) && is_array($args[1])) {
352
					$data .= ', {' . $this->__options($args[1]) . '}';
353
				}
354
				$data .= ');';
355
 
356
				if ($this->pattern !== null) {
357
					$data = $this->each($data);
358
				}
359
			break;
360
			case 'remove':
361
			case 'toggle':
362
			case 'show':
363
			case 'hide':
364
				if (empty($args)) {
365
					$obj = 'Element';
366
					$params = '';
367
				} else {
368
					$obj = 'Effect';
369
					$params = ', "' . $args[0] . '"';
370
				}
371
 
372
				if ($this->pattern != null) {
373
					$data = $this->each($obj . ".{$name}(item);");
374
				} else {
375
					$data = $obj . ".{$name}(" . $this->literal() . ');';
376
				}
377
			break;
378
			case 'visible':
379
				$data = $this->literal() . '.visible();';
380
			break;
381
			case 'update':
382
				$data = $this->literal() . ".update({$args[0]});";
383
			break;
384
			case 'load':
385
				$data = 'new Ajax.Updater("' . $this->id . '", "' . $args[0] . '"';
386
				if (isset($args[1]) && is_array($args[1])) {
387
					$data .= ', {' . $this->__options($args[1]) . '}';
388
				}
389
				$data .= ');';
390
			break;
391
			case 'each':
392
			case 'all':
393
			case 'any':
394
			case 'detect':
395
			case 'findAll':
396
				if ($this->pattern != null) {
397
					$data = $this->__iterate($name, $args[0]);
398
				}
399
			break;
400
			case 'addClass':
401
			case 'removeClass':
402
			case 'hasClass':
403
			case 'toggleClass':
404
				$data = $this->literal() . ".{$name}Name(\"{$args[0]}\");";
405
			break;
406
			case 'clone':
407
			case 'inspect':
408
			case 'keys':
409
			case 'values':
410
				$data = "Object.{$name}(" . $this->literal() . ");";
411
			break;
412
			case 'extend':
413
				$data = "Object.extend(" . $this->literal() . ", {$args[0]});";
414
			break;
415
			case '...':
416
				// Handle other methods here
417
				// including interfaces to load other files on-the-fly
418
				// that add support for additional methods/replacing existing methods
419
			break;
420
			default:
421
				$data = $this->literal() . '.' . $name . '();';
422
			break;
423
		}
424
 
425
		if ($this->__parent->output) {
426
			echo $data;
427
		} else {
428
			return $data;
429
		}
430
	}
431
 
432
	function __iterate($method, $data) {
433
		return '$$("' . $this->pattern . '").' . $method . '(function(item) {' . $data . '});';
434
	}
435
 
436
	function setParent(&$parent) {
437
		$this->__parent =& $parent;
438
	}
439
 
440
	function __options($opts) {
441
		$options = array();
442
		foreach ($opts as $key => $val) {
443
			if (!is_int($val)) {
444
				$val = '"' . $val . '"';
445
			}
446
			$options[] = $key . ':' . $val;
447
		}
448
		return join(', ', $options);
449
	}
450
}
451
?>