* // Приклад 1. Опції беруться по урлу
* // Примітки:
* // - в даному прикладі встановлюється одна опція для того щоб в режимі редагування бачити в полі
* // яке текстове значення відповідає хіддену. Задача по вибірці цього значення лягає на ViewController.
* // - урл повинен віддавати JSON: [{value: 'value 1', title: 'title 1'}, ...]
* $form->addElement('autocomplete', 'state', array('label' => 'State', 'required' => true));
* $form->state->setDataUrl($this->url(array('action' => 'autocompleteState')));
* if (null !== ($state = $this->_getData('state'))) {
* if (null !== ($stateTitle = $this->_getDataObj()->tableDState->search($state, 'title'))) {
* $form->state->setTitle($stateTitle);
* }
* }
*
*
*
* // Приклад 2. Опції задано одразу у форматі array('value' => 'title', ...)
* $form->addElement('autocomplete', 'state', array('label' => 'State', 'required' => true));
* $form->state->setMultiOptions($this->_getDataObj()->getDState4Select());
*
*
*
* // Приклад 3. Опції повертає колбек у форматі [{value: 'value 1', title: 'title 1'}, ...]
* $form->addElement('autocomplete', 'state', array('label' => 'State', 'required' => true));
* $form->state->setDataCallback('getStates');
*
*
* Options that can be passed to script: 'autoFocus', 'delay', 'minLength', 'position'.
* Callbacks: 'renderItem', 'search', 'open', 'focus', 'select', 'close', 'change'.
*/
class Qs_Form_Element_Autocomplete extends Zend_Form_Element_Multi
{
// sources priority dataUrl, dataCallback, dataArray, multiOptions
protected $_dataUrl;
protected $_dataCallback;
protected $_dataArray;
protected $_title;
protected $_notFoundMessage = '"%value%" was not found in the haystack';
/**
* Sets url for ajax requests, data should be returned in format: [{value: 'value 1', title: 'title 1'}, ...]
* @param string $url
* @return Qs_Form_Element_Autocomplete
*/
public function setDataUrl($url)
{
$this->_dataUrl = $url;
$this->setRegisterInArrayValidator(false);
return $this;
}
public function getDataUrl()
{
return $this->_dataUrl;
}
/**
* Sets JavaScript callback for data requests.
* Callback should return result in format [{value: 'value 1', title: 'title 1'}, ...]
* @param string $callback
* @return Qs_Form_Element_Autocomplete
*/
public function setDataCallback($callback)
{
$this->_dataCallback = $callback;
$this->setRegisterInArrayValidator(false);
return $this;
}
public function getDataCallback()
{
return $this->_dataCallback;
}
/**
* Sets data for autocomplete.
* Supported formats:
* [[value: 'value 1', title: 'title 1', ...], ...]
* [value => [title: 'title 1', ...], ...]
* @throws Qs_Form_Element_Exception
* @param array $data
* @return Qs_Form_Element_Autocomplete
*/
public function setDataArray(array $data)
{
if (null !== $data && !is_array($data)) {
throw new Qs_Form_Element_Exception('Parameter $data should be array but "' . gettype($data) . '" provided');
}
$this->setRegisterInArrayValidator(false);
$this->_dataArray = array();
foreach ((array) $data as $value => $info) {
if (!array_key_exists('title', $info)) {
throw new Qs_Form_Element_Exception('Incorrect dataArray format, items should contain "title" field');
}
if (!array_key_exists('value', $info)) {
$info['value'] = $value;
}
$this->_dataArray[] = $info;
}
return $this;
}
public function getDataArray()
{
return $this->_dataArray;
}
public function getNotFoundMessage()
{
$translator = $this->getTranslator();
if (null !== $translator) {
return $translator->translate($this->_notFoundMessage);
}
return $this->_notFoundMessage;
}
public function setNotFoundMessage($message)
{
$this->_notFoundMessage = $message;
return $this;
}
public function loadDefaultDecorators()
{
if ($this->loadDefaultDecoratorsIsDisabled()) {
return;
}
$decorators = $this->getDecorators();
if (empty($decorators)) {
$this->addDecorator('JQuery_Autocomplete')
->addDecorator('Errors')
->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
->addDecorator('HtmlTag', array('tag' => 'dd', 'id' => $this->getName() . '-element'))
->addDecorator('Label', array('tag' => 'dt', 'disableFor' => true));
}
}
public function isValid($value, $context = null)
{
if ($this->_dataArray && !$this->_dataCallback && !$this->_dataUrl) {
if (!$this->getValidator('InArray')) {
$dataArray = $this->getDataArray();
$options = array();
foreach ($dataArray as $info) {
$options[] = $info['value'];
}
$this->addValidator('InArray', true, array($options));
}
}
$isValid = parent::isValid($value, $context);
if (is_array($context)) {
$display = Qs_Array::get($context, $this->getFullyQualifiedDisplayName());
$title = Qs_Array::get($context, $this->getFullyQualifiedTitleName());
if ($display != $title) {
$this->_messages['isEmpty'] = str_replace('%value%', $display, $this->getNotFoundMessage());
$isValid = false;
}
}
return $isValid;
}
public function getFullyQualifiedDisplayName()
{
return $this->_getSystemName($this->getFullyQualifiedName());
}
public function getFullyQualifiedTitleName()
{
return $this->_getSystemName($this->getFullyQualifiedDisplayName());
}
protected function _getSystemName($name)
{
if (false !== ($pos = strrpos($name, '['))) {
$pos++;
$_name = substr($name, 0, $pos) . '_' . substr($name, $pos);
} else {
$_name = '_' . $name;
}
return $_name;
}
public function getTitleId()
{
return $this->_getSystemId($this->getDisplayId());
}
public function getDisplayId()
{
return $this->_getSystemId($this->getId());
}
protected function _getSystemId($id)
{
if (false !== ($pos = strrpos($id, '-'))) {
$pos++;
$_id = substr($id, 0, $pos) . '_' . substr($id, $pos);
} else {
$_id = '_' . $id;
}
return $_id;
}
/**
* Sets display title
* @param string $title
* @return Qs_Form_Element_Autocomplete
*/
public function setTitle($title)
{
$this->_title = (string) $title;
return $this;
}
public function getTitle()
{
if (null === $this->_title) {
$this->_title = $this->_initTitle();
}
return $this->_title;
}
protected function _initTitle()
{
if (null === $this->_title) {
if ($this->_dataUrl || $this->_dataCallback) {
$this->_title = '';
} else if ($this->_getMultiOptions()) {
$this->_title = $this->getMultiOption($this->_value);
} else if ($this->_dataArray) {
foreach ($this->_dataArray as $item) {
if ($this->_value === $item['value']) {
$this->_title = $item['title'];
break;
}
}
}
}
$this->_title = (null === $this->_title) ? '' : $this->_title;
return $this->_title;
}
}