Zend_Form element to select an image

Hello. Without further ADO, I want to show how the item looks, which I am going to tell:

Zend_Form Element RadioImage

I decided to call it a RadioImage.

Recently needed to give the user the ability to download and select icons for the statuses of the products in the online store. Previously, the task of selecting small icons I have decided with the help of various jQuery plugins (this picture is not mine):

Element Select with icons

(and, by the way was very lazy and did not write a separate decorator/item, and just treated JavaScript ω).

But this time, icons can be different sizes and generally do not want to go into too much detail, and if you do select large images, it will stand out from the common form.

I remembered that I did this and went to check:
Checkboxes with images

In principle, a normal variant, but I think normal for us developers. For some it may not be clear why it takes such an intermediary as a checkbox. Plus, again, this is not a Zend_Form element type MultiImageCheckbox, just the generated html directly in the view script — no good. If useful the second time, you need to do on a human.

This time, I need to choose only one icon, so our item will not allow multiple choice (but it's not difficult to fix, creating another element on the basis of this, CheckImage, for example).

There is still one requirement is jQuery, I used to use the helper ZendX_JQuery view, but you can connect a file with js code using Zend_VIew_Helper_HeadScript.

Come on, code with comments. Start backwards — with the form:

application/forms/ProductStatus.php
the
<?php
class Form_ProductStatus extends Zend_Form
{
public function init()
{
$this->setMethod('post');
$this->setName('statusform');
$this->setAttrib('enctype', 'multipart/form-data');

$this->addElement('text', 'prodstatus_name', array(
'required' => true,
'label' => 'Status Name',
'filters' => array('StringTrim')
));

// Initialize our new item
$img = new App_Form_Element_RadioImage('prodstatus_icon', array(
'label' => 'Select Icon',
// The HTML attributes like this will be applied to each picture <img />
'width' => '48'
));

// BaseUrl think it is mainly in order
// if your app is NOT in the root of the web server
$bu = $this->getView()->baseUrl();

// for simplicity, removed scanning directory/DB query, 
// will show at once what should be an array
$icons = array(
"black_new.png" => $bu.'/icons/black_new.png',
"black_sale.png" => $bu.'/icons/black_sale.png',
"blue_new.png" => $bu.'/icons/blue_new.png',
"label_sale.png" => $bu.'/icons/label_sale.png',
"new_blue.png" => $bu.'/icons/new_blue.png',
"new_red.png" => $bu.'/icons/new_red.png',
"sale_blue.png" => $bu.'/icons/sale_blue.png',
"sale_green.png" => $bu.'/icons/sale_green.png',
"sale_yellow.png" => $bu.'/icons/sale_yellow.png',
"sticker_blue_sale.png" => $bu.'/icons/sticker_blue_sale.png'
);

// here $key is the  value  of the element when the form is submitted 
// i.e. the controller will come ["prodstatus_icon"] => $key (if the image is selected)
// $val is the path to the image to img tag i.e. <img src="$val"/>
foreach ($icons as $key => $val) {
// and just add each picture (as well as the options in the select element)
// you can of course add using the addMultiOptions() without a loop 
// but for clarity I've made a cycle
$img- > addMultiOption($key, $val);
}
$this->addElement($img);

$this->addElement('submit', 'Save');
}
}


Maybe at first glance it looks like a lot of code in a live project I have it takes a few lines:
the
 $img = new App_Form_Element_SelectImage('prodstatus_icon', array(
'label' => 'Select Icon',
'width' => '48'
));
$icons = App_Tool::scandir(PUBLIC_PATH.'/modules/products/icons', 'png');
foreach ($icons as $icon) {
$img- > addMultiOption($icon, $this->getView()->baseUrl().'/modules/products/icons/'.$icon);
}
$this->addElement($img);


I think the initialization of an element is simple enough — that, for reuse. Here is how it is implemented in the library:
App/Form/Element/RadioImage.php
the
<?php
require_once 'Zend/Form/Element/Multi.php';

/**
* RadioImage form element
*
* @category App
* @package App_Form
* @subpackage Element
*/
class App_Form_Element_RadioImage extends Zend_Form_Element_Multi
{
/**
* @var string
*/
public $helper = 'FormRadioImage';
}


By analogy with many built-in elements of Zend_Form, our item is the only interface to the helper FormRadioImage, and all the logic in it:

App/View/Helper/FormRadioImage.php
the
<?php
require_once 'Zend/View/Helper/FormElement.php';

/**
* @category App
* @package App_View
* @subpackage Helper
* @uses ZendX_Jquery
*/
class App_View_Helper_FormRadioImage extends Zend_View_Helper_FormElement
{
/**
* @param string|array $name the name of the element for the parameter "name" tag <input />
* @param mixed $value the Chosen default that would be 
* to mark the selected image.
* @param array|string $attribs Html attributes to all images.
* @param array $options an array containing the value and path for each image.
* @return string the resulting html
*/
public function formRadioImage($name, $value = null, $attribs = null, $options = null)
{

$info = $this- > _getInfo($name, $value, $attribs, $options);
extract($info); // name, value, attribs, options

// Make sure we have an array (with paths and values for images)
$options = (array) $options;

$xhtml = ";
$list = array();
// here is the main element bearing functionality, the rest of the interface
$list[] = '<input type="hidden" id="'.$name.'" name="'.$name.'" value="'.$value.'" />';

require_once 'Zend/Filter/Alnum.php';
$filter = new Zend_Filter_Alnum();

// You can specify a  CSS  class to illustrate vybrannoi element
// the default is class="selected"
$selectedClass = (isset($attribs['selectedClass']) 
&& !empty ($attribs['selectedClass']))?$attribs['selectedClass']:'selected';
$selectedClass = $filter- > filter($selectedClass);
if(!isset($attribs['class']))
$attribs['class'] = null;
// save specified when initializing the element's CSS classes (if specified)
$classBck = $attribs['class'];

// start add image
foreach ($options as $optVal => $imgPath) {

// generate the id for the tag <img />
$imgId = $id . '-' . $filter- > filter($optVal);

// if selected, add to the specified class still selected
if ($optVal == $value) {
$attribs['class'] .= "".$selectedClass;
}

// the code for pictures
$list[] = '<img '
. 'src="'.$imgPath.'" '
. 'id="'.$imgId.'" '
. 'rel="'.$optVal.'" '
. $this->_htmlAttribs($attribs)
. '/>';

// remove the class selected, what would the rest of the images were not selected
if(strstr($attribs['class'], $selectedClass))
$attribs['class'] = $classBck;
}
// Add the option to cancel the selection, you can sdelat here icon instead of text
$list[] = '<br /><a href=\"javascript\">Reset Selection</a>'.PHP_EOL;
$xhtml .= implode(PHP_EOL, $list);

// highlight the selected image with jQuery
// and substitute the value in the hidden element
$this->view->jQuery ()- > addOnLoad("
// click on the image
$('#$name-element img').click(function(){
$('#$name').val($(this).attr('rel'));
$('#$name-element img').removeClass('$selectedClass');
$(this).addClass('$selectedClass');
});
// cancel button selection
$('#$name-element a').click(function(){
$('#$name-element img').removeClass('$selectedClass');
$('#$name').val(")
return false;
});
");
// style for selected image (default)
// you can specify a different css class and describe it in CSS
$this- > view- > headStyle("
#$name-element img {cursor:pointer; border:3px solid white}
#$name-element img.selected {border:3px solid blue}
");

return $xhtml;
}
}


All. It seems nothing is forgotten.

Picture again that would not have to scroll up:

Zend_Form Element RadioImage


Thank you for your attention.
Article based on information from habrahabr.ru

Популярные сообщения из этого блога

Approval of WSUS updates: import, export, copy

The Hilbert curve vs. Z-order

Configuring a C++ project in Eclipse for example SFML application