Monday

HTML5 forms in Zend Framework


Since W3C published its HTML5 specs in January 2008 many browsers have started their implementation of the improved XML structure and its new attributes. But what does this mean and how can we as developers benefit from all this on a form level? This talk is about implementing HTML5 specific tags in your forms created with Zend_Form.

New features HTML5 for forms and validation

First of all to clarify the meaning of all these new goodies, we first look at what’s available. HTML4 had a few different input elements that could be added to your form : text, password, hidden, checkboxes etc. HTML5 brings even more types that can be added to your tag. For instance:
  • email
  • url
  • number
  • range
  • Date pickers (date, month, week, time, datetime, datetime-local)
  • search
  • color
The email attribute to start with isn’t much of a help in a basic browser that runs on your pc/laptop. It is handy though on a mobile platform as the keyboard changes to a type where the @ sign is not tucked away in some dark corner. The one major advantage in browsers that support this new feature is that they trigger a validation process (client sided!). No more tedious javascripting of your own to pre-validate email addresses. The same goes for the other fields. Each input type triggers a certain validation (which, unfortunately, is browser dependent!) so the user is aware of what is expected.
Besides the new input-types, HTML5 also provides some other tags that are interessing when dealing with our forms:
  • datalist
  • keygen
  • output
I won’t go into detail on these elements but I have them prepared in the codebase. First the datalist is a mixture of the input and select elements. With “basic” HTML it required some javascript to generate such a feature and even then it wasn’t flawless. The keygen is a client sided keygen generator for authentication purposes. I’ve tested it with Firefox 3.6.10 and Opera 10.60 and both generate a bit of a different element with different results. I quote from the w3schools site: “Currently, the browser support for this element is not good enough to be a useful security standard.”
The last element that is new is the output element, which well does nothing except that it is reserved for output. It’s just a container for different types of output, like calculations or script output.
That’s about it on the introduction to HTML5 and forms. Let’s proceed to the awesome part!

Applying HTML5 to your Zend_Form

(Note: all code can be found on GitHub)
Basically all that we need is an extended Zend_Form_Element_Text and some view helpers that do the rendering. In this case I’ve used Glitch as the namespace for the classes.
An example:

/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 datalist element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Datalist extends Zend_Form_Element_Multi
{
    /**
* Viewhelper to be used
*
* @var string
*/
    public $helper = 'formDatalist';
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 email element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Keygen extends Zend_Form_Element
{
    /**
* Viewhelper to be used
*
* @var string
*/
    public $helper = 'formKeygen';
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 output element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Output extends Zend_Form_Element
{
    /**
* Viewhelper to be used
*
* @var string
*/
    public $helper = 'formOutput';
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 text based elements
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text extends Zend_Form_Element_Text
{
    /**#@+
* Constants that are used for types of elements
*
* @var string
*/
    const DEFAULT_TYPE = 'text';
    const FIELD_EMAIL = 'email';
    const FIELD_EMAIL_ADDRESS = 'emailaddress';
    const FIELD_URL = 'url';
    const FIELD_NUMBER = 'number';
    const FIELD_RANGE = 'range';
    const FIELD_DATE = 'date';
    const FIELD_MONTH = 'month';
    const FIELD_WEEK = 'week';
    const FIELD_TIME = 'time';
    const FIELD_DATE_TIME = 'datetime';
    const FIELD_DATE_TIME_LOCAL = 'datetime-local';
    const FIELD_SEARCH = 'search';
    const FIELD_COLOR = 'color';
    /**#@-*/
    /**
* Mapping of key => value pairs for the elements
*
* @var array
*/
    protected static $_mapping = array(
        self::FIELD_EMAIL => 'email',
        self::FIELD_EMAIL_ADDRESS => 'email',
        self::FIELD_URL => 'url',
        self::FIELD_NUMBER => 'number',
        self::FIELD_RANGE => 'range',
        self::FIELD_DATE => 'date',
        self::FIELD_MONTH => 'month',
        self::FIELD_WEEK => 'week',
        self::FIELD_TIME => 'time',
        self::FIELD_DATE_TIME => 'datetime',
        self::FIELD_DATE_TIME_LOCAL => 'datetime-local',
        self::FIELD_SEARCH => 'search',
        self::FIELD_COLOR => 'color',
    );
    /**
* Check if the validators should be auto loaded
*
* @var bool
*/
    private $_autoloadValidators = true;
    /**
* Check if the filters should be auto loaded
*
* @var bool
*/
    private $_autoloadFilters = true;
    /**
* Return the mapping for elements
*
* @return array
*/
    public static function getTypes()
    {
        return self::$_mapping;
    }
    /**
* Constructor that takes into account the type given, if given
* Proxies its parent constructor to provide rest of functionality
*
* @param $spec
* @param $options
* @uses Zend_Form_Element
*/
    public function __construct($spec, $options = null)
    {
        if ($this->_isHtml5() && !isset($options['type']))
        {
            $options['type'] = $this->_getType($spec);
        }
        parent::__construct($spec, $options);
    }
    /**
* Flag if the the validators should be autoloaded
*
* @param bool $flag
* @return Glitch_Form_Element_Text Provides a fluent interface
*/
    public function setAutoloadValidators($flag)
    {
        $this->_autoloadValidators = (bool) $flag;
        return $this;
    }
    /**
* Flag if the the validators should be autoloaded
*
* @return bool
*/
    public function isAutoloadValidators()
    {
        return $this->_autoloadValidators;
    }
    /**
* Flag if the the filters should be autoloaded
*
* @param bool $flag
* @return Glitch_Form_Element_Text Provides a fluent interface
*/
    public function setAutoloadFilters($flag)
    {
        $this->_autoloadFilters = (bool) $flag;
        return $this;
    }
    /**
* Flag if the the validators should be autoloaded
*
* @return bool
*/
    public function isAutoloadFilters()
    {
        return $this->_autoloadFilters;
    }
    /**
* Check if the doctype is HTML5
*
* @return bool
*/
    protected function _isHtml5()
    {
        return $this->getView()->getHelper('doctype')->isHtml5();
    }
    /**
* Check if the given type is specified in the mapping and use it if it's available
* Else return the constant DEFAULT_TYPE value
*
* @param $spec
* @return string
*/
    private function _getType($spec)
    {
        if (array_key_exists(strtolower($spec), self::$_mapping))
        {
            return self::$_mapping[$spec];
        }
        return self::DEFAULT_TYPE;
    }
}
As you can see I’ve provided a basic set of key value pairs that are represented by constants to deliver the basics. Further down the I’ve used the constructor to decide to get the type of the element based on the name of the element if the type key is not given in the options argument. The type of the element points directly to the “type” attribute of the element. I’ve made the _getType method to map the element name to its matching type attribute. So far nothing exceptional, just some matching of keys and returning their values. As a treat I’ve build in get/set methods that allows us to disable automated filters and validators for our new elements. Next up is the actual element and for this example lets use the number field where I’ve implemented automated filters and validation based on the settings given to the element upon constructing it.

/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 date element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Date extends Glitch_Form_Element_Text
{
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 date time element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_DateTime extends Glitch_Form_Element_Text
{
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 date time with local awareness element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_DateTimeLocal extends Glitch_Form_Element_Text
{
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 email element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Email extends Glitch_Form_Element_Text
{
    /**
* Initialize additional element options
*
* @return Glitch_Form_Element_Text_Email
*/
    public function init()
    {
        if ($this->isAutoloadValidators())
        {
            $this->addValidator('EmailAddress');
        }
        return $this;
    }
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 month element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Month extends Glitch_Form_Element_Text
{
    public function init()
    {
        if ($this->isAutoloadValidators())
        {
            //@todo: base month numbers on Zend_Locale
            $this->addValidator('Between', false, array('min' => 1, 'max' => 52));
        }
    }
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 number element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Number extends Glitch_Form_Element_Text
{
    /**
* Initialize additional element options
*
* @return Glitch_Form_Element_Text_Email
*/
    public function init()
    {
        if ($this->isAutoloadFilters())
        {
            $this->addFilter('Digits');
        }
        if ($this->isAutoloadValidators())
        {
            $this->addValidator('Digits');
            $validatorOpts = array_filter(array(
                'min' => $this->getAttrib('min'),
                'max' => $this->getAttrib('max'),
            ));
            $validator = null;
            if (2 === count($validatorOpts))
            {
                $validator = 'Between';
            }
            else if (isset($validatorOpts['min']))
            {
                $validator = 'GreaterThan';
            }
            else if (isset($validatorOpts['max']))
            {
                $validator = 'LessThan';
            }
            if (null !== $validator)
            {
                $this->addValidator($validator, false, $validatorOpts);
            }
        }
        return $this;
    }
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 range element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Range extends Glitch_Form_Element_Text_Number
{
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 search element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Search extends Glitch_Form_Element_Text
{
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 time element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Time extends Glitch_Form_Element_Text
{
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* Base class for HTML5 color element
*
* @category Glitch
* @package Glitch_Form
* @subpackage Element
*/
class Glitch_Form_Element_Text_Color extends Glitch_Form_Element_Text
{
}
The init() method does a check for the attributes that are used in HTML5 (see specs) for the number type and adds a logical validator to the element. In this case the min and max attributes are used.
Now let’s take a crack at a view helper for the new types (yes, just 1 view helper!)

/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* View helper for generating a HTML5 datalist
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
*/
class Glitch_View_Helper_FormDatalist extends Zend_View_Helper_FormSelect
{
    /**
* Generates 'select' list of options.
*
* @access public
*
* @param string|array $name If a string, the element name. If an
* array, all other parameters are ignored, and the array elements
* are extracted in place of added parameters.
*
* @param mixed $value The option value to mark as 'selected'; if an
* array, will mark all values in the array as 'selected' (used for
* multiple-select elements).
*
* @param array|string $attribs Attributes added to the 'select' tag.
*
* @param array $options An array of key-value pairs where the array
* key is the radio value, and the array value is the radio text.
*
* @param string $listsep When disabled, use this list separator string
* between list values.
*
* @return string The select tag and options XHTML.
*/
    public function formDatalist($name, $value = null, $attribs = null,
        $options = null, $listsep = "\n")
    {
        $info = $this->_getInfo($name, $value, $attribs, $options, $listsep);
        extract($info); // name, id, value, attribs, options, listsep, disable
        // force $value to array so we can compare multiple values to multiple
        // options; also ensure it's a string for comparison purposes.
        $value = array_map('strval', (array) $value);
        // Build the surrounding select element first.
        $xhtml = '. $this->view->escape($name) . '" />';
        $xhtml .= '
                . ' name="' . $this->view->escape($name) . '"'
                . ' id="' . $this->view->escape($id) . '"'
                . $this->_htmlAttribs($attribs)
                . ">\n ";
        // build the list of options
        $list = array();
        $translator = $this->getTranslator();
        foreach ((array) $options as $opt_value => $opt_label) {
            if (is_array($opt_label)) {
                $opt_disable = '';
                if (is_array($disable) && in_array($opt_value, $disable)) {
                    $opt_disable = ' disabled="disabled"';
                }
                if (null !== $translator) {
                    $opt_value = $translator->translate($opt_value);
                }
                $list[] = '
                        . $opt_disable
                        . ' label="' . $this->view->escape($opt_value) .'">';
                foreach ($opt_label as $val => $lab) {
                    $list[] = $this->_build($val, $lab, $value, $disable);
                }
                $list[] = '';
            } else {
                $list[] = $this->_build($opt_value, $opt_label, $value, $disable);
            }
        }
        // add the options to the xhtml and close the select
        $xhtml .= implode("\n ", $list) . "\n";
        return $xhtml;
    }
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* View helper for generating a HTML5 keygen
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
*/
class Glitch_View_Helper_FormKeygen extends Zend_View_Helper_FormText
{
    /**
* Generates a 'keygen' element.
*
* @access public
*
* @param string|array $name If a string, the element name. If an
* array, all other parameters are ignored, and the array elements
* are used in place of added parameters.
*
* @param mixed $value The element value.
*
* @param array $attribs Attributes for the element tag.
*
* @return string The element XHTML.
*/
    public function formKeygen($name, $value = null, $attribs = null)
    {
        $info = $this->_getInfo($name, $value, $attribs);
        extract($info); // name, value, attribs, options, listsep, disable
        // build the element
        $disabled = '';
        if ($disable) {
            // disabled
            $disabled = ' disabled="disabled"';
        }
        // XHTML or HTML end tag?
        $endTag = ' />';
        if (($this->view instanceof Zend_View_Abstract) && !$this->view->doctype()->isXhtml()) {
            $endTag= '>';
        }
        unset($attribs['type']);
        $xhtml = '
                . ' name="' . $this->view->escape($name) . '"'
                . ' id="' . $this->view->escape($id) . '"'
                . $disabled
                . $this->_htmlAttribs($attribs)
                . $endTag;
        return $xhtml;
    }
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* View helper for generating a HTML5 output element
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
*/
class Glitch_View_Helper_FormOutput extends Zend_View_Helper_FormElement
{
    /**
* Generates a 'output' element.
*
* @access public
*
* @param string|array $name If a string, the element name. If an
* array, all other parameters are ignored, and the array elements
* are used in place of added parameters.
*
* @param mixed $value The element value.
*
* @param array $attribs Attributes for the element tag.
*
* @return string The element XHTML.
*/
    public function formOutput($name, $value = null, $attribs = null)
    {
        $info = $this->_getInfo($name, $value, $attribs);
        extract($info); // name, value, attribs, options, listsep, disable
        // XHTML or HTML end tag?
        $endTag = ' />';
        if (($this->view instanceof Zend_View_Abstract) && !$this->view->doctype()->isXhtml()) {
            $endTag= '>';
        }
        $xhtml = '
                . ' name="' . $this->view->escape($name) . '"'
                . ' id="' . $this->view->escape($id) . '"'
                . $this->_htmlAttribs($attribs)
                . $endTag;
        return $xhtml;
    }
}
/**
* Glitch
*
* Copyright (c) 2010, Enrise BV (www.enrise.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Enrise nor the names of his contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
* @author Enrise
* @copyright 2010, Enrise
* @license http://www.opensource.org/licenses/bsd-license.php
* @version $Id: $
*/
/**
* View helper for generating a HTML5 datalist
*
* @category Glitch
* @package Glitch_View
* @subpackage Helper
*/
class Glitch_View_Helper_FormText extends Zend_View_Helper_FormText
{
    /**
* Generates a 'text' element.
*
* @access public
*
* @param string|array $name If a string, the element name. If an
* array, all other parameters are ignored, and the array elements
* are used in place of added parameters.
*
* @param mixed $value The element value.
*
* @param array $attribs Attributes for the element tag.
*
* @return string The element XHTML.
*/
    public function formText($name, $value = null, $attribs = null)
    {
        $info = $this->_getInfo($name, $value, $attribs);
        extract($info); // name, value, attribs, options, listsep, disable
        // build the element
        $disabled = '';
        if ($disable) {
            // disabled
            $disabled = ' disabled="disabled"';
        }
        // XHTML or HTML end tag?
        $endTag = ' />';
        if (($this->view instanceof Zend_View_Abstract) && !$this->view->doctype()->isXhtml()) {
            $endTag= '>';
        }
        $type = 'text';
        if ($this->view->doctype()->isHtml5()
            && isset($attribs['type'])
            && in_array($attribs['type'], Glitch_Form_Element_Text::getTypes()))
        {
            $type = $attribs['type'];
            unset($attribs['type']);
        }
        $xhtml = '. $type . '" '
                . ' name="' . $this->view->escape($name) . '"'
                . ' id="' . $this->view->escape($id) . '"'
                . ' value="' . $this->view->escape($value) . '"'
                . $disabled
                . $this->_htmlAttribs($attribs)
                . $endTag;
        return $xhtml;
    }
}
Now let’s build our form and add all the new elements.

class Application_Model_Form_Html5 extends Zend_Form
{
    public function init()
    {
        $email = new Glitch_Form_Element_Text_Email('email');
        $email->setLabel('Email');
        $url = new Glitch_Form_Element_Text_Url('url');
        $url->setLabel('Url');
        $number = new Glitch_Form_Element_Text_Number('number', array(
            'min' => 2,
            'step' => 2,
            'label' => 'Number',
        ));
        $range = new Glitch_Form_Element_Text_Range('range', array(
            'min' => 5,
            'max' => 100,
            'step' => 5,
            'autoloadValidators' => false,
            'autoloadFilters' => false,
            'label' => 'Range',
        ));
        $date = new Glitch_Form_Element_Text_Date('date');
        $date->setLabel('Date');
        $month = new Glitch_Form_Element_Text_Month('month');
        $month->setLabel('Month');
        $week = new Glitch_Form_Element_Text_Week('week');
        $week->setLabel('Week');
        $time = new Glitch_Form_Element_Text_Time('time');
        $time->setLabel('Time');
        $dateTime = new Glitch_Form_Element_Text_DateTime('datetime');
        $dateTime->setLabel('DateTime');
        $dateTimeLocal = new Glitch_Form_Element_Text_DateTimeLocal('datetime-local');
        $dateTimeLocal->setLabel('DateTimeLocal');
        $search = new Glitch_Form_Element_Text_Search('search');
        $search->setLabel('Search');
        $color = new Glitch_Form_Element_Text_Color('color');
        $color->setLabel('Color');
        $opts = array(
            'foo' => 'bar',
            'baz' => 'bat',
        );
        $datalist = new Glitch_Form_Element_Datalist('datalist');
        $datalist->setLabel('Datalist')
                 ->setMultiOptions($opts);
        $output = new Glitch_Form_Element_Output('output');
        $output->setLabel('Output')->setAttrib('onforminput', 'resCalc()');
        $keygen = new Glitch_Form_Element_Keygen('keygen');
        $keygen->setAttrib('keytype', 'rsa');
        $password = new Zend_Form_Element_Password('password');
        $password->setLabel('Password');
        $submit = new Zend_Form_Element_Submit('submit');
        $submit->setValue('submit');
        $elements = array($email, $url, $number, $range, $date, $month, $week, $time,
            $dateTime, $dateTimeLocal, $search, $color, $output, $datalist, $submit
        );
        $this->addElements($elements);
    }
}
view raw Html5.php This Gist brought to you by GitHub.

As you can see, nothing special going on. With the small exception of the range and number fields where we have provided specs for the attributes and more important, specs for our server sided validation. For the range element I’ve disabled the automated filtering and validation with the keys ‘autoloadValidators’ and ‘autoloadValidators’ set to false.
(Note the onforminput attribute on the output element, there is code for that in the view layer)
The datalist, output and keygen elements do require some more code as they rely on their own new view helpers which renders the right tags but this is nothing you should be worried about as it all included in the download package.
So now that we have our HTML5 form filled with elements and just 1 step away from yes, RESULT! Paste this in your view

echo $this->form;
$this->headScript()->captureStart();
?>
function resCalc()
{
    numA=document.getElementById("range").value;
    numB=document.getElementById("number").value;
    document.getElementById("output").value=Number(numA)+Number(numB);
}
$this->headScript()->captureEnd();
?>
view raw index.phtml This Gist brought to you by GitHub.
These lines render the entire form and add some javascript code to calculate the sum of the 2 form input fields.
Now to see the new form in all its glory I recommend Opera for viewing the beauty of your newly generated elements and take it for a test run. (Opera has the best support for the new input types)
(Reminder: there is client sided validation but that does not take away that you still are responsible for the data that comes in! Read: write your own validation chain.)
Now let’s see what happens when we don’t want the (still experimental) HTML5 elements. Just replace this code in your application.ini:
resources.view.doctype = "HTML5" with
resources.view.doctype = "XHTML1_STRICT"
Now refresh your page and see how everything just falls back to input elements with the attribute text instead of the funky HTML5 attributes.

Conclusion

One of the great joys (for me at least) of working with Zend and specific Zend_Form and Zend_Form_Element is that it so extendible!
With a few classes of your own you can create almost any kind of element you want, it’s all up to your imagination.
I hope that you will agree that we extend to support the future ;)
All code can be found on GitHub

curtsy: David Papadogiannakis

Thursday

Zend Framework 2.0.0beta1 Released


The Zend Framework community is pleased to announce the immediate availability of Zend Framework 2.0.0beta1. Packages and installation instructions are available at:
http://packages.zendframework.com/
This is the first in a series of planned beta releases. The beta release cycle will follow the "gmail" style of betas, whereby new features will be added in each new release, and BC will not be guaranteed; beta releases will happen no less than every six weeks. The desire is for developers to adopt and work with new components as they are shipped, and provide feedback so we can polish the distribution.
Once all code in the proposed standard distribution has reached maturity and reasonable stability, we will freeze the API and prepare for Release Candidate status.
Featured components and functionality of 2.0.0beta1 include:
  • New and refactored autoloaders:
    • Zend\Loader\StandardAutoloader
    • Zend\Loader\ClassMapAutoloader
    • Zend\Loader\AutoloaderFactory
  • New plugin broker strategy
    • Zend\Loader\Broker and Zend\Loader\PluginBroker
  • Reworked Exception system
    • Allow catching by specific Exception type
    • Allow catching by component Exception type
    • Allow catching by SPL Exception type
    • Allow catching by base Exception type
  • Rewritten Session component
  • Refactored View component
    • Split helpers into a PluginBroker
    • Split variables into a Variables container
    • Split script paths into a TemplateResolver
    • Renamed base View class "PhpRenderer"
    • Refactored helpers to utilize __invoke() when possible
  • Refactored HTTP component
  • New Zend\Cloud\Infrastructure component
  • New EventManager component
  • New Dependency Injection (Zend\Di) component
  • New Code component
    • Incorporates refactored versions of former Reflection and CodeGenerator components.
    • Introduces Scanner component.
    • Introduces annotation system.
The above components provide a solid foundation for Zend Framework 2, and largely make up the framework "core". However, the cornerstone feature of beta1 is what they enable: the new MVC layer:
  • Zend\Module, for developing modular application architectures.
  • Zend\Mvc, a completely reworked MVC layer built on top of HTTP, EventManager, and Di.
We've built a skeleton application and a skeleton module to help get you started, as well as a quick start guide to the MVC; the new MVC is truly flexible, and moreover, simple and powerful.
Additionally, for those who haven't clicked on the packages link above, we are debuting our new distribution mechanisms for ZF2: the ability to use Pyrus to install individual components and/or groups of components.
Since mid-August, we've gone from a few dozen pull requests on the ZF2 git repository to over 500, originating from both long-time Zend Framework contributors as well as those brand-new to the project. I'd like to thank each and every one of them, but also call out several individuals who have made some outstanding and important contributions during that time frame:
  • Evan Coury, who prototyped and then implemented the new module system.
  • Rob Allen, who, because he was doing a tutorial at PHPNW on ZF2, provided a lot of early feedback, ideas, and advice on the direction of the MVC.
  • Ben Scholzen, who wrote a new router system, in spite of a massive injury from a cycling accident.
  • Ralph Schindler, who has had to put up with my daily "devil's advocate" and "think of the user!" rants for the past several months, and still managed to provide comprehensive code manipulation tools, a Dependency Injection framework, and major contributions to the HTTP component.
  • Enrico Zimuel, who got tossed requirements for the cloud infrastructure component, and then had to rework most of it after rewriting the HTTP client from the ground up... and who still managed three back-to-back-to-back conferences as we prepared the release.
  • Artur Bodera, who often has played devil's advocate, and persisted pressing his opinions on the direction of the framework, often despite heavy opposition. We may not implement all (or many) of the features you want, but you've definitely influenced the direction of the MVC incredibly.
  • Pádraic Brady, who started the runaway train rolling with a rant, and helped make the project much more transparent, enabling the MVC development to occur in the first place.

Welcome to the ZF2 beta cycle!

courtsy: zend

Monday

Build A Web 2.0 Voting Widget With Flex


IThere are few things that people like to do more than give their opinion about a subject of interest to them – especially on the Web. This can be very useful for engaging your site’s visitors, measuring their interest in a topic, or just allowing them to express themselves. Web 2.0, and the advent of Rich Internet Applications (RIAs), allow for the installation of polling widgets on your web site, making it easier than ever to take the pulse of your community.

There are several different technologies you could use to build an interactive voting widget, but the end user needs to be considered carefully. For instance, you could use Ajax – but this approach can introduce issues with client-side compatibility. You could use Applets, but that’s not a popular choice at the moment – too many web surfers disable the Java VM in their browsers.
A very good option, on the other hand, is Flash. Practically everyone has it installed – who hasn’t come across a link to YouTube at some point and wanted to watch a video?
But what if you’re not across Flash? And isn’t Flash really an animator’s tool anyway? Well, as we’ll see, it’s easy for developers to build Flash applications using the Flex framework – freely available as open source from Adobe. In this article, the first of two on this complex subject, we’ll walk through the process of building a Flash widget for voting using the Flex framework.
Flex Basics
Before we go any further, we’ll pause for a minute to talk about the Flex and Flash applications and where they fit into the client landscape. Take a look at the following graphic.
Where Flash applications fit into the client landscape
This diagram demonstrates how a Web 2.0 web page interacts with a PHP web server. The web page uses one of several tools to communicate with the web server. It can use Javascript and Ajax to make a request of the server, then update the page with the new data. Or it can use a Flash application to provide functionality to the user. This Flash application can either take up the entire page, or it may be contained to a widget that takes up just a portion of it. Flex has been used very successfully in both scenarios.
Flex applications are made of roughly three parts: the MXML that defines the interface, the ActionScript code that contains the application logic, and resources such as images and audio. To draw an analogy with web technologies, the MXML and ActionScript would be HTML and JavaScript respectively.
Now you could download the SDK and program your application using a simple text editor, but there’s a better option – a really good IDE called Flex Builder 3, available free from Adobe as a 30-day trial.
The following diagram shows Flex Builder 3 and how its function fits into the life cycle of generating a Flash application SWF.
How Flex Builder works
Flex Builder manages the MXML, ActionScript, and resources as a project. It uses the Flex SDK compiler to continuously compile the project as you make changes. That temporary output SWF file is then launched in your default browser to do the testing.
Hopefully this provides some context for getting started with Flex. If you’d like a more detailed walk-through of this subject, I recommend you try this excellent tutorial on Flex for beginners.
Getting Flex Up and Running
The Flex Builder 3 installer comes with everything you need built in. It automatically installs the Flex SDK, as well as the Eclipse-based IDE and the AIR runtime (which is useful if you want to build a desktop application rather than a web app.
Once you have Flex Builder 3 installed on your machine, launch it and you should see something like this.
The starting point with Flex Builder 3
This is the empty Flex IDE. The next step is to create our first Flex project. Select Flex Project from the New menu and you should see this window.
Creating your first project
You can name your project whatever you like. I chose Voteview, since for the purposes of this article I’m only going to build an application that views the current vote totals. We’ll discover the interactive widget in the next article.

After you hit Finish to build the project, you should see the result pictured below.
The auto-generated application
Flex Builder 3 automatically creates an MXML application with the same name as the project. In this case, the “voteview” project has one source file, voteviewer.mxml.
At this point, you’re probably thinking, “I thought we were doing Flex, so what’s this MXML?” MXML is one of the two major technologies in a Flex application; it’s a tag-based language used to build user interfaces. The other is ActionScript 3, which is the programming language that we use to add interactivity to the interface.
To make sure that everything’s working okay, we’ll add just a single tag to the MXML file, as shown here:

  1.   

  2.   
  3.   
      
  4.   




  

The tag specifies that we want a control of type Label with the text of Hello World where the font size is 20px. This figure shows the result of launching it in Flex Builder.
Just checking to make sure everything works
If that works, you know that everything is installed correctly and you’re all set to start developing in Flex.
The next step is to put an XML file on a web server that will contain the current vote totals. This is the data that the Flex application will fetch and display.
You can format your XML any way you choose, but something along these lines is simple enough:

  1.   
  2.   What is the best Star Wars movie?
      
  3.   
      
  4.     
      
  5.     
      
  6.     
      
  7.   
      
  8.   
  

  What is the best Star Wars movie?  

    

      

This XML defines that there is one question with three options, where each option has a name and a count of votes.
Once this XML file is up on your server somewhere (in my case, the localhost Apache server on my Mac), we can add some more tags to the MXML and get this party started!
Here’s a simple Flex application that reads the data from the XML file and then displays the question in a Label control, and the current votes in a DataGrid control:

  1.   
  2.   
  3.   creationComplete="votes.send()">
      
  4.   
      
  5.   
      
  6.   
      
  7.     
      
  8.       
      
  9.       
      
  10.     
      
  11.   
      
  12.   
  


  creationComplete="votes.send()">  

    

    

    

      

        

        

      

    

There are two key elements involved in the code above. The first is the mx:HTTPService tag that defines where we will retrieve the data, and specifies an id for the data source. This service is invoked by the code attached to the creationComplete event on the Application tag.
The data display is handled automatically by Flex through the magic of the Flex event model. When the HTTService has successfully downloaded the XML, the lastResult variable on the service notifies the Label and the DataGrid that it has changed. Those controls then update themselves automatically to show the new values returned by the server.
Here’s the result of launching this in Flex Builder.
A grid presentation of the data
Well, it works okay, but it’s not very sexy in appearance, is it? I’m all about the sexy look, so I’m going to use Flex’s built-in charting service to display the votes in a pie chart instead of a DataGrid.
This updated code is shown below:

  1.   
  2.   
  3.   creationComplete="votes.send()">
      
  4.   
      
  5.   
      
  6.   
  7.     showAllDataTips="true"
      
  8.     dataProvider="{votes.lastResult.votes.options.option}">
      
  9.     
      
  10.       
      
  11.     
      
  12.   
      
  13.   
  


  creationComplete="votes.send()">  

    

    

  
    showAllDataTips="true"  

    dataProvider="{votes.lastResult.votes.options.option}">  

      

        

      

    

The only change here is that we replaced the DataGrid with a PieChart control. When we run this in Flex Builder, we’ll see the window shown here.
A pie chart that displays the data
Now, that’s certainly better. A picture is worth a thousand words, as they say. But could it be even cooler? As it turns out, it can; the Elixir data visualization components available from ILOG offers a set of amazing charting controls that you can use on a trial basis.

Once we’ve installed the ILOG Elixir controls on the machine, we can link them into the project by referencing the Elixir libraries. From there, we add a reference to the Elixir PieChart3D instead of to the original PieChart control.
This updated code is shown below:
  1.  
      
  2.   
  3.   creationComplete="votes.send()" xmlns:ilog="http://www.ilog.com/2007/ilog/flex"> 
      
  4.    
      
  5.    
      
  6.   
  7.     showAllDataTips="true" 
      
  8.     dataProvider="{votes.lastResult.votes.options.option}" elevationAngle="30"> 
      
  9.      
      
  10.        
      
  11.      
      
  12.    
      
  13.   
   


  creationComplete="votes.send()" xmlns:ilog="http://www.ilog.com/2007/ilog/flex">   

     

     

  
    showAllDataTips="true"   

    dataProvider="{votes.lastResult.votes.options.option}" elevationAngle="30">   

       

         

       

     

And when brought up in Flex Builder 3, it looks like this figure.
A cool 3D pie chart of the vote results using Elixir
Now we’re really cooking with gas! With Elixir we can change the rotation of the chart, the colors, the viewing angle, the lighting, and more. We can even do all that on the fly by responding to mouseclick events and changing the parameters on the chart using ActionScript. This functionality allows the voter to spin the chart around and view it from different angles.
This is about as far as I’m going to go with the interface in this article series. To finish up, I’ll demonstrate how to use a different data transport technology, AMF, instead of XML. AMF is easier to use, particularly when you’re both reading and writing data – more on this in the next instalment!
NOTE:
AMF and XML aren’t the only ways that Flex can access data. Your applications can read JSON, text, AMF, or go direct to binary data through sockets. In other words, wherever your data is and whatever the format, Flex applications can get to it.

Going to AMF
Let’s use the free AMFPHP package to build an AMF service on the web server. AMFPHP comes with a built-in service browser, which I’ll show you in a minute, plus a directory where you put your services. In this case, we’ll add a new service to a new “votes” directory called VoteService.
Here’s the PHP code for VoteService:
  1.   
  2. include_once(AMFPHP_BASE . "shared/util/MethodTable.php"); 
      
  3. class VoteService 
      

  4.   
  5.   function getVotes() 
      
  6.   { 
      
  7.     return array( 'topic' => 'What is the best Star Wars movie?', 
      
  8.         'votes' => array(  
      
  9.             array( 'name' => 'Episode IV', 'count' => 150 ), 
      
  10.             array( 'name' => 'Episode V', 'count' => 250 ), 
      
  11.             array( 'name' => 'Episode III', 'count' => 50 ) 
      
  12.           ) 
      
  13.         ); 
      
  14.   } 
      
  15. }  

include_once(AMFPHP_BASE . "shared/util/MethodTable.php");   

class VoteService   

{   

  function getVotes()   

  {   

    return array( 'topic' => 'What is the best Star Wars movie?',   

        'votes' => array(    

            array( 'name' => 'Episode IV', 'count' => 150 ),   

            array( 'name' => 'Episode V', 'count' => 250 ),   

            array( 'name' => 'Episode III', 'count' => 50 )   

          )   

        );   

  }   

}
For this example, we’re just going to return the same data as we’d have gained from the XML file on the server. That way, if the results look the same we know everything’s in order.
To test the service, navigate to the amfphp/browser directory in your browser. You should see something like this.
The AMF data service viewed in the AMFPHP browser
Next, click on the votes/VoteService and hit the Call button. This causes the AMF browser to invoke the service and display the results, as shown here.
The AMF browser showing the vote service result
We can see that the data is returned correctly as an ActionScript object that’s very easy to manipulate.
From here, we can change the HTTPService from the original PieChart application to a RemoteObject service. The RemoteObject class connects to the AMF endpoint and then defines a bunch of methods. You can see this in the updated source:
  1.  
      
  2.   
  3.   creationComplete="voteRO.getVotes.send()"> 
      
  4.   endpoint="http://localhost/amfphp/gateway.php" 
      
  5.   source="votes.VoteService" destination="votes.VoteService" 
      
  6.   showBusyCursor="true"> 
      
  7.  
      
  8.  
      
  9.    
      
  10.   
  11.     showAllDataTips="true" 
      
  12.     dataProvider="{voteRO.getVotes.lastResult.votes}"> 
      
  13. ... 
      
  14.    
      
  15.   
   


  creationComplete="voteRO.getVotes.send()">   


  endpoint="http://localhost/amfphp/gateway.php"   

  source="votes.VoteService" destination="votes.VoteService"   

  showBusyCursor="true">   

   

   

     

  
    showAllDataTips="true"   

    dataProvider="{voteRO.getVotes.lastResult.votes}">   

...   

     

Yes, that’s a lot more code than the HTTPService required to achieve the same outcome (don’t forget to download the code archive for this article). But using AMF instead of XML will make it a lot easier to perform both the vote collection and vote addition from the widget that we’ll create in the next article of this series.


There are few things that people like to do more than give their opinion about a subject of interest to them – especially on the Web. This can be very useful for engaging your site’s visitors, measuring their interest in a topic, or just allowing them to express themselves. Web 2.0, and the advent of Rich Internet Applications (RIAs), allow for the installation of polling widgets on your web site, making it easier than ever to take the pulse of your community.
There are several different technologies you could use to build an interactive voting widget, but the end user needs to be considered carefully. For instance, you could use Ajax – but this approach can introduce issues with client-side compatibility. You could use Applets, but that’s not a popular choice at the moment – too many web surfers disable the Java VM in their browsers.
A very good option, on the other hand, is Flash. Practically everyone has it installed – who hasn’t come across a link to YouTube at some point and wanted to watch a video?
But what if you’re not across Flash? And isn’t Flash really an animator’s tool anyway? Well, as we’ll see, it’s easy for developers to build Flash applications using the Flex framework – freely available as open source from Adobe. In this article, the first of two on this complex subject, we’ll walk through the process of building a Flash widget for voting using the Flex framework.
Flex Basics
Before we go any further, we’ll pause for a minute to talk about the Flex and Flash applications and where they fit into the client landscape. Take a look at the following graphic.
Where Flash applications fit into the client landscape
This diagram demonstrates how a Web 2.0 web page interacts with a PHP web server. The web page uses one of several tools to communicate with the web server. It can use Javascript and Ajax to make a request of the server, then update the page with the new data. Or it can use a Flash application to provide functionality to the user. This Flash application can either take up the entire page, or it may be contained to a widget that takes up just a portion of it. Flex has been used very successfully in both scenarios.
Flex applications are made of roughly three parts: the MXML that defines the interface, the ActionScript code that contains the application logic, and resources such as images and audio. To draw an analogy with web technologies, the MXML and ActionScript would be HTML and JavaScript respectively.
Now you could download the SDK and program your application using a simple text editor, but there’s a better option – a really good IDE called Flex Builder 3, available free from Adobe as a 30-day trial.
The following diagram shows Flex Builder 3 and how its function fits into the life cycle of generating a Flash application SWF.
How Flex Builder works
Flex Builder manages the MXML, ActionScript, and resources as a project. It uses the Flex SDK compiler to continuously compile the project as you make changes. That temporary output SWF file is then launched in your default browser to do the testing.
Hopefully this provides some context for getting started with Flex. If you’d like a more detailed walk-through of this subject, I recommend you try this excellent tutorial on Flex for beginners.
Getting Flex Up and Running
The Flex Builder 3 installer comes with everything you need built in. It automatically installs the Flex SDK, as well as the Eclipse-based IDE and the AIR runtime (which is useful if you want to build a desktop application rather than a web app.
Once you have Flex Builder 3 installed on your machine, launch it and you should see something like this.
The starting point with Flex Builder 3
This is the empty Flex IDE. The next step is to create our first Flex project. Select Flex Project from the New menu and you should see this window.
Creating your first project
You can name your project whatever you like. I chose Voteview, since for the purposes of this article I’m only going to build an application that views the current vote totals. We’ll discover the interactive widget in the next article.

After you hit Finish to build the project, you should see the result pictured below.
The auto-generated application
Flex Builder 3 automatically creates an MXML application with the same name as the project. In this case, the “voteview” project has one source file, voteviewer.mxml.
At this point, you’re probably thinking, “I thought we were doing Flex, so what’s this MXML?” MXML is one of the two major technologies in a Flex application; it’s a tag-based language used to build user interfaces. The other is ActionScript 3, which is the programming language that we use to add interactivity to the interface.
To make sure that everything’s working okay, we’ll add just a single tag to the MXML file, as shown here:

  1.   

  2.   
  3.   
      
  4.   




  

The tag specifies that we want a control of type Label with the text of Hello World where the font size is 20px. This figure shows the result of launching it in Flex Builder.
Just checking to make sure everything works
If that works, you know that everything is installed correctly and you’re all set to start developing in Flex.
The next step is to put an XML file on a web server that will contain the current vote totals. This is the data that the Flex application will fetch and display.
You can format your XML any way you choose, but something along these lines is simple enough:

  1.   
  2.   What is the best Star Wars movie?
      
  3.   
      
  4.     
      
  5.     
      
  6.     
      
  7.   
      
  8.   
  

  What is the best Star Wars movie?  

    

      

This XML defines that there is one question with three options, where each option has a name and a count of votes.
Once this XML file is up on your server somewhere (in my case, the localhost Apache server on my Mac), we can add some more tags to the MXML and get this party started!
Here’s a simple Flex application that reads the data from the XML file and then displays the question in a Label control, and the current votes in a DataGrid control:

  1.   
  2.   
  3.   creationComplete="votes.send()">
      
  4.   
      
  5.   
      
  6.   
      
  7.     
      
  8.       
      
  9.       
      
  10.     
      
  11.   
      
  12.   
  


  creationComplete="votes.send()">  

    

    

    

      

        

        

      

    

There are two key elements involved in the code above. The first is the mx:HTTPService tag that defines where we will retrieve the data, and specifies an id for the data source. This service is invoked by the code attached to the creationComplete event on the Application tag.
The data display is handled automatically by Flex through the magic of the Flex event model. When the HTTService has successfully downloaded the XML, the lastResult variable on the service notifies the Label and the DataGrid that it has changed. Those controls then update themselves automatically to show the new values returned by the server.
Here’s the result of launching this in Flex Builder.
A grid presentation of the data
Well, it works okay, but it’s not very sexy in appearance, is it? I’m all about the sexy look, so I’m going to use Flex’s built-in charting service to display the votes in a pie chart instead of a DataGrid.
This updated code is shown below:

  1.   
  2.   
  3.   creationComplete="votes.send()">
      
  4.   
      
  5.   
      
  6.   
  7.     showAllDataTips="true"
      
  8.     dataProvider="{votes.lastResult.votes.options.option}">
      
  9.     
      
  10.       
      
  11.     
      
  12.   
      
  13.   
  


  creationComplete="votes.send()">  

    

    

  
    showAllDataTips="true"  

    dataProvider="{votes.lastResult.votes.options.option}">  

      

        

      

    

The only change here is that we replaced the DataGrid with a PieChart control. When we run this in Flex Builder, we’ll see the window shown here.
A pie chart that displays the data
Now, that’s certainly better. A picture is worth a thousand words, as they say. But could it be even cooler? As it turns out, it can; the Elixir data visualization components available from ILOG offers a set of amazing charting controls that you can use on a trial basis.

Once we’ve installed the ILOG Elixir controls on the machine, we can link them into the project by referencing the Elixir libraries. From there, we add a reference to the Elixir PieChart3D instead of to the original PieChart control.
This updated code is shown below:
  1.  
      
  2.   
  3.   creationComplete="votes.send()" xmlns:ilog="http://www.ilog.com/2007/ilog/flex"> 
      
  4.    
      
  5.    
      
  6.   
  7.     showAllDataTips="true" 
      
  8.     dataProvider="{votes.lastResult.votes.options.option}" elevationAngle="30"> 
      
  9.      
      
  10.        
      
  11.      
      
  12.    
      
  13.   
   


  creationComplete="votes.send()" xmlns:ilog="http://www.ilog.com/2007/ilog/flex">   

     

     

  
    showAllDataTips="true"   

    dataProvider="{votes.lastResult.votes.options.option}" elevationAngle="30">   

       

         

       

     

And when brought up in Flex Builder 3, it looks like this figure.
A cool 3D pie chart of the vote results using Elixir
Now we’re really cooking with gas! With Elixir we can change the rotation of the chart, the colors, the viewing angle, the lighting, and more. We can even do all that on the fly by responding to mouseclick events and changing the parameters on the chart using ActionScript. This functionality allows the voter to spin the chart around and view it from different angles.
This is about as far as I’m going to go with the interface in this article series. To finish up, I’ll demonstrate how to use a different data transport technology, AMF, instead of XML. AMF is easier to use, particularly when you’re both reading and writing data – more on this in the next instalment!
NOTE:
AMF and XML aren’t the only ways that Flex can access data. Your applications can read JSON, text, AMF, or go direct to binary data through sockets. In other words, wherever your data is and whatever the format, Flex applications can get to it.

Going to AMF
Let’s use the free AMFPHP package to build an AMF service on the web server. AMFPHP comes with a built-in service browser, which I’ll show you in a minute, plus a directory where you put your services. In this case, we’ll add a new service to a new “votes” directory called VoteService.
Here’s the PHP code for VoteService:
  1.   
  2. include_once(AMFPHP_BASE . "shared/util/MethodTable.php"); 
      
  3. class VoteService 
      

  4.   
  5.   function getVotes() 
      
  6.   { 
      
  7.     return array( 'topic' => 'What is the best Star Wars movie?', 
      
  8.         'votes' => array(  
      
  9.             array( 'name' => 'Episode IV', 'count' => 150 ), 
      
  10.             array( 'name' => 'Episode V', 'count' => 250 ), 
      
  11.             array( 'name' => 'Episode III', 'count' => 50 ) 
      
  12.           ) 
      
  13.         ); 
      
  14.   } 
      
  15. }  

include_once(AMFPHP_BASE . "shared/util/MethodTable.php");   

class VoteService   

{   

  function getVotes()   

  {   

    return array( 'topic' => 'What is the best Star Wars movie?',   

        'votes' => array(    

            array( 'name' => 'Episode IV', 'count' => 150 ),   

            array( 'name' => 'Episode V', 'count' => 250 ),   

            array( 'name' => 'Episode III', 'count' => 50 )   

          )   

        );   

  }   

}
For this example, we’re just going to return the same data as we’d have gained from the XML file on the server. That way, if the results look the same we know everything’s in order.
To test the service, navigate to the amfphp/browser directory in your browser. You should see something like this.
The AMF data service viewed in the AMFPHP browser
Next, click on the votes/VoteService and hit the Call button. This causes the AMF browser to invoke the service and display the results, as shown here.
The AMF browser showing the vote service result
We can see that the data is returned correctly as an ActionScript object that’s very easy to manipulate.
From here, we can change the HTTPService from the original PieChart application to a RemoteObject service. The RemoteObject class connects to the AMF endpoint and then defines a bunch of methods. You can see this in the updated source:
  1.  
      
  2.   
  3.   creationComplete="voteRO.getVotes.send()"> 
      
  4.   endpoint="http://localhost/amfphp/gateway.php" 
      
  5.   source="votes.VoteService" destination="votes.VoteService" 
      
  6.   showBusyCursor="true"> 
      
  7.  
      
  8.  
      
  9.    
      
  10.   
  11.     showAllDataTips="true" 
      
  12.     dataProvider="{voteRO.getVotes.lastResult.votes}"> 
      
  13. ... 
      
  14.    
      
  15.   
   


  creationComplete="voteRO.getVotes.send()">   


  endpoint="http://localhost/amfphp/gateway.php"   

  source="votes.VoteService" destination="votes.VoteService"   

  showBusyCursor="true">   

   

   

     

  
    showAllDataTips="true"   

    dataProvider="{voteRO.getVotes.lastResult.votes}">   

...   

     



Written By:Jack Herrington
Jack Herrington is an engineer, author, and presenter who lives and works in the San Francisco Bay Area. He lives with his wife, daughter and two adopted dogs. When he's not writing software, books, or articles you can find him cycling, running, or in the pool training for triathlons. You can keep up with Jack's work and his writing at http://jackherrington.com.

Sunday

How To Optimize Websites


Google found that moving from a 10-result page loading in 0.4 seconds to a 30-result page loading in 0.9 seconds decreased traffic and ad revenues by 20% (Linden 2006). When the home page of Google Maps was reduced from 100KB to 70-80KB, traffic went up 10% in the first week, and an additional 25% in the following three weeks (Farber 2006).
Tests at Amazon revealed similar results: every 100 ms increase in load time of Amazon.com decreased sales by 1%. (Kohavi and Longbotham 2007).


It’s quite clear. Everyone hates slow websites. The question is, how can you make your WordPress website faster? Keep reading and I’ll show you how you can take proactive steps towards speeding up your site.

What Determines Website Page Speed?

The Yahoo! YSlow and Google Page Speed Mozilla Firefox plugins evaluate your site against the widely accepted rules of website performance. The problem is, they don’t tell you what to do with the information they provide.
So, I’ll break down the top performance recommendations and show you you can apply them to your website.
Let’s do it.
  1. Minimize the number of HTTP requests
  2. Optimize and correctly display images
  3. Minify HTML, CSS, and Javascript
  4. Use a Content Delivery Network
  5. Gzip and compress components
  6. Choose over @import
  7. Put stylesheets at the top
  8. Put scripts at the bottom
  9. Utilize browser caching
  10. Use CSS Sprites

1. Minimize the number of HTTP requests

Translation: Limit the number of files required to display your website
When someone visits your website, the corresponding files must be sent to that person’s browser. This includes CSS files, Javascript library references, and images.
As expected, every file you use to enhance your design detracts from its performance. Similary, WordPress plugins are notorious for injecting extraneous CSS code in the head of your site without giving you the option to manually add the required styles to your stylesheet.
The key takeaway is this: eliminate everything that’s unnecessary. If you’re using a plugin because you like, take a look at how it impacts your code. The extra page-load time may not be worth it.

2. Optimize and correctly display images

Translation: Make images as small as possible and don’t require the browser to resize them
Depending on the format, many images contain a ton of extraneous metadata that can drastically increase the size of the file. Many designers fail to compress their images before uploading them to the web, and the overall impact of this can be dramatic with image-intensive designs.
Another cardinal sin of inexperienced webmasters is to upload and serve an image far larger than what is required for the design. WordPress is an unfortunate enabler of this, as many novice website owners upload large images directly off of their digital cameras and utilize WordPress’s image resizing functionality to display a smaller version.
With free applications like Picnik and Image Optimizer at our disposal, there is simply no excuse not to resize and optimize! Visitors (and your server) will thank you.

3. Minify HTML, CSS, and Javascript

Translation: Remove all white space from code when possible before serving it to visitors
The spaces, tabs, and orderly structure used in code is to make it more human-readable. Servers and browsers don’t care about what the code looks like as long as it’s valid and executes without error. If you want your files to download faster, you can remove this whitespace before serving your code.
Since it would be impractical to remove white space from files that are constantly edited (unlike Javascript libraries like jQuery, which are almost always served minified), we’ll want to leverage a plugin like WP-Minify (good) or W3 Total Cache (best) to handle this at runtime without affecting the files we need to edit.
Whitespace is great for web design but in our code? Not so much.

4. Use a Content Delivery Network (CDN)

Translation: Use a CDN to lighten the load on your server and turbocharge its performance
A CDN is a high-performance network of servers across the globe that replicate the static assets of your website and serve them to visitors from the closest POP.
What?
I know, I know. The good news is that we don’t have to understand the mechanics behind Content Delivery Networks in order to understand their power: you have a team of servers distributing your static assets to visitors across the globe. I’ve written a post on making WordPress faster by integrating a CDN if you’re interested in further reading on the topic.
CDNs are among the most effective ways to absolutely turbocharge the speed of our sites. We can’t neglect the other areas of optimization in the process, so this should be treated as the crowning jewel atop your beautifully optimized website.

5. Gzip and compress components

Translation: Compress files at the server level before sending them to browsers
If you were instructed to hurl a piece of paper across the room as far as it can go, would you lightly crumple it or squeeze it with all your might? That’s right, you’d get your Hulk Smash on.
The sample principle applies here: we want to allow our webserver to compress our files before sending them to visitors. We can drop a few lines of code in our .htaccess file to accomplish this:
#Begin gzip and deflate

    AddOutputFilterByType DEFLATE text/html text/css application/x-javascript text/plain text/xml image/x-icon
This code might look a bit intimidating, but it’s actually pretty simple. We’re just checking to see if the Apache mod_deflate module exists and if so, electing to serve HTML, CSS, Javascript, plain text, and favicon files using gzip compression.
Note that this requires the Apache webserver and the mod_deflate module. To enable gzip compression with NGINX, ensure that the following lines exist inside of the appropriate directive:
server {
        gzip on;
        gzip_types text/html text/css application/x-javascript text/plain text/xml image/x-icon;
    }
Easy!

6. Choose over @import

Translation: Beware the suck of IE!
When including your stylesheets, always link to the files instead of using the @import reference. IE handles them differently by loading them as if the reference was at the bottom of the document. [sarcasm] Nice work, Microsoft! [/sarcasm]

7. Put stylesheets at the top

Translation: All interface-related stylesheet references should be included in the of your document
We never, ever, ever want to display unstyled content to visitors—not even for a split second. Files responsible for the appearance of our site should be loaded first so they can be applied to the HTML as it loads. Makes sense, right?
Nothing more to it.

8. Put scripts at the bottom

Translation: All functionality-related files can be loaded after our content is loaded
As we think through how to deliver our content to visitors as fast as possible and the subsequent steps that users will take, we will use the following priorities:
  1. Get content to visitors as fast as possible
  2. Don’t allow unstyled content to appear in the browser (put CSS in the )
  3. Load the files required for interaction (tabbed widgets, certain external API calls, etc.) last
The thinking behind this is simple: users aren’t going to interact with the content before they can see it!

9. Utilize browser caching

Urban Translation: Where the cache at?
Standard Translation: Don’t require browsers to pull down another copy of static files every time
With browser caching, we’re explicitly instructing browsers to hang onto particular files for a specified period of time. When the file is needed again, the browser is to pull from its local cache instead of requesting it from the server again.
Running a website without caching in place makes as much sense as driving to the store for a glass of water every time you’re thirsty. Not only is in impractical and short-sighted, it takes more work!
The ExpiresByType directive is used to tell browsers which files to cache and how long to hang onto them. The example below would tell our visitors’ browsers to hang onto HTML, CSS, Javascript, and images, and favicon for an hour (3600 seconds):

    ExpiresActive On
    ExpiresByType text/html M3600
    ExpiresByType text/css M3600
    ExpiresByType application/x-javascript M3600
    ExpiresByType image/bmp M3600
    ExpiresByType image/gif M3600
    ExpiresByType image/x-icon M3600
    ExpiresByType image/jpeg M3600
Again, the code above is for your .htaccess file on an Apache server. The corresponding settings in NGINX would look something like this:
location ~* \.(jpg|png|gif|jpeg|css|js)$ {
        expires 1h;
}
Boom.

10. Use CSS Sprites

Translation: Serve one highly optimized image for your design to minimize the performance impact
A CSS sprite is an an image comprised of other images used by your design as something of a map containing the coordinates of all the images. Some clever CSS is used to show the proper section of the sprite when your design is loaded.
There are fantastic articles on the topic available across the web that dive into the mechanics of CSS sprites and wonderful resources for creating them. SpriteMe is a utility that generates the sprite and code required to make it work. If you inspect the code for the nav menu on Pearsonified.com, you’ll see a great example of how to implement a CSS sprite.

Whew! Still reading?

If so, great! You’re well on your way to a much faster website. If you implement even a handful of the techniques outlined in this post, you will see an immediate and dramatic improvement in your site’s performance. It’s not important that we know how everything works from database calls to HTTP requests—I surely don’t—it’s important that we’re familiar enough with the concepts to work towards them on our sites.

Work smarter, not harder

You could spend a few months learning the ins and outs of web server architecture, how different browsers implement caching, and how to tie it all together…or you could simply install and configure the W3 Total Cache plugin by Frederick Townes (CTO of Mashable).
I can give no higher recommendation for a performance-related plugin than this one. The features could easily fill another post, but I’ll give you the important part: W3TC helps you thoroughly address 80% of the recommendations outlined in this post. There are other solid options for caching plugins, but W3TC stands head and shoulders above the rest.

sources curtsy: diythemes.com

Beyond Spot-Checking: Why LLM Applications Require Specialized Evaluation

  images generated by meta ai Building applications with Large Language Models (LLMs) feels deceptively fast at first. A single engineer can...