Friday, November 25, 2011

[ZF] Adding timepickers to forms

Validating forms is important to preserve data integrity throughout a project. In a user could simply enter any kind of data, this would generate many bugs and be a big nuisance security-wise.

One of the tricky input types (or let's say Zend_Form_Element types) is anything that has to do with dates. There are many ways to write the date and the time... here's a simple difference example:
USA: mm/dd/yyyy
Europe: dd/mm/yyyy

So if a user enters 05/11/2011, how can we know if we're using the 5th of november or the 11th of may as the date?

To make it easier for everyone, a simple datetimepicker is available on Binpress (← click me and follow instructions). If you're here, I'm guessing you know how to deal with PHP, Zend Framework, and you know how to RTFM (and know what that means).

The picker is based on jQuery. It's beautiful and awesome. You can configure it anyway you want and it'll work.

Right. So now your user can just click on a calendar and drag nifty little knobs to graciously select the time.

However, there is no easy way to actually have a simple timepicker as a Zend_Form_Element object.

This time is now over, and it's actually quite simple to have only the timepicker.

First of all, let's go to where the DateTimePicker is. If you've followed the simple instructions, the folder should be: \project\library\Core\Form\Element. Now duplicate the DateTimePicker.php file and rename the new one to TimePicker.php.

In this file, do the obvious: change Core_Form_Element_DateTimePicker for Core_Form_Element_TimePicker and 'dateTimePicker' for 'timePicker'.

Do the same thing for this folder: \project\library\Core\View\Helper... duplicate the DateTimePicker.php file and rename the new one to TimePicker.php, and in this file change Core_View_Helper_dateTimePicker to Core_View_Helper_timePicker, dateTimePicker to timePicker, and '%s("#%s").datetimepicker(%s);' to '%s("#%s").timepicker(%s);'.

If you're still smart, basically copy everything and remove the "date" part of it to only keep the time. Genius.

Next, well, you're done!

If you had this for a datetimepicker:
$element = new Core_Form_Element_DateTimePicker(
 $name,
 array(
  'jQueryParams' => array(
   'dateFormat' => 'dd/mm/yy',
   'defaultDate' => date('d/m/Y'),
   'timeFormat' => 'hh:mm'
  )
 )
);
Now you can simply have this for a timepicker:
$element = new Core_Form_Element_TimePicker(
 $name,
 array(
  'jQueryParams' => array(
   'dateFormat' => '',
   'defaultDate' => date('hh:mm'),
   'timeFormat' => 'hh:mm'
  )
 )
);
Oh, and just to make sure everything stays safe, let's add a little validator:
$element->addValidator('Date', true, array('format' => 'H:m'));
There you have it, a shiny little timepicker! If not, then try again or ask for help.

Now you can easily create sliders in a form so people can enter the time it took them to do something. Eat a donut, make coffee, take a bathroom break, go to work, sleep, anything! Awesome!

Friday, November 11, 2011

[ZF] Containing form elements in DIVs (or other HTML tags) with classes

Long time, no see.

So, let's say you're building a dynamic form and would like each dt (label) and dd (input field) pair to be grouped in a div,with one or more specific classes added to this div.

It's quite easy, actually!
// Wrap element in div with classes
$element->addDecorator(
array('openDiv' =>'HtmlTag'),
array(
'tag' => 'div',
'openOnly' => true,
'class' => $attrib_class
)
);
$element->addDecorator(
array('closeDiv' =>'HtmlTag'),
array('tag' => 'div', 'closeOnly' => true)
);

Considering your custom class name(s) are in the $attrib_class variable, this will output something similar to this:
<div class="class-1 class-2">
<dt id="item-id-label">
<label for="item-id">label</label>
</dt>
<dd id="item-id-element">
<input type="text" name="item-id" id="item-id" value="">
</dd>
</div>

And there you have it, customizable form elements!