Ticket #18 (assigned enhancement)

Opened 5 years ago

Last modified 4 years ago

Build HTML wrappers

Reported by: VexedPanda Owned by: somebody
Priority: important Milestone: 1.2
Component: QForms Version:
Keywords: Cc:

Description

It would be nice to have PHP-based OO wrappers for common HTML elements. These would be very simple QHtml based controls with no events, and would basically be a way to represent and control rendering of HTML elements.

eg:
$li = new QHtmlList($this->pnlSummary);
$li->Tag = ‘ul’;
$li->Name = QApplication::Translate(‘A ul list’);
$item1 = $li->AddItem?(‘Some Text’);
$item2 = $li->AddItem?(‘Some other text’);
$li->RemoveItem?($item1);

Attachments

QHtml.class.php Download (1.0 KB) - added by VexedPanda 4 years ago.
Bad QHtml class. Too much overhead.

Change History

Changed 5 years ago by fcool

Are you sure about this? Won't this mean, Code and Output will get totally mixed up?
You can achieve this kind of things with a QDataRepeater, can't you?

Changed 5 years ago by alex94040

I'm also not sure about the benefit of this. Indeed, the controller/view separation would get really mixed up if we were to do this. QControls are meant to encapsulate much more than HTML markup. Kristof, I'm imagining you have a particular scenario in mind - can you share it?

Changed 5 years ago by VexedPanda

  • reporter changed from kmeirlaen to VexedPanda

I believe this was originally my ticket.
The reason I want this is because I do a lot of server-side manipulation of the output, and need to be able to affect things that are otherwise only text in a template.

eg: the unordered list shown. There's no client-side functionality there, but being able to dynamically remove items after it has been rendered in the past was useful. Rather than just looping through an array as part of my template, it made sense to make a QHtmlList class that took care of it for me. The only real overhead was the extra class creation.

Another example is the QModule Framework, which queues up rendering of controls and allows modules to intercept them. It's just as beneficial to allow modules to intercept and change plain HTML elements as it is QControls. Thankfully, the QHtml control largely accomplished this, I'm just suggesting we expand on it to make it easier to create each kind of HTML element.

Changed 4 years ago by basilieus

I say no to this.

You can simply make a custom control defined for your business logic, just extend QListControl.

Changed 4 years ago by VexedPanda

This really isn't about business logic...? It's a way to more easily control non-interactive elements of the page.

Changed 4 years ago by basilieus

I understand what you are saying.

I know you already know the following points, but I will put it out here because this is just what I was thinking: If part of the code is dynamic and you want to control it, just create a simple control that allows you to do that. If its static, hand code it into the document.

I would actually be more interested in what you were thinking by creating some sample code (class file), maybe I'll understand a bit better. To me it sounds like QHtmlList would be a custom control which can be extended upon to create different controllable html elements on a page?

Changed 4 years ago by VexedPanda

I don't really envision extending these, just creating QControls that generate standard HTML elements, without action, etc support.

Ok, here's an example class, though the implementation is overboard, since it extends QListControl instead of just QHtml:

<?php
	// This class will render an HTML DropDown or MultiSelect box <SELECT>.
	// It extends ListControl, which has methods to handle the ListItem array.
	// * "Rows" specifies how many rows you want to have shown.
// * "SelectionMode" specifies if this is a "Single" or "Multiple" select control.
//   Typically, for a standard dropdown, you will want "Rows" set to 1 and "SelectionMode" set to
//   SelectionMode::Single (which is the default setting).

class QHtmlList extends QListControl {
	///////////////////////////
	// Private Member Variables
	///////////////////////////
	protected $strTag = 'ul';
	protected $blnHtmlEntities = true;

	//////////
	// Methods
	//////////
	public function ParsePostData() {}
	public function Validate() {}

	protected function GetItemHtml($objItem, $intIndex) {
		$strToReturn = sprintf('<li>%s</li>',
				($this->blnHtmlEntities) ? QApplication::HtmlEntities($objItem->Name) : $objItem->Name
				);
		
		return $strToReturn;
	}
	
	protected function GetControlHtml() {
		$strStyle = $this->GetStyleAttributes();
		if ($strStyle)
			$strStyle = sprintf('style="%s"', $strStyle);
		
		$strToReturn = sprintf('<%s name="%s" id="%s" %s%s>', 
				$this->strTag,
				$this->strControlId,
				$this->strControlId,
				$this->GetAttributes(),
				$strStyle);
		
		$strCurrentGroup = null;
		if (is_array($this->objItemsArray)) {
			for ($intIndex = 0; $intIndex < $this->ItemCount; $intIndex++) {
				$objItem = $this->objItemsArray[$intIndex];

				$strToReturn .= $this->GetItemHtml($objItem, $intIndex);
			}
		}
		$strToReturn .= '</'.$this->strTag.'>';
		
		return $strToReturn;
	}
	
	/////////////////////////
	// Public Properties: GET
	/////////////////////////
	public function __get($strName) {
		switch ($strName) {
			// APPEARANCE
			case "HtmlEntities": return $this->blnHtmlEntities;
			
			default:
			try {
				return parent::__get($strName);
			} catch (QCallerException $objExc) {
				$objExc->IncrementOffset();
				throw $objExc;
			}
		}
	}
	
	/////////////////////////
	// Public Properties: SET
	/////////////////////////
	public function __set($strName, $mixValue) {
		$this->blnModified = true;
		
		switch ($strName) {
			// APPEARANCE
			case "HtmlEntities":
			try {
				$this->blnHtmlEntities = QType::Cast($mixValue, QType::Boolean);
				break;
			} catch (QInvalidCastException $objExc) {
				$objExc->IncrementOffset();
				throw $objExc;
			}
			
			default:
				try {
					parent::__set($strName, $mixValue);
				} catch (QCallerException $objExc) {
					$objExc->IncrementOffset();
					throw $objExc;
				}
				break;
		}
	}
}
?>

Changed 4 years ago by scottux

I wrote this class awhile back for an unordered list generator:

<?php
class QUnorderedList extends QControl {
	protected $_arrList = array();
	
	// Because we're generating a Block Element (at its core, the control is a
	// DIV with a bunch of stuff inside), let's set this to true.
	// (This is required for X/HTML Strict Standards Compliance)
	protected $blnIsBlockElement = true;
	
	/**
	 * If this control needs to update itself from the $_POST data, the logic to do so
	 * will be performed in this method.
	 */
	public function ParsePostData() {}
	
	/**
	 * If this control has validation rules, the logic to do so
	 * will be performed in this method.
	 * @return boolean
	 */
	public function Validate() {return true;}

	/**
	 * Get the HTML for this Control.
	 * @return string
	 */
	public function GetControlHtml() {
		// Pull any Attributes
		$strAttributes = $this->GetAttributes();

		// Pull any styles
		if ($strStyle = $this->GetStyleAttributes())
			$strStyle = 'style="' . $strStyle . '"';
		
		return sprintf('<div id="%s" %s%s>%s</div>',$this->strControlId, $strAttributes, $strStyle,$this->BuildList($this->_arrList));
	}

	/**
	 * Constructor for this control
	 * @param mixed $objParentObject Parent QForm or QControl that is responsible for rendering this control
	 * @param string $strControlId optional control ID
	 */
	public function __construct($objParentObject, $strControlId = null) {
		try {
			parent::__construct($objParentObject, $strControlId);
		} catch (QCallerException $objExc) { $objExc->IncrementOffset(); throw $objExc; }
	}

	public function AddListItem($array) {
		try {
			$this->_arrList = array_merge_recursive($this->_arrList , $array);
		} catch (QCallerException $objExc) { $objExc->IncrementOffset(); throw $objExc; }	
	}
	
	public function BuildList($array) {
		if (!is_array($array)) return $array;
		if (empty($array)) return '';
		$list = '<ul>'."\n";
		foreach ($array as $k => $v)
			$list .= '<li class="item'.$k.'">'.$this->HTMLList($v).'</li>'."\n";
		$list .= '</ul>'."\n"; 
		return $list;
	}
}
?>

I agree that there should be more QControls generating HTML elements. I have actually extended this further to create a QMenu class that creates a common CSS menu using unordered lists.

Changed 4 years ago by VexedPanda

Bad QHtml class. Too much overhead.

Changed 4 years ago by alex94040

  • status changed from new to in_QA
  • milestone set to 1.2

Changed 4 years ago by VexedPanda

  • status changed from in_QA to assigned

There's still a lot of work to be done. What I've submitted is not worthy of being part of core due to there being a ton of overhead with a standard QControl. It's mostly here as inspiration / a usable example for desperate people.

Note: See TracTickets for help on using tickets.