<?php
/**
 * File:        htmlElement.class.php
 *
 * This class (actually a layer) is respondable for drawing the HTML layer
 * It depends on you how you use it, just for internal objects or for your whole webapplication. 
 * 
 * @copyright 2006 Kees Schepers
 * @author Kees Schepers <kees@roosendaler.nl> 
 * @version 0.6.3
 */
define('_SYSTEM_ENCODING','utf-8');

interface htmlElementInterface {
      public function getHTML();
}

abstract class htmlDomSingleton {
	static $objInstance = null;

	public function Instantiate() {
		if (!self::$objInstance) {
			self::$objInstance = new DOMDocument('1.0',_SYSTEM_ENCODING);;
		}
		return self::$objInstance;
	}
}

abstract class htmlElement implements htmlElementInterface {	
	private $objDomDocument;
	protected $objNode;
	protected $allowedAttributes;
	/**
	 * Function which starts the domobject, assign's default attributes.
	 * A htmlEelement is an extension of domNode and appends hisself to the domdocument, so it can
	 * be displayed with the saveXML function of the domdocument object.
	 *
	 * @return void
	 */
	public function __Construct($p_sTagName,$p_sElementValue='') {		
	  /**
	  * Start the DOM document for creating HTML
	  **/                       
	  $this->objDomDocument = htmlDomSingleton::instantiate();
	  $this->objNode = $this->objDomDocument->createElement($p_sTagName,$p_sElementValue);
	  $this->allowedAttributes = array();
	  $this->allowedAttributes[]='id';	  
	}
	/**
	 * Function to set attributes like object properties
	 *
	 * @param string $p_sKey
	 * @param string $p_sValue
	 */
	public function __Set($p_sKey,$p_sValue) {
    if( in_array($p_sKey,$this->allowedAttributes) ) {
          $this->objNode->setAttribute($p_sKey,$p_sValue);
    } else {
          throw new exception('htmlElement::__Set -> attribute: '.$p_sKey.' not allowed in current HTML element!');
    }
	}
	/**
	 * Function to append an html element to another
	 *
	 * @param object $p_objHtmlElement
	 */
	public function appendChild($p_objHtmlElement) {
		$this->objNode->appendChild($p_objHtmlElement->getNode());
	}
	/**
	 * Function return the node object
	 */
	public function getNode() {
		if( is_a($this->objNode,'DOMElement')) {
			return $this->objNode;
		} else {
			throw new Exception('htmlElement::getNode() -> objNode was not a valid DOMElement object (not created yet?)');
		}
	}
	/**
	 * Retrieve the HTML of the element, and all childs
	 *
	 * @return string html of current object and childs
	 */
  public function getHTML() {  	
    return $this->objDomDocument->saveXML($this->objNode);
  }	     
}

final class XHTMLselect extends htmlElement {
	function __construct() {
		parent::__Construct('select');
		$this->allowedAttributes[] = 'multiple';
		$this->allowedAttributes[] = 'onchange';
		$this->allowedAttributes[] = 'ondblclick';		
	}
}
final class XHTMLOption extends htmlElement {
	function __construct($p_sName,$p_sValue='') {
		parent::__Construct('option',$p_sName);
		if(empty($p_sValue)) $p_sValue = $p_sName;
		$this->allowedAttributes[] = 'value';	
		$this->objNode->setAttribute('value',$p_sValue);
	}
}
final class XHTMLdiv extends htmlElement {
	function __construct($p_sValue='') {
		parent::__Construct('div',$p_sValue);
		$this->allowedAttributes[] = 'style';
		$this->allowedAttributes[] = 'title';
	}
}

/**
 * Maak een div, met daarin een select box.
 */
$div = new XHTMLdiv();
$div->style = 'border:1px solid black; width:200px;';

$selectBox = new XHTMLselect();
$selectBox->id = 'selectBox1';
$selectBox->onchange = 'alert(this.value);';

$selectBox->appendChild(new XHTMLOption('dit'));
$selectBox->appendChild(new XHTMLOption('script'));
$selectBox->appendChild(new XHTMLOption('is'));
$selectBox->appendChild(new XHTMLOption('met'));
$selectBox->appendChild(new XHTMLOption('dank'));
$selectBox->appendChild(new XHTMLOption('aan'));
$selectBox->appendChild(new XHTMLOption('kees'));
$selectBox->appendChild(new XHTMLOption('schepers'));

$div->appendChild($selectBox);
echo $div->getHTML();
?>
