comparison cake/libs/view/helpers/html.php @ 0:261e66bd5a0c

hg init
author Shoshi TAMAKI <shoshi@cr.ie.u-ryukyu.ac.jp>
date Sun, 24 Jul 2011 21:08:31 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:261e66bd5a0c
1 <?php
2 /**
3 * Html Helper class file.
4 *
5 * Simplifies the construction of HTML elements.
6 *
7 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8 * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
9 *
10 * Licensed under The MIT License
11 * Redistributions of files must retain the above copyright notice.
12 *
13 * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
14 * @link http://cakephp.org CakePHP(tm) Project
15 * @package cake
16 * @subpackage cake.cake.libs.view.helpers
17 * @since CakePHP(tm) v 0.9.1
18 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
19 */
20 /**
21 * Html Helper class for easy use of HTML widgets.
22 *
23 * HtmlHelper encloses all methods needed while working with HTML pages.
24 *
25 * @package cake
26 * @subpackage cake.cake.libs.view.helpers
27 * @link http://book.cakephp.org/view/1434/HTML
28 */
29 class HtmlHelper extends AppHelper {
30 /**
31 * html tags used by this helper.
32 *
33 * @var array
34 * @access public
35 */
36 var $tags = array(
37 'meta' => '<meta%s/>',
38 'metalink' => '<link href="%s"%s/>',
39 'link' => '<a href="%s"%s>%s</a>',
40 'mailto' => '<a href="mailto:%s" %s>%s</a>',
41 'form' => '<form %s>',
42 'formend' => '</form>',
43 'input' => '<input name="%s" %s/>',
44 'textarea' => '<textarea name="%s" %s>%s</textarea>',
45 'hidden' => '<input type="hidden" name="%s" %s/>',
46 'checkbox' => '<input type="checkbox" name="%s" %s/>',
47 'checkboxmultiple' => '<input type="checkbox" name="%s[]"%s />',
48 'radio' => '<input type="radio" name="%s" id="%s" %s />%s',
49 'selectstart' => '<select name="%s"%s>',
50 'selectmultiplestart' => '<select name="%s[]"%s>',
51 'selectempty' => '<option value=""%s>&nbsp;</option>',
52 'selectoption' => '<option value="%s"%s>%s</option>',
53 'selectend' => '</select>',
54 'optiongroup' => '<optgroup label="%s"%s>',
55 'optiongroupend' => '</optgroup>',
56 'checkboxmultiplestart' => '',
57 'checkboxmultipleend' => '',
58 'password' => '<input type="password" name="%s" %s/>',
59 'file' => '<input type="file" name="%s" %s/>',
60 'file_no_model' => '<input type="file" name="%s" %s/>',
61 'submit' => '<input %s/>',
62 'submitimage' => '<input type="image" src="%s" %s/>',
63 'button' => '<button type="%s"%s>%s</button>',
64 'image' => '<img src="%s" %s/>',
65 'tableheader' => '<th%s>%s</th>',
66 'tableheaderrow' => '<tr%s>%s</tr>',
67 'tablecell' => '<td%s>%s</td>',
68 'tablerow' => '<tr%s>%s</tr>',
69 'block' => '<div%s>%s</div>',
70 'blockstart' => '<div%s>',
71 'blockend' => '</div>',
72 'tag' => '<%s%s>%s</%s>',
73 'tagstart' => '<%s%s>',
74 'tagend' => '</%s>',
75 'para' => '<p%s>%s</p>',
76 'parastart' => '<p%s>',
77 'label' => '<label for="%s"%s>%s</label>',
78 'fieldset' => '<fieldset%s>%s</fieldset>',
79 'fieldsetstart' => '<fieldset><legend>%s</legend>',
80 'fieldsetend' => '</fieldset>',
81 'legend' => '<legend>%s</legend>',
82 'css' => '<link rel="%s" type="text/css" href="%s" %s/>',
83 'style' => '<style type="text/css"%s>%s</style>',
84 'charset' => '<meta http-equiv="Content-Type" content="text/html; charset=%s" />',
85 'ul' => '<ul%s>%s</ul>',
86 'ol' => '<ol%s>%s</ol>',
87 'li' => '<li%s>%s</li>',
88 'error' => '<div%s>%s</div>',
89 'javascriptblock' => '<script type="text/javascript"%s>%s</script>',
90 'javascriptstart' => '<script type="text/javascript">',
91 'javascriptlink' => '<script type="text/javascript" src="%s"%s></script>',
92 'javascriptend' => '</script>'
93 );
94
95 /**
96 * Breadcrumbs.
97 *
98 * @var array
99 * @access protected
100 */
101 var $_crumbs = array();
102
103 /**
104 * Names of script files that have been included once
105 *
106 * @var array
107 * @access private
108 */
109 var $__includedScripts = array();
110 /**
111 * Options for the currently opened script block buffer if any.
112 *
113 * @var array
114 * @access protected
115 */
116 var $_scriptBlockOptions = array();
117 /**
118 * Document type definitions
119 *
120 * @var array
121 * @access private
122 */
123 var $__docTypes = array(
124 'html4-strict' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
125 'html4-trans' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
126 'html4-frame' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
127 'xhtml-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
128 'xhtml-trans' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
129 'xhtml-frame' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
130 'xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
131 );
132
133 /**
134 * Adds a link to the breadcrumbs array.
135 *
136 * @param string $name Text for link
137 * @param string $link URL for link (if empty it won't be a link)
138 * @param mixed $options Link attributes e.g. array('id'=>'selected')
139 * @return void
140 * @see HtmlHelper::link() for details on $options that can be used.
141 * @access public
142 */
143 function addCrumb($name, $link = null, $options = null) {
144 $this->_crumbs[] = array($name, $link, $options);
145 }
146
147 /**
148 * Returns a doctype string.
149 *
150 * Possible doctypes:
151 *
152 * - html4-strict: HTML4 Strict.
153 * - html4-trans: HTML4 Transitional.
154 * - html4-frame: HTML4 Frameset.
155 * - xhtml-strict: XHTML1 Strict.
156 * - xhtml-trans: XHTML1 Transitional.
157 * - xhtml-frame: XHTML1 Frameset.
158 * - xhtml11: XHTML1.1.
159 *
160 * @param string $type Doctype to use.
161 * @return string Doctype string
162 * @access public
163 * @link http://book.cakephp.org/view/1439/docType
164 */
165 function docType($type = 'xhtml-strict') {
166 if (isset($this->__docTypes[$type])) {
167 return $this->__docTypes[$type];
168 }
169 return null;
170 }
171
172 /**
173 * Creates a link to an external resource and handles basic meta tags
174 *
175 * ### Options
176 *
177 * - `inline` Whether or not the link element should be output inline, or in scripts_for_layout.
178 *
179 * @param string $type The title of the external resource
180 * @param mixed $url The address of the external resource or string for content attribute
181 * @param array $options Other attributes for the generated tag. If the type attribute is html,
182 * rss, atom, or icon, the mime-type is returned.
183 * @return string A completed `<link />` element.
184 * @access public
185 * @link http://book.cakephp.org/view/1438/meta
186 */
187 function meta($type, $url = null, $options = array()) {
188 $inline = isset($options['inline']) ? $options['inline'] : true;
189 unset($options['inline']);
190
191 if (!is_array($type)) {
192 $types = array(
193 'rss' => array('type' => 'application/rss+xml', 'rel' => 'alternate', 'title' => $type, 'link' => $url),
194 'atom' => array('type' => 'application/atom+xml', 'title' => $type, 'link' => $url),
195 'icon' => array('type' => 'image/x-icon', 'rel' => 'icon', 'link' => $url),
196 'keywords' => array('name' => 'keywords', 'content' => $url),
197 'description' => array('name' => 'description', 'content' => $url),
198 );
199
200 if ($type === 'icon' && $url === null) {
201 $types['icon']['link'] = $this->webroot('favicon.ico');
202 }
203
204 if (isset($types[$type])) {
205 $type = $types[$type];
206 } elseif (!isset($options['type']) && $url !== null) {
207 if (is_array($url) && isset($url['ext'])) {
208 $type = $types[$url['ext']];
209 } else {
210 $type = $types['rss'];
211 }
212 } elseif (isset($options['type']) && isset($types[$options['type']])) {
213 $type = $types[$options['type']];
214 unset($options['type']);
215 } else {
216 $type = array();
217 }
218 } elseif ($url !== null) {
219 $inline = $url;
220 }
221 $options = array_merge($type, $options);
222 $out = null;
223
224 if (isset($options['link'])) {
225 if (isset($options['rel']) && $options['rel'] === 'icon') {
226 $out = sprintf($this->tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' '));
227 $options['rel'] = 'shortcut icon';
228 } else {
229 $options['link'] = $this->url($options['link'], true);
230 }
231 $out .= sprintf($this->tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' '));
232 } else {
233 $out = sprintf($this->tags['meta'], $this->_parseAttributes($options, array('type'), ' ', ' '));
234 }
235
236 if ($inline) {
237 return $out;
238 } else {
239 $view =& ClassRegistry::getObject('view');
240 $view->addScript($out);
241 }
242 }
243
244 /**
245 * Returns a charset META-tag.
246 *
247 * @param string $charset The character set to be used in the meta tag. If empty,
248 * The App.encoding value will be used. Example: "utf-8".
249 * @return string A meta tag containing the specified character set.
250 * @access public
251 * @link http://book.cakephp.org/view/1436/charset
252 */
253 function charset($charset = null) {
254 if (empty($charset)) {
255 $charset = strtolower(Configure::read('App.encoding'));
256 }
257 return sprintf($this->tags['charset'], (!empty($charset) ? $charset : 'utf-8'));
258 }
259
260 /**
261 * Creates an HTML link.
262 *
263 * If $url starts with "http://" this is treated as an external link. Else,
264 * it is treated as a path to controller/action and parsed with the
265 * HtmlHelper::url() method.
266 *
267 * If the $url is empty, $title is used instead.
268 *
269 * ### Options
270 *
271 * - `escape` Set to false to disable escaping of title and attributes.
272 *
273 * @param string $title The content to be wrapped by <a> tags.
274 * @param mixed $url Cake-relative URL or array of URL parameters, or external URL (starts with http://)
275 * @param array $options Array of HTML attributes.
276 * @param string $confirmMessage JavaScript confirmation message.
277 * @return string An `<a />` element.
278 * @access public
279 * @link http://book.cakephp.org/view/1442/link
280 */
281 function link($title, $url = null, $options = array(), $confirmMessage = false) {
282 $escapeTitle = true;
283 if ($url !== null) {
284 $url = $this->url($url);
285 } else {
286 $url = $this->url($title);
287 $title = $url;
288 $escapeTitle = false;
289 }
290
291 if (isset($options['escape'])) {
292 $escapeTitle = $options['escape'];
293 }
294
295 if ($escapeTitle === true) {
296 $title = h($title);
297 } elseif (is_string($escapeTitle)) {
298 $title = htmlentities($title, ENT_QUOTES, $escapeTitle);
299 }
300
301 if (!empty($options['confirm'])) {
302 $confirmMessage = $options['confirm'];
303 unset($options['confirm']);
304 }
305 if ($confirmMessage) {
306 $confirmMessage = str_replace("'", "\'", $confirmMessage);
307 $confirmMessage = str_replace('"', '\"', $confirmMessage);
308 $options['onclick'] = "return confirm('{$confirmMessage}');";
309 } elseif (isset($options['default']) && $options['default'] == false) {
310 if (isset($options['onclick'])) {
311 $options['onclick'] .= ' event.returnValue = false; return false;';
312 } else {
313 $options['onclick'] = 'event.returnValue = false; return false;';
314 }
315 unset($options['default']);
316 }
317 return sprintf($this->tags['link'], $url, $this->_parseAttributes($options), $title);
318 }
319
320 /**
321 * Creates a link element for CSS stylesheets.
322 *
323 * ### Options
324 *
325 * - `inline` If set to false, the generated tag appears in the head tag of the layout. Defaults to true
326 *
327 * @param mixed $path The name of a CSS style sheet or an array containing names of
328 * CSS stylesheets. If `$path` is prefixed with '/', the path will be relative to the webroot
329 * of your application. Otherwise, the path will be relative to your CSS path, usually webroot/css.
330 * @param string $rel Rel attribute. Defaults to "stylesheet". If equal to 'import' the stylesheet will be imported.
331 * @param array $options Array of HTML attributes.
332 * @return string CSS <link /> or <style /> tag, depending on the type of link.
333 * @access public
334 * @link http://book.cakephp.org/view/1437/css
335 */
336 function css($path, $rel = null, $options = array()) {
337 $options += array('inline' => true);
338 if (is_array($path)) {
339 $out = '';
340 foreach ($path as $i) {
341 $out .= "\n\t" . $this->css($i, $rel, $options);
342 }
343 if ($options['inline']) {
344 return $out . "\n";
345 }
346 return;
347 }
348
349 if (strpos($path, '://') !== false) {
350 $url = $path;
351 } else {
352 if ($path[0] !== '/') {
353 $path = CSS_URL . $path;
354 }
355
356 if (strpos($path, '?') === false) {
357 if (substr($path, -4) !== '.css') {
358 $path .= '.css';
359 }
360 }
361 $url = $this->assetTimestamp($this->webroot($path));
362
363 if (Configure::read('Asset.filter.css')) {
364 $pos = strpos($url, CSS_URL);
365 if ($pos !== false) {
366 $url = substr($url, 0, $pos) . 'ccss/' . substr($url, $pos + strlen(CSS_URL));
367 }
368 }
369 }
370
371 if ($rel == 'import') {
372 $out = sprintf($this->tags['style'], $this->_parseAttributes($options, array('inline'), '', ' '), '@import url(' . $url . ');');
373 } else {
374 if ($rel == null) {
375 $rel = 'stylesheet';
376 }
377 $out = sprintf($this->tags['css'], $rel, $url, $this->_parseAttributes($options, array('inline'), '', ' '));
378 }
379
380 if ($options['inline']) {
381 return $out;
382 } else {
383 $view =& ClassRegistry::getObject('view');
384 $view->addScript($out);
385 }
386 }
387
388 /**
389 * Returns one or many `<script>` tags depending on the number of scripts given.
390 *
391 * If the filename is prefixed with "/", the path will be relative to the base path of your
392 * application. Otherwise, the path will be relative to your JavaScript path, usually webroot/js.
393 *
394 * Can include one or many Javascript files.
395 *
396 * ### Options
397 *
398 * - `inline` - Whether script should be output inline or into scripts_for_layout.
399 * - `once` - Whether or not the script should be checked for uniqueness. If true scripts will only be
400 * included once, use false to allow the same script to be included more than once per request.
401 *
402 * @param mixed $url String or array of javascript files to include
403 * @param mixed $options Array of options, and html attributes see above. If boolean sets $options['inline'] = value
404 * @return mixed String of `<script />` tags or null if $inline is false or if $once is true and the file has been
405 * included before.
406 * @access public
407 * @link http://book.cakephp.org/view/1589/script
408 */
409 function script($url, $options = array()) {
410 if (is_bool($options)) {
411 list($inline, $options) = array($options, array());
412 $options['inline'] = $inline;
413 }
414 $options = array_merge(array('inline' => true, 'once' => true), $options);
415 if (is_array($url)) {
416 $out = '';
417 foreach ($url as $i) {
418 $out .= "\n\t" . $this->script($i, $options);
419 }
420 if ($options['inline']) {
421 return $out . "\n";
422 }
423 return null;
424 }
425 if ($options['once'] && isset($this->__includedScripts[$url])) {
426 return null;
427 }
428 $this->__includedScripts[$url] = true;
429
430 if (strpos($url, '://') === false) {
431 if ($url[0] !== '/') {
432 $url = JS_URL . $url;
433 }
434 if (strpos($url, '?') === false && substr($url, -3) !== '.js') {
435 $url .= '.js';
436 }
437 $url = $this->assetTimestamp($this->webroot($url));
438
439 if (Configure::read('Asset.filter.js')) {
440 $url = str_replace(JS_URL, 'cjs/', $url);
441 }
442 }
443 $attributes = $this->_parseAttributes($options, array('inline', 'once'), ' ');
444 $out = sprintf($this->tags['javascriptlink'], $url, $attributes);
445
446 if ($options['inline']) {
447 return $out;
448 } else {
449 $view =& ClassRegistry::getObject('view');
450 $view->addScript($out);
451 }
452 }
453
454 /**
455 * Wrap $script in a script tag.
456 *
457 * ### Options
458 *
459 * - `safe` (boolean) Whether or not the $script should be wrapped in <![CDATA[ ]]>
460 * - `inline` (boolean) Whether or not the $script should be added to $scripts_for_layout or output inline
461 *
462 * @param string $script The script to wrap
463 * @param array $options The options to use.
464 * @return mixed string or null depending on the value of `$options['inline']`
465 * @access public
466 * @link http://book.cakephp.org/view/1604/scriptBlock
467 */
468 function scriptBlock($script, $options = array()) {
469 $options += array('safe' => true, 'inline' => true);
470 if ($options['safe']) {
471 $script = "\n" . '//<![CDATA[' . "\n" . $script . "\n" . '//]]>' . "\n";
472 }
473 $inline = $options['inline'];
474 unset($options['inline'], $options['safe']);
475 $attributes = $this->_parseAttributes($options, ' ', ' ');
476 if ($inline) {
477 return sprintf($this->tags['javascriptblock'], $attributes, $script);
478 } else {
479 $view =& ClassRegistry::getObject('view');
480 $view->addScript(sprintf($this->tags['javascriptblock'], $attributes, $script));
481 return null;
482 }
483 }
484
485 /**
486 * Begin a script block that captures output until HtmlHelper::scriptEnd()
487 * is called. This capturing block will capture all output between the methods
488 * and create a scriptBlock from it.
489 *
490 * ### Options
491 *
492 * - `safe` Whether the code block should contain a CDATA
493 * - `inline` Should the generated script tag be output inline or in `$scripts_for_layout`
494 *
495 * @param array $options Options for the code block.
496 * @return void
497 * @access public
498 * @link http://book.cakephp.org/view/1605/scriptStart
499 */
500 function scriptStart($options = array()) {
501 $options += array('safe' => true, 'inline' => true);
502 $this->_scriptBlockOptions = $options;
503 ob_start();
504 return null;
505 }
506
507 /**
508 * End a Buffered section of Javascript capturing.
509 * Generates a script tag inline or in `$scripts_for_layout` depending on the settings
510 * used when the scriptBlock was started
511 *
512 * @return mixed depending on the settings of scriptStart() either a script tag or null
513 * @access public
514 * @link http://book.cakephp.org/view/1606/scriptEnd
515 */
516 function scriptEnd() {
517 $buffer = ob_get_clean();
518 $options = $this->_scriptBlockOptions;
519 $this->_scriptBlockOptions = array();
520 return $this->scriptBlock($buffer, $options);
521 }
522
523 /**
524 * Builds CSS style data from an array of CSS properties
525 *
526 * ### Usage:
527 *
528 * {{{
529 * echo $html->style(array('margin' => '10px', 'padding' => '10px'), true);
530 *
531 * // creates
532 * 'margin:10px;padding:10px;'
533 * }}}
534 *
535 * @param array $data Style data array, keys will be used as property names, values as property values.
536 * @param boolean $oneline Whether or not the style block should be displayed on one line.
537 * @return string CSS styling data
538 * @access public
539 * @link http://book.cakephp.org/view/1440/style
540 */
541 function style($data, $oneline = true) {
542 if (!is_array($data)) {
543 return $data;
544 }
545 $out = array();
546 foreach ($data as $key=> $value) {
547 $out[] = $key.':'.$value.';';
548 }
549 if ($oneline) {
550 return join(' ', $out);
551 }
552 return implode("\n", $out);
553 }
554
555 /**
556 * Returns the breadcrumb trail as a sequence of &raquo;-separated links.
557 *
558 * @param string $separator Text to separate crumbs.
559 * @param string $startText This will be the first crumb, if false it defaults to first crumb in array
560 * @return string Composed bread crumbs
561 * @access public
562 */
563 function getCrumbs($separator = '&raquo;', $startText = false) {
564 if (!empty($this->_crumbs)) {
565 $out = array();
566 if ($startText) {
567 $out[] = $this->link($startText, '/');
568 }
569
570 foreach ($this->_crumbs as $crumb) {
571 if (!empty($crumb[1])) {
572 $out[] = $this->link($crumb[0], $crumb[1], $crumb[2]);
573 } else {
574 $out[] = $crumb[0];
575 }
576 }
577 return join($separator, $out);
578 } else {
579 return null;
580 }
581 }
582
583 /**
584 * Creates a formatted IMG element. If `$options['url']` is provided, an image link will be
585 * generated with the link pointed at `$options['url']`. This method will set an empty
586 * alt attribute if one is not supplied.
587 *
588 * ### Usage
589 *
590 * Create a regular image:
591 *
592 * `echo $html->image('cake_icon.png', array('alt' => 'CakePHP'));`
593 *
594 * Create an image link:
595 *
596 * `echo $html->image('cake_icon.png', array('alt' => 'CakePHP', 'url' => 'http://cakephp.org'));`
597 *
598 * @param string $path Path to the image file, relative to the app/webroot/img/ directory.
599 * @param array $options Array of HTML attributes.
600 * @return string completed img tag
601 * @access public
602 * @link http://book.cakephp.org/view/1441/image
603 */
604 function image($path, $options = array()) {
605 if (is_array($path)) {
606 $path = $this->url($path);
607 } elseif (strpos($path, '://') === false) {
608 if ($path[0] !== '/') {
609 $path = IMAGES_URL . $path;
610 }
611 $path = $this->assetTimestamp($this->webroot($path));
612 }
613
614 if (!isset($options['alt'])) {
615 $options['alt'] = '';
616 }
617
618 $url = false;
619 if (!empty($options['url'])) {
620 $url = $options['url'];
621 unset($options['url']);
622 }
623
624 $image = sprintf($this->tags['image'], $path, $this->_parseAttributes($options, null, '', ' '));
625
626 if ($url) {
627 return sprintf($this->tags['link'], $this->url($url), null, $image);
628 }
629 return $image;
630 }
631
632 /**
633 * Returns a row of formatted and named TABLE headers.
634 *
635 * @param array $names Array of tablenames.
636 * @param array $trOptions HTML options for TR elements.
637 * @param array $thOptions HTML options for TH elements.
638 * @return string Completed table headers
639 * @access public
640 * @link http://book.cakephp.org/view/1446/tableHeaders
641 */
642 function tableHeaders($names, $trOptions = null, $thOptions = null) {
643 $out = array();
644 foreach ($names as $arg) {
645 $out[] = sprintf($this->tags['tableheader'], $this->_parseAttributes($thOptions), $arg);
646 }
647 return sprintf($this->tags['tablerow'], $this->_parseAttributes($trOptions), join(' ', $out));
648 }
649
650 /**
651 * Returns a formatted string of table rows (TR's with TD's in them).
652 *
653 * @param array $data Array of table data
654 * @param array $oddTrOptions HTML options for odd TR elements if true useCount is used
655 * @param array $evenTrOptions HTML options for even TR elements
656 * @param bool $useCount adds class "column-$i"
657 * @param bool $continueOddEven If false, will use a non-static $count variable,
658 * so that the odd/even count is reset to zero just for that call.
659 * @return string Formatted HTML
660 * @access public
661 * @link http://book.cakephp.org/view/1447/tableCells
662 */
663 function tableCells($data, $oddTrOptions = null, $evenTrOptions = null, $useCount = false, $continueOddEven = true) {
664 if (empty($data[0]) || !is_array($data[0])) {
665 $data = array($data);
666 }
667
668 if ($oddTrOptions === true) {
669 $useCount = true;
670 $oddTrOptions = null;
671 }
672
673 if ($evenTrOptions === false) {
674 $continueOddEven = false;
675 $evenTrOptions = null;
676 }
677
678 if ($continueOddEven) {
679 static $count = 0;
680 } else {
681 $count = 0;
682 }
683
684 foreach ($data as $line) {
685 $count++;
686 $cellsOut = array();
687 $i = 0;
688 foreach ($line as $cell) {
689 $cellOptions = array();
690
691 if (is_array($cell)) {
692 $cellOptions = $cell[1];
693 $cell = $cell[0];
694 } elseif ($useCount) {
695 $cellOptions['class'] = 'column-' . ++$i;
696 }
697 $cellsOut[] = sprintf($this->tags['tablecell'], $this->_parseAttributes($cellOptions), $cell);
698 }
699 $options = $this->_parseAttributes($count % 2 ? $oddTrOptions : $evenTrOptions);
700 $out[] = sprintf($this->tags['tablerow'], $options, implode(' ', $cellsOut));
701 }
702 return implode("\n", $out);
703 }
704
705 /**
706 * Returns a formatted block tag, i.e DIV, SPAN, P.
707 *
708 * ### Options
709 *
710 * - `escape` Whether or not the contents should be html_entity escaped.
711 *
712 * @param string $name Tag name.
713 * @param string $text String content that will appear inside the div element.
714 * If null, only a start tag will be printed
715 * @param array $options Additional HTML attributes of the DIV tag, see above.
716 * @return string The formatted tag element
717 * @access public
718 * @link http://book.cakephp.org/view/1443/tag
719 */
720 function tag($name, $text = null, $options = array()) {
721 if (is_array($options) && isset($options['escape']) && $options['escape']) {
722 $text = h($text);
723 unset($options['escape']);
724 }
725 if (!is_array($options)) {
726 $options = array('class' => $options);
727 }
728 if ($text === null) {
729 $tag = 'tagstart';
730 } else {
731 $tag = 'tag';
732 }
733 return sprintf($this->tags[$tag], $name, $this->_parseAttributes($options, null, ' ', ''), $text, $name);
734 }
735
736 /**
737 * Returns a formatted DIV tag for HTML FORMs.
738 *
739 * ### Options
740 *
741 * - `escape` Whether or not the contents should be html_entity escaped.
742 *
743 * @param string $class CSS class name of the div element.
744 * @param string $text String content that will appear inside the div element.
745 * If null, only a start tag will be printed
746 * @param array $options Additional HTML attributes of the DIV tag
747 * @return string The formatted DIV element
748 * @access public
749 * @link http://book.cakephp.org/view/1444/div
750 */
751 function div($class = null, $text = null, $options = array()) {
752 if (!empty($class)) {
753 $options['class'] = $class;
754 }
755 return $this->tag('div', $text, $options);
756 }
757
758 /**
759 * Returns a formatted P tag.
760 *
761 * ### Options
762 *
763 * - `escape` Whether or not the contents should be html_entity escaped.
764 *
765 * @param string $class CSS class name of the p element.
766 * @param string $text String content that will appear inside the p element.
767 * @param array $options Additional HTML attributes of the P tag
768 * @return string The formatted P element
769 * @access public
770 * @link http://book.cakephp.org/view/1445/para
771 */
772 function para($class, $text, $options = array()) {
773 if (isset($options['escape'])) {
774 $text = h($text);
775 }
776 if ($class != null && !empty($class)) {
777 $options['class'] = $class;
778 }
779 if ($text === null) {
780 $tag = 'parastart';
781 } else {
782 $tag = 'para';
783 }
784 return sprintf($this->tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $text);
785 }
786
787 /**
788 * Build a nested list (UL/OL) out of an associative array.
789 *
790 * @param array $list Set of elements to list
791 * @param array $options Additional HTML attributes of the list (ol/ul) tag or if ul/ol use that as tag
792 * @param array $itemOptions Additional HTML attributes of the list item (LI) tag
793 * @param string $tag Type of list tag to use (ol/ul)
794 * @return string The nested list
795 * @access public
796 */
797 function nestedList($list, $options = array(), $itemOptions = array(), $tag = 'ul') {
798 if (is_string($options)) {
799 $tag = $options;
800 $options = array();
801 }
802 $items = $this->__nestedListItem($list, $options, $itemOptions, $tag);
803 return sprintf($this->tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $items);
804 }
805
806 /**
807 * Internal function to build a nested list (UL/OL) out of an associative array.
808 *
809 * @param array $items Set of elements to list
810 * @param array $options Additional HTML attributes of the list (ol/ul) tag
811 * @param array $itemOptions Additional HTML attributes of the list item (LI) tag
812 * @param string $tag Type of list tag to use (ol/ul)
813 * @return string The nested list element
814 * @access private
815 * @see HtmlHelper::nestedList()
816 */
817 function __nestedListItem($items, $options, $itemOptions, $tag) {
818 $out = '';
819
820 $index = 1;
821 foreach ($items as $key => $item) {
822 if (is_array($item)) {
823 $item = $key . $this->nestedList($item, $options, $itemOptions, $tag);
824 }
825 if (isset($itemOptions['even']) && $index % 2 == 0) {
826 $itemOptions['class'] = $itemOptions['even'];
827 } else if (isset($itemOptions['odd']) && $index % 2 != 0) {
828 $itemOptions['class'] = $itemOptions['odd'];
829 }
830 $out .= sprintf($this->tags['li'], $this->_parseAttributes($itemOptions, array('even', 'odd'), ' ', ''), $item);
831 $index++;
832 }
833 return $out;
834 }
835 }