0. Intro.
В процессе разработки достаточно часто нужно использовать различные кастомные селекты, инпуты, загрузщики файлов и прочее. В этом случае приходится писать дополнительные обработчики на стороне клиента, так как ZF из коробки не знает ничего, кроме стандартных элементов форм (капча есть исключение). В этой статье будет рассмотрено создание элемента на базе facebook-like TextboxList плагина для jQuery, который выглядит вот так:
1. Теория.
Собственно, для того, что бы создать новый элемент, нужно соблюсти два условия:- нужен класс элемента, наследуемый от Zend_Form_Element_Xhtml;
- view helper, который будет отвечать за отрисовку;
- название элемента должно быть в нашем namespace (в этом случае Eve_) и оно должно быть корректно настроено.
2. Практика.
2.1. Создаем Eve_Form_Element_TextboxList
Структура класса состоит из следующих основных частей:- указания помощника вида, который отрендерит элемент;
- задания опций по умолчанию;
- перегрузка метода для установки (либо объединения) опций (опционально);
- остальные опции\методы на этом этапе не нужны и их можно подсмотреть в Zend_Form_Element.
Исходник класса в листинге с комментариями:
class Eve_Form_Element_TextboxList extends Zend_Form_Element_Xhtml { /** * Имя хелпера * @var string */ public $helper = 'formTextboxList'; /** * Опции по-умолчанию * @var array */ public $options = array( 'js_main' => '/js/jquery.textboxlist.js', // путь к главному скрипту плагина 'js_autocomplete' => '/js/jquery.textboxlist.autocomplete.js', // путь к скрипту плагина для плагина (поддержка подсказок) 'js_growinginput' => '/js/jquery.growinginput.js', // зависимость скрипта 'use_autocompletion' => '0', // использовать подсказки или нет 'autocomplete_script' => null, // backend, откуда брать подсказки 'css_main' => '/css/textboxlist.css', // стили 'css_autocomplete' => '/css/textboxlist.autocomplete.css', ); /** * Высчитывает только указанные пользователем опции и их устанавливает * * @param array $options * @return Eve_Form_Element_TextboxList */ public function setOptions(array $options) { /** * В отличии от самого фреймворка, здесь выбираются только опции, которые были заданы * на этапе описания эелемента */ $diff = array_intersect_key($options, $this->options); $this->options = array_merge($this->options, $diff); /** * затем все кастомные опции необходимо удалить, иначе они попадут в html как аттрибуты элемента */ foreach ($diff as $key => $option) { unset ($options[$key]); } parent::setOptions($options); return $this; } }
2.2. Создаем помощник вида Eve_View_Helper_FormTextboxList
Класс должен иметь метод совпадающий с названием класса, который вызовется автоматически при обращении к помощнику.Код в листинге + комменты:
class Eve_View_Helper_FormTextboxList extends Zend_View_Helper_FormElement { /** * Generates a 'textboxList' 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 extracted 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 formTextboxList($name, $value = '', $attribs = null, $options = null) { $id = $name; $elemId = $this->view->escape($id); $xhtml = '<input type="text" name="' . $this->view->escape($name) . '" id="' . $this->view->escape($id) . '"'; // установка значения по умолчанию if (!empty($value)) { $xhtml .= ' value="' . $this->view->escape($value) . '"'; } // присвоение аттрибутов уже к html элементу $xhtml .= $this->_htmlAttribs($attribs); $xhtml .= '/>' . PHP_EOL; /** * Здесь стоит заметить, что код нуждается в дополнение, т.к. в случае, если на странице будет * больше одного такого элемента, то нет необходимости в повторной инициализации. */ // add content and end tag $xhtml .= $content . ($this->view->doctype()->isXhtml() ? '/>' : '>') . PHP_EOL; $this->view->headScript->appendFile($options['js_growinginput']); $this->view->headScript->appendFile($options['js_main']); $this->view->headScript->appendFile($options['js_autocomplete']); $this->view->headLink->appendStylesheet($options['css_main']); $this->view->headLink->appendStylesheet($options['css_autocomplete']); $xhtml .= '<script type="text/javascript"> var tl_' . $elemId . ' = new $.TextboxList("#' . $elemId. '", {unique: true, plugins: {autocomplete: {}}}); '; if ((int) $options['use_autocompletion'] == 1) { if (!$options['autocomplete_script']) { throw new Zend_View_Exception('No autocompletion backend is set for ' . __CLASS__ . ' plugin.'); } else { $.getJSON('" . $options['autocomplete_script'] . "', null, function (data) { tl.plugins['autocomplete'].setValues(data); tl.getContainer().removeClass('textboxlist-loading'); });"; } } $xhtml .= '</script>'; return $xhtml; } }
2.3. Инициализация через конфиг.
Она ничем не отличается от привычной многим:elements.categories.type = textboxList elements.categories.options.label = Categories elements.categories.options.use_autocompletion = 1 elements.categories.options.autocomplete_script = /categories/ajax/get-all/
3. Outro.
Таким образом, были создан отдельный элемент, который рисует совершенно новый тип инпутов.Jquery плагин можно найти вон там — http://devthought.com/projects/jquery/textboxlist/.
Плагин имеет достаточно опций, которые не были реализованы в рамках этого компонента.И да, плагин не под свободной лицензией.
UPD:1. обновлено (см. этот коммент
