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 <?php
include '../src/HTML5.php'; include '../src/HTML5.php';
use Canteen\HTML5\HTML5; use Canteen\HTML5\HTML5;
HTML5::autoload(); // Autoload the classes, helpful if using outside composer 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 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;
?> 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 <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* An HTML attribute used on the Node, this is used internally. * An HTML attribute used on the Node, this is used internally.
* Do not initiate this class directly, use the `html()` function * Do not initiate this class directly, use the `html()` function
* to create attributes on elements. * to create attributes on elements.
* *
* echo html('a', 'Link', 'class=button href="about.html"'); * echo html('a', 'Link', 'class=button href="about.html"');
* *
* echo html('a', 'Link') * echo html('a', 'Link')
* ->setAttribute('class', 'button') * ->setAttribute('class', 'button')
* ->setAttribute('href', 'about.html'); * ->setAttribute('href', 'about.html');
* *
* @class Attribute * @class Attribute
* @constructor * @constructor
* @param {String} [name=null] The name of the attribute * @param {String} [name=null] The name of the attribute
* @param {String} [value=null] The value of the attribute * @param {String} [value=null] The value of the attribute
*/ */
class Attribute class Attribute
{ {
/** /**
* The name of the attribute * The name of the attribute
* @property {String} _name * @property {String} _name
* @private * @private
*/ */
private $_name; private $_name;
/**
* The value of the attribute
* @property {String} _value
* @private
*/
private $_value;
public function __construct($name = null, $value = null) /**
{ * The value of the attribute
$this->name = $name; * @property {String} _value
$this->value = $value; * @private
} */
private $_value;
/** public function __construct($name = null, $value = null)
* Convert the attribute to an HTML tag attribute string {
* @method __toString $this->name = $name;
* @return {String} String representation of attribute $this->value = $value;
*/ }
public function __toString()
{
return " " . $this->_name . "=\"" . $this->_value . "\"";
}
/** /**
* Get the name of this attribute * Convert the attribute to an HTML tag attribute string
* @method getName * @method __toString
* @return {String} The attribute's name * @return {String} String representation of attribute
*/ */
public function getName() public function __toString()
{ {
return $this->_name; return " " . $this->_name . "=\"" . $this->_value . "\"";
} }
/** /**
* Set the name of this attribute, cannot be empty * Get the name of this attribute
* @method setName * @method getName
* @param {String} [name=null] The name of the attribute * @return {String} The attribute's name
*/ */
public function setName($name = null) public function getName()
{ {
if (is_null($name) || empty($name)) return $this->_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;
}
/** /**
* Set the value of this attribute, this cannot be empty * Set the name of this attribute, cannot be empty
* @method setValue * @method setName
* @protected * @param {String} [name=null] The name of the attribute
* @param {String} value The value to set */
*/ public function setName($name = null)
protected function setValue($value) {
{ if (is_null($name) || empty($name))
$this->_value = $value; {
} throw new HTML5Error(HTML5Error::EMPTY_ATTRIBUTE_NAME);
}
/** $this->_name = $name;
* 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 * Get the value of this attribute
* @public __set * @method getValue
* @param {String} name The name of the attribute * @protected
* @param {String} value The value of the attribute * @return {String} The value of attribute
*/ */
public function __set($name, $value) protected function getValue()
{ {
if (method_exists($this , $method =('set' . ucfirst($name)))) return $this->_value;
return $this->$method($value); }
else
throw new HTML5Error(HTML5Error::INVALID_SETTER, $name);
}
/** /**
* See if a property exists * Set the value of this attribute, this cannot be empty
* @method __isset * @method setValue
* @param {String} name The name of the property * @protected
*/ * @param {String} value The value to set
public function __isset($name) */
{ protected function setValue($value)
return method_exists($this , 'get' . ucfirst($name)) {
|| method_exists($this , 'set' . ucfirst($name)); $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 <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* Special node type representing an HTML5 inline comment. * Special node type representing an HTML5 inline comment.
* Do not initiate this class directly, use the `html('comment')` function: * Do not initiate this class directly, use the `html('comment')` function:
* *
* echo html('comment', 'Hidden HTML comment here'); * echo html('comment', 'Hidden HTML comment here');
* *
* @class Comment * @class Comment
* @extends NodeContainer * @extends NodeContainer
* @constructor * @constructor
* @param {String} text the plain text string * @param {String} text the plain text string
*/ */
class Comment extends NodeContainer class Comment extends NodeContainer
{ {
public function __construct($text) public function __construct($text)
{ {
parent::__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.' -->';
}
}
}
?> /**
* 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 <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* Create an HTML document. Basic barebones structure. * Create an HTML document. Basic barebones structure.
* Located in the namespace __Canteen\HTML5__. * Located in the namespace __Canteen\HTML5__.
* *
* $doc = new HTML5\Document('Untitled'); * $doc = new HTML5\Document('Untitled');
* $doc->head->addChild(html('script src=main.js')); * $doc->head->addChild(html('script src=main.js'));
* $doc->body->addChild(html('div#frame')); * $doc->body->addChild(html('div#frame'));
* echo $doc; * echo $doc;
* *
* @class Document * @class Document
* @extends NodeContainer * @extends NodeContainer
* @constructor * @constructor
* @param {String} [title=''] The title of the document * @param {String} [title=''] The title of the document
* @param {String} [charset='utf-8'] The character encoding set of this HTML 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. * @param {Boolean} [beautify=false] If we should add whitespace to the output to make it look nice markup.
*/ */
class Document extends NodeContainer class Document extends NodeContainer
{ {
/** /**
* The document type * The document type
* @property {NodeContainer} docType * @property {NodeContainer} docType
*/ */
private $docType; private $docType;
/** /**
* The head node * The head node
* @property {NodeContainer} head * @property {NodeContainer} head
*/ */
public $head; public $head;
/** /**
* The body node * The body node
* @property {NodeContainer} body * @property {NodeContainer} body
*/ */
public $body; public $body;
/** /**
* The title node * The title node
* @property {NodeContainer} title * @property {NodeContainer} title
*/ */
public $title; public $title;
/** /**
* Beautify the output * Beautify the output
* @property {Boolean} beautify * @property {Boolean} beautify
*/ */
public $beautify = false; public $beautify = false;
/** /**
* Constructor for Docs * Constructor for Docs
*/ */
public function __construct($title='', $charset='utf-8', $beautify=false) public function __construct($title='', $charset='utf-8', $beautify=false)
{ {
parent::__construct('html', null, null, parent::__construct('html', null, null,
array_merge( array_merge(
array('manifest'), array('manifest'),
Specification::$ATTRIBUTES Specification::$ATTRIBUTES
) )
); );
$this->docType = html('doctype'); $this->docType = html('doctype');
$this->head = html('head'); $this->head = html('head');
$this->body = html('body'); $this->body = html('body');
$this->title = html('title', $title); $this->title = html('title', $title);
$this->head->addChild(html('meta', 'charset='.$charset)); $this->head->addChild(html('meta', 'charset=' . $charset));
$this->head->addChild($this->title); $this->head->addChild($this->title);
$this->addChild($this->head); $this->addChild($this->head);
$this->addChild($this->body); $this->addChild($this->body);
} }
/** /**
* Write to HTML * Write to HTML
* @method __toString * @method __toString
* @return {String} The string representation of this HTML node * @return {String} The string representation of this HTML node
*/ */
public function __toString() public function __toString()
{ {
$result = $this->docType . parent::__toString(); $result = $this->docType . parent::__toString();
if ($this->beautify) if ($this->beautify)
$result = self::beautify($result); {
return $result; $result = self::beautify($result);
} }
return $result;
/** }
* Beautifies an HTML string into a human-readable and indented work of art.
* @method beautify /**
* @static * Beautifies an HTML string into a human-readable and indented work of art.
* @param {String} html The XML-compatible HTML as a string * @method beautify
* @return {String} The formatted string * @static
*/ * @param {String} html The XML-compatible HTML as a string
public static function beautify($html) * @return {String} The formatted string
{ */
// Conver the HTML -> SimpleXML -> DOMDocument public static function beautify($html)
$dom = dom_import_simplexml(new \SimpleXMLElement($html))->ownerDocument; {
// Conver the HTML -> SimpleXML -> DOMDocument
// Format the DOMDocument $dom = dom_import_simplexml(new \SimpleXMLElement($html))->ownerDocument;
$dom->formatOutput = true;
// Format the DOMDocument
// Save the output as XML $dom->formatOutput = true;
$buffer = $dom->saveXML();
// Save the output as XML
// Remove the first line which has the XML declaration $buffer = $dom->saveXML();
return substr($buffer, strpos($buffer, "\n")+1);
} // 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 namespace Canteen\HTML5
{ {
/** /**
* Represents a set of HTML tags without a wrapper. * Represents a set of HTML tags without a wrapper.
* Do not initiate this class directly, use the `html()` function: * Do not initiate this class directly, use the `html()` function:
* *
* $div = html('fragment'); * $div = html('fragment');
* *
* @class Fragment * @class Fragment
* @extends NodeContainer * @extends NodeContainer
* @constructor * @constructor
* @param {Node|Array} [children=null] The collection of children or single child * @param {Node|Array} [children=null] The collection of children or single child
*/ */
class Fragment extends NodeContainer class Fragment extends NodeContainer
{ {
public function __construct($children = null) public function __construct($children = null)
{ {
parent::__construct('fragment', $children, null); parent::__construct('fragment', $children, null);
} }
/** /**
* Write to HTML * Write to HTML
* @method __toString * @method __toString
* @return {String} The string representation of this HTML node * @return {String} The string representation of this HTML node
*/ */
public function __toString() public function __toString()
{ {
$buffer = ''; $buffer = '';
foreach($this->getChildren() as $child) foreach ($this->getChildren() as $child)
{ {
$buffer .= $child->__toString(); $buffer .= $child->__toString();
} }
return $buffer; return $buffer;
} }
} }
} }
?>

View File

@ -1,170 +1,175 @@
<?php <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* Main class of the library * Main class of the library
* @class HTML5 * @class HTML5
*/ */
class HTML5 class HTML5
{ {
/** /**
* Turn on autoloading for the library * Turn on autoloading for the library
* @method autoload * @method autoload
* @static * @static
*/ */
static public function autoload() static public function autoload()
{ {
spl_autoload_register(function($name) spl_autoload_register(function($name)
{ {
// Ignore class names not in the HTML5 namespace // Ignore class names not in the HTML5 namespace
if (!preg_match('/^Canteen\\\HTML5\\\/', $name)) return; if (!preg_match('/^Canteen\\\HTML5\\\/', $name))
{
// Remove the HTML5 namespace return;
$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';
});
}
/** // Remove the HTML5 namespace
* Use the global `html()` method $name = preg_replace('/^Canteen\\\HTML5\\\/', '', $name);
* @method {Boolean} useGlobal
*/
static public function useGlobal()
{
include __DIR__.'/html.php';
}
}
/** // Convert the rest to directories
* This is the global function is the main entry for interacting with the HTML5 for PHP library. $name = str_replace("\\", '/', $name);
* 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 // Include the class relative to here
if ($tag == 'comment') include __DIR__ . '/' . $name . '.php';
{ });
return new Comment($childrenOrAttributes); }
}
// Document type declaration /**
else if ($tag == 'doctype') * Use the global `html()` method
{ * @method {Boolean} useGlobal
return '<!DOCTYPE html>'; */
} static public function useGlobal()
// Any normal text {
else if ($tag == 'text') include __DIR__ . '/html.php';
{ }
return new Text($childrenOrAttributes); }
}
// Untagged container /**
else if ($tag == 'fragment') * 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
return new Fragment($childrenOrAttributes); * examples and instruction on how to use this library, please refer to the the
} * <a href="https://github.com/Canteen/CanteenHTML5">GitHub project</a>.
// Check for task specification * To install the library simply include `html.php`, this takes care of any autoloading that's needed
else if (isset(Specification::$TAGS[$tag])) * for the rest of the library.
{ *
// Check to see if this is a self closing tag * echo html('img src=home.jpg');
$selfClosing = in_array($tag, Specification::$SELF_CLOSING); * echo html('img', 'src=home.jpg');
} * echo html('a', array('href'=>'about.html'));
else *
{ *
throw new HTML5Error(HTML5Error::INVALID_TAG, $tag); *
} * @method html
* @param {String} tag The name of the tag as a string for example 'tr', 'table', can be followed
// Create the attributes collection, either string or array * by CSS selector, e.g. 'a#backButton' or 'a.button'
$attributes = $selfClosing ? $childrenOrAttributes : $attributes; * @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
// If there are attributes and they are in a string format * be an array or chain of attributes
// convert to an attributes array * @param {Dictionary|String} [attributes=null] The attributes list for container tags (e.g., 'class:selected')
if ($attributes !== null && is_string($attributes)) * @return {Node} Return the html node
{ */
$attributes = Attribute::shorthand($attributes); function html($tag, $childrenOrAttributes=null, $attributes=null)
} {
// Get the tag ID from the tag string
// Combine the attributes and the tags // for instance 'a.button rel=external', a.button is the tagId, the rest are the attributes
if (is_array($attributes)) $endPos = strpos(trim($tag), ' ');
{
$attributes = array_merge($tagAttributes, $attributes); // The tag attributes
} $tagAttributes = array();
// Or just add any tag attributes
else if (count($tagAttributes)) // If the tag also has some attributes
{ if ($endPos !== false)
$attributes = $tagAttributes; {
} $tagOriginal = $tag;
$tag = substr($tag, 0, $endPos);
// Create the node or container $tagAttributes = Attribute::shorthand(substr($tagOriginal, $endPos + 1));
$node = $selfClosing ? }
new Node($tag, $attributes) :
new NodeContainer($tag, $childrenOrAttributes, $attributes); // Match the tag name without the CSS selectors
preg_match('/^([a-z1-6]{1,10})(.*)/', $tag, $tagParts);
// Take the selectors convert them into id or class
foreach($selectors[0] as $selector) // 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);
switch($selector[0])
{ $tag = strtolower($tagParts[1]); // the name of the tag
case '#' : $selfClosing = false;
$node->id = substr($selector, 1);
break; // Comment tags are special
case '.' : if ($tag == 'comment')
if ($node->class) $node->class .= ' '; {
$node->class .= substr($selector, 1); return new Comment($childrenOrAttributes);
break; }
} // Document type declaration
} else if ($tag == 'doctype')
return $node; {
} 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 <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* Exceptions with using the HTML5 API. * Exceptions with using the HTML5 API.
* *
* try * try
* { * {
* html('invalid', 'something'); * html('invalid', 'something');
* } * }
* catch(Canteen\HTML5\HTML5Error $e) * catch(Canteen\HTML5\HTML5Error $e)
* { * {
* $e->getMessage(); * $e->getMessage();
* } * }
* *
* @class HTML5Error * @class HTML5Error
* @extends Exception * @extends Exception
* @constructor * @constructor
* @param {int} code The code of the error * @param {int} code The code of the error
* @param {String} [data=''] Additional data to associate with this error * @param {String} [data=''] Additional data to associate with this error
*/ */
class HTML5Error extends \Exception class HTML5Error extends \Exception
{ {
/** /**
* The database connection failed * The database connection failed
* @property {int} EMPTY_ATTRIBUTE_NAME * @property {int} EMPTY_ATTRIBUTE_NAME
* @static * @static
* @final * @final
*/ */
const EMPTY_ATTRIBUTE_NAME = 500; 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);
}
}
}
?> /**
* 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 <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* A generic html tag with any children or closing tag. (e.g., img, br, hr). * 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: * Do not initiate this class directly, use the `html()` function:
* *
* echo html('br'); * echo html('br');
* *
* @class Node * @class Node
* @extends Proto * @extends Proto
* @constructor * @constructor
* @param {String} [tag=null] The name of the tag * @param {String} [tag=null] The name of the tag
* @param {Array|String} [attributes=null] The collection of tag attributes * @param {Array|String} [attributes=null] The collection of tag attributes
*/ */
class Node extends Proto class Node extends Proto
{ {
/** /**
* The string name of the tag * The string name of the tag
* @property {String} _tag * @property {String} _tag
* @protected * @protected
*/ */
protected $_tag; 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();
if (isset(Specification::$TAGS[$tag])) /**
{ * The collection of Attributes objects
$this->_validAttrs = array_merge( * @property {Array} _attributes
Specification::$TAGS[$tag], * @protected
Specification::$ATTRIBUTES */
); protected $_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)) /**
{ * The parent node, if any
throw new HTML5Error(HTML5Error::EMPTY_ATTRIBUTE_NAME); * @property {NodeContainer} _parent
} * @protected
foreach($this->_attributes as $attribute) */
{ protected $_parent;
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 * The collection of valid attributes names for given tag
* @method __set * @property {Array} _validAttrs
* @param {String} name The name of the attribute * @protected
* @param {String} value The value of the attribute */
*/ protected $_validAttrs;
public function __set($name, $value)
{
if (in_array($name, $this->_validAttrs) || strpos($name, 'data-') === 0)
{
return $this->setAttribute($name, $value);
}
}
/** public function __construct($tag = null, $attributes = null)
* See if a property exists {
* @method __isset if ($this->isEmpty($tag))
* @param {String} name The name of the attribute {
*/ throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG);
public function __isset($name) }
{ $this->_parent = null;
return in_array($name, $this->_validAttrs) || parent::__isset($name); $this->_tag = $tag;
} $this->_attributes = array();
/** if (isset(Specification::$TAGS[$tag]))
* 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 $this->_validAttrs = array_merge(
* previously using empty() to see if a variable is empty or not. But Specification::$TAGS[$tag],
* empty() dosen't work for attributes that have a value of "0", so we need Specification::$ATTRIBUTES
* something more robust here. );
* <ul> }
* <li>an unset variable -> empty</li> else
* <li>null -> empty</li> {
* <li>0 -> NOT empty</li> $this->_validAttrs = array();
* <li>"0" -> NOT empty</li> }
* <li>false -> empty</li>
* <li>true -> NOT empty</li> if ($attributes !== null)
* <li>'string value' -> NOT empty</li> {
* <li>" "(white space) -> empty</li> if (is_string($attributes))
* <li>array()(empty array) -> empty</li> {
* </ul> $attributes = Attribute::shorthand($attributes);
* @method isEmpty }
* @protected
* @param {mixed} var The variable to check for empty on if (is_array($attributes))
*/ {
protected function isEmpty($var) $this->setAttributes($attributes);
{ }
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))); /**
} * 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 <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* Represents an HTML that that can contain other tags (e.g., br, p, div). * Represents an HTML that that can contain other tags (e.g., br, p, div).
* Do not initiate this class directly, use the `html()` function: * Do not initiate this class directly, use the `html()` function:
* *
* $div = html('div'); * $div = html('div');
* *
* @class NodeContainer * @class NodeContainer
* @extends Node * @extends Node
* @constructor * @constructor
* @param {String} [tag=null] The name of the tag element * @param {String} [tag=null] The name of the tag element
* @param {Node|Array} [children=null] The collection of children or single child * @param {Node|Array} [children=null] The collection of children or single child
* @param {String|Dictionary} [attributes=null] The tag attributes * @param {String|Dictionary} [attributes=null] The tag attributes
*/ */
class NodeContainer extends Node class NodeContainer extends Node
{ {
/** /**
* The collection of children nodes * The collection of children nodes
* @property {Array} _children * @property {Array} _children
* @private * @private
*/ */
private $_children; private $_children;
public function __construct($tag = null, $children = null, $attributes = null) public function __construct($tag = null, $children = null, $attributes = null)
{ {
if ($this->isEmpty($tag)) if ($this->isEmpty($tag))
{ {
throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG); throw new HTML5Error(HTML5Error::EMPTY_NODE_TAG);
} }
parent::__construct($tag, $attributes); 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);
}
}
}
}
/** $this->_children = array();
* 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;
}
/** if (!$this->isEmpty($children))
* Removes the first instance of child from this. {
* Once the first instance of the child if (!is_array($children))
* is removed, this function will return. It returns {
* true if a child was removed and false if no child $children = array($children);
* was removed. }
* @method removeChild if (is_array($children))
* @param {Node} [childNode=null] The node to remove {
* @return {Boolean} If successfully removed foreach ($children as $child)
*/ {
public function removeChild(Node $childNode = null) $this->addChild($child);
{ }
if ($this->isEmpty($childNode)) }
{ }
throw new HTML5Error(HTML5Error::EMPTY_CHILD); }
}
for($i = 0; $i < count($this->_children); $i++) /**
{ * Add's a child to this NodeContainer. The child to add cannot be null.
$child = $this->_children[$i]; * @method addChild
if ($child === $childNode) * @param {Node|String|Number|Boolean} childNode The child Node to add
{ * @return {NodeContainer} The instance of this container
unset($this->_children[$i]); */
return true; public function addChild($childNode)
} {
} array_push($this->_children, $this->prepareChild($childNode));
return false; return $this;
} }
/**
* 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 * Add a child at a specific index
* @method removeChildren * @method addChildAt
* @return {NodeContainer} The instance of the node container * @param {Node|String|Number|Boolean} childNode The child Node to add
*/ * @param {int} index The index to add child at, 0 is top
public function removeChildren() * @return {NodeContainer} The instance of this container
{ */
unset($this->_children); public function addChildAt($childNode, $index)
$this->_children = array(); {
return $this; 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. * Before adding a child, we should do some checking for basic types
* @method getChildren * and convert it into a more useable Node object.
* @return {Array} The collection of Node objects * @method prepareChild
*/ * @protected
public function getChildren() * @param {Node|String|Number|Boolean} childNode The child node to add
{ * @return {Node} The child node
return $this->_children; */
} 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 * Removes the first instance of child from this.
* index. If no index is passed in, getChild() * Once the first instance of the child
* will return the child at index zero (0). * is removed, this function will return. It returns
* @method getChildAt * true if a child was removed and false if no child
* @param {int} [index=0] The index to fetch child Node at * was removed.
* @return {Node} The child Node * @method removeChild
*/ * @param {Node} [childNode=null] The node to remove
public function getChildAt($index = 0) * @return {Boolean} If successfully removed
{ */
return $this->_children[$index]; public function removeChild(Node $childNode = null)
} {
if ($this->isEmpty($childNode))
/** {
* Close the writing of this container as HTML throw new HTML5Error(HTML5Error::EMPTY_CHILD);
* @method writeClose }
* @protected
* @return {String} The closing HTML tag element
*/
protected function writeClose()
{
return "</" . $this->_tag . ">";
}
/** for ($i = 0; $i < count($this->_children); $i++)
* Write to HTML {
* @method __toString $child = $this->_children[$i];
* @return {String} The string representation of this HTML node if ($child === $childNode)
*/ {
public function __toString() unset($this->_children[$i]);
{ return true;
$buffer = $this->writeOpen(false); }
foreach($this->_children as $child) }
{ return false;
$buffer .= $child->__toString(); }
}
$buffer .= $this->writeClose();
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 <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* Convenience class for creating an ordered or un-ordered list. * Convenience class for creating an ordered or un-ordered list.
* *
* $list = new Canteen\HTML5\SimpleList( * $list = new Canteen\HTML5\SimpleList(
* array( * array(
* html('b', 'first'), * html('b', 'first'),
* 'second', * 'second',
* 'third', * 'third',
* array( * array(
* 'sub-third', * 'sub-third',
* 'sub-forth' * 'sub-forth'
* ) * )
* ) * )
* ); * );
* *
* @class SimpleList * @class SimpleList
* @extends NodeContainer * @extends NodeContainer
* @constructor * @constructor
* @param {Array} [elements=null] The array of child Nodes, Strings, etc. * @param {Array} [elements=null] The array of child Nodes, Strings, etc.
* @param {String|Dictionary} [attributes=null] The optional attributes * @param {String|Dictionary} [attributes=null] The optional attributes
* @param {String} [type='ul'] The type of list, either ul or ol * @param {String} [type='ul'] The type of list, either ul or ol
*/ */
class SimpleList extends NodeContainer class SimpleList extends NodeContainer
{ {
public function __construct($elements=null, $attributes=null, $type='ul') public function __construct($elements=null, $attributes=null, $type='ul')
{ {
parent::__construct($type, null, $attributes); parent::__construct($type, null, $attributes);
if ($elements != null)
{
assert(is_array($elements));
foreach($elements as $child) if ($elements != null)
{ {
$this->addChild($child); 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. * Override for the prepareChild method on NodeContainer which
* @return {Node} The child node * wraps each elements in a list item
*/ * @method prepareChild
protected function prepareChild($childNode) * @protected
{ * @param {Node|String|Number|Boolean|Array} childNode The child node to add, an array will get converted into another list elements.
// Recursively create new lists for each array * @return {Node} The child node
if (is_array($childNode)) */
{ protected function prepareChild($childNode)
$list = new SimpleList($childNode, null, $this->_tag); {
return $this->prepareChild($list); // Recursively create new lists for each array
} if (is_array($childNode))
else {
{ $list = new SimpleList($childNode, null, $this->_tag);
$childNode = parent::prepareChild($childNode); return $this->prepareChild($list);
return html('li', $childNode); }
} else
} {
} $childNode = parent::prepareChild($childNode);
return html('li', $childNode);
}
}
}
} }
?>

View File

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

View File

@ -1,86 +1,87 @@
<?php <?php
/** /**
* @module Canteen\HTML5 * @module Canteen\HTML5
*/ */
namespace Canteen\HTML5 namespace Canteen\HTML5
{ {
/** /**
* Convenience class for building a Table. Useful for display * Convenience class for building a Table. Useful for display
* rows of data from a database or another collection * rows of data from a database or another collection
* of associative arrays. * of associative arrays.
* *
* $table = new Canteen\HTML5\Table( * $table = new Canteen\HTML5\Table(
* array( * array(
* array('id'=>1, 'first'=>'James', 'last'=>'Smith'), * array('id'=>1, 'first'=>'James', 'last'=>'Smith'),
* array('id'=>2, 'first'=>'Mary', 'last'=>'Denver'), * array('id'=>2, 'first'=>'Mary', 'last'=>'Denver'),
* array('id'=>3, 'first'=>'Charlie', 'last'=>'Rose') * array('id'=>3, 'first'=>'Charlie', 'last'=>'Rose')
* ), * ),
* array('ID', 'First Name', 'Last Name') * array('ID', 'First Name', 'Last Name')
* ); * );
* *
* @class Table * @class Table
* @extends NodeContainer * @extends NodeContainer
* @constructor * @constructor
* @param {Array} data The collection of Dictionary objects * @param {Array} data The collection of Dictionary objects
* @param {Array} [headers=null] An optional collection of header labels for each value * @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 * @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 * of the attribute to use as a value. For instance `array('id'=>2)` is
* `<input type="checkbox" name="id[]" value="2">` * `<input type="checkbox" name="id[]" value="2">`
*/ */
class Table extends NodeContainer class Table extends NodeContainer
{ {
public function __construct($data, $headers=null, $checkbox=null) public function __construct($data, $headers=null, $checkbox=null)
{ {
parent::__construct('table', null, 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);
}
}
}
?> 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 namespace Canteen\HTML5
{ {
/** /**
* Special Node representing plain text. Do not initiate this * Special Node representing plain text. Do not initiate this
* class directly, it is created whenever a text is passed into * class directly, it is created whenever a text is passed into
* a container tag: * a container tag:
* *
* echo html('p', 'Some Text Here'); * echo html('p', 'Some Text Here');
* *
* @class Text * @class Text
* @extends Node * @extends Node
* @constructor * @constructor
* @param {String} text the plain text string * @param {String} text the plain text string
*/ */
class Text extends Node class Text extends Node
{ {
public function __construct($text) public function __construct($text)
{ {
parent::__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;
}
}
}
?> /**
* 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 * @module global
*/ */
namespace namespace
{ {
/** /**
* The global method which is an alias for Canteen\HTML5\html() * The global method which is an alias for Canteen\HTML5\html()
* to use this method globally call Canteen\HTML5\HTML5::useGlobal() * to use this method globally call Canteen\HTML5\HTML5::useGlobal()
* @class html * @class html
* @constructor * @constructor
* @param {String} tag The name of the tag as a string for example 'tr', 'table', can be followed * @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' * 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 * @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 * of attributes, another html node or some text. If the tag is a single node, this can
* be an array or chain of attributes * be an array or chain of attributes
* @param {Dictionary|String} [attributes=null] The attributes list for container tags (e.g., 'class:selected') * @param {Dictionary|String} [attributes=null] The attributes list for container tags (e.g., 'class:selected')
* @return {Node} Return the html node * @return {Node} Return the html node
*/ */
function html($tag, $childrenOrAttributes=null, $attributes=null) function html($tag, $childrenOrAttributes=null, $attributes=null)
{ {
return Canteen\HTML5\html($tag, $childrenOrAttributes, $attributes); return Canteen\HTML5\html($tag, $childrenOrAttributes, $attributes);
} }
} }