2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * select type form element
21 * Class to dynamically create an HTML SELECT with all options grouped in optgroups
24 * @copyright 2007 Jamie Pratt <me@jamiep.org>
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 require_once('HTML/QuickForm/element.php');
31 * select type form element
33 * Class to dynamically create an HTML SELECT with all options grouped in optgroups
37 * @copyright 2007 Jamie Pratt <me@jamiep.org>
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 class MoodleQuickForm_selectgroups
extends HTML_QuickForm_element
{
42 /** @var bool add choose option */
43 var $showchoose = false;
45 /** @var array Contains the select optgroups */
46 var $_optGroups = array();
48 /** @var string Default values of the SELECT */
51 /** @var string html for help button, if empty then no help */
54 /** @var bool if true label will be hidden */
55 var $_hiddenLabel=false;
60 * @param string $elementName Select name attribute
61 * @param mixed $elementLabel Label(s) for the select
62 * @param array $optgrps Data to be used to populate options
63 * @param mixed $attributes Either a typical HTML attribute string or an associative array
64 * @param bool $showchoose add standard moodle "Choose..." option as first item
66 function MoodleQuickForm_selectgroups($elementName=null, $elementLabel=null, $optgrps=null, $attributes=null, $showchoose=false)
68 $this->showchoose
= $showchoose;
69 HTML_QuickForm_element
::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
70 $this->_persistantFreeze
= true;
71 $this->_type
= 'selectgroups';
72 if (isset($optgrps)) {
73 $this->loadArrayOptGroups($optgrps);
78 * Sets the default values of the select box
80 * @param mixed $values Array or comma delimited string of selected values
82 function setSelected($values)
84 if (is_string($values) && $this->getMultiple()) {
85 $values = preg_split("/[ ]?,[ ]?/", $values);
87 if (is_array($values)) {
88 $this->_values
= array_values($values);
90 $this->_values
= array($values);
95 * Returns an array of the selected values
97 * @return array of selected values
99 function getSelected()
101 return $this->_values
;
105 * Sets the input field name
107 * @param string $name Input field name attribute
109 function setName($name)
111 $this->updateAttributes(array('name' => $name));
115 * Returns the element name
121 return $this->getAttribute('name');
125 * Returns the element name (possibly with brackets appended)
129 function getPrivateName()
131 if ($this->getAttribute('multiple')) {
132 return $this->getName() . '[]';
134 return $this->getName();
139 * Sets the value of the form element
141 * @param mixed $value Array or comma delimited string of selected values
143 function setValue($value)
145 $this->setSelected($value);
149 * Returns an array of the selected values
151 * @return array of selected values
155 return $this->_values
;
159 * Sets the select field size, only applies to 'multiple' selects
161 * @param int $size Size of select field
163 function setSize($size)
165 $this->updateAttributes(array('size' => $size));
169 * Returns the select field size
175 return $this->getAttribute('size');
179 * Sets the select mutiple attribute
181 * @param bool $multiple Whether the select supports multi-selections
183 function setMultiple($multiple)
186 $this->updateAttributes(array('multiple' => 'multiple'));
188 $this->removeAttribute('multiple');
193 * Returns the select mutiple attribute
195 * @return bool true if multiple select, false otherwise
197 function getMultiple()
199 return (bool)$this->getAttribute('multiple');
203 * Loads the options from an associative array
205 * @param array $arr Associative array of options
206 * @param mixed $values (optional) Array or comma delimited string of selected values
207 * @return PEAR_Error|bool on error or true
210 function loadArrayOptGroups($arr, $values=null)
212 if (!is_array($arr)) {
213 return self
::raiseError('Argument 1 of HTML_Select::loadArrayOptGroups is not a valid array');
215 if (isset($values)) {
216 $this->setSelected($values);
218 foreach ($arr as $key => $val) {
219 // Warning: new API since release 2.3
220 $this->addOptGroup($key, $val);
226 * Adds a new OPTION to the SELECT
228 * @param string $text Display text for the OPTION
229 * @param string $value Value for the OPTION
230 * @param mixed $attributes Either a typical HTML attribute string
231 * or an associative array
233 function addOptGroup($text, $value, $attributes=null)
235 if (null === $attributes) {
236 $attributes = array('label' => $text);
238 $attributes = $this->_parseAttributes($attributes);
239 $this->_updateAttrArray($attributes, array('label' => $text));
241 $index = count($this->_optGroups
);
242 $this->_optGroups
[$index] = array('attr' => $attributes);
243 $this->loadArrayOptions($index, $value);
247 * Loads the options from an associative array
249 * @param string $optgroup name of the options group
250 * @param array $arr Associative array of options
251 * @param mixed $values (optional) Array or comma delimited string of selected values
252 * @return PEAR_Error|bool on error or true
255 function loadArrayOptions($optgroup, $arr, $values=null)
257 if (!is_array($arr)) {
258 return self
::raiseError('Argument 1 of HTML_Select::loadArray is not a valid array');
260 if (isset($values)) {
261 $this->setSelected($values);
263 foreach ($arr as $key => $val) {
264 // Warning: new API since release 2.3
265 $this->addOption($optgroup, $val, $key);
271 * Adds a new OPTION to an optgroup
273 * @param string $optgroup name of the option group
274 * @param string $text Display text for the OPTION
275 * @param string $value Value for the OPTION
276 * @param mixed $attributes Either a typical HTML attribute string
277 * or an associative array
279 function addOption($optgroup, $text, $value, $attributes=null)
281 if (null === $attributes) {
282 $attributes = array('value' => $value);
284 $attributes = $this->_parseAttributes($attributes);
285 if (isset($attributes['selected'])) {
286 // the 'selected' attribute will be set in toHtml()
287 $this->_removeAttr('selected', $attributes);
288 if (is_null($this->_values
)) {
289 $this->_values
= array($value);
290 } elseif (!in_array($value, $this->_values
)) {
291 $this->_values
[] = $value;
294 $this->_updateAttrArray($attributes, array('value' => $value));
296 $this->_optGroups
[$optgroup]['options'][] = array('text' => $text, 'attr' => $attributes);
300 * Returns the SELECT in HTML
306 if ($this->_flagFrozen
) {
307 return $this->getFrozenHtml();
309 $tabs = $this->_getTabs();
312 if ($this->getComment() != '') {
313 $strHtml .= $tabs . '<!-- ' . $this->getComment() . " //-->\n";
316 if (!$this->getMultiple()) {
317 $attrString = $this->_getAttrString($this->_attributes
);
319 $myName = $this->getName();
320 $this->setName($myName . '[]');
321 $attrString = $this->_getAttrString($this->_attributes
);
322 $this->setName($myName);
325 if ($this->_hiddenLabel
){
326 $this->_generateId();
327 $strHtml .= '<label class="accesshide" for="'.$this->getAttribute('id').'" >'.
328 $this->getLabel().'</label>';
330 $strHtml .= '<select' . $attrString . ">\n";
331 if ($this->showchoose
) {
332 $strHtml .= $tabs . "\t\t<option value=\"\">" . get_string('choose') . "...</option>\n";
334 foreach ($this->_optGroups
as $optGroup) {
335 if (empty($optGroup['options'])) {
339 $strHtml .= $tabs . "\t<optgroup" . ($this->_getAttrString($optGroup['attr'])) . '>';
340 foreach ($optGroup['options'] as $option){
341 if (is_array($this->_values
) && in_array((string)$option['attr']['value'], $this->_values
)) {
342 $this->_updateAttrArray($option['attr'], array('selected' => 'selected'));
344 $strHtml .= $tabs . "\t\t<option" . $this->_getAttrString($option['attr']) . '>' .
345 $option['text'] . "</option>\n";
347 $strHtml .= $tabs . "\t</optgroup>\n";
349 return $strHtml . $tabs . '</select>';
354 * Returns the value of field without HTML tags
358 function getFrozenHtml()
361 if (is_array($this->_values
)) {
362 foreach ($this->_values
as $key => $val) {
363 foreach ($this->_optGroups
as $optGroup) {
364 for ($i = 0, $optCount = count($optGroup['options']); $i < $optCount; $i++
) {
365 if ((string)$val == (string)$optGroup['options'][$i]['attr']['value']) {
366 $value[$key] = $optGroup['options'][$i]['text'];
373 $html = empty($value)?
' ': join('<br />', $value);
374 if ($this->_persistantFreeze
) {
375 $name = $this->getPrivateName();
376 // Only use id attribute if doing single hidden input
377 if (1 == count($value)) {
378 $id = $this->getAttribute('id');
379 $idAttr = isset($id)?
array('id' => $id): array();
383 foreach ($value as $key => $item) {
384 $html .= '<input' . $this->_getAttrString(array(
387 'value' => $this->_values
[$key]
388 ) +
$idAttr) . ' />';
395 * We check the options and return only the values that _could_ have been
396 * selected. We also return a scalar value if select is not "multiple"
398 * @param array $submitValues submitted values
399 * @param bool $assoc if true the retured value is associated array
402 function exportValue(&$submitValues, $assoc = false)
404 if (empty($this->_optGroups
)) {
405 return $this->_prepareValue(null, $assoc);
408 $value = $this->_findValue($submitValues);
409 if (is_null($value)) {
410 $value = $this->getValue();
412 $value = (array)$value;
415 foreach ($value as $v) {
416 foreach ($this->_optGroups
as $optGroup){
417 if (empty($optGroup['options'])) {
420 foreach ($optGroup['options'] as $option) {
421 if ((string)$option['attr']['value'] === (string)$v) {
422 $cleaned[] = (string)$option['attr']['value'];
429 if (empty($cleaned)) {
430 return $this->_prepareValue(null, $assoc);
432 if ($this->getMultiple()) {
433 return $this->_prepareValue($cleaned, $assoc);
435 return $this->_prepareValue($cleaned[0], $assoc);
440 * Called by HTML_QuickForm whenever form event is made on this element
442 * @param string $event Name of event
443 * @param mixed $arg event arguments
444 * @param object $caller calling object
447 function onQuickFormEvent($event, $arg, &$caller)
449 if ('updateValue' == $event) {
450 $value = $this->_findValue($caller->_constantValues
);
451 if (null === $value) {
452 $value = $this->_findValue($caller->_submitValues
);
453 // Fix for bug #4465 & #5269
454 // XXX: should we push this to element::onQuickFormEvent()?
455 if (null === $value && (!$caller->isSubmitted() ||
!$this->getMultiple())) {
456 $value = $this->_findValue($caller->_defaultValues
);
459 if (null !== $value) {
460 $this->setValue($value);
464 return parent
::onQuickFormEvent($event, $arg, $caller);
469 * Sets label to be hidden
471 * @param bool $hiddenLabel sets if label should be hidden
473 function setHiddenLabel($hiddenLabel){
474 $this->_hiddenLabel
= $hiddenLabel;
478 * get html for help button
480 * @return string html for help button
482 function getHelpButton(){
483 return $this->_helpbutton
;
487 * Slightly different container template when frozen. Don't want to use a label tag
488 * with a for attribute in that case for the element label but instead use a div.
489 * Templates are defined in renderer constructor.
493 function getElementTemplateType(){
494 if ($this->_flagFrozen
){