elements.
*
* @since 1.16
*/
class Html {
// List of void elements from HTML5, section 8.1.2 as of 2011-08-12
private static $voidElements = array(
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr',
);
// Boolean attributes, which may have the value omitted entirely. Manually
// collected from the HTML5 spec as of 2011-08-12.
private static $boolAttribs = array(
'async',
'autofocus',
'autoplay',
'checked',
'controls',
'default',
'defer',
'disabled',
'formnovalidate',
'hidden',
'ismap',
'itemscope',
'loop',
'multiple',
'muted',
'novalidate',
'open',
'pubdate',
'readonly',
'required',
'reversed',
'scoped',
'seamless',
'selected',
'truespeed',
'typemustmatch',
// HTML5 Microdata
'itemscope',
);
/**
* Modifies a set of attributes meant for button elements
* and apply a set of default attributes when $wgUseMediaWikiUIEverywhere enabled.
* @param array $modifiers to add to the button
* @see https://tools.wmflabs.org/styleguide/desktop/index.html for guidance on available modifiers
* @return array $attrs A modified attribute array
*/
public static function buttonAttributes( $attrs, $modifiers = array() ) {
global $wgUseMediaWikiUIEverywhere;
if ( $wgUseMediaWikiUIEverywhere ) {
if ( isset( $attrs['class'] ) ) {
if ( is_array( $attrs['class'] ) ) {
$attrs['class'][] = 'mw-ui-button';
$attrs = array_merge( $attrs, $modifiers );
// ensure compatibility with Xml
$attrs['class'] = implode( ' ', $attrs['class'] );
} else {
$attrs['class'] .= ' mw-ui-button ' . implode( ' ', $modifiers );
}
} else {
$attrs['class'] = array( 'mw-ui-button' );
// ensure compatibility with Xml
$attrs['class'] = implode( ' ', array_merge( $attrs['class'], $modifiers ) );
}
}
return $attrs;
}
/**
* Modifies a set of attributes meant for text input elements
* and apply a set of default attributes.
* Removes size attribute when $wgUseMediaWikiUIEverywhere enabled.
* @param array $attrs An attribute array.
* @return array $attrs A modified attribute array
*/
public static function getTextInputAttributes( $attrs ) {
global $wgUseMediaWikiUIEverywhere;
if ( !$attrs ) {
$attrs = array();
}
if ( isset( $attrs['class'] ) ) {
if ( is_array( $attrs['class'] ) ) {
$attrs['class'][] = 'mw-ui-input';
} else {
$attrs['class'] .= ' mw-ui-input';
}
} else {
$attrs['class'] = 'mw-ui-input';
}
if ( $wgUseMediaWikiUIEverywhere ) {
// Note that size can effect the desired width rendering of mw-ui-input elements
// so it is removed. Left intact when mediawiki ui not enabled.
unset( $attrs['size'] );
}
return $attrs;
}
/**
* Returns an HTML link element in a string styled as a button (when $wgUseMediaWikiUIEverywhere is enabled).
*
* @param string $contents The raw HTML contents of the element: *not*
* escaped!
* @param array $attrs Associative array of attributes, e.g., array(
* 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
* further documentation.
* @param array $modifiers to add to the button
* @see http://tools.wmflabs.org/styleguide/desktop/index.html for guidance on available modifiers
* @return string Raw HTML
*/
public static function linkButton( $contents, $attrs, $modifiers = array() ) {
return Html::element( 'a',
self::buttonAttributes( $attrs, $modifiers ),
$contents
);
}
/**
* Returns an HTML link element in a string styled as a button (when $wgUseMediaWikiUIEverywhere is enabled).
*
* @param string $contents The raw HTML contents of the element: *not*
* escaped!
* @param array $attrs Associative array of attributes, e.g., array(
* 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
* further documentation.
* @param array $modifiers to add to the button
* @see http://tools.wmflabs.org/styleguide/desktop/index.html for guidance on available modifiers
* @return string Raw HTML
*/
public static function submitButton( $contents, $attrs, $modifiers = array() ) {
$attrs['type'] = 'submit';
$attrs['value'] = $contents;
return Html::element( 'input', self::buttonAttributes( $attrs, $modifiers ) );
}
/**
* Returns an HTML element in a string. The major advantage here over
* manually typing out the HTML is that it will escape all attribute
* values. If you're hardcoding all the attributes, or there are none, you
* should probably just type out the html element yourself.
*
* This is quite similar to Xml::tags(), but it implements some useful
* HTML-specific logic. For instance, there is no $allowShortTag
* parameter: the closing tag is magically omitted if $element has an empty
* content model. If $wgWellFormedXml is false, then a few bytes will be
* shaved off the HTML output as well.
*
* @param string $element The element's name, e.g., 'a'
* @param array $attribs Associative array of attributes, e.g., array(
* 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for
* further documentation.
* @param string $contents The raw HTML contents of the element: *not*
* escaped!
* @return string Raw HTML
*/
public static function rawElement( $element, $attribs = array(), $contents = '' ) {
global $wgWellFormedXml;
$start = self::openElement( $element, $attribs );
if ( in_array( $element, self::$voidElements ) ) {
if ( $wgWellFormedXml ) {
// Silly XML.
return substr( $start, 0, -1 ) . ' />';
}
return $start;
} else {
return "$start$contents" . self::closeElement( $element );
}
}
/**
* Identical to rawElement(), but HTML-escapes $contents (like
* Xml::element()).
*
* @param string $element
* @param array $attribs
* @param string $contents
*
* @return string
*/
public static function element( $element, $attribs = array(), $contents = '' ) {
return self::rawElement( $element, $attribs, strtr( $contents, array(
// There's no point in escaping quotes, >, etc. in the contents of
// elements.
'&' => '&',
'<' => '<'
) ) );
}
/**
* Identical to rawElement(), but has no third parameter and omits the end
* tag (and the self-closing '/' in XML mode for empty elements).
*
* @param string $element
* @param array $attribs
*
* @return string
*/
public static function openElement( $element, $attribs = array() ) {
global $wgWellFormedXml;
$attribs = (array)$attribs;
// This is not required in HTML5, but let's do it anyway, for
// consistency and better compression.
$element = strtolower( $element );
// In text/html, initial and
tags can be omitted under
// pretty much any sane circumstances, if they have no attributes. See:
//
if ( !$wgWellFormedXml && !$attribs
&& in_array( $element, array( 'html', 'head' ) ) ) {
return '';
}
// Remove invalid input types
if ( $element == 'input' ) {
$validTypes = array(
'hidden',
'text',
'password',
'checkbox',
'radio',
'file',
'submit',
'image',
'reset',
'button',
// HTML input types
'datetime',
'datetime-local',
'date',
'month',
'time',
'week',
'number',
'range',
'email',
'url',
'search',
'tel',
'color',
);
if ( isset( $attribs['type'] )
&& !in_array( $attribs['type'], $validTypes ) ) {
unset( $attribs['type'] );
}
}
// According to standard the default type for