alamin ahmed: a typical geek 2.0

ideas.experiments.thoughts.life

home blog about me

Archive


Topics:


My projects

home » blog

Representing HTML Elements in php object PART 1 (php5)

posted on: Thursday 28th May 2009
In this article, we will create a HTML element wrapper class in php 5, that can represent any HTML tag such as '<p>', '<A>', '<div>'. 

Sometimes this is necessary, especially when are working with MVC design pattern.  This gives Controller class access to View elements for manipulating before that HTML tag/element is rendered.

Here are list of the benefits of wrapping HTML tags in PHP class object:
  1. Various parts of application can access View elements
  2. Work with HTML code as you would for php objects.
  3. Customize and reuse HTML tags
  4. Easier and useful to work with nested and complex tags such as lists (<ul>,<ol>, <dl>), forms (<form>)
  5. Create compound HTML elements, such as a input control with a label.  This requires two different tags, but using php object we can encapsulate them into one object.

How to use HTML element object in php

Lets first look at how we will use the HTML element objects.  Then we will explore how to write the class file.  We will name our class 'HtmlElement'.   

<?php 
// create the paragraph tag 
$p = new HtmlElement('p'); 
$p->align "center"// adding html tag attribute 
$p->append('This is a paragraph.'); // add the inner text of the tag 

// create a div section  
$content = new HtmlElement('div'); 
$content->style 'padding:4px'
$content->id 'main_section'
$content->append($p); // add the p tag previously created. 

// finally outputting 
print $content

// this will output 
// <div style="padding:4px;" id="main_section"><p align="center">This is a paragraph</p></div> 
?>


In the real world, you may not want use this technique to render all of your HTML tags.  However lets say you want plugins or other parts of application to be able to modify and customize the $content element.  In such case you can simply pass the $content variable among various parts of your application. When they are all done, you can then simply render the $content variable.

Things will start to get more interesting when we extend the HtmlElement and start building customized controls and views.  We will look into that in the next part of this series.  Now lets get started with the code.

Coding HtmlElement

HtmlElement will be our base class for rendering all HTML tags.  All compound HTML objects will inherit from this. There are three part in the implementation of the HtmlElement
  1. HTML tag name
  2. attributes for that HTML tag
  3. finally rendering
Let's get started.

class HtmlElement 

    
protected  
        $_attributes 
= array(),    // holds html tag attributes 
        
$_tag null,              // name of the tag 
        
$_content '';            // contents of the tag 

    /** 
     * constructing the tag element 
     * we enforce to specify the tag name when creating to make things logically accurate.   
     */ 
    
public function __construct($tag$content ''$attributes null
    { 
        
$this->_tag $tag
        
$this->_content $content
        
$this->_attributes $attributes
    } 

    
/** 
     * we add given string after current content 
     */ 
    
public function append($str
    { 
        
$this->_content .= $str
    } 

    
/** 
     * will add given string before the content 
     */ 
    
public function prepend($str
    { 
        
$this->_content $str $this->_content
    } 

    
// ... rest of the code here 

 

Construction is self explanatory.  First argument is the tag name which is required.  Second and third arguments are optional.  They are for content of the tag and it's attributes respectively.  We also added two additional methods to add to the content (inner html/text of the tag).  As name implies, append adds string end of the current text and prepend adds in the begining.

So lets started with attributes.  Attributes are implemented using php's magic __get and __set methods and fairly easy to do so.

class HtmlElement 

    
// ... previous codes 
     
    /** 
     * sets an attribute 
     */ 
    
public function __set($key$value
    { 
        
$this->_attributes[$key] = $value
    } 

    
/** 
     * get attribute value 
     */ 
    
public function __get($key
    { 
        if(isset(
$this->_attributes[$key])) return $this->_attributes[$key]; 
        return 
null
    } 

    
/** 
     * returns all attributes as key=value string 
     */ 
    
public function attributeString() 
    { 
        if(empty(
$this->_attributes)) return; 

        
$str ''
        foreach(
$this->_attributes as $key => $value) { 
            
$str .= "{$key}=\"{$value}\" "
        } 
        return 
trim($str); 
    } 

    ... 
// rest of the code 

 
As you can see, in addition to magic function, we created a special method called attributeString().  This method will return all attributes in key=value text format which is used for HTML tags.  When we render the tag to output HTML, we need this method.  So, let's get started with rendering!

Rendering HTML output


class HtmlElement 

    
// ... previous codes 

    /** 
     * render the html tag and returns html string 
     */ 
    
public function render() 
    { 
        
$output  $this->_renderStartTag(); 
        
$output .= $this->_renderInnerHtml(); 
        
$output .= $this->_renderEndTag(); 

        return 
$output;   
    } 

    
protected function _renderStartTag() 
    { 
        
$attributes $this->attributeString(); 
        if(
attributes) { 
            return 
"<{$this->_tag} {$attributes}>"
        } else { 
            return 
"<{$this->_tag}>"
        } 
    } 

    
protected function _renderInnerHtml() 
    { 
        return 
$this->_content
    } 

    
protected function _renderEndTag() 
    { 
        return 
"</{$this->_tag}>"
    } 

    
public function __toString() 
    { 
        return 
$this->render(); 
    } 

 

Ok, lets see what's going on here.  We have divided rendering into four different methods.  First one is render(), which is public, and the rest three are protected methods responsibles for rendering start of the tag, tag content and end of the tag.  You can think of these protected methods as internal events. When subclassing, these events comes very handly.  This will be discussed in next part of this article.

Finally we implemented another php magic function called __toString().  This method simply calls render method.  By implementing this method, we are able to output and treat this object as a string.

There are lots of room for improvement, but to keep things simple and to focus on the concept, this implementation will be sufficient.  Remember this HtmlElement class will be base class for all further UI elements.
Tagged: php   html   programming   1 comment(s)

CSS based table - table without TABLE

posted on: Thursday 24th July 2008
Why CSS and not TABLE.
Honestly, I have no good answer or explanation for you.  In fact I don't think any one does.  There are equal weight of advantage and disadvantage on both approaches.  Many people have tried to be strict and only show CSS benefit, and others did exactly same vice verse.

In this new "Web 2.0" era, CSS is becoming primary tool for designing and shaping web pages.  This is a good thing. CSS is really the best thing that happened to web designing.  Now designers can separate "data" from "presentation".  CSS also gives designers much more flexibilities and controls.  In terms of web standards and future, CSS certainly looks brighter.  So any attempt to migrate your any part of your web site to CSS, is a step toward right direction.  But if you taking your time then you can feel comfort knowing that tech giant like Google still uses TABLEs all over the place.  There is no sign of TABLE being deprecated from HTML, at least not any time soon.


Migrating HTML TABLE to CSS-P
Traditionally, you would use TABLE tag as follows:

<table>
    <thead>

        <tr>

            <td>Header Column 1</td>

            <td>Header Column 2</td>

        </tr>

    </thead>

    <tbody>

        <tr>

            <td>Body column 1</td>

            <td>body column 2</td>

        </tr>

    </tbody>

</table>
output:
Header Column 1 Header Column 2
Body Column 1 Body Column 2


My goal is to bring the same structure and coding layout using CSS.  To be precise, here is an example:

  <div class="table">

    <div class="row header">

       <div class="cell">Header Column 1</div>

       <div class="cell">Header Column 2</div>

    </div>

    <div class="row body">

        <div class="cell">Body Column 1</div>

        <div class="cell">Body Column 2</div>

    </div>

</div>
Looks good right? But we are far from being done.  Let's look at the output first:
output:
Header Column 1
Header Column 2
Body Column 1
Body Column 2

As you can see,  It is not at all what we expected.  Everything is showing in a single column in separate rows.  This needs to be fixed in CSS section.

CSS, time to play
If you noted, you know that we have used several classes inside our "div", for example -'table', 'row', 'cell'.  Our next step is to define those classes in css.  In "perfect world" (which basically means geniuses at Redmond complying with W3C web standard), creating table using CSS is extremely easy.  We can be done with the following lines of CSS codes:
  .table {

    display: table; }

.table .row {

    display: table-row; }

.table row .cell {

    display: table-cell; }


that's it. Simple right? Unfortunately, above styles are not supported by most browsers including Internet Explorer 6 and 7.  So it's basically useless for now.

CROSS BROWSER APPROACH:
alternative approach is to use 'inline-block' to define 'cell'.  In this case we additionally need to specify width of every cell in HTML code.  It is tedious depending on your table size and structure.  However, this is the only "good" solution we have.  Here is how:

Your CSS code is simple.  All we have to do is declare cell to be 'inline-block'.  This allows you to re-size your cell to any width/height you want.
.table { }

.table .row { }

.table .row .cell { display: inline-block; }

now in HTML add additional style to specify width of each column.

<div class="table">

    <div class="row header">

       <span class="cell" style='width:50px;'>Header Column 1</span>

       <span class="cell" style='width:50px;'>Header Column 2</span>

    </div>

    <div class="row body">

        <span class="cell" style='width:50px;'>Body Column 1</span>

        <span class="cell" style='width:50px;'>Body Column 2</span>

    </div>

</div>

This approach works for most browsers.  For IE 6 to work, you have to use "span" instead of "div" for the columns.  Don't ask me why.  This breaks W3C regulation since you are making "span" as a block element.

ANOTHER APPROACH:
Another approach is to use 'float'ing columns.
  .table { }

.table .row { clear: left; }

.table .row .column { float: left; }

We still have to specify width of every cell.  In additional, we have to clear the the floating after the last row.  For example:
<div class="table">

    <div class="row header">

       <span class="cell" style='width:50px;'>Header Column 1</span>

       <span class="cell" style='width:50px;'>Header Column 2</span>

    </div>

    <div class="row body">

        <span class="cell" style='width:50px;'>Body Column 1</span>

        <span class="cell" style='width:50px;'>Body Column 2</span>

    </div>

<div style='clear:left;'></div>

</div>
This approach is most widely compatible among browsers.  Your best bet is to chose between 'floating' cell or 'inline-block' cell.


FORMATTING TABLE
power of CSS comes when it's time to format - "presentation".  For example, we can format our headers and table in following css properties:

  .header {

    font-size:18px;

    font-weight:bold; }

.header .cell {

    line-height:24px; }



.table {

    border:2px solid #ccc; }

.table .row .cell {

    padding:3px;

    margin:2px; }

EXTENDING TABLE USING MULTIPLE CSS CLASSES:
another power of css is the ability to have multiple classes for an element.  We have already done this on row '<div class='row header'> so 'row' is one class and 'header' is another class.  Browser will join these two classes (append their properties) to render the element.

This technique comes in handy when using different types of tables, such as - table for creating form, table for listing items and so on.  For example:
  <div class='table form'>

    <div class='row'>

       <div class='cell label'>Enter your name:</div>

       <div class='cell input'><input type='text' /></div>

    </div>

</div>

and css codes
  .form {

    width:500px; }

.form .row .label {

    width:150px;

    font-weight:bold;

    text-align:right; }
As you can see we have added 'form' class with table and additional 'lable' and 'input' classes with cells.  You can imagine the possibilities when you start working with may different kinds of tables.

Mapping some of table's attributes to CSS properties:
cellpadding=2
.cell { padding:2px }

cellspacing=4
.cell { margin:4px; }

border=1
.table { border:1px solid red}
css allows you to define three dimension of border - color, style and size
width=100%
.table {width:100%}
can be applied to table, row or cell
align=center
.cell { text-align:center; }
if you want to center the table, then you have to use different approach. just wrap the table with another div and set it's text-align to center.
valign=middle
.cell {vertical-align:middle; }
different browser produce different result
bgcolor='#000000'
.cell {background-color:#000000;}




Tagged: css   html   Add comment

copyright© 2008 alaminahmed.com || powered by me! | v0.40