Fix code styling

This commit is contained in:
Fedor A. Fetisov 2021-07-09 23:19:03 +03:00
parent 7bdec8e106
commit 9f7340ec78
14 changed files with 1853 additions and 1837 deletions

View File

@ -1,57 +1,55 @@
<?php
include '../src/HTML5.php';
use Canteen\HTML5\HTML5;
include '../src/HTML5.php';
use Canteen\HTML5\HTML5;
HTML5::autoload(); // Autoload the classes, helpful if using outside composer
HTML5::useGlobal(); // if you want to use the global html() method instead of namespaced one
use Canteen\HTML5\Document;
use Canteen\HTML5\SimpleList;
use Canteen\HTML5\Table;
// Create a new document
$doc = new Document('Test Document');
$doc->beautify = true;
// Add a link to the page
$link = html('a#google.external rel=external', 'Link', 'class="test something" target=blank rel=test');
$link->href = 'http://google.com';
$link->onclick = "return confirm('Navigate away?');";
$link->appendTo($doc->body);
// Create an unordered list for an array of items
// the array can be other html elements or text
$list = new SimpleList(
array(
html('b', 'first'),
'second',
'third',
array(
'sub-third',
'sub-forth'
)
)
);
$list->appendTo($doc->body);
// Create a sample table with some rows of dummy data
$table = new Table(
array(
array('id'=>1, 'first'=>'James', 'last'=>'Smith'),
array('id'=>2, 'first'=>'Mary', 'last'=>'Denver'),
array('id'=>3, 'first'=>'Charlie', 'last'=>'Rose')
),
array('ID', 'First Name', 'Last Name')
);
// We'll set some of the table properties
$table->style = 'border:1px solid black';
$table->border = 0;
$table->id = 'people';
$table->appendTo($doc->body);
// Output the result formatted nice with indents
echo $doc;
HTML5::autoload(); // Autoload the classes, helpful if using outside composer
HTML5::useGlobal(); // if you want to use the global html() method instead of namespaced one
?>
use Canteen\HTML5\Document;
use Canteen\HTML5\SimpleList;
use Canteen\HTML5\Table;
// Create a new document
$doc = new Document('Test Document');
$doc->beautify = true;
// Add a link to the page
$link = html('a#google.external rel=external', 'Link', 'class="test something" target=blank rel=test');
$link->href = 'http://google.com';
$link->onclick = "return confirm('Navigate away?');";
$link->appendTo($doc->body);
// Create an unordered list for an array of items
// the array can be other html elements or text
$list = new SimpleList(
array(
html('b', 'first'),
'second',
'third',
array(
'sub-third',
'sub-forth'
)
)
);
$list->appendTo($doc->body);
// Create a sample table with some rows of dummy data
$table = new Table(
array(
array('id'=>1, 'first'=>'James', 'last'=>'Smith'),
array('id'=>2, 'first'=>'Mary', 'last'=>'Denver'),
array('id'=>3, 'first'=>'Charlie', 'last'=>'Rose')
),
array('ID', 'First Name', 'Last Name')
);
// We'll set some of the table properties
$table->style = 'border:1px solid black';
$table->border = 0;
$table->id = 'people';
$table->appendTo($doc->body);
// Output the result formatted nice with indents
echo $doc;

View File

@ -1,170 +1,176 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* An HTML attribute used on the Node, this is used internally.
* Do not initiate this class directly, use the `html()` function
* to create attributes on elements.
*
* echo html('a', 'Link', 'class=button href="about.html"');
*
* echo html('a', 'Link')
* ->setAttribute('class', 'button')
* ->setAttribute('href', 'about.html');
*
* @class Attribute
* @constructor
* @param {String} [name=null] The name of the attribute
* @param {String} [value=null] The value of the attribute
*/
class Attribute
{
/**
* The name of the attribute
* @property {String} _name
* @private
*/
private $_name;
/**
* The value of the attribute
* @property {String} _value
* @private
*/
private $_value;
/**
* An HTML attribute used on the Node, this is used internally.
* Do not initiate this class directly, use the `html()` function
* to create attributes on elements.
*
* echo html('a', 'Link', 'class=button href="about.html"');
*
* echo html('a', 'Link')
* ->setAttribute('class', 'button')
* ->setAttribute('href', 'about.html');
*
* @class Attribute
* @constructor
* @param {String} [name=null] The name of the attribute
* @param {String} [value=null] The value of the attribute
*/
class Attribute
{
/**
* The name of the attribute
* @property {String} _name
* @private
*/
private $_name;
public function __construct($name = null, $value = null)
{
$this->name = $name;
$this->value = $value;
}
/**
* The value of the attribute
* @property {String} _value
* @private
*/
private $_value;
/**
* Convert the attribute to an HTML tag attribute string
* @method __toString
* @return {String} String representation of attribute
*/
public function __toString()
{
return " " . $this->_name . "=\"" . $this->_value . "\"";
}
public function __construct($name = null, $value = null)
{
$this->name = $name;
$this->value = $value;
}
/**
* Get the name of this attribute
* @method getName
* @return {String} The attribute's name
*/
public function getName()
{
return $this->_name;
}
/**
* Convert the attribute to an HTML tag attribute string
* @method __toString
* @return {String} String representation of attribute
*/
public function __toString()
{
return " " . $this->_name . "=\"" . $this->_value . "\"";
}
/**
* Set the name of this attribute, cannot be empty
* @method setName
* @param {String} [name=null] The name of the attribute
*/
public function setName($name = null)
{
if (is_null($name) || empty($name))
{
throw new HTML5Error(HTML5Error::EMPTY_ATTRIBUTE_NAME);
}
$this->_name = $name;
}
/**
* Get the value of this attribute
* @method getValue
* @protected
* @return {String} The value of attribute
*/
protected function getValue()
{
return $this->_value;
}
/**
* Get the name of this attribute
* @method getName
* @return {String} The attribute's name
*/
public function getName()
{
return $this->_name;
}
/**
* Set the value of this attribute, this cannot be empty
* @method setValue
* @protected
* @param {String} value The value to set
*/
protected function setValue($value)
{
$this->_value = $value;
}
/**
* Convert a string into an associative array
* @method shorthand
* @static
* @param {String} str The string, delineated by semicolons, and colons for attributes:values
* @return {Dictionary} The collection of attributes
*/
static public function shorthand($str)
{
$res = array();
// Match the name=value in the attributes string
preg_match_all('/([a-z]+[a-z\-]*)\=("[^\"]*"|\'[^\']*\'|[^\s\"\']*)/',$str, $arr);
foreach($arr[1] as $i=>$name)
{
$value = $arr[2][$i];
// Remove containing quotes if present
if (preg_match('/^[\'\"][^\n]*[\'\"]$/', $value))
{
$value = substr($value, 1, -1);
}
$res[$name] = $value;
}
return $res;
}
/**
* General purpose getter for getting attribute->name and attribute->value
* @public __get
* @param {String} name The name of the property to get
*/
public function __get($name)
{
if (method_exists($this , $method =('get' . ucfirst($name))))
return $this->$method();
else
throw new HTML5Error(HTML5Error::INVALID_GETTER, $name);
}
/**
* Set the name of this attribute, cannot be empty
* @method setName
* @param {String} [name=null] The name of the attribute
*/
public function setName($name = null)
{
if (is_null($name) || empty($name))
{
throw new HTML5Error(HTML5Error::EMPTY_ATTRIBUTE_NAME);
}
$this->_name = $name;
}
/**
* General purpose setter for setting attribute->name and attribute->value
* @public __set
* @param {String} name The name of the attribute
* @param {String} value The value of the attribute
*/
public function __set($name, $value)
{
if (method_exists($this , $method =('set' . ucfirst($name))))
return $this->$method($value);
else
throw new HTML5Error(HTML5Error::INVALID_SETTER, $name);
}
/**
* Get the value of this attribute
* @method getValue
* @protected
* @return {String} The value of attribute
*/
protected function getValue()
{
return $this->_value;
}
/**
* See if a property exists
* @method __isset
* @param {String} name The name of the property
*/
public function __isset($name)
{
return method_exists($this , 'get' . ucfirst($name))
|| method_exists($this , 'set' . ucfirst($name));
}
}
/**
* Set the value of this attribute, this cannot be empty
* @method setValue
* @protected
* @param {String} value The value to set
*/
protected function setValue($value)
{
$this->_value = $value;
}
/**
* Convert a string into an associative array
* @method shorthand
* @static
* @param {String} str The string, delineated by semicolons, and colons for attributes:values
* @return {Dictionary} The collection of attributes
*/
static public function shorthand($str)
{
$res = array();
// Match the name=value in the attributes string
preg_match_all('/([a-z]+[a-z\-]*)\=("[^\"]*"|\'[^\']*\'|[^\s\"\']*)/',$str, $arr);
foreach ($arr[1] as $i=>$name)
{
$value = $arr[2][$i];
// Remove containing quotes if present
if (preg_match('/^[\'\"][^\n]*[\'\"]$/', $value))
{
$value = substr($value, 1, -1);
}
$res[$name] = $value;
}
return $res;
}
/**
* General purpose getter for getting attribute->name and attribute->value
* @public __get
* @param {String} name The name of the property to get
*/
public function __get($name)
{
if (method_exists($this , $method =('get' . ucfirst($name))))
{
return $this->$method();
}
else
{
throw new HTML5Error(HTML5Error::INVALID_GETTER, $name);
}
}
/**
* General purpose setter for setting attribute->name and attribute->value
* @public __set
* @param {String} name The name of the attribute
* @param {String} value The value of the attribute
*/
public function __set($name, $value)
{
if (method_exists($this , $method =('set' . ucfirst($name))))
{
return $this->$method($value);
}
else
{
throw new HTML5Error(HTML5Error::INVALID_SETTER, $name);
}
}
/**
* See if a property exists
* @method __isset
* @param {String} name The name of the property
*/
public function __isset($name)
{
return method_exists($this , 'get' . ucfirst($name))
|| method_exists($this , 'set' . ucfirst($name));
}
}
}
?>

View File

@ -1,38 +1,36 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* Special node type representing an HTML5 inline comment.
* Do not initiate this class directly, use the `html('comment')` function:
*
* echo html('comment', 'Hidden HTML comment here');
*
* @class Comment
* @extends NodeContainer
* @constructor
* @param {String} text the plain text string
*/
class Comment extends NodeContainer
{
public function __construct($text)
{
parent::__construct($text);
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
return '<!-- '.$this->_tag.' -->';
}
}
}
{
/**
* Special node type representing an HTML5 inline comment.
* Do not initiate this class directly, use the `html('comment')` function:
*
* echo html('comment', 'Hidden HTML comment here');
*
* @class Comment
* @extends NodeContainer
* @constructor
* @param {String} text the plain text string
*/
class Comment extends NodeContainer
{
public function __construct($text)
{
parent::__construct($text);
}
?>
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
return '<!-- ' . $this->_tag . ' -->';
}
}
}

View File

@ -1,117 +1,117 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* Create an HTML document. Basic barebones structure.
* Located in the namespace __Canteen\HTML5__.
*
* $doc = new HTML5\Document('Untitled');
* $doc->head->addChild(html('script src=main.js'));
* $doc->body->addChild(html('div#frame'));
* echo $doc;
*
* @class Document
* @extends NodeContainer
* @constructor
* @param {String} [title=''] The title of the document
* @param {String} [charset='utf-8'] The character encoding set of this HTML document
* @param {Boolean} [beautify=false] If we should add whitespace to the output to make it look nice markup.
*/
class Document extends NodeContainer
{
/**
* The document type
* @property {NodeContainer} docType
*/
private $docType;
{
/**
* Create an HTML document. Basic barebones structure.
* Located in the namespace __Canteen\HTML5__.
*
* $doc = new HTML5\Document('Untitled');
* $doc->head->addChild(html('script src=main.js'));
* $doc->body->addChild(html('div#frame'));
* echo $doc;
*
* @class Document
* @extends NodeContainer
* @constructor
* @param {String} [title=''] The title of the document
* @param {String} [charset='utf-8'] The character encoding set of this HTML document
* @param {Boolean} [beautify=false] If we should add whitespace to the output to make it look nice markup.
*/
class Document extends NodeContainer
{
/**
* The document type
* @property {NodeContainer} docType
*/
private $docType;
/**
* The head node
* @property {NodeContainer} head
*/
public $head;
/**
* The body node
* @property {NodeContainer} body
*/
public $body;
/**
* The title node
* @property {NodeContainer} title
*/
public $title;
/**
* Beautify the output
* @property {Boolean} beautify
*/
public $beautify = false;
/**
* Constructor for Docs
*/
public function __construct($title='', $charset='utf-8', $beautify=false)
{
parent::__construct('html', null, null,
array_merge(
array('manifest'),
Specification::$ATTRIBUTES
)
);
$this->docType = html('doctype');
$this->head = html('head');
$this->body = html('body');
$this->title = html('title', $title);
$this->head->addChild(html('meta', 'charset='.$charset));
$this->head->addChild($this->title);
$this->addChild($this->head);
$this->addChild($this->body);
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
$result = $this->docType . parent::__toString();
if ($this->beautify)
$result = self::beautify($result);
return $result;
}
/**
* Beautifies an HTML string into a human-readable and indented work of art.
* @method beautify
* @static
* @param {String} html The XML-compatible HTML as a string
* @return {String} The formatted string
*/
public static function beautify($html)
{
// Conver the HTML -> SimpleXML -> DOMDocument
$dom = dom_import_simplexml(new \SimpleXMLElement($html))->ownerDocument;
// Format the DOMDocument
$dom->formatOutput = true;
// Save the output as XML
$buffer = $dom->saveXML();
// Remove the first line which has the XML declaration
return substr($buffer, strpos($buffer, "\n")+1);
}
}
/**
* The head node
* @property {NodeContainer} head
*/
public $head;
/**
* The body node
* @property {NodeContainer} body
*/
public $body;
/**
* The title node
* @property {NodeContainer} title
*/
public $title;
/**
* Beautify the output
* @property {Boolean} beautify
*/
public $beautify = false;
/**
* Constructor for Docs
*/
public function __construct($title='', $charset='utf-8', $beautify=false)
{
parent::__construct('html', null, null,
array_merge(
array('manifest'),
Specification::$ATTRIBUTES
)
);
$this->docType = html('doctype');
$this->head = html('head');
$this->body = html('body');
$this->title = html('title', $title);
$this->head->addChild(html('meta', 'charset=' . $charset));
$this->head->addChild($this->title);
$this->addChild($this->head);
$this->addChild($this->body);
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
$result = $this->docType . parent::__toString();
if ($this->beautify)
{
$result = self::beautify($result);
}
return $result;
}
/**
* Beautifies an HTML string into a human-readable and indented work of art.
* @method beautify
* @static
* @param {String} html The XML-compatible HTML as a string
* @return {String} The formatted string
*/
public static function beautify($html)
{
// Conver the HTML -> SimpleXML -> DOMDocument
$dom = dom_import_simplexml(new \SimpleXMLElement($html))->ownerDocument;
// Format the DOMDocument
$dom->formatOutput = true;
// Save the output as XML
$buffer = $dom->saveXML();
// Remove the first line which has the XML declaration
return substr($buffer, strpos($buffer, "\n")+1);
}
}
}
?>

View File

@ -5,39 +5,37 @@
*/
namespace Canteen\HTML5
{
/**
* Represents a set of HTML tags without a wrapper.
* Do not initiate this class directly, use the `html()` function:
*
* $div = html('fragment');
*
* @class Fragment
* @extends NodeContainer
* @constructor
* @param {Node|Array} [children=null] The collection of children or single child
*/
class Fragment extends NodeContainer
{
public function __construct($children = null)
{
parent::__construct('fragment', $children, null);
}
/**
* Represents a set of HTML tags without a wrapper.
* Do not initiate this class directly, use the `html()` function:
*
* $div = html('fragment');
*
* @class Fragment
* @extends NodeContainer
* @constructor
* @param {Node|Array} [children=null] The collection of children or single child
*/
class Fragment extends NodeContainer
{
public function __construct($children = null)
{
parent::__construct('fragment', $children, null);
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
$buffer = '';
foreach($this->getChildren() as $child)
{
$buffer .= $child->__toString();
}
return $buffer;
}
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
$buffer = '';
foreach ($this->getChildren() as $child)
{
$buffer .= $child->__toString();
}
return $buffer;
}
}
}
?>

View File

@ -1,170 +1,175 @@
<?php
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* Main class of the library
* @class HTML5
*/
class HTML5
{
/**
* Turn on autoloading for the library
* @method autoload
* @static
*/
static public function autoload()
{
spl_autoload_register(function($name)
{
// Ignore class names not in the HTML5 namespace
if (!preg_match('/^Canteen\\\HTML5\\\/', $name)) return;
// Remove the HTML5 namespace
$name = preg_replace('/^Canteen\\\HTML5\\\/', '', $name);
// Convert the rest to directories
$name = str_replace("\\", '/', $name);
// Include the class relative to here
include __DIR__.'/'.$name.'.php';
});
}
{
/**
* Main class of the library
* @class HTML5
*/
class HTML5
{
/**
* Turn on autoloading for the library
* @method autoload
* @static
*/
static public function autoload()
{
spl_autoload_register(function($name)
{
// Ignore class names not in the HTML5 namespace
if (!preg_match('/^Canteen\\\HTML5\\\/', $name))
{
return;
}
/**
* Use the global `html()` method
* @method {Boolean} useGlobal
*/
static public function useGlobal()
{
include __DIR__.'/html.php';
}
}
// Remove the HTML5 namespace
$name = preg_replace('/^Canteen\\\HTML5\\\/', '', $name);
/**
* This is the global function is the main entry for interacting with the HTML5 for PHP library.
* using `html()` global function you can create HTML5 quickly and easily. For more
* examples and instruction on how to use this library, please refer to the the
* <a href="https://github.com/Canteen/CanteenHTML5">GitHub project</a>.
* To install the library simply include `html.php`, this takes care of any autoloading that's needed
* for the rest of the library.
*
* echo html('img src=home.jpg');
* echo html('img', 'src=home.jpg');
* echo html('a', array('href'=>'about.html'));
*
*
*
* @method html
* @param {String} tag The name of the tag as a string for example 'tr', 'table', can be followed
* by CSS selector, e.g. 'a#backButton' or 'a.button'
* @param {Dictionary|Node|String|Array} [childrenOrAttributes=null] If the tag is a NodeContainer, this can be an array
* of attributes, another html node or some text. If the tag is a single node, this can
* be an array or chain of attributes
* @param {Dictionary|String} [attributes=null] The attributes list for container tags (e.g., 'class:selected')
* @return {Node} Return the html node
*/
function html($tag, $childrenOrAttributes=null, $attributes=null)
{
// Get the tag ID from the tag string
// for instance 'a.button rel=external', a.button is the tagId, the rest are the attributes
$endPos = strpos(trim($tag), ' ');
// The tag attributes
$tagAttributes = array();
// If the tag also has some attributes
if ($endPos !== false)
{
$tagOriginal = $tag;
$tag = substr($tag, 0, $endPos);
$tagAttributes = Attribute::shorthand(substr($tagOriginal, $endPos + 1));
}
// Match the tag name without the CSS selectors
preg_match('/^([a-z1-6]{1,10})(.*)/', $tag, $tagParts);
// Valid class ane id names must begin with a -, _, or a-z letter
preg_match_all('/(\.|\#)\-?[\_a-zA-Z]+[\_a-zA-Z0-9\-]*/', $tagParts[2], $selectors);
$tag = strtolower($tagParts[1]); // the name of the tag
$selfClosing = false;
// Convert the rest to directories
$name = str_replace("\\", '/', $name);
// Comment tags are special
if ($tag == 'comment')
{
return new Comment($childrenOrAttributes);
}
// Document type declaration
else if ($tag == 'doctype')
{
return '<!DOCTYPE html>';
}
// Any normal text
else if ($tag == 'text')
{
return new Text($childrenOrAttributes);
}
// Untagged container
else if ($tag == 'fragment')
{
return new Fragment($childrenOrAttributes);
}
// Check for task specification
else if (isset(Specification::$TAGS[$tag]))
{
// Check to see if this is a self closing tag
$selfClosing = in_array($tag, Specification::$SELF_CLOSING);
}
else
{
throw new HTML5Error(HTML5Error::INVALID_TAG, $tag);
}
// Create the attributes collection, either string or array
$attributes = $selfClosing ? $childrenOrAttributes : $attributes;
// If there are attributes and they are in a string format
// convert to an attributes array
if ($attributes !== null && is_string($attributes))
{
$attributes = Attribute::shorthand($attributes);
}
// Combine the attributes and the tags
if (is_array($attributes))
{
$attributes = array_merge($tagAttributes, $attributes);
}
// Or just add any tag attributes
else if (count($tagAttributes))
{
$attributes = $tagAttributes;
}
// Create the node or container
$node = $selfClosing ?
new Node($tag, $attributes) :
new NodeContainer($tag, $childrenOrAttributes, $attributes);
// Take the selectors convert them into id or class
foreach($selectors[0] as $selector)
{
switch($selector[0])
{
case '#' :
$node->id = substr($selector, 1);
break;
case '.' :
if ($node->class) $node->class .= ' ';
$node->class .= substr($selector, 1);
break;
}
}
return $node;
}
}
// Include the class relative to here
include __DIR__ . '/' . $name . '.php';
});
}
/**
* Use the global `html()` method
* @method {Boolean} useGlobal
*/
static public function useGlobal()
{
include __DIR__ . '/html.php';
}
}
/**
* This is the global function is the main entry for interacting with the HTML5 for PHP library.
* using `html()` global function you can create HTML5 quickly and easily. For more
* examples and instruction on how to use this library, please refer to the the
* <a href="https://github.com/Canteen/CanteenHTML5">GitHub project</a>.
* To install the library simply include `html.php`, this takes care of any autoloading that's needed
* for the rest of the library.
*
* echo html('img src=home.jpg');
* echo html('img', 'src=home.jpg');
* echo html('a', array('href'=>'about.html'));
*
*
*
* @method html
* @param {String} tag The name of the tag as a string for example 'tr', 'table', can be followed
* by CSS selector, e.g. 'a#backButton' or 'a.button'
* @param {Dictionary|Node|String|Array} [childrenOrAttributes=null] If the tag is a NodeContainer, this can be an array
* of attributes, another html node or some text. If the tag is a single node, this can
* be an array or chain of attributes
* @param {Dictionary|String} [attributes=null] The attributes list for container tags (e.g., 'class:selected')
* @return {Node} Return the html node
*/
function html($tag, $childrenOrAttributes=null, $attributes=null)
{
// Get the tag ID from the tag string
// for instance 'a.button rel=external', a.button is the tagId, the rest are the attributes
$endPos = strpos(trim($tag), ' ');
// The tag attributes
$tagAttributes = array();
// If the tag also has some attributes
if ($endPos !== false)
{
$tagOriginal = $tag;
$tag = substr($tag, 0, $endPos);
$tagAttributes = Attribute::shorthand(substr($tagOriginal, $endPos + 1));
}
// Match the tag name without the CSS selectors
preg_match('/^([a-z1-6]{1,10})(.*)/', $tag, $tagParts);
// Valid class ane id names must begin with a -, _, or a-z letter
preg_match_all('/(\.|\#)\-?[\_a-zA-Z]+[\_a-zA-Z0-9\-]*/', $tagParts[2], $selectors);
$tag = strtolower($tagParts[1]); // the name of the tag
$selfClosing = false;
// Comment tags are special
if ($tag == 'comment')
{
return new Comment($childrenOrAttributes);
}
// Document type declaration
else if ($tag == 'doctype')
{
return '<!DOCTYPE html>';
}
// Any normal text
else if ($tag == 'text')
{
return new Text($childrenOrAttributes);
}
// Untagged container
else if ($tag == 'fragment')
{
return new Fragment($childrenOrAttributes);
}
// Check for task specification
else if (isset(Specification::$TAGS[$tag]))
{
// Check to see if this is a self closing tag
$selfClosing = in_array($tag, Specification::$SELF_CLOSING);
}
else
{
throw new HTML5Error(HTML5Error::INVALID_TAG, $tag);
}
// Create the attributes collection, either string or array
$attributes = $selfClosing ? $childrenOrAttributes : $attributes;
// If there are attributes and they are in a string format
// convert to an attributes array
if ($attributes !== null && is_string($attributes))
{
$attributes = Attribute::shorthand($attributes);
}
// Combine the attributes and the tags
if (is_array($attributes))
{
$attributes = array_merge($tagAttributes, $attributes);
}
// Or just add any tag attributes
else if (count($tagAttributes))
{
$attributes = $tagAttributes;
}
// Create the node or container
$node = $selfClosing ?
new Node($tag, $attributes) :
new NodeContainer($tag, $childrenOrAttributes, $attributes);
// Take the selectors convert them into id or class
foreach ($selectors[0] as $selector)
{
switch ($selector[0])
{
case '#' :
$node->id = substr($selector, 1);
break;
case '.' :
if ($node->class) {
$node->class .= ' ';
}
$node->class .= substr($selector, 1);
break;
}
}
return $node;
}
}

View File

@ -1,144 +1,142 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* Exceptions with using the HTML5 API.
*
* try
* {
* html('invalid', 'something');
* }
* catch(Canteen\HTML5\HTML5Error $e)
* {
* $e->getMessage();
* }
*
* @class HTML5Error
* @extends Exception
* @constructor
* @param {int} code The code of the error
* @param {String} [data=''] Additional data to associate with this error
*/
class HTML5Error extends \Exception
{
/**
* The database connection failed
* @property {int} EMPTY_ATTRIBUTE_NAME
* @static
* @final
*/
const EMPTY_ATTRIBUTE_NAME = 500;
/**
* The alias for a database is invalid
* @property {int} EMPTY_ATTRIBUTE_VALUE
* @static
* @final
*/
const EMPTY_ATTRIBUTE_VALUE = 501;
/**
* The database name we're trying to switch to is invalid
* @property {int} INVALID_SETTER
* @static
* @final
*/
const INVALID_SETTER = 502;
/**
* The mysql where trying to execute was a problem
* @property {int} INVALID_GETTER
* @static
* @final
*/
const INVALID_GETTER = 503;
/**
* The html tag name is invalid
* @property {int} INVALID_TAG
* @static
* @final
*/
const INVALID_TAG = 504;
/**
* When trying to create a node, the name is empty
* @property {int} EMPTY_NODE_TAG
* @static
* @final
*/
const EMPTY_NODE_TAG = 505;
/**
* The parent cannot be empty
* @property {int} EMPTY_PARENT
* @static
* @final
*/
const EMPTY_PARENT = 506;
/**
* THe addChildAt is out of bounds
* @property {int} OUT_OF_BOUNDS
* @static
* @final
*/
const OUT_OF_BOUNDS = 507;
/**
* The child node is empty
* @property {int} EMPTY_CHILD
* @static
* @final
*/
const EMPTY_CHILD = 508;
/**
* The node is not of instance type Node
* @property {int} INVALID_NODE
* @static
* @final
*/
const INVALID_NODE = 509;
/**
* Look-up for error messages
* @property {Dictionary} messages
* @private
* @static
*/
private static $messages = array(
self::EMPTY_ATTRIBUTE_NAME => 'Attribute names cannot be empty',
self::EMPTY_ATTRIBUTE_VALUE => 'Attribute values cannot be empty',
self::INVALID_SETTER => 'Cannot set the property because name is invalid',
self::INVALID_GETTER => 'Cannot get the property because name is invalid',
self::INVALID_TAG => 'Not a valid HTML5 tag name',
self::EMPTY_NODE_TAG => 'Node tag is empty',
self::EMPTY_PARENT => 'The parent cannot be empty',
self::OUT_OF_BOUNDS => 'The index is out of bounds',
self::EMPTY_CHILD => 'Cannot addChild an empty child node',
self::INVALID_NODE => 'Child node must be a valid tag'
);
/**
* The label for an error that is unknown or unfound in messages
* @property {String} UNKNOWN
* @static
* @final
*/
const UNKNOWN = 'Unknown error';
public function __construct($code, $data='')
{
$message = (isset(self::$messages[$code]) ? self::$messages[$code]: self::UNKNOWN)
. ($data ? ' : ' . $data : $data);
parent::__construct($message, $code);
}
}
}
{
/**
* Exceptions with using the HTML5 API.
*
* try
* {
* html('invalid', 'something');
* }
* catch(Canteen\HTML5\HTML5Error $e)
* {
* $e->getMessage();
* }
*
* @class HTML5Error
* @extends Exception
* @constructor
* @param {int} code The code of the error
* @param {String} [data=''] Additional data to associate with this error
*/
class HTML5Error extends \Exception
{
/**
* The database connection failed
* @property {int} EMPTY_ATTRIBUTE_NAME
* @static
* @final
*/
const EMPTY_ATTRIBUTE_NAME = 500;
?>
/**
* The alias for a database is invalid
* @property {int} EMPTY_ATTRIBUTE_VALUE
* @static
* @final
*/
const EMPTY_ATTRIBUTE_VALUE = 501;
/**
* The database name we're trying to switch to is invalid
* @property {int} INVALID_SETTER
* @static
* @final
*/
const INVALID_SETTER = 502;
/**
* The mysql where trying to execute was a problem
* @property {int} INVALID_GETTER
* @static
* @final
*/
const INVALID_GETTER = 503;
/**
* The html tag name is invalid
* @property {int} INVALID_TAG
* @static
* @final
*/
const INVALID_TAG = 504;
/**
* When trying to create a node, the name is empty
* @property {int} EMPTY_NODE_TAG
* @static
* @final
*/
const EMPTY_NODE_TAG = 505;
/**
* The parent cannot be empty
* @property {int} EMPTY_PARENT
* @static
* @final
*/
const EMPTY_PARENT = 506;
/**
* THe addChildAt is out of bounds
* @property {int} OUT_OF_BOUNDS
* @static
* @final
*/
const OUT_OF_BOUNDS = 507;
/**
* The child node is empty
* @property {int} EMPTY_CHILD
* @static
* @final
*/
const EMPTY_CHILD = 508;
/**
* The node is not of instance type Node
* @property {int} INVALID_NODE
* @static
* @final
*/
const INVALID_NODE = 509;
/**
* Look-up for error messages
* @property {Dictionary} messages
* @private
* @static
*/
private static $messages = array(
self::EMPTY_ATTRIBUTE_NAME => 'Attribute names cannot be empty',
self::EMPTY_ATTRIBUTE_VALUE => 'Attribute values cannot be empty',
self::INVALID_SETTER => 'Cannot set the property because name is invalid',
self::INVALID_GETTER => 'Cannot get the property because name is invalid',
self::INVALID_TAG => 'Not a valid HTML5 tag name',
self::EMPTY_NODE_TAG => 'Node tag is empty',
self::EMPTY_PARENT => 'The parent cannot be empty',
self::OUT_OF_BOUNDS => 'The index is out of bounds',
self::EMPTY_CHILD => 'Cannot addChild an empty child node',
self::INVALID_NODE => 'Child node must be a valid tag'
);
/**
* The label for an error that is unknown or unfound in messages
* @property {String} UNKNOWN
* @static
* @final
*/
const UNKNOWN = 'Unknown error';
public function __construct($code, $data='')
{
$message = (isset(self::$messages[$code]) ? self::$messages[$code]: self::UNKNOWN)
. ($data ? ' : ' . $data : $data);
parent::__construct($message, $code);
}
}
}

View File

@ -1,341 +1,343 @@
<?php
/**
* @module Canteen\HTML5
* @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
* @extends Proto
* @constructor
* @param {String} [tag=null] The name of the tag
* @param {Array|String} [attributes=null] The collection of tag attributes
*/
class Node extends Proto
{
/**
* 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;
public function __construct($tag = null, $attributes = null)
{
if ($this->isEmpty($tag))
{
throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG);
}
$this->_parent = null;
$this->_tag = $tag;
$this->_attributes = array();
/**
* 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
* @extends Proto
* @constructor
* @param {String} [tag=null] The name of the tag
* @param {Array|String} [attributes=null] The collection of tag attributes
*/
class Node extends Proto
{
/**
* The string name of the tag
* @property {String} _tag
* @protected
*/
protected $_tag;
if (isset(Specification::$TAGS[$tag]))
{
$this->_validAttrs = array_merge(
Specification::$TAGS[$tag],
Specification::$ATTRIBUTES
);
}
else
{
$this->_validAttrs = array();
}
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;
/**
* The collection of Attributes objects
* @property {Array} _attributes
* @protected
*/
protected $_attributes;
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);
}
/**
* The parent node, if any
* @property {NodeContainer} _parent
* @protected
*/
protected $_parent;
/**
* 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);
}
}
/**
* The collection of valid attributes names for given tag
* @property {Array} _validAttrs
* @protected
*/
protected $_validAttrs;
/**
* 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)));
}
}
public function __construct($tag = null, $attributes = null)
{
if ($this->isEmpty($tag))
{
throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG);
}
$this->_parent = null;
$this->_tag = $tag;
$this->_attributes = array();
if (isset(Specification::$TAGS[$tag]))
{
$this->_validAttrs = array_merge(
Specification::$TAGS[$tag],
Specification::$ATTRIBUTES
);
}
else
{
$this->_validAttrs = array();
}
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);
}
}
/**
* 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)));
}
}
}
?>

View File

@ -1,237 +1,235 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* Represents an HTML that that can contain other tags (e.g., br, p, div).
* Do not initiate this class directly, use the `html()` function:
*
* $div = html('div');
*
* @class NodeContainer
* @extends Node
* @constructor
* @param {String} [tag=null] The name of the tag element
* @param {Node|Array} [children=null] The collection of children or single child
* @param {String|Dictionary} [attributes=null] The tag attributes
*/
class NodeContainer extends Node
{
/**
* The collection of children nodes
* @property {Array} _children
* @private
*/
private $_children;
{
/**
* Represents an HTML that that can contain other tags (e.g., br, p, div).
* Do not initiate this class directly, use the `html()` function:
*
* $div = html('div');
*
* @class NodeContainer
* @extends Node
* @constructor
* @param {String} [tag=null] The name of the tag element
* @param {Node|Array} [children=null] The collection of children or single child
* @param {String|Dictionary} [attributes=null] The tag attributes
*/
class NodeContainer extends Node
{
/**
* The collection of children nodes
* @property {Array} _children
* @private
*/
private $_children;
public function __construct($tag = null, $children = null, $attributes = null)
{
if ($this->isEmpty($tag))
{
throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG);
}
parent::__construct($tag, $attributes);
$this->_children = array();
if (!$this->isEmpty($children))
{
if (!is_array($children))
{
$children = array($children);
}
if (is_array($children))
{
foreach($children as $child)
{
$this->addChild($child);
}
}
}
}
public function __construct($tag = null, $children = null, $attributes = null)
{
if ($this->isEmpty($tag))
{
throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG);
}
parent::__construct($tag, $attributes);
/**
* Add's a child to this NodeContainer. The child to add cannot be null.
* @method addChild
* @param {Node|String|Number|Boolean} childNode The child Node to add
* @return {NodeContainer} The instance of this container
*/
public function addChild($childNode)
{
array_push($this->_children, $this->prepareChild($childNode));
return $this;
}
/**
* Add a child at a specific index
* @method addChildAt
* @param {Node|String|Number|Boolean} childNode The child Node to add
* @param {int} index The index to add child at, 0 is top
* @return {NodeContainer} The instance of this container
*/
public function addChildAt($childNode, $index)
{
if ($index < 0)
{
throw new HTML5Error(HTML5Error::OUT_OF_BOUNDS, $index);
}
$childNode = $this->prepareChild($childNode);
if ($index == 0)
{
array_unshift($this->_children, $childNode);
}
else if ($index > (count($this->_children) - 1))
{
$this->addChild($childNode);
}
else
{
array_splice($this->_children, $index , 0, array($childNode));
}
return $this;
}
/**
* Before adding a child, we should do some checking for basic types
* and convert it into a more useable Node object.
* @method prepareChild
* @protected
* @param {Node|String|Number|Boolean} childNode The child node to add
* @return {Node} The child node
*/
protected function prepareChild($childNode)
{
if ($this->isEmpty($childNode))
{
throw new HTML5Error(HTML5Error::EMPTY_CHILD);
}
if (is_bool($childNode))
{
$childNode = new Text($childNode ? 'true' : 'false');
}
else if (is_string($childNode) || is_numeric($childNode))
{
$childNode = new Text($childNode);
}
if (!($childNode instanceof Node))
{
throw new HTML5Error(HTML5Error::INVALID_NODE);
}
$childNode->setParent($this);
return $childNode;
}
$this->_children = array();
/**
* Removes the first instance of child from this.
* Once the first instance of the child
* is removed, this function will return. It returns
* true if a child was removed and false if no child
* was removed.
* @method removeChild
* @param {Node} [childNode=null] The node to remove
* @return {Boolean} If successfully removed
*/
public function removeChild(Node $childNode = null)
{
if ($this->isEmpty($childNode))
{
throw new HTML5Error(HTML5Error::EMPTY_CHILD);
}
if (!$this->isEmpty($children))
{
if (!is_array($children))
{
$children = array($children);
}
if (is_array($children))
{
foreach ($children as $child)
{
$this->addChild($child);
}
}
}
}
for($i = 0; $i < count($this->_children); $i++)
{
$child = $this->_children[$i];
if ($child === $childNode)
{
unset($this->_children[$i]);
return true;
}
}
return false;
}
/**
* Remove a child as a specific index
* @method removeChildAt
* @param {int} index The index to remove child at
* @return {NodeContainer} The instance of the node container
*/
public function removeChildAt($index)
{
if ($index >= $this->_children || $index < 0)
{
throw new HTML5Error(HTML5Error::OUT_OF_BOUNDS, $index);
}
array_splice($this->_children, $index, 1);
return $this;
}
/**
* Add's a child to this NodeContainer. The child to add cannot be null.
* @method addChild
* @param {Node|String|Number|Boolean} childNode The child Node to add
* @return {NodeContainer} The instance of this container
*/
public function addChild($childNode)
{
array_push($this->_children, $this->prepareChild($childNode));
return $this;
}
/**
* Removes all children attached to this Node container
* @method removeChildren
* @return {NodeContainer} The instance of the node container
*/
public function removeChildren()
{
unset($this->_children);
$this->_children = array();
return $this;
}
/**
* Add a child at a specific index
* @method addChildAt
* @param {Node|String|Number|Boolean} childNode The child Node to add
* @param {int} index The index to add child at, 0 is top
* @return {NodeContainer} The instance of this container
*/
public function addChildAt($childNode, $index)
{
if ($index < 0)
{
throw new HTML5Error(HTML5Error::OUT_OF_BOUNDS, $index);
}
$childNode = $this->prepareChild($childNode);
if ($index == 0)
{
array_unshift($this->_children, $childNode);
}
else if ($index > (count($this->_children) - 1))
{
$this->addChild($childNode);
}
else
{
array_splice($this->_children, $index , 0, array($childNode));
}
return $this;
}
/**
* Returns an array of all children attached to this Node container.
* @method getChildren
* @return {Array} The collection of Node objects
*/
public function getChildren()
{
return $this->_children;
}
/**
* Before adding a child, we should do some checking for basic types
* and convert it into a more useable Node object.
* @method prepareChild
* @protected
* @param {Node|String|Number|Boolean} childNode The child node to add
* @return {Node} The child node
*/
protected function prepareChild($childNode)
{
if ($this->isEmpty($childNode))
{
throw new HTML5Error(HTML5Error::EMPTY_CHILD);
}
if (is_bool($childNode))
{
$childNode = new Text($childNode ? 'true' : 'false');
}
else if (is_string($childNode) || is_numeric($childNode))
{
$childNode = new Text($childNode);
}
if (!($childNode instanceof Node))
{
throw new HTML5Error(HTML5Error::INVALID_NODE);
}
$childNode->setParent($this);
return $childNode;
}
/**
* Gets a child of this Node container at given
* index. If no index is passed in, getChild()
* will return the child at index zero (0).
* @method getChildAt
* @param {int} [index=0] The index to fetch child Node at
* @return {Node} The child Node
*/
public function getChildAt($index = 0)
{
return $this->_children[$index];
}
/**
* Close the writing of this container as HTML
* @method writeClose
* @protected
* @return {String} The closing HTML tag element
*/
protected function writeClose()
{
return "</" . $this->_tag . ">";
}
/**
* Removes the first instance of child from this.
* Once the first instance of the child
* is removed, this function will return. It returns
* true if a child was removed and false if no child
* was removed.
* @method removeChild
* @param {Node} [childNode=null] The node to remove
* @return {Boolean} If successfully removed
*/
public function removeChild(Node $childNode = null)
{
if ($this->isEmpty($childNode))
{
throw new HTML5Error(HTML5Error::EMPTY_CHILD);
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
$buffer = $this->writeOpen(false);
foreach($this->_children as $child)
{
$buffer .= $child->__toString();
}
$buffer .= $this->writeClose();
for ($i = 0; $i < count($this->_children); $i++)
{
$child = $this->_children[$i];
if ($child === $childNode)
{
unset($this->_children[$i]);
return true;
}
}
return false;
}
return $buffer;
}
}
/**
* Remove a child as a specific index
* @method removeChildAt
* @param {int} index The index to remove child at
* @return {NodeContainer} The instance of the node container
*/
public function removeChildAt($index)
{
if ($index >= $this->_children || $index < 0)
{
throw new HTML5Error(HTML5Error::OUT_OF_BOUNDS, $index);
}
array_splice($this->_children, $index, 1);
return $this;
}
/**
* Removes all children attached to this Node container
* @method removeChildren
* @return {NodeContainer} The instance of the node container
*/
public function removeChildren()
{
unset($this->_children);
$this->_children = array();
return $this;
}
/**
* Returns an array of all children attached to this Node container.
* @method getChildren
* @return {Array} The collection of Node objects
*/
public function getChildren()
{
return $this->_children;
}
/**
* Gets a child of this Node container at given
* index. If no index is passed in, getChild()
* will return the child at index zero (0).
* @method getChildAt
* @param {int} [index=0] The index to fetch child Node at
* @return {Node} The child Node
*/
public function getChildAt($index = 0)
{
return $this->_children[$index];
}
/**
* Close the writing of this container as HTML
* @method writeClose
* @protected
* @return {String} The closing HTML tag element
*/
protected function writeClose()
{
return "</" . $this->_tag . ">";
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
$buffer = $this->writeOpen(false);
foreach ($this->_children as $child)
{
$buffer .= $child->__toString();
}
$buffer .= $this->writeClose();
return $buffer;
}
}
}
?>

View File

@ -1,72 +1,70 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* Convenience class for creating an ordered or un-ordered list.
*
* $list = new Canteen\HTML5\SimpleList(
* array(
* html('b', 'first'),
* 'second',
* 'third',
* array(
* 'sub-third',
* 'sub-forth'
* )
* )
* );
*
* @class SimpleList
* @extends NodeContainer
* @constructor
* @param {Array} [elements=null] The array of child Nodes, Strings, etc.
* @param {String|Dictionary} [attributes=null] The optional attributes
* @param {String} [type='ul'] The type of list, either ul or ol
*/
class SimpleList extends NodeContainer
{
public function __construct($elements=null, $attributes=null, $type='ul')
{
parent::__construct($type, null, $attributes);
if ($elements != null)
{
assert(is_array($elements));
{
/**
* Convenience class for creating an ordered or un-ordered list.
*
* $list = new Canteen\HTML5\SimpleList(
* array(
* html('b', 'first'),
* 'second',
* 'third',
* array(
* 'sub-third',
* 'sub-forth'
* )
* )
* );
*
* @class SimpleList
* @extends NodeContainer
* @constructor
* @param {Array} [elements=null] The array of child Nodes, Strings, etc.
* @param {String|Dictionary} [attributes=null] The optional attributes
* @param {String} [type='ul'] The type of list, either ul or ol
*/
class SimpleList extends NodeContainer
{
public function __construct($elements=null, $attributes=null, $type='ul')
{
parent::__construct($type, null, $attributes);
foreach($elements as $child)
{
$this->addChild($child);
}
}
}
/**
* Override for the prepareChild method on NodeContainer which
* wraps each elements in a list item
* @method prepareChild
* @protected
* @param {Node|String|Number|Boolean|Array} childNode The child node to add, an array will get converted into another list elements.
* @return {Node} The child node
*/
protected function prepareChild($childNode)
{
// Recursively create new lists for each array
if (is_array($childNode))
{
$list = new SimpleList($childNode, null, $this->_tag);
return $this->prepareChild($list);
}
else
{
$childNode = parent::prepareChild($childNode);
return html('li', $childNode);
}
}
}
if ($elements != null)
{
assert(is_array($elements));
foreach ($elements as $child)
{
$this->addChild($child);
}
}
}
/**
* Override for the prepareChild method on NodeContainer which
* wraps each elements in a list item
* @method prepareChild
* @protected
* @param {Node|String|Number|Boolean|Array} childNode The child node to add, an array will get converted into another list elements.
* @return {Node} The child node
*/
protected function prepareChild($childNode)
{
// Recursively create new lists for each array
if (is_array($childNode))
{
$list = new SimpleList($childNode, null, $this->_tag);
return $this->prepareChild($list);
}
else
{
$childNode = parent::prepareChild($childNode);
return html('li', $childNode);
}
}
}
}
?>

View File

@ -1,413 +1,429 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* The HTML5 Specification
*
* @class Specification
* @constructor
*/
class Specification
{
/**
* The list of all tags and their specific attributes
* @property {array} TAGS
* @final
* @readOnly
* @static
*/
public static $TAGS = array(
'a' => array(
'href',
'hreflang',
'media',
'rel',
'target',
'type'
),
'abbr' => array(),
'address' => array(),
'area' => array(
'alt',
'coords',
'href',
'hreflang',
'media',
'rel',
'shape',
'target',
'type'
),
'article' => array(),
'aside' => array(),
'audio' => array(
'autoplay',
'controls',
'loop',
'muted',
'preload',
'src'
),
'b' => array(),
'base' => array(
'href',
'target'
),
'bdo' => array(),
'blockquote' => array('cite'),
'body' => array(),
'br' => array(),
'button' => array(
'autofocus',
'disabled',
'form',
'formaction',
'formenctype',
'formmethod',
'formnovalidate',
'formtarget',
'name',
'type',
'value'
),
'canvas' => array(
'height',
'width'
),
'caption' => array(),
'cite' => array(),
'code' => array(),
'col' => null,
'colgroup' => array('span'),
'command' => array(
'checked',
'disabled',
'icon',
'label',
'radiogroup',
'type'
),
'datalist' => array(),
'dd' => array(),
'del' => array(
'cite',
'datetime'
),
'dfn' => array(),
'div' => array(),
'dl' => array(),
'dt' => array(),
'em' => array(),
'embed' => array(
'height',
'src',
'type',
'width'
),
'fieldset' => array(
'disabled',
'form_id',
'text'
),
'figcaption' => array(),
'figure' => array(),
'footer' => array(),
'form' => array(
'accept',
'accept-charset',
'action',
'autocomplete',
'enctype',
'method',
'name',
'novalidate',
'target'
),
'h1' => array(),
'h2' => array(),
'h3' => array(),
'h4' => array(),
'h5' => array(),
'h6' => array(),
'head' => array(),
'header' => array(),
'hgroup' => array(),
'hr' => array(),
'html' => array('manifest'),
'img' => array(
'alt',
'crossorigin',
'height',
'src',
'usemap',
'width'
),
'i' => array(),
'iframe' => array(
'src',
'srcdoc',
'name',
'width',
'height'
),
'input' => array(
'accept',
'alt',
'autocomplete',
'autofocus',
'checked',
'disabled',
'form',
'formaction',
'formenctype',
'formmethod',
'formnovalidate',
'formtarget',
'height',
'list',
'max',
'maxlength',
'min',
'multiple',
'name',
'pattern',
'placeholder',
'readonly',
'required',
'size',
'src',
'step',
'type',
'value',
'width'
),
'keygen' => array(
'autofocus',
'challenge',
'disabled',
'form',
'keytype',
'name'
),
'label' => array(
'for',
'form'
),
'legend' => array(),
'li' => array(),
'link' => array(
'href',
'hreflang',
'media',
'rel',
'sizes',
'type'
),
'map' => array('name'),
'mark' => array(),
'menu' => array(),
'meta' => array(
'charset',
'content',
'http-equiv',
'name'
),
'meter' => array(
'form',
'heigh',
'low',
'max',
'min',
'optimum',
'value'
),
'nav' => array(),
'noscript' => array(),
'object' => array(
'data',
'form',
'height',
'name',
'type',
'usemap',
'width'
),
'ol' => array(
'reversed',
'start',
'type'
),
'optgroup' => array(
'disabled',
'label'
),
'option' => array(
'disabled',
'label',
'selected',
'value'
),
'output' => array(
'for',
'form',
'name'
),
'p' => array(),
'param' => array(
'name',
'value'
),
'pre' => array(),
'progress' => array(
'max',
'value'
),
'q' => array('cite'),
'rp' => array(),
'rt' => array(),
'ruby' => array(),
's' => array(),
'sample' => array(),
'script' => array(
'async',
'charset',
'defer',
'src',
'type'
),
'section' => array(),
'select' => array(
'autofocus',
'disabled',
'form',
'multiple',
'name',
'required',
'size'
),
'small' => array(),
'source' => array('media',
'src',
'type'
),
'span' => array(),
'strong' => array(),
'style' => array('media',
'scoped',
'type'
),
'sub' => array(),
'table' => array('border'),
'tbody' => array(),
'td' => array(
'colspan',
'headers',
'scope'
),
'textarea' => array(
'autofocus',
'cols',
'disabled',
'form',
'maxlength',
'name',
'placeholder',
'readonly',
'required',
'row',
'wrap'
),
'tfoot' => array(),
'th' => array(
'colspan',
'headers',
'rowspan',
'scope'
),
'thead' => array(),
'time' => array('datetime'),
'title' => array(),
'tr' => array(),
'track' => array(
'default',
'kind',
'label',
'src',
'srclang'
),
'u' => array(),
'ul' => array(),
'var' => array(),
'video' => array(
'autoplay',
'controls',
'height',
'loop',
'muted',
'poster',
'preload',
'src',
'width'
),
'wbr' => null
);
{
/**
* The HTML5 Specification
*
* @class Specification
* @constructor
*/
class Specification
{
/**
* The list of all tags and their specific attributes
* @property {array} TAGS
* @final
* @readOnly
* @static
*/
public static $TAGS = array(
'a' => array(
'href',
'hreflang',
'media',
'rel',
'target',
'type'
),
'abbr' => array(),
'address' => array(),
'area' => array(
'alt',
'coords',
'href',
'hreflang',
'media',
'rel',
'shape',
'target',
'type'
),
'article' => array(),
'aside' => array(),
'audio' => array(
'autoplay',
'controls',
'loop',
'muted',
'preload',
'src'
),
'b' => array(),
'base' => array(
'href',
'target'
),
'bdo' => array(),
'blockquote' => array(
'cite'
),
'body' => array(),
'br' => array(),
'button' => array(
'autofocus',
'disabled',
'form',
'formaction',
'formenctype',
'formmethod',
'formnovalidate',
'formtarget',
'name',
'type',
'value'
),
'canvas' => array(
'height',
'width'
),
'caption' => array(),
'cite' => array(),
'code' => array(),
'col' => null,
'colgroup' => array(
'span'
),
'command' => array(
'checked',
'disabled',
'icon',
'label',
'radiogroup',
'type'
),
'datalist' => array(),
'dd' => array(),
'del' => array(
'cite',
'datetime'
),
'dfn' => array(),
'div' => array(),
'dl' => array(),
'dt' => array(),
'em' => array(),
'embed' => array(
'height',
'src',
'type',
'width'
),
'fieldset' => array(
'disabled',
'form_id',
'text'
),
'figcaption' => array(),
'figure' => array(),
'footer' => array(),
'form' => array(
'accept',
'accept-charset',
'action',
'autocomplete',
'enctype',
'method',
'name',
'novalidate',
'target'
),
'h1' => array(),
'h2' => array(),
'h3' => array(),
'h4' => array(),
'h5' => array(),
'h6' => array(),
'head' => array(),
'header' => array(),
'hgroup' => array(),
'hr' => array(),
'html' => array(
'manifest'
),
'img' => array(
'alt',
'crossorigin',
'height',
'src',
'usemap',
'width'
),
'i' => array(),
'iframe' => array(
'src',
'srcdoc',
'name',
'width',
'height'
),
'input' => array(
'accept',
'alt',
'autocomplete',
'autofocus',
'checked',
'disabled',
'form',
'formaction',
'formenctype',
'formmethod',
'formnovalidate',
'formtarget',
'height',
'list',
'max',
'maxlength',
'min',
'multiple',
'name',
'pattern',
'placeholder',
'readonly',
'required',
'size',
'src',
'step',
'type',
'value',
'width'
),
'keygen' => array(
'autofocus',
'challenge',
'disabled',
'form',
'keytype',
'name'
),
'label' => array(
'for',
'form'
),
'legend' => array(),
'li' => array(),
'link' => array(
'href',
'hreflang',
'media',
'rel',
'sizes',
'type'
),
'map' => array(
'name'
),
'mark' => array(),
'menu' => array(),
'meta' => array(
'charset',
'content',
'http-equiv',
'name'
),
'meter' => array(
'form',
'heigh',
'low',
'max',
'min',
'optimum',
'value'
),
'nav' => array(),
'noscript' => array(),
'object' => array(
'data',
'form',
'height',
'name',
'type',
'usemap',
'width'
),
'ol' => array(
'reversed',
'start',
'type'
),
'optgroup' => array(
'disabled',
'label'
),
'option' => array(
'disabled',
'label',
'selected',
'value'
),
'output' => array(
'for',
'form',
'name'
),
'p' => array(),
'param' => array(
'name',
'value'
),
'pre' => array(),
'progress' => array(
'max',
'value'
),
'q' => array(
'cite'
),
'rp' => array(),
'rt' => array(),
'ruby' => array(),
's' => array(),
'sample' => array(),
'script' => array(
'async',
'charset',
'defer',
'src',
'type'
),
'section' => array(),
'select' => array(
'autofocus',
'disabled',
'form',
'multiple',
'name',
'required',
'size'
),
'small' => array(),
'source' => array(
'media',
'src',
'type'
),
'span' => array(),
'strong' => array(),
'style' => array(
'media',
'scoped',
'type'
),
'sub' => array(),
'table' => array(
'border'
),
'tbody' => array(),
'td' => array(
'colspan',
'headers',
'scope'
),
'textarea' => array(
'autofocus',
'cols',
'disabled',
'form',
'maxlength',
'name',
'placeholder',
'readonly',
'required',
'row',
'wrap'
),
'tfoot' => array(),
'th' => array(
'colspan',
'headers',
'rowspan',
'scope'
),
'thead' => array(),
'time' => array(
'datetime'
),
'title' => array(),
'tr' => array(),
'track' => array(
'default',
'kind',
'label',
'src',
'srclang'
),
'u' => array(),
'ul' => array(),
'var' => array(),
'video' => array(
'autoplay',
'controls',
'height',
'loop',
'muted',
'poster',
'preload',
'src',
'width'
),
'wbr' => null
);
/**
* The list of self-closing tags
* @property {array} SELF_CLOSING
* @final
* @readOnly
* @static
*/
public static $SELF_CLOSING = array(
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr'
);
/**
* The list of self-closing tags
* @property {array} SELF_CLOSING
* @final
* @readOnly
* @static
*/
public static $SELF_CLOSING = array(
'area',
'base',
'br',
'col',
'command',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'meta',
'param',
'source',
'track',
'wbr'
);
/**
* Global valid attributes for all HTML5 tags
* See: http://www.w3.org/TR/html5/dom.html#global-attributes
* @property {Array} ATTRIBUTES
* @final
* @static
* @readOnly
*/
public static $ATTRIBUTES = array(
/**
* Global valid attributes for all HTML5 tags
* See: http://www.w3.org/TR/html5/dom.html#global-attributes
* @property {Array} ATTRIBUTES
* @final
* @static
* @readOnly
*/
public static $ATTRIBUTES = array(
// Event handler context attributes
'onabort', 'onblur', 'oncancel', 'oncanplay', 'oncanplaythrough',
'onchange', 'onclick', 'oncuechange', 'ondblclick', 'ondurationchange',
'onemptied', 'onended', 'onerror', 'onfocus', 'oninput', 'oninvalid',
'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onloadeddata',
'onloadedmetadata', 'onloadstart', 'onmousedown', 'onmouseenter',
'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup',
'onmousewheel', 'onpause', 'onplay', 'onplaying', 'onprogress',
'onratechange', 'onreset', 'onresize', 'onscroll', 'onseeked',
'onseeking', 'onselect', 'onshow', 'onstalled', 'onsubmit', 'onsuspend',
'ontimeupdate', 'ontoggle', 'onvolumechange', 'onwaiting',
// Event handler context attributes
'onabort', 'onblur', 'oncancel', 'oncanplay', 'oncanplaythrough',
'onchange', 'onclick', 'oncuechange', 'ondblclick', 'ondurationchange',
'onemptied', 'onended', 'onerror', 'onfocus', 'oninput', 'oninvalid',
'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onloadeddata',
'onloadedmetadata', 'onloadstart', 'onmousedown', 'onmouseenter',
'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup',
'onmousewheel', 'onpause', 'onplay', 'onplaying', 'onprogress',
'onratechange', 'onreset', 'onresize', 'onscroll', 'onseeked',
'onseeking', 'onselect', 'onshow', 'onstalled', 'onsubmit', 'onsuspend',
'ontimeupdate', 'ontoggle', 'onvolumechange', 'onwaiting',
// Allow-able on all tags
'accesskey', 'class', 'contenteditable', 'contextmenu', 'dir', 'draggable',
'dropzone', 'hidden', 'id', 'lang', 'spellcheck', 'style', 'tabindex',
'title', 'translate'
);
}
}
// Allow-able on all tags
'accesskey', 'class', 'contenteditable', 'contextmenu', 'dir', 'draggable',
'dropzone', 'hidden', 'id', 'lang', 'spellcheck', 'style', 'tabindex',
'title', 'translate'
);
}
}

View File

@ -1,86 +1,87 @@
<?php
/**
* @module Canteen\HTML5
* @module Canteen\HTML5
*/
namespace Canteen\HTML5
{
/**
* Convenience class for building a Table. Useful for display
* rows of data from a database or another collection
* of associative arrays.
*
* $table = new Canteen\HTML5\Table(
* array(
* array('id'=>1, 'first'=>'James', 'last'=>'Smith'),
* array('id'=>2, 'first'=>'Mary', 'last'=>'Denver'),
* array('id'=>3, 'first'=>'Charlie', 'last'=>'Rose')
* ),
* array('ID', 'First Name', 'Last Name')
* );
*
* @class Table
* @extends NodeContainer
* @constructor
* @param {Array} data The collection of Dictionary objects
* @param {Array} [headers=null] An optional collection of header labels for each value
* @param {String} [checkbox=null] If we should add a checkbox to each row, this is the name
* of the attribute to use as a value. For instance `array('id'=>2)` is
* `<input type="checkbox" name="id[]" value="2">`
*/
class Table extends NodeContainer
{
public function __construct($data, $headers=null, $checkbox=null)
{
parent::__construct('table', null, null);
if ($headers != null && is_array($headers))
{
$head = html('thead');
$this->addChild($head);
$row = html('tr');
if ($checkbox != null)
{
$row->addChild(html('th', html('span', $checkbox)));
}
foreach($headers as $header)
{
$row->addChild(html('th', $header));
}
$head->addChild($row);
}
$body = html('tbody');
foreach($data as $d)
{
$row = html('tr');
if ($checkbox != null)
{
$td = html('td',
html(
'input',
'type=checkbox name='.$checkbox.'[] value='.$d[$checkbox]
),
'class='.$checkbox
);
$row->addChild($td);
}
foreach($d as $name=>$value)
{
if ($name == $checkbox) continue;
$td = html('td', $value, 'class='.$name);
$row->addChild($td);
}
$body->addChild($row);
}
$this->addChild($body);
}
}
}
{
/**
* Convenience class for building a Table. Useful for display
* rows of data from a database or another collection
* of associative arrays.
*
* $table = new Canteen\HTML5\Table(
* array(
* array('id'=>1, 'first'=>'James', 'last'=>'Smith'),
* array('id'=>2, 'first'=>'Mary', 'last'=>'Denver'),
* array('id'=>3, 'first'=>'Charlie', 'last'=>'Rose')
* ),
* array('ID', 'First Name', 'Last Name')
* );
*
* @class Table
* @extends NodeContainer
* @constructor
* @param {Array} data The collection of Dictionary objects
* @param {Array} [headers=null] An optional collection of header labels for each value
* @param {String} [checkbox=null] If we should add a checkbox to each row, this is the name
* of the attribute to use as a value. For instance `array('id'=>2)` is
* `<input type="checkbox" name="id[]" value="2">`
*/
class Table extends NodeContainer
{
public function __construct($data, $headers=null, $checkbox=null)
{
parent::__construct('table', null, null);
?>
if ($headers != null && is_array($headers))
{
$head = html('thead');
$this->addChild($head);
$row = html('tr');
if ($checkbox != null)
{
$row->addChild(html('th', html('span', $checkbox)));
}
foreach ($headers as $header)
{
$row->addChild(html('th', $header));
}
$head->addChild($row);
}
$body = html('tbody');
foreach ($data as $d)
{
$row = html('tr');
if ($checkbox != null)
{
$td = html('td',
html(
'input',
'type=checkbox name=' . $checkbox . '[] value='.$d[$checkbox]
),
'class=' . $checkbox
);
$row->addChild($td);
}
foreach ($d as $name=>$value)
{
if ($name == $checkbox)
{
continue;
}
$td = html('td', $value, 'class=' . $name);
$row->addChild($td);
}
$body->addChild($row);
}
$this->addChild($body);
}
}
}

View File

@ -5,35 +5,33 @@
*/
namespace Canteen\HTML5
{
/**
* Special Node representing plain text. Do not initiate this
* class directly, it is created whenever a text is passed into
* a container tag:
*
* echo html('p', 'Some Text Here');
*
* @class Text
* @extends Node
* @constructor
* @param {String} text the plain text string
*/
class Text extends Node
{
public function __construct($text)
{
parent::__construct($text);
}
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
return $this->_tag;
}
}
}
/**
* Special Node representing plain text. Do not initiate this
* class directly, it is created whenever a text is passed into
* a container tag:
*
* echo html('p', 'Some Text Here');
*
* @class Text
* @extends Node
* @constructor
* @param {String} text the plain text string
*/
class Text extends Node
{
public function __construct($text)
{
parent::__construct($text);
}
?>
/**
* Write to HTML
* @method __toString
* @return {String} The string representation of this HTML node
*/
public function __toString()
{
return $this->_tag;
}
}
}

View File

@ -1,25 +1,25 @@
<?php
<?php
/**
* @module global
*/
namespace
{
/**
* The global method which is an alias for Canteen\HTML5\html()
* to use this method globally call Canteen\HTML5\HTML5::useGlobal()
* @class html
* @constructor
* @param {String} tag The name of the tag as a string for example 'tr', 'table', can be followed
* by CSS selector, e.g. 'a#backButton' or 'a.button'
* @param {Dictionary|Node|String|Array} [childrenOrAttributes=null] If the tag is a NodeContainer, this can be an array
* of attributes, another html node or some text. If the tag is a single node, this can
* be an array or chain of attributes
* @param {Dictionary|String} [attributes=null] The attributes list for container tags (e.g., 'class:selected')
* @return {Node} Return the html node
*/
function html($tag, $childrenOrAttributes=null, $attributes=null)
{
return Canteen\HTML5\html($tag, $childrenOrAttributes, $attributes);
}
}
/**
* The global method which is an alias for Canteen\HTML5\html()
* to use this method globally call Canteen\HTML5\HTML5::useGlobal()
* @class html
* @constructor
* @param {String} tag The name of the tag as a string for example 'tr', 'table', can be followed
* by CSS selector, e.g. 'a#backButton' or 'a.button'
* @param {Dictionary|Node|String|Array} [childrenOrAttributes=null] If the tag is a NodeContainer, this can be an array
* of attributes, another html node or some text. If the tag is a single node, this can
* be an array or chain of attributes
* @param {Dictionary|String} [attributes=null] The attributes list for container tags (e.g., 'class:selected')
* @return {Node} Return the html node
*/
function html($tag, $childrenOrAttributes=null, $attributes=null)
{
return Canteen\HTML5\html($tag, $childrenOrAttributes, $attributes);
}
}