diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index bcd1d7ee32d7a221529545dec900c8735c8af82d..3c8289899b0b036a2dbb4cccf1c9354564d07cce 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -1256,6 +1256,9 @@ class SelectionField extends FormField { $widgetClass = false; if ($config['widget'] == 'typeahead' && $config['multiselect'] == false) $widgetClass = 'TypeaheadSelectionWidget'; + elseif ($config['widget'] == 'textbox') + $widgetClass = 'TextboxSelectionWidget'; + return parent::getWidget($widgetClass); } @@ -1271,9 +1274,12 @@ class SelectionField extends FormField { foreach ($value as $k=>$v) { if (($i=$list->getItem((int) $k))) $selection[$i->getId()] = $i->getValue(); - elseif (isset($choices[$v])) - $selection[$v] = $choices[$v]; + elseif (isset($choices[$k])) + $selection[$k] = $choices[$k]; } + } elseif($value) { + //Assume invalid textbox input to be validated + $selection[] = $value; } // Don't return an empty array @@ -1339,7 +1345,16 @@ class SelectionField extends FormField { parent::validateEntry($entry); if (!$this->errors()) { $config = $this->getConfiguration(); - if ($config['typeahead'] + if ($config['widget'] == 'textbox') { + if ($entry && ( + !($k=key($entry)) + || !($i=$this->getList()->getItem((int) $k)) + )) { + $config = $this->getConfiguration(); + $this->_errors[] = $this->getLocal('validator-error', $config['validator-error']) + ?: __('Unknown or invalid input'); + } + } elseif ($config['typeahead'] && ($entered = $this->getWidget()->getEnteredValue()) && !in_array($entered, $entry)) $this->_errors[] = __('Select a value from the list'); @@ -1361,7 +1376,8 @@ class SelectionField extends FormField { 'required'=>false, 'default' => 'dropdown', 'choices'=>array( 'dropdown' => __('Drop Down'), - 'typeahead' =>__('Typeahead'), + 'typeahead' => __('Typeahead'), + 'textbox' => __('Text Input'), ), 'configuration'=>array( 'multiselect' => false, @@ -1372,6 +1388,17 @@ class SelectionField extends FormField { ), 'hint'=>__('Typeahead will work better for large lists') )), + 'validator-error' => new TextboxField(array( + 'id'=>5, 'label'=>__('Validation Error'), 'default'=>'', + 'configuration'=>array('size'=>40, 'length'=>80, + 'translatable'=>$this->getTranslateTag('validator-error') + ), + 'visibility' => new VisibilityConstraint( + new Q(array('widget__eq'=>'textbox')), + VisibilityConstraint::HIDDEN + ), + 'hint'=>__('Message shown to user if the item entered is not in the list') + )), 'prompt' => new TextboxField(array( 'id'=>3, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'', @@ -1403,21 +1430,27 @@ class SelectionField extends FormField { function getChoices($verbose=false) { if (!$this->_choices || $verbose) { - $this->_choices = array(); + $choices = array(); foreach ($this->getList()->getItems() as $i) - $this->_choices[$i->getId()] = $i->getValue(); + $choices[$i->getId()] = $i->getValue(); // Retired old selections $values = ($a=$this->getAnswer()) ? $a->getValue() : array(); if ($values && is_array($values)) { foreach ($values as $k => $v) { - if (!isset($this->_choices[$k])) { + if (!isset($choices[$k])) { if ($verbose) $v .= ' '.__('(retired)'); - $this->_choices[$k] = $v; + $choices[$k] = $v; } } } + + if ($verbose) // Don't cache + return $choices; + + $this->_choices = $choices; } + return $this->_choices; } @@ -1547,6 +1580,10 @@ class TypeaheadSelectionWidget extends ChoicesWidget { <?php } + function parsedValue() { + return array($this->getValue() => $this->getEnteredValue()); + } + function getValue() { $data = $this->field->getSource(); if (isset($data[$this->name])) diff --git a/include/class.forms.php b/include/class.forms.php index 3345669da755517199ec6a29d75ac76d8aa0147d..0f89971ec862f548d026beff74155422e94e93bb 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -2274,6 +2274,30 @@ class TextboxWidget extends Widget { } } + +class TextboxSelectionWidget extends TextboxWidget { + //TODO: Support multi-input e.g comma separated inputs + function render($options=array()) { + + if ($this->value && is_array($this->value)) + $this->value = current($this->value); + + parent::render($options); + } + + function getValue() { + + $value = parent::getValue(); + if (($i=$this->field->getList()->getItem((string) $value))) + $value = array($i->getId() => $i->getValue()); + elseif (($choices=$this->field->getChoices()) + && ($k=array_search($value, $choices))) + $value = array($k => $choices[$k]); + + return $value; + } +} + class PasswordWidget extends TextboxWidget { static $input_type = 'password';