diff --git a/_test/tests/inc/form/dropdownelement.test.php b/_test/tests/inc/form/dropdownelement.test.php new file mode 100644 index 0000000000000000000000000000000000000000..989469182c7a52a70f030bf3870d42f966173a2c --- /dev/null +++ b/_test/tests/inc/form/dropdownelement.test.php @@ -0,0 +1,69 @@ +<?php + +use dokuwiki\Form; + +class form_dropdownelement_test extends DokuWikiTest { + + function test_defaults() { + $form = new Form\Form(); + + // basic tests + $options = array ('first', 'second', 'third'); + $element = $form->addDropdown('foo', $options, 'label text'); + $this->assertEquals('first', $element->val()); + $element->val('second'); + $this->assertEquals('second', $element->val()); + $element->val('nope'); + $this->assertEquals('first', $element->val()); + + // associative array + $options = array ('first'=>'A first Label', 'second'=>'The second Label', 'third'=>'Just 3'); + $element->options($options); + $this->assertEquals('first', $element->val()); + $element->val('second'); + $this->assertEquals('second', $element->val()); + $element->val('nope'); + $this->assertEquals('first', $element->val()); + + // HTML + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $select = $pq->find('select[name=foo]'); + $this->assertTrue($select->length == 1); + $this->assertEquals('first', $select->val()); + + $options = $pq->find('option'); + $this->assertTrue($options->length == 3); + + $option = $pq->find('option[selected=selected]'); + $this->assertTrue($option->length == 1); + $this->assertEquals('first', $option->val()); + $this->assertEquals('A first Label', $option->text()); + + $label = $pq->find('label'); + $this->assertTrue($label->length == 1); + $this->assertEquals('label text', $label->find('span')->text()); + } + + /** + * check that posted values overwrite preset default + */ + function test_prefill() { + global $INPUT; + $INPUT->post->set('foo', 'second'); + + $form = new Form\Form(); + $options = array ('first'=>'A first Label', 'second'=>'The second Label', 'third'=>'Just 3'); + $element = $form->addDropdown('foo', $options, 'label text')->val('third'); + $this->assertEquals('third', $element->val()); + + $html = $form->toHTML(); + $pq = phpQuery::newDocumentXHTML($html); + + $option = $pq->find('option[selected=selected]'); + $this->assertTrue($option->length == 1); + $this->assertEquals('second', $option->val()); + $this->assertEquals('The second Label', $option->text()); + } +} diff --git a/inc/Form/DropdownElement.php b/inc/Form/DropdownElement.php new file mode 100644 index 0000000000000000000000000000000000000000..fc9ce54ec9e767a80bbbd004d1b8f10e92a35051 --- /dev/null +++ b/inc/Form/DropdownElement.php @@ -0,0 +1,113 @@ +<?php +namespace dokuwiki\Form; + +/** + * Class DropdownElement + * + * Represents a HTML select. Please note that this does not support multiple selected options! + * + * @package dokuwiki\Form + */ +class DropdownElement extends InputElement { + + protected $options = array(); + + protected $value = ''; + + /** + * @param string $name The name of this form element + * @param string $options The available options + * @param string $label The label text for this element (will be autoescaped) + */ + public function __construct($name, $options, $label = '') { + parent::__construct('dropdown', $name, $label); + $this->options($options); + } + + /** + * Get or set the options of the Dropdown + * + * Options can be given as associative array (value => label) or as an + * indexd array (label = value). + * + * @param null|array $options + * @return $this|array + */ + public function options($options = null) { + if($options === null) return $this->options; + if(!is_array($options)) throw new \InvalidArgumentException('Options have to be an array'); + $this->options = array(); + + foreach($options as $key => $val) { + if(is_int($key)) { + $this->options[$val] = (string) $val; + } else { + $this->options[$key] = (string) $val; + } + } + $this->val(''); // set default value (empty or first) + return $this; + } + + /** + * Gets or sets an attribute + * + * When no $value is given, the current content of the attribute is returned. + * An empty string is returned for unset attributes. + * + * When a $value is given, the content is set to that value and the Element + * itself is returned for easy chaining + * + * @param string $name Name of the attribute to access + * @param null|string $value New value to set + * @return string|$this + */ + public function attr($name, $value = null) { + if(strtolower($name) == 'multiple') { + throw new \InvalidArgumentException('Sorry, the dropdown element does not support the "multiple" attribute'); + } + return parent::attr($name, $value); + } + + /** + * Get or set the current value + * + * When setting a value that is not defined in the options, the value is ignored + * and the first option's value is selected instead + * + * @param null|string $value The value to set + * @return $this|string + */ + public function val($value = null) { + if($value === null) return $this->value; + + if(isset($this->options[$value])) { + $this->value = $value; + } else { + // unknown value set, select first option instead + $keys = array_keys($this->options); + $this->value = (string) array_shift($keys); + } + + return $this; + } + + /** + * Create the HTML for the select it self + * + * @return string + */ + protected function mainElementHTML() { + if($this->useInput) $this->prefillInput(); + + $html = '<select ' . buildAttributes($this->attrs()) . '>'; + foreach($this->options as $key => $val) { + $selected = ($key == $this->value) ? ' selected="selected"' : ''; + $html .= '<option' . $selected . ' value="' . hsc($key) . '">' . hsc($val) . '</option>'; + } + $html .= '</select>'; + + return $html; + } + +} diff --git a/inc/Form/Form.php b/inc/Form/Form.php index 7eaa53041ff6685d2ba760f494d44f3386b474d6..6f83e9014f6d762bc2e577b30fb4a6cc72b1c60a 100644 --- a/inc/Form/Form.php +++ b/inc/Form/Form.php @@ -221,6 +221,19 @@ class Form extends Element { return $this->addElement(new CheckableElement('checkbox', $name, $label), $pos); } + /** + * Adds a dropdown field + * + * @param $name + * @param array $options + * @param string $label + * @param int $pos + * @return DropdownElement + */ + public function addDropdown($name, $options, $label = '', $pos = -1) { + return $this->addElement(new DropdownElement($name, $options, $label), $pos); + } + /** * Adds a textarea field *