mirror of
https://github.com/Mibew/CanteenHTML5.git
synced 2025-03-12 20:34:08 +03:00
346 lines
8.8 KiB
PHP
346 lines
8.8 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @module Canteen\HTML5
|
|
*/
|
|
namespace Canteen\HTML5
|
|
{
|
|
/**
|
|
* A generic html tag with any children or closing tag. (e.g., img, br, hr).
|
|
* Do not initiate this class directly, use the `html()` function:
|
|
*
|
|
* echo html('br');
|
|
*
|
|
* @class Node
|
|
* @constructor
|
|
* @param {String} [tag=null] The name of the tag
|
|
* @param {Array|String} [attributes=null] The collection of tag attributes
|
|
* @param {String} [validAttrs=null] The list of non-global valid attributes for the tag, comma separated
|
|
*/
|
|
class Node
|
|
{
|
|
/**
|
|
* The string name of the tag
|
|
* @property {String} _tag
|
|
* @protected
|
|
*/
|
|
protected $_tag;
|
|
|
|
/**
|
|
* The collection of Attributes objects
|
|
* @property {Array} _attributes
|
|
* @protected
|
|
*/
|
|
protected $_attributes;
|
|
|
|
/**
|
|
* The parent node, if any
|
|
* @property {NodeContainer} _parent
|
|
* @protected
|
|
*/
|
|
protected $_parent;
|
|
|
|
/**
|
|
* The collection of valid attributes names for given tag
|
|
* @property {Array} _validAttrs
|
|
* @protected
|
|
*/
|
|
protected $_validAttrs;
|
|
|
|
/**
|
|
* The default valid attributes
|
|
* @property {String} GLOBAL_ATTRS
|
|
* @final
|
|
* @static
|
|
*/
|
|
const GLOBAL_ATTRS = 'accesskey,class,contenteditable,contextmenu,dir,draggable,dropzone,hidden,id,lang,spellcheck,style,tabindex,title,translate';
|
|
|
|
public function __construct($tag = null, $attributes = null, $validAttrs = null)
|
|
{
|
|
if ($this->isEmpty($tag))
|
|
{
|
|
throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG);
|
|
}
|
|
$this->_parent = null;
|
|
$this->_tag = $tag;
|
|
$this->_attributes = array();
|
|
|
|
$validAttrs = is_string($validAttrs) ? explode(',', $validAttrs) : $validAttrs;
|
|
$this->_validAttrs = explode(',', self::GLOBAL_ATTRS);
|
|
|
|
if ($validAttrs !== null)
|
|
{
|
|
$this->_validAttrs = array_merge($this->_validAttrs, $validAttrs);
|
|
}
|
|
|
|
if ($attributes !== null)
|
|
{
|
|
if (is_string($attributes))
|
|
{
|
|
$attributes = Attribute::shorthand($attributes);
|
|
}
|
|
|
|
if (is_array($attributes))
|
|
{
|
|
$this->setAttributes($attributes);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the parent node of this node, if
|
|
* a parent exists. If no parent exists,
|
|
* this function returns null.
|
|
* @method getParent
|
|
* @private
|
|
* @return {NodeContainer} The parent node object
|
|
*/
|
|
private function getParent()
|
|
{
|
|
return $this->_parent;
|
|
}
|
|
|
|
/**
|
|
* Sets the parent of this Node. Note that this
|
|
* function is protected and can only be called by
|
|
* classes that extend Node. The parent cannot
|
|
* be null; this function will throw an Exception
|
|
* if the parent node is empty.
|
|
* @method setParent
|
|
* @protected
|
|
* @param {NodeContainer} [parent=null] The parent container node
|
|
*/
|
|
protected function setParent(NodeContainer $parent = null)
|
|
{
|
|
if ($this->isEmpty($parent))
|
|
{
|
|
throw new HTML5Error(HTML5Error::EMPTY_PARENT);
|
|
}
|
|
$this->_parent = $parent;
|
|
}
|
|
|
|
/**
|
|
* Given a name and value pair, sets an attribute on this Node.
|
|
* The name and value cannot be empty; if so, this function
|
|
* will throw an Exception. Note if the attribute already exists
|
|
* and the caller wants to set an attribute of the same name,
|
|
* this function will not create a new Attribute, but rather
|
|
* update the value of the existing named attribute.
|
|
*
|
|
* @method setAttribute
|
|
* @param {String} [name=null] The name of the attribute to add
|
|
* @param {String} [value=null] The value of the attribute
|
|
* @param {Node} The instance of this node
|
|
*/
|
|
public function setAttribute($name = null, $value = null)
|
|
{
|
|
if ($this->isEmpty($name))
|
|
{
|
|
throw new HTML5Error(HTML5Error::EMPTY_ATTRIBUTE_NAME);
|
|
}
|
|
foreach($this->_attributes as $i=>$attribute)
|
|
{
|
|
if ($attribute->name === $name)
|
|
{
|
|
if (!$this->isEmpty($value))
|
|
$attribute->value = $value;
|
|
else
|
|
unset($this->_attributes[$i]);
|
|
return $this;
|
|
}
|
|
}
|
|
$this->_attributes[] = new Attribute($name, $value);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Fetch and attribute by name from this Node. The attribute
|
|
* name cannot be null; if so, this function will throw an
|
|
* Exception.
|
|
* @method getAttribute
|
|
* @param {String} [name=null] The name of the attribute to fetch
|
|
* @return {String} The attribute's value, if any or null
|
|
*/
|
|
protected function getAttribute($name = null)
|
|
{
|
|
$returnAttr = null;
|
|
|
|
if ($this->isEmpty($name))
|
|
{
|
|
throw new HTML5Error(HTML5Error::EMPTY_ATTRIBUTE_NAME);
|
|
}
|
|
foreach($this->_attributes as $attribute)
|
|
{
|
|
if ($attribute->name === $name)
|
|
{
|
|
$returnAttr = $attribute->value;
|
|
break;
|
|
}
|
|
}
|
|
return $returnAttr;
|
|
}
|
|
|
|
/**
|
|
* Set the list of all attributes.
|
|
* @method setAttributes
|
|
* @param {Dictionary} values An attributes array(name=>value, name=>value)
|
|
* @return {Node} The instance of this Node
|
|
*/
|
|
public function setAttributes($values)
|
|
{
|
|
if (is_array($values))
|
|
{
|
|
foreach($values as $name=>$value)
|
|
{
|
|
$this->setAttribute($name, $value);
|
|
}
|
|
return $this;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the a data-* HTML5 Attribute
|
|
* @param {String} name The name of the data, for instance "id" is an attribute "data-id"
|
|
* @param {String} value The value of the attribute
|
|
* @return {Node} The instance of this Node
|
|
*/
|
|
public function setData($name, $value)
|
|
{
|
|
return $this->setAttribute('data-'.$name, $value);
|
|
}
|
|
|
|
/**
|
|
* Add this child to a node container at the end
|
|
* @method appendTo
|
|
* @param {NodeContainer} container The node container to add to
|
|
* @return {Node} The instance of this Node
|
|
*/
|
|
public function appendTo(NodeContainer $container)
|
|
{
|
|
$container->addChild($this);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Add this child to the beginning of a node container
|
|
* @method prependTo
|
|
* @param {NodeContainer} container The node container to prepend to to
|
|
* @return {Node} The instance of this Node
|
|
*/
|
|
public function prependTo(NodeContainer $container)
|
|
{
|
|
$container->addChildAt($this, 0);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the data-* HTML5 attribute value, if set
|
|
* @method getData
|
|
* @param {String} name The name of the data attribute
|
|
* @return {String} The value of the data
|
|
*/
|
|
public function getData($name)
|
|
{
|
|
return $this->getAttribute('data-'.$name);
|
|
}
|
|
|
|
/**
|
|
* Write to HTML
|
|
* @method __toString
|
|
* @return {String} The string representation of this HTML node
|
|
*/
|
|
public function __toString()
|
|
{
|
|
return $this->writeOpen();
|
|
}
|
|
|
|
/**
|
|
* Start the writing the tag
|
|
* @method writeOpen
|
|
* @protected
|
|
* @param {Boolean} [selfClose=true] If the tag is a self closing tag (e.g., br, img, hr)
|
|
* @return {String} The buffer of HTML
|
|
*/
|
|
protected function writeOpen($selfClose=true)
|
|
{
|
|
$buffer = '<';
|
|
$buffer .= $this->_tag;
|
|
foreach($this->_attributes as $attribute)
|
|
{
|
|
$buffer .= (string)$attribute;
|
|
}
|
|
$buffer .= ($selfClose ? ' />' : '>');
|
|
return $buffer;
|
|
}
|
|
|
|
/**
|
|
* General purpose getter to get attribute values
|
|
* @method __get
|
|
* @param {String} name The name of the property to set
|
|
*/
|
|
public function __get($name)
|
|
{
|
|
if (in_array($name, $this->_validAttrs) || strpos($name, 'data-') === 0)
|
|
{
|
|
return $this->getAttribute($name);
|
|
}
|
|
return parent::__get($name);
|
|
}
|
|
|
|
/**
|
|
* General purpose setter to set attribute values
|
|
* @method __set
|
|
* @param {String} name The name of the attribute
|
|
* @param {String} value The value of the attribute
|
|
*/
|
|
public function __set($name, $value)
|
|
{
|
|
if (in_array($name, $this->_validAttrs) || strpos($name, 'data-') === 0)
|
|
{
|
|
return $this->setAttribute($name, $value);
|
|
}
|
|
return parent::__set($name);
|
|
}
|
|
|
|
/**
|
|
* See if a property exists
|
|
* @method __isset
|
|
* @param {String} name The name of the attribute
|
|
*/
|
|
public function __isset($name)
|
|
{
|
|
return in_array($name, $this->_validAttrs) || parent::__isset($name);
|
|
}
|
|
|
|
/**
|
|
* Checks if a variable is really "empty". Code borrowed from PHP.net at
|
|
* http://us3.php.net/manual/en/function.empty.php#90767 because we were
|
|
* previously using empty() to see if a variable is empty or not. But
|
|
* empty() dosen't work for attributes that have a value of "0", so we need
|
|
* something more robust here.
|
|
* <ul>
|
|
* <li>an unset variable -> empty</li>
|
|
* <li>null -> empty</li>
|
|
* <li>0 -> NOT empty</li>
|
|
* <li>"0" -> NOT empty</li>
|
|
* <li>false -> empty</li>
|
|
* <li>true -> NOT empty</li>
|
|
* <li>'string value' -> NOT empty</li>
|
|
* <li>" "(white space) -> empty</li>
|
|
* <li>array()(empty array) -> empty</li>
|
|
* </ul>
|
|
* @method isEmpty
|
|
* @protected
|
|
* @param {mixed} var The variable to check for empty on
|
|
*/
|
|
protected function isEmpty($var)
|
|
{
|
|
return (!isset($var) || is_null($var) ||
|
|
(!is_object($var) && is_string($var) && trim($var) == '' && !is_bool($var)) ||
|
|
(is_bool($var) && $var === false) ||
|
|
(is_array($var) && empty($var)));
|
|
}
|
|
}
|
|
}
|
|
|
|
?>
|