You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1128 lines
43 KiB
1128 lines
43 KiB
<?php |
|
/** |
|
* @link http://www.yiiframework.com/ |
|
* @copyright Copyright (c) 2008 Yii Software LLC |
|
* @license http://www.yiiframework.com/license/ |
|
*/ |
|
|
|
namespace yii\util; |
|
|
|
use Yii; |
|
|
|
/** |
|
* @author Qiang Xue <qiang.xue@gmail.com> |
|
* @since 2.0 |
|
*/ |
|
class Html |
|
{ |
|
/** |
|
* @var boolean whether to close void (empty) elements. Defaults to true. |
|
* @see voidElements |
|
*/ |
|
public static $closeVoidElements = true; |
|
/** |
|
* @var array list of void elements (element name => 1) |
|
* @see http://www.w3.org/TR/html-markup/syntax.html#void-element |
|
*/ |
|
public static $voidElements = array( |
|
'area' => 1, |
|
'base' => 1, |
|
'br' => 1, |
|
'col' => 1, |
|
'command' => 1, |
|
'embed' => 1, |
|
'hr' => 1, |
|
'img' => 1, |
|
'input' => 1, |
|
'keygen' => 1, |
|
'link' => 1, |
|
'meta' => 1, |
|
'param' => 1, |
|
'source' => 1, |
|
'track' => 1, |
|
'wbr' => 1, |
|
); |
|
/** |
|
* @var boolean whether to render special attributes value. Defaults to true. Can be set to false for HTML5. |
|
*/ |
|
public static $renderSpecialAttributesValue = true; |
|
|
|
|
|
/** |
|
* Encodes special characters into HTML entities. |
|
* The [[yii\base\Application::charset|application charset]] will be used for encoding. |
|
* @param string $content the content to be encoded |
|
* @return string the encoded content |
|
* @see decode |
|
* @see http://www.php.net/manual/en/function.htmlspecialchars.php |
|
*/ |
|
public static function encode($content) |
|
{ |
|
return htmlspecialchars($content, ENT_QUOTES, Yii::$app->charset); |
|
} |
|
|
|
/** |
|
* Decodes special HTML entities back to the corresponding characters. |
|
* This is the opposite of [[encode()]]. |
|
* @param string $content the content to be decoded |
|
* @return string the decoded content |
|
* @see encode |
|
* @see http://www.php.net/manual/en/function.htmlspecialchars-decode.php |
|
*/ |
|
public static function decode($content) |
|
{ |
|
return htmlspecialchars_decode($content, ENT_QUOTES); |
|
} |
|
|
|
/** |
|
* Generates a complete HTML tag. |
|
* @param string $name the tag name |
|
* @param string $content the content to be enclosed between the start and end tags. It will not be HTML-encoded. |
|
* @param array $attributes the element attributes. The values will be HTML-encoded using [[encode()]]. |
|
* Attributes whose value is null will be ignored and not put in the tag returned. |
|
* @return string the generated HTML tag |
|
* @see beginTag |
|
* @see endTag |
|
*/ |
|
public static function tag($name, $content = '', $attributes = array()) |
|
{ |
|
$html = '<' . $name . static::renderAttributes($attributes); |
|
if (isset(static::$voidElements[strtolower($name)])) { |
|
return $html . (static::$closeVoidElements ? ' />' : '>'); |
|
} else { |
|
return $html . ">$content</$name>"; |
|
} |
|
} |
|
|
|
/** |
|
* Generates a start tag. |
|
* @param string $name the tag name |
|
* @param array $attributes the element attributes. The values will be HTML-encoded using [[encode()]]. |
|
* Attributes whose value is null will be ignored and not put in the tag returned. |
|
* @return string the generated start tag |
|
* @see endTag |
|
* @see tag |
|
*/ |
|
public static function beginTag($name, $attributes = array()) |
|
{ |
|
return '<' . $name . static::renderAttributes($attributes) . '>'; |
|
} |
|
|
|
/** |
|
* Generates an end tag. |
|
* @param string $name the tag name |
|
* @return string the generated end tag |
|
* @see beginTag |
|
* @see tag |
|
*/ |
|
public static function endTag($name) |
|
{ |
|
return !static::$closeVoidElements && isset(static::$voidElements[strtolower($name)]) ? '' : "</$name>"; |
|
} |
|
|
|
/** |
|
* Encloses the given content within a CDATA tag. |
|
* @param string $content the content to be enclosed within the CDATA tag |
|
* @return string the CDATA tag with the enclosed content. |
|
*/ |
|
public static function cdata($content) |
|
{ |
|
return '<![CDATA[' . $content . ']]>'; |
|
} |
|
|
|
/** |
|
* Generates a style tag. |
|
* @param string $content the style content |
|
* @param array $attributes the attributes of the style tag. The values will be HTML-encoded using [[encode()]]. |
|
* Attributes whose value is null will be ignored and not put in the tag returned. |
|
* If the attributes does not contain "type", a default one with value "text/css" will be used. |
|
* @return string the generated style tag |
|
*/ |
|
public static function style($content, $attributes = array()) |
|
{ |
|
if (!isset($attributes['type'])) { |
|
$attributes['type'] = 'text/css'; |
|
} |
|
return static::beginTag('style', $attributes) |
|
. "\n/*<![CDATA[*/\n{$content}\n/*]]>*/\n" |
|
. static::endTag('style'); |
|
} |
|
|
|
/** |
|
* Generates a script tag. |
|
* @param string $content the script content |
|
* @param array $attributes the attributes of the script tag. The values will be HTML-encoded using [[encode()]]. |
|
* Attributes whose value is null will be ignored and not put in the tag returned. |
|
* If the attributes does not contain "type", a default one with value "text/javascript" will be used. |
|
* @return string the generated script tag |
|
*/ |
|
public static function script($content, $attributes = array()) |
|
{ |
|
if (!isset($attributes['type'])) { |
|
$attributes['type'] = 'text/javascript'; |
|
} |
|
return static::beginTag('script', $attributes) |
|
. "\n/*<![CDATA[*/\n{$content}\n/*]]>*/\n" |
|
. static::endTag('script'); |
|
} |
|
|
|
/** |
|
* Registers a 'refresh' meta tag. |
|
* This method can be invoked anywhere in a view. It will register a 'refresh' |
|
* meta tag with {@link CClientScript} so that the page can be refreshed in |
|
* the specified seconds. |
|
* @param integer $seconds the number of seconds to wait before refreshing the page |
|
* @param string $url the URL to which the page should be redirected to. If empty, it means the current page. |
|
* @since 1.1.1 |
|
*/ |
|
public static function refresh($seconds, $url = '') |
|
{ |
|
$content = "$seconds"; |
|
if ($url !== '') { |
|
$content .= ';' . static::normalizeUrl($url); |
|
} |
|
Yii::app()->clientScript->registerMetaTag($content, null, 'refresh'); |
|
} |
|
|
|
/** |
|
* Links to the specified CSS file. |
|
* @param string $url the CSS URL |
|
* @param string $media the media that this CSS should apply to. |
|
* @return string the CSS link. |
|
*/ |
|
public static function cssFile($url, $media = '') |
|
{ |
|
return CHtml::linkTag('stylesheet', 'text/css', $url, $media !== '' ? $media : null); |
|
} |
|
|
|
/** |
|
* Encloses the given JavaScript within a script tag. |
|
* @param string $text the JavaScript to be enclosed |
|
* @return string the enclosed JavaScript |
|
*/ |
|
public static function script($text) |
|
{ |
|
return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n</script>"; |
|
} |
|
|
|
/** |
|
* Includes a JavaScript file. |
|
* @param string $url URL for the JavaScript file |
|
* @return string the JavaScript file tag |
|
*/ |
|
public static function scriptFile($url) |
|
{ |
|
return '<script type="text/javascript" src="' . static::encode($url) . '"></script>'; |
|
} |
|
|
|
/** |
|
* Generates an opening form tag. |
|
* This is a shortcut to {@link beginForm}. |
|
* @param mixed $action the form action URL (see {@link normalizeUrl} for details about this parameter.) |
|
* @param string $method form method (e.g. post, get) |
|
* @param array $htmlOptions additional HTML attributes (see {@link tag}). |
|
* @return string the generated form tag. |
|
*/ |
|
public static function form($action = '', $method = 'post', $htmlOptions = array()) |
|
{ |
|
return static::beginForm($action, $method, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates an opening form tag. |
|
* Note, only the open tag is generated. A close tag should be placed manually |
|
* at the end of the form. |
|
* @param mixed $action the form action URL (see {@link normalizeUrl} for details about this parameter.) |
|
* @param string $method form method (e.g. post, get) |
|
* @param array $htmlOptions additional HTML attributes (see {@link tag}). |
|
* @return string the generated form tag. |
|
* @see endForm |
|
*/ |
|
public static function beginForm($action = '', $method = 'post', $htmlOptions = array()) |
|
{ |
|
$htmlOptions['action'] = $url = static::normalizeUrl($action); |
|
$htmlOptions['method'] = $method; |
|
$form = static::tag('form', $htmlOptions, false, false); |
|
$hiddens = array(); |
|
if (!strcasecmp($method, 'get') && ($pos = strpos($url, '?')) !== false) { |
|
foreach (explode('&', substr($url, $pos + 1)) as $pair) { |
|
if (($pos = strpos($pair, '=')) !== false) { |
|
$hiddens[] = static::hiddenField(urldecode(substr($pair, 0, $pos)), urldecode(substr($pair, $pos + 1)), array('id' => false)); |
|
} else { |
|
$hiddens[] = static::hiddenField(urldecode($pair), '', array('id' => false)); |
|
} |
|
} |
|
} |
|
$request = Yii::app()->request; |
|
if ($request->enableCsrfValidation && !strcasecmp($method, 'post')) { |
|
$hiddens[] = static::hiddenField($request->csrfTokenName, $request->getCsrfToken(), array('id' => false)); |
|
} |
|
if ($hiddens !== array()) { |
|
$form .= "\n" . static::tag('div', array('style' => 'display:none'), implode("\n", $hiddens)); |
|
} |
|
return $form; |
|
} |
|
|
|
/** |
|
* Generates a closing form tag. |
|
* @return string the generated tag |
|
* @see beginForm |
|
*/ |
|
public static function endForm() |
|
{ |
|
return '</form>'; |
|
} |
|
|
|
/** |
|
* Generates a hyperlink tag. |
|
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code such as an image tag. |
|
* @param mixed $url a URL or an action route that can be used to create a URL. |
|
* See {@link normalizeUrl} for more details about how to specify this parameter. |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated hyperlink |
|
* @see normalizeUrl |
|
* @see clientChange |
|
*/ |
|
public static function link($text, $url = '#', $htmlOptions = array()) |
|
{ |
|
if ($url !== '') { |
|
$htmlOptions['href'] = static::normalizeUrl($url); |
|
} |
|
static::clientChange('click', $htmlOptions); |
|
return static::tag('a', $htmlOptions, $text); |
|
} |
|
|
|
/** |
|
* Generates a mailto link. |
|
* @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code such as an image tag. |
|
* @param string $email email address. If this is empty, the first parameter (link body) will be treated as the email address. |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated mailto link |
|
* @see clientChange |
|
*/ |
|
public static function mailto($text, $email = '', $htmlOptions = array()) |
|
{ |
|
if ($email === '') { |
|
$email = $text; |
|
} |
|
return static::link($text, 'mailto:' . $email, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates an image tag. |
|
* @param string $src the image URL |
|
* @param string $alt the alternative text display |
|
* @param array $htmlOptions additional HTML attributes (see {@link tag}). |
|
* @return string the generated image tag |
|
*/ |
|
public static function image($src, $alt = '', $htmlOptions = array()) |
|
{ |
|
$htmlOptions['src'] = $src; |
|
$htmlOptions['alt'] = $alt; |
|
return static::tag('img', $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a button. |
|
* @param string $label the button label |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated button tag |
|
* @see clientChange |
|
*/ |
|
public static function button($name, $label = 'button', $htmlOptions = array()) |
|
{ |
|
if (!isset($htmlOptions['name'])) { |
|
if (!array_key_exists('name', $htmlOptions)) { |
|
$htmlOptions['name'] = static::ID_PREFIX . static::$count++; |
|
} |
|
} |
|
if (!isset($htmlOptions['type'])) { |
|
$htmlOptions['type'] = 'button'; |
|
} |
|
if (!isset($htmlOptions['value'])) { |
|
$htmlOptions['value'] = $label; |
|
} |
|
static::clientChange('click', $htmlOptions); |
|
return static::tag('input', $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a button using HTML button tag. |
|
* This method is similar to {@link button} except that it generates a 'button' |
|
* tag instead of 'input' tag. |
|
* @param string $label the button label. Note that this value will be directly inserted in the button element |
|
* without being HTML-encoded. |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated button tag |
|
* @see clientChange |
|
*/ |
|
public static function htmlButton($label = 'button', $htmlOptions = array()) |
|
{ |
|
if (!isset($htmlOptions['name'])) { |
|
$htmlOptions['name'] = static::ID_PREFIX . static::$count++; |
|
} |
|
if (!isset($htmlOptions['type'])) { |
|
$htmlOptions['type'] = 'button'; |
|
} |
|
static::clientChange('click', $htmlOptions); |
|
return static::tag('button', $htmlOptions, $label); |
|
} |
|
|
|
/** |
|
* Generates a submit button. |
|
* @param string $label the button label |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated button tag |
|
* @see clientChange |
|
*/ |
|
public static function submitButton($label = 'submit', $htmlOptions = array()) |
|
{ |
|
$htmlOptions['type'] = 'submit'; |
|
return static::button($label, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a reset button. |
|
* @param string $label the button label |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated button tag |
|
* @see clientChange |
|
*/ |
|
public static function resetButton($label = 'reset', $htmlOptions = array()) |
|
{ |
|
$htmlOptions['type'] = 'reset'; |
|
return static::button($label, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates an image submit button. |
|
* @param string $src the image URL |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated button tag |
|
* @see clientChange |
|
*/ |
|
public static function imageButton($src, $htmlOptions = array()) |
|
{ |
|
$htmlOptions['src'] = $src; |
|
$htmlOptions['type'] = 'image'; |
|
return static::button('submit', $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a link submit button. |
|
* @param string $label the button label |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated button tag |
|
* @see clientChange |
|
*/ |
|
public static function linkButton($label = 'submit', $htmlOptions = array()) |
|
{ |
|
if (!isset($htmlOptions['submit'])) { |
|
$htmlOptions['submit'] = isset($htmlOptions['href']) ? $htmlOptions['href'] : ''; |
|
} |
|
return static::link($label, '#', $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a label tag. |
|
* @param string $label label text. Note, you should HTML-encode the text if needed. |
|
* @param string $for the ID of the HTML element that this label is associated with. |
|
* If this is false, the 'for' attribute for the label tag will not be rendered. |
|
* @param array $htmlOptions additional HTML attributes. |
|
* The following HTML option is recognized: |
|
* <ul> |
|
* <li>required: if this is set and is true, the label will be styled |
|
* with CSS class 'required' (customizable with CHtml::$requiredCss), |
|
* and be decorated with {@link CHtml::beforeRequiredLabel} and |
|
* {@link CHtml::afterRequiredLabel}.</li> |
|
* </ul> |
|
* @return string the generated label tag |
|
*/ |
|
public static function label($label, $for, $htmlOptions = array()) |
|
{ |
|
if ($for === false) { |
|
unset($htmlOptions['for']); |
|
} else { |
|
$htmlOptions['for'] = $for; |
|
} |
|
if (isset($htmlOptions['required'])) { |
|
if ($htmlOptions['required']) { |
|
if (isset($htmlOptions['class'])) { |
|
$htmlOptions['class'] .= ' ' . static::$requiredCss; |
|
} else { |
|
$htmlOptions['class'] = static::$requiredCss; |
|
} |
|
$label = static::$beforeRequiredLabel . $label . static::$afterRequiredLabel; |
|
} |
|
unset($htmlOptions['required']); |
|
} |
|
return static::tag('label', $htmlOptions, $label); |
|
} |
|
|
|
/** |
|
* Generates a text field input. |
|
* @param string $name the input name |
|
* @param string $value the input value |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated input field |
|
* @see clientChange |
|
* @see inputField |
|
*/ |
|
public static function textField($name, $value = '', $htmlOptions = array()) |
|
{ |
|
static::clientChange('change', $htmlOptions); |
|
return static::inputField('text', $name, $value, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a hidden input. |
|
* @param string $name the input name |
|
* @param string $value the input value |
|
* @param array $htmlOptions additional HTML attributes (see {@link tag}). |
|
* @return string the generated input field |
|
* @see inputField |
|
*/ |
|
public static function hiddenField($name, $value = '', $htmlOptions = array()) |
|
{ |
|
return static::inputField('hidden', $name, $value, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a password field input. |
|
* @param string $name the input name |
|
* @param string $value the input value |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated input field |
|
* @see clientChange |
|
* @see inputField |
|
*/ |
|
public static function passwordField($name, $value = '', $htmlOptions = array()) |
|
{ |
|
static::clientChange('change', $htmlOptions); |
|
return static::inputField('password', $name, $value, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a file input. |
|
* Note, you have to set the enclosing form's 'enctype' attribute to be 'multipart/form-data'. |
|
* After the form is submitted, the uploaded file information can be obtained via $_FILES[$name] (see |
|
* PHP documentation). |
|
* @param string $name the input name |
|
* @param string $value the input value |
|
* @param array $htmlOptions additional HTML attributes (see {@link tag}). |
|
* @return string the generated input field |
|
* @see inputField |
|
*/ |
|
public static function fileField($name, $value = '', $htmlOptions = array()) |
|
{ |
|
return static::inputField('file', $name, $value, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a text area input. |
|
* @param string $name the input name |
|
* @param string $value the input value |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* @return string the generated text area |
|
* @see clientChange |
|
* @see inputField |
|
*/ |
|
public static function textArea($name, $value = '', $htmlOptions = array()) |
|
{ |
|
$htmlOptions['name'] = $name; |
|
if (!isset($htmlOptions['id'])) { |
|
$htmlOptions['id'] = static::getIdByName($name); |
|
} elseif ($htmlOptions['id'] === false) { |
|
unset($htmlOptions['id']); |
|
} |
|
static::clientChange('change', $htmlOptions); |
|
return static::tag('textarea', $htmlOptions, isset($htmlOptions['encode']) && !$htmlOptions['encode'] ? $value : static::encode($value)); |
|
} |
|
|
|
/** |
|
* Generates a radio button. |
|
* @param string $name the input name |
|
* @param boolean $checked whether the radio button is checked |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* Since version 1.1.2, a special option named 'uncheckValue' is available that can be used to specify |
|
* the value returned when the radio button is not checked. When set, a hidden field is rendered so that |
|
* when the radio button is not checked, we can still obtain the posted uncheck value. |
|
* If 'uncheckValue' is not set or set to NULL, the hidden field will not be rendered. |
|
* @return string the generated radio button |
|
* @see clientChange |
|
* @see inputField |
|
*/ |
|
public static function radioButton($name, $checked = false, $htmlOptions = array()) |
|
{ |
|
if ($checked) { |
|
$htmlOptions['checked'] = 'checked'; |
|
} else { |
|
unset($htmlOptions['checked']); |
|
} |
|
$value = isset($htmlOptions['value']) ? $htmlOptions['value'] : 1; |
|
static::clientChange('click', $htmlOptions); |
|
|
|
if (array_key_exists('uncheckValue', $htmlOptions)) { |
|
$uncheck = $htmlOptions['uncheckValue']; |
|
unset($htmlOptions['uncheckValue']); |
|
} else { |
|
$uncheck = null; |
|
} |
|
|
|
if ($uncheck !== null) { |
|
// add a hidden field so that if the radio button is not selected, it still submits a value |
|
if (isset($htmlOptions['id']) && $htmlOptions['id'] !== false) { |
|
$uncheckOptions = array('id' => static::ID_PREFIX . $htmlOptions['id']); |
|
} else { |
|
$uncheckOptions = array('id' => false); |
|
} |
|
$hidden = static::hiddenField($name, $uncheck, $uncheckOptions); |
|
} else { |
|
$hidden = ''; |
|
} |
|
|
|
// add a hidden field so that if the radio button is not selected, it still submits a value |
|
return $hidden . static::inputField('radio', $name, $value, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a check box. |
|
* @param string $name the input name |
|
* @param boolean $checked whether the check box is checked |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized (see {@link clientChange} and {@link tag} for more details.) |
|
* Since version 1.1.2, a special option named 'uncheckValue' is available that can be used to specify |
|
* the value returned when the checkbox is not checked. When set, a hidden field is rendered so that |
|
* when the checkbox is not checked, we can still obtain the posted uncheck value. |
|
* If 'uncheckValue' is not set or set to NULL, the hidden field will not be rendered. |
|
* @return string the generated check box |
|
* @see clientChange |
|
* @see inputField |
|
*/ |
|
public static function checkBox($name, $checked = false, $htmlOptions = array()) |
|
{ |
|
if ($checked) { |
|
$htmlOptions['checked'] = 'checked'; |
|
} else { |
|
unset($htmlOptions['checked']); |
|
} |
|
$value = isset($htmlOptions['value']) ? $htmlOptions['value'] : 1; |
|
static::clientChange('click', $htmlOptions); |
|
|
|
if (array_key_exists('uncheckValue', $htmlOptions)) { |
|
$uncheck = $htmlOptions['uncheckValue']; |
|
unset($htmlOptions['uncheckValue']); |
|
} else { |
|
$uncheck = null; |
|
} |
|
|
|
if ($uncheck !== null) { |
|
// add a hidden field so that if the check box is not checked, it still submits a value |
|
if (isset($htmlOptions['id']) && $htmlOptions['id'] !== false) { |
|
$uncheckOptions = array('id' => static::ID_PREFIX . $htmlOptions['id']); |
|
} else { |
|
$uncheckOptions = array('id' => false); |
|
} |
|
$hidden = static::hiddenField($name, $uncheck, $uncheckOptions); |
|
} else { |
|
$hidden = ''; |
|
} |
|
|
|
// add a hidden field so that if the check box is not checked, it still submits a value |
|
return $hidden . static::inputField('checkbox', $name, $value, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a drop down list. |
|
* @param string $name the input name |
|
* @param string $select the selected value |
|
* @param array $data data for generating the list options (value=>display). |
|
* You may use {@link listData} to generate this data. |
|
* Please refer to {@link listOptions} on how this data is used to generate the list options. |
|
* Note, the values and labels will be automatically HTML-encoded by this method. |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are recognized. See {@link clientChange} and {@link tag} for more details. |
|
* In addition, the following options are also supported specifically for dropdown list: |
|
* <ul> |
|
* <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li> |
|
* <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li> |
|
* <li>empty: string, specifies the text corresponding to empty selection. Its value is empty. |
|
* The 'empty' option can also be an array of value-label pairs. |
|
* Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li> |
|
* <li>options: array, specifies additional attributes for each OPTION tag. |
|
* The array keys must be the option values, and the array values are the extra |
|
* OPTION tag attributes in the name-value pairs. For example, |
|
* <pre> |
|
* array( |
|
* 'value1'=>array('disabled'=>true, 'label'=>'value 1'), |
|
* 'value2'=>array('label'=>'value 2'), |
|
* ); |
|
* </pre> |
|
* </li> |
|
* </ul> |
|
* Since 1.1.13, a special option named 'unselectValue' is available. It can be used to set the value |
|
* that will be returned when no option is selected in multiple mode. When set, a hidden field is |
|
* rendered so that if no option is selected in multiple mode, we can still obtain the posted |
|
* unselect value. If 'unselectValue' is not set or set to NULL, the hidden field will not be rendered. |
|
* @return string the generated drop down list |
|
* @see clientChange |
|
* @see inputField |
|
* @see listData |
|
*/ |
|
public static function dropDownList($name, $select, $data, $htmlOptions = array()) |
|
{ |
|
$htmlOptions['name'] = $name; |
|
|
|
if (!isset($htmlOptions['id'])) { |
|
$htmlOptions['id'] = static::getIdByName($name); |
|
} elseif ($htmlOptions['id'] === false) { |
|
unset($htmlOptions['id']); |
|
} |
|
|
|
static::clientChange('change', $htmlOptions); |
|
$options = "\n" . static::listOptions($select, $data, $htmlOptions); |
|
$hidden = ''; |
|
|
|
if (isset($htmlOptions['multiple'])) { |
|
if (substr($htmlOptions['name'], -2) !== '[]') { |
|
$htmlOptions['name'] .= '[]'; |
|
} |
|
|
|
if (isset($htmlOptions['unselectValue'])) { |
|
$hiddenOptions = isset($htmlOptions['id']) ? array('id' => static::ID_PREFIX . $htmlOptions['id']) : array('id' => false); |
|
$hidden = static::hiddenField(substr($htmlOptions['name'], 0, -2), $htmlOptions['unselectValue'], $hiddenOptions); |
|
unset($htmlOptions['unselectValue']); |
|
} |
|
} |
|
// add a hidden field so that if the option is not selected, it still submits a value |
|
return $hidden . static::tag('select', $htmlOptions, $options); |
|
} |
|
|
|
/** |
|
* Generates a list box. |
|
* @param string $name the input name |
|
* @param mixed $select the selected value(s). This can be either a string for single selection or an array for multiple selections. |
|
* @param array $data data for generating the list options (value=>display) |
|
* You may use {@link listData} to generate this data. |
|
* Please refer to {@link listOptions} on how this data is used to generate the list options. |
|
* Note, the values and labels will be automatically HTML-encoded by this method. |
|
* @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special |
|
* attributes are also recognized. See {@link clientChange} and {@link tag} for more details. |
|
* In addition, the following options are also supported specifically for list box: |
|
* <ul> |
|
* <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li> |
|
* <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li> |
|
* <li>empty: string, specifies the text corresponding to empty selection. Its value is empty. |
|
* The 'empty' option can also be an array of value-label pairs. |
|
* Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li> |
|
* <li>options: array, specifies additional attributes for each OPTION tag. |
|
* The array keys must be the option values, and the array values are the extra |
|
* OPTION tag attributes in the name-value pairs. For example, |
|
* <pre> |
|
* array( |
|
* 'value1'=>array('disabled'=>true, 'label'=>'value 1'), |
|
* 'value2'=>array('label'=>'value 2'), |
|
* ); |
|
* </pre> |
|
* </li> |
|
* </ul> |
|
* @return string the generated list box |
|
* @see clientChange |
|
* @see inputField |
|
* @see listData |
|
*/ |
|
public static function listBox($name, $select, $data, $htmlOptions = array()) |
|
{ |
|
if (!isset($htmlOptions['size'])) { |
|
$htmlOptions['size'] = 4; |
|
} |
|
if (isset($htmlOptions['multiple'])) { |
|
if (substr($name, -2) !== '[]') { |
|
$name .= '[]'; |
|
} |
|
} |
|
return static::dropDownList($name, $select, $data, $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates a check box list. |
|
* A check box list allows multiple selection, like {@link listBox}. |
|
* As a result, the corresponding POST value is an array. |
|
* @param string $name name of the check box list. You can use this name to retrieve |
|
* the selected value(s) once the form is submitted. |
|
* @param mixed $select selection of the check boxes. This can be either a string |
|
* for single selection or an array for multiple selections. |
|
* @param array $data value-label pairs used to generate the check box list. |
|
* Note, the values will be automatically HTML-encoded, while the labels will not. |
|
* @param array $htmlOptions additional HTML options. The options will be applied to |
|
* each checkbox input. The following special options are recognized: |
|
* <ul> |
|
* <li>template: string, specifies how each checkbox is rendered. Defaults |
|
* to "{input} {label}", where "{input}" will be replaced by the generated |
|
* check box input tag while "{label}" be replaced by the corresponding check box label.</li> |
|
* <li>separator: string, specifies the string that separates the generated check boxes.</li> |
|
* <li>checkAll: string, specifies the label for the "check all" checkbox. |
|
* If this option is specified, a 'check all' checkbox will be displayed. Clicking on |
|
* this checkbox will cause all checkboxes checked or unchecked.</li> |
|
* <li>checkAllLast: boolean, specifies whether the 'check all' checkbox should be |
|
* displayed at the end of the checkbox list. If this option is not set (default) |
|
* or is false, the 'check all' checkbox will be displayed at the beginning of |
|
* the checkbox list.</li> |
|
* <li>labelOptions: array, specifies the additional HTML attributes to be rendered |
|
* for every label tag in the list.</li> |
|
* <li>container: string, specifies the checkboxes enclosing tag. Defaults to 'span'. |
|
* If the value is an empty string, no enclosing tag will be generated</li> |
|
* <li>baseID: string, specifies the base ID prefix to be used for checkboxes in the list. |
|
* This option is available since version 1.1.13.</li> |
|
* </ul> |
|
* @return string the generated check box list |
|
*/ |
|
public static function checkBoxList($name, $select, $data, $htmlOptions = array()) |
|
{ |
|
$template = isset($htmlOptions['template']) ? $htmlOptions['template'] : '{input} {label}'; |
|
$separator = isset($htmlOptions['separator']) ? $htmlOptions['separator'] : "<br/>\n"; |
|
$container = isset($htmlOptions['container']) ? $htmlOptions['container'] : 'span'; |
|
unset($htmlOptions['template'], $htmlOptions['separator'], $htmlOptions['container']); |
|
|
|
if (substr($name, -2) !== '[]') { |
|
$name .= '[]'; |
|
} |
|
|
|
if (isset($htmlOptions['checkAll'])) { |
|
$checkAllLabel = $htmlOptions['checkAll']; |
|
$checkAllLast = isset($htmlOptions['checkAllLast']) && $htmlOptions['checkAllLast']; |
|
} |
|
unset($htmlOptions['checkAll'], $htmlOptions['checkAllLast']); |
|
|
|
$labelOptions = isset($htmlOptions['labelOptions']) ? $htmlOptions['labelOptions'] : array(); |
|
unset($htmlOptions['labelOptions']); |
|
|
|
$items = array(); |
|
$baseID = isset($htmlOptions['baseID']) ? $htmlOptions['baseID'] : static::getIdByName($name); |
|
unset($htmlOptions['baseID']); |
|
$id = 0; |
|
$checkAll = true; |
|
|
|
foreach ($data as $value => $label) { |
|
$checked = !is_array($select) && !strcmp($value, $select) || is_array($select) && in_array($value, $select); |
|
$checkAll = $checkAll && $checked; |
|
$htmlOptions['value'] = $value; |
|
$htmlOptions['id'] = $baseID . '_' . $id++; |
|
$option = static::checkBox($name, $checked, $htmlOptions); |
|
$label = static::label($label, $htmlOptions['id'], $labelOptions); |
|
$items[] = strtr($template, array('{input}' => $option, '{label}' => $label)); |
|
} |
|
|
|
if (isset($checkAllLabel)) { |
|
$htmlOptions['value'] = 1; |
|
$htmlOptions['id'] = $id = $baseID . '_all'; |
|
$option = static::checkBox($id, $checkAll, $htmlOptions); |
|
$label = static::label($checkAllLabel, $id, $labelOptions); |
|
$item = strtr($template, array('{input}' => $option, '{label}' => $label)); |
|
if ($checkAllLast) { |
|
$items[] = $item; |
|
} else { |
|
array_unshift($items, $item); |
|
} |
|
$name = strtr($name, array('[' => '\\[', ']' => '\\]')); |
|
$js = <<<EOD |
|
jQuery('#$id').click(function() { |
|
jQuery("input[name='$name']").prop('checked', this.checked); |
|
}); |
|
jQuery("input[name='$name']").click(function() { |
|
jQuery('#$id').prop('checked', !jQuery("input[name='$name']:not(:checked)").length); |
|
}); |
|
jQuery('#$id').prop('checked', !jQuery("input[name='$name']:not(:checked)").length); |
|
EOD; |
|
$cs = Yii::app()->getClientScript(); |
|
$cs->registerCoreScript('jquery'); |
|
$cs->registerScript($id, $js); |
|
} |
|
|
|
if (empty($container)) { |
|
return implode($separator, $items); |
|
} else { |
|
return static::tag($container, array('id' => $baseID), implode($separator, $items)); |
|
} |
|
} |
|
|
|
/** |
|
* Generates a radio button list. |
|
* A radio button list is like a {@link checkBoxList check box list}, except that |
|
* it only allows single selection. |
|
* @param string $name name of the radio button list. You can use this name to retrieve |
|
* the selected value(s) once the form is submitted. |
|
* @param string $select selection of the radio buttons. |
|
* @param array $data value-label pairs used to generate the radio button list. |
|
* Note, the values will be automatically HTML-encoded, while the labels will not. |
|
* @param array $htmlOptions additional HTML options. The options will be applied to |
|
* each radio button input. The following special options are recognized: |
|
* <ul> |
|
* <li>template: string, specifies how each radio button is rendered. Defaults |
|
* to "{input} {label}", where "{input}" will be replaced by the generated |
|
* radio button input tag while "{label}" will be replaced by the corresponding radio button label.</li> |
|
* <li>separator: string, specifies the string that separates the generated radio buttons. Defaults to new line (<br/>).</li> |
|
* <li>labelOptions: array, specifies the additional HTML attributes to be rendered |
|
* for every label tag in the list.</li> |
|
* <li>container: string, specifies the radio buttons enclosing tag. Defaults to 'span'. |
|
* If the value is an empty string, no enclosing tag will be generated</li> |
|
* <li>baseID: string, specifies the base ID prefix to be used for radio buttons in the list. |
|
* This option is available since version 1.1.13.</li> |
|
* </ul> |
|
* @return string the generated radio button list |
|
*/ |
|
public static function radioButtonList($name, $select, $data, $htmlOptions = array()) |
|
{ |
|
$template = isset($htmlOptions['template']) ? $htmlOptions['template'] : '{input} {label}'; |
|
$separator = isset($htmlOptions['separator']) ? $htmlOptions['separator'] : "<br/>\n"; |
|
$container = isset($htmlOptions['container']) ? $htmlOptions['container'] : 'span'; |
|
unset($htmlOptions['template'], $htmlOptions['separator'], $htmlOptions['container']); |
|
|
|
$labelOptions = isset($htmlOptions['labelOptions']) ? $htmlOptions['labelOptions'] : array(); |
|
unset($htmlOptions['labelOptions']); |
|
|
|
$items = array(); |
|
$baseID = isset($htmlOptions['baseID']) ? $htmlOptions['baseID'] : static::getIdByName($name); |
|
unset($htmlOptions['baseID']); |
|
$id = 0; |
|
foreach ($data as $value => $label) { |
|
$checked = !strcmp($value, $select); |
|
$htmlOptions['value'] = $value; |
|
$htmlOptions['id'] = $baseID . '_' . $id++; |
|
$option = static::radioButton($name, $checked, $htmlOptions); |
|
$label = static::label($label, $htmlOptions['id'], $labelOptions); |
|
$items[] = strtr($template, array('{input}' => $option, '{label}' => $label)); |
|
} |
|
if (empty($container)) { |
|
return implode($separator, $items); |
|
} else { |
|
return static::tag($container, array('id' => $baseID), implode($separator, $items)); |
|
} |
|
} |
|
|
|
/** |
|
* Normalizes the input parameter to be a valid URL. |
|
* |
|
* If the input parameter is an empty string, the currently requested URL will be returned. |
|
* |
|
* If the input parameter is a non-empty string, it is treated as a valid URL and will |
|
* be returned without any change. |
|
* |
|
* If the input parameter is an array, it is treated as a controller route and a list of |
|
* GET parameters, and the {@link CController::createUrl} method will be invoked to |
|
* create a URL. In this case, the first array element refers to the controller route, |
|
* and the rest key-value pairs refer to the additional GET parameters for the URL. |
|
* For example, <code>array('post/list', 'page'=>3)</code> may be used to generate the URL |
|
* <code>/index.php?r=post/list&page=3</code>. |
|
* |
|
* @param mixed $url the parameter to be used to generate a valid URL |
|
* @return string the normalized URL |
|
*/ |
|
public static function normalizeUrl($url) |
|
{ |
|
if (is_array($url)) { |
|
if (isset($url[0])) { |
|
if (($c = Yii::app()->getController()) !== null) { |
|
$url = $c->createUrl($url[0], array_splice($url, 1)); |
|
} else { |
|
$url = Yii::app()->createUrl($url[0], array_splice($url, 1)); |
|
} |
|
} else { |
|
$url = ''; |
|
} |
|
} |
|
return $url === '' ? Yii::app()->getRequest()->getUrl() : $url; |
|
} |
|
|
|
/** |
|
* Generates an input HTML tag. |
|
* This method generates an input HTML tag based on the given input name and value. |
|
* @param string $type the input type (e.g. 'text', 'radio') |
|
* @param string $name the input name |
|
* @param string $value the input value |
|
* @param array $htmlOptions additional HTML attributes for the HTML tag (see {@link tag}). |
|
* @return string the generated input tag |
|
*/ |
|
protected static function inputField($type, $name, $value, $htmlOptions) |
|
{ |
|
$htmlOptions['type'] = $type; |
|
$htmlOptions['value'] = $value; |
|
$htmlOptions['name'] = $name; |
|
if (!isset($htmlOptions['id'])) { |
|
$htmlOptions['id'] = static::getIdByName($name); |
|
} elseif ($htmlOptions['id'] === false) { |
|
unset($htmlOptions['id']); |
|
} |
|
return static::tag('input', $htmlOptions); |
|
} |
|
|
|
/** |
|
* Generates the list options. |
|
* @param mixed $selection the selected value(s). This can be either a string for single selection or an array for multiple selections. |
|
* @param array $listData the option data (see {@link listData}) |
|
* @param array $htmlOptions additional HTML attributes. The following two special attributes are recognized: |
|
* <ul> |
|
* <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li> |
|
* <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li> |
|
* <li>empty: string, specifies the text corresponding to empty selection. Its value is empty. |
|
* The 'empty' option can also be an array of value-label pairs. |
|
* Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li> |
|
* <li>options: array, specifies additional attributes for each OPTION tag. |
|
* The array keys must be the option values, and the array values are the extra |
|
* OPTION tag attributes in the name-value pairs. For example, |
|
* <pre> |
|
* array( |
|
* 'value1'=>array('disabled'=>true, 'label'=>'value 1'), |
|
* 'value2'=>array('label'=>'value 2'), |
|
* ); |
|
* </pre> |
|
* </li> |
|
* <li>key: string, specifies the name of key attribute of the selection object(s). |
|
* This is used when the selection is represented in terms of objects. In this case, |
|
* the property named by the key option of the objects will be treated as the actual selection value. |
|
* This option defaults to 'primaryKey', meaning using the 'primaryKey' property value of the objects in the selection. |
|
* This option has been available since version 1.1.3.</li> |
|
* </ul> |
|
* @return string the generated list options |
|
*/ |
|
public static function listOptions($selection, $listData, &$htmlOptions) |
|
{ |
|
$raw = isset($htmlOptions['encode']) && !$htmlOptions['encode']; |
|
$content = ''; |
|
if (isset($htmlOptions['prompt'])) { |
|
$content .= '<option value="">' . strtr($htmlOptions['prompt'], array('<' => '<', '>' => '>')) . "</option>\n"; |
|
unset($htmlOptions['prompt']); |
|
} |
|
if (isset($htmlOptions['empty'])) { |
|
if (!is_array($htmlOptions['empty'])) { |
|
$htmlOptions['empty'] = array('' => $htmlOptions['empty']); |
|
} |
|
foreach ($htmlOptions['empty'] as $value => $label) { |
|
$content .= '<option value="' . static::encode($value) . '">' . strtr($label, array('<' => '<', '>' => '>')) . "</option>\n"; |
|
} |
|
unset($htmlOptions['empty']); |
|
} |
|
|
|
if (isset($htmlOptions['options'])) { |
|
$options = $htmlOptions['options']; |
|
unset($htmlOptions['options']); |
|
} else { |
|
$options = array(); |
|
} |
|
|
|
$key = isset($htmlOptions['key']) ? $htmlOptions['key'] : 'primaryKey'; |
|
if (is_array($selection)) { |
|
foreach ($selection as $i => $item) { |
|
if (is_object($item)) { |
|
$selection[$i] = $item->$key; |
|
} |
|
} |
|
} elseif (is_object($selection)) { |
|
$selection = $selection->$key; |
|
} |
|
|
|
foreach ($listData as $key => $value) { |
|
if (is_array($value)) { |
|
$content .= '<optgroup label="' . ($raw ? $key : static::encode($key)) . "\">\n"; |
|
$dummy = array('options' => $options); |
|
if (isset($htmlOptions['encode'])) { |
|
$dummy['encode'] = $htmlOptions['encode']; |
|
} |
|
$content .= static::listOptions($selection, $value, $dummy); |
|
$content .= '</optgroup>' . "\n"; |
|
} else { |
|
$attributes = array('value' => (string)$key, 'encode' => !$raw); |
|
if (!is_array($selection) && !strcmp($key, $selection) || is_array($selection) && in_array($key, $selection)) { |
|
$attributes['selected'] = 'selected'; |
|
} |
|
if (isset($options[$key])) { |
|
$attributes = array_merge($attributes, $options[$key]); |
|
} |
|
$content .= static::tag('option', $attributes, $raw ? (string)$value : static::encode((string)$value)) . "\n"; |
|
} |
|
} |
|
|
|
unset($htmlOptions['key']); |
|
|
|
return $content; |
|
} |
|
|
|
/** |
|
* Renders the HTML tag attributes. |
|
* Since version 1.1.5, attributes whose value is null will not be rendered. |
|
* Special attributes, such as 'checked', 'disabled', 'readonly', will be rendered |
|
* properly based on their corresponding boolean value. |
|
* @param array $attributes attributes to be rendered |
|
* @return string the rendering result |
|
*/ |
|
public static function renderAttributes($attributes) |
|
{ |
|
static $specialAttributes = array( |
|
'async' => 1, |
|
'autofocus' => 1, |
|
'autoplay' => 1, |
|
'checked' => 1, |
|
'controls' => 1, |
|
'declare' => 1, |
|
'default' => 1, |
|
'defer' => 1, |
|
'disabled' => 1, |
|
'formnovalidate' => 1, |
|
'hidden' => 1, |
|
'ismap' => 1, |
|
'loop' => 1, |
|
'multiple' => 1, |
|
'muted' => 1, |
|
'nohref' => 1, |
|
'noresize' => 1, |
|
'novalidate' => 1, |
|
'open' => 1, |
|
'readonly' => 1, |
|
'required' => 1, |
|
'reversed' => 1, |
|
'scoped' => 1, |
|
'seamless' => 1, |
|
'selected' => 1, |
|
'typemustmatch' => 1, |
|
); |
|
|
|
if ($attributes === array()) { |
|
return ''; |
|
} |
|
|
|
$html = ''; |
|
if (isset($attributes['encode'])) { |
|
$raw = !$attributes['encode']; |
|
unset($attributes['encode']); |
|
} else { |
|
$raw = false; |
|
} |
|
|
|
foreach ($attributes as $name => $value) { |
|
if (isset($specialAttributes[$name])) { |
|
if ($value) { |
|
$html .= ' ' . $name; |
|
if (static::$renderSpecialAttributesValue) { |
|
$html .= '="' . $name . '"'; |
|
} |
|
} |
|
} elseif ($value !== null) { |
|
$html .= ' ' . $name . '="' . ($raw ? $value : static::encode($value)) . '"'; |
|
} |
|
} |
|
|
|
return $html; |
|
} |
|
}
|
|
|