From f161729e21570233298768d633f5d005f6e70457 Mon Sep 17 00:00:00 2001 From: jamiesensei Date: Sun, 20 May 2007 11:48:02 +0000 Subject: [PATCH] new element for formslib selectgroups is a select drop down with options grouped into optgroups --- lib/form/selectgroups.php | 596 ++++++++++++++++++++++++++++++++++++++ lib/formslib.php | 1 + 2 files changed, 597 insertions(+) create mode 100644 lib/form/selectgroups.php diff --git a/lib/form/selectgroups.php b/lib/form/selectgroups.php new file mode 100644 index 0000000000..3516df091d --- /dev/null +++ b/lib/form/selectgroups.php @@ -0,0 +1,596 @@ + | +// | Bertrand Mansion | +// +----------------------------------------------------------------------+ +// +// $Id$ + +require_once('HTML/QuickForm/element.php'); + +/** + * Class to dynamically create an HTML SELECT with all options grouped in optgroups + * + * @author Adam Daniel + * @author Bertrand Mansion + * @version 1.0 + * @since PHP4.04pl1 + * @access public + */ +class MoodleQuickForm_selectgroups extends HTML_QuickForm_element { + + // {{{ properties + + /** + * Contains the select optgroups + * + * @var array + * @since 1.0 + * @access private + */ + var $_optGroups = array(); + + /** + * Default values of the SELECT + * + * @var string + * @since 1.0 + * @access private + */ + var $_values = null; + + /** + * html for help button, if empty then no help + * + * @var string + */ + var $_helpbutton=''; + var $_hiddenLabel=false; + + /** + * Class constructor + * + * @param string Select name attribute + * @param mixed Label(s) for the select + * @param mixed Data to be used to populate options + * @param mixed An array whose keys are labels for optgroups and whose values are arrays similar to those passed + * to the select element with keys that are values for options and values are strings for display. + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function MoodleQuickForm_selectgroups($elementName=null, $elementLabel=null, $optgrps=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_type = 'selectgroups'; + if (isset($optgrps)) { + $this->loadArrayOptGroups($optgrps); + } + } //end constructor + + // }}} + // {{{ apiVersion() + + + /** + * Sets the default values of the select box + * + * @param mixed $values Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return void + */ + function setSelected($values) + { + if (is_string($values) && $this->getMultiple()) { + $values = split("[ ]?,[ ]?", $values); + } + if (is_array($values)) { + $this->_values = array_values($values); + } else { + $this->_values = array($values); + } + } //end func setSelected + + // }}} + // {{{ getSelected() + + /** + * Returns an array of the selected values + * + * @since 1.0 + * @access public + * @return array of selected values + */ + function getSelected() + { + return $this->_values; + } // end func getSelected + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name' => $name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ getPrivateName() + + /** + * Returns the element name (possibly with brackets appended) + * + * @since 1.0 + * @access public + * @return string + */ + function getPrivateName() + { + if ($this->getAttribute('multiple')) { + return $this->getName() . '[]'; + } else { + return $this->getName(); + } + } //end func getPrivateName + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param mixed $values Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->setSelected($value); + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns an array of the selected values + * + * @since 1.0 + * @access public + * @return array of selected values + */ + function getValue() + { + return $this->_values; + } // end func getValue + + // }}} + // {{{ setSize() + + /** + * Sets the select field size, only applies to 'multiple' selects + * + * @param int $size Size of select field + * @since 1.0 + * @access public + * @return void + */ + function setSize($size) + { + $this->updateAttributes(array('size' => $size)); + } //end func setSize + + // }}} + // {{{ getSize() + + /** + * Returns the select field size + * + * @since 1.0 + * @access public + * @return int + */ + function getSize() + { + return $this->getAttribute('size'); + } //end func getSize + + // }}} + // {{{ setMultiple() + + /** + * Sets the select mutiple attribute + * + * @param bool $multiple Whether the select supports multi-selections + * @since 1.2 + * @access public + * @return void + */ + function setMultiple($multiple) + { + if ($multiple) { + $this->updateAttributes(array('multiple' => 'multiple')); + } else { + $this->removeAttribute('multiple'); + } + } //end func setMultiple + + // }}} + // {{{ getMultiple() + + /** + * Returns the select mutiple attribute + * + * @since 1.2 + * @access public + * @return bool true if multiple select, false otherwise + */ + function getMultiple() + { + return (bool)$this->getAttribute('multiple'); + } //end func getMultiple + + /** + * Loads the options from an associative array + * + * @param array $arr Associative array of options + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function loadArrayOptGroups($arr, $values=null) + { + if (!is_array($arr)) { + return PEAR::raiseError('Argument 1 of HTML_Select::loadArrayOptGroups is not a valid array'); + } + if (isset($values)) { + $this->setSelected($values); + } + foreach ($arr as $key => $val) { + // Warning: new API since release 2.3 + $this->addOptGroup($key, $val); + } + return true; + } + /** + * Adds a new OPTION to the SELECT + * + * @param string $text Display text for the OPTION + * @param string $value Value for the OPTION + * @param mixed $attributes Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function addOptGroup($text, $value, $attributes=null) + { + if (null === $attributes) { + $attributes = array('label' => $text); + } else { + $attributes = $this->_parseAttributes($attributes); + $this->_updateAttrArray($attributes, array('label' => $text)); + } + $index = count($this->_optGroups); + $this->_optGroups[$index] = array('attr' => $attributes); + $this->loadArrayOptions($index, $value); + } + + /** + * Loads the options from an associative array + * + * @param array $arr Associative array of options + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function loadArrayOptions($optgroup, $arr, $values=null) + { + if (!is_array($arr)) { + return PEAR::raiseError('Argument 1 of HTML_Select::loadArray is not a valid array'); + } + if (isset($values)) { + $this->setSelected($values); + } + foreach ($arr as $key => $val) { + // Warning: new API since release 2.3 + $this->addOption($optgroup, $val, $key); + } + return true; + } + + /** + * Adds a new OPTION to an optgroup + * + * @param string $text Display text for the OPTION + * @param string $value Value for the OPTION + * @param mixed $attributes Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function addOption($optgroup, $text, $value, $attributes=null) + { + if (null === $attributes) { + $attributes = array('value' => $value); + } else { + $attributes = $this->_parseAttributes($attributes); + if (isset($attributes['selected'])) { + // the 'selected' attribute will be set in toHtml() + $this->_removeAttr('selected', $attributes); + if (is_null($this->_values)) { + $this->_values = array($value); + } elseif (!in_array($value, $this->_values)) { + $this->_values[] = $value; + } + } + $this->_updateAttrArray($attributes, array('value' => $value)); + } + $this->_optGroups[$optgroup]['options'][] = array('text' => $text, 'attr' => $attributes); + } + + /** + * Returns the SELECT in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if ($this->_flagFrozen) { + return $this->getFrozenHtml(); + } else { + $tabs = $this->_getTabs(); + $strHtml = ''; + + if ($this->getComment() != '') { + $strHtml .= $tabs . '\n"; + } + + if (!$this->getMultiple()) { + $attrString = $this->_getAttrString($this->_attributes); + } else { + $myName = $this->getName(); + $this->setName($myName . '[]'); + $attrString = $this->_getAttrString($this->_attributes); + $this->setName($myName); + } + $strHtml .= $tabs; + if ($this->_hiddenLabel){ + $this->_generateId(); + $strHtml .= ''; + } + $strHtml .= '\n"; + foreach ($this->_optGroups as $optGroup) { + $strHtml .= $tabs . "\t_getAttrString($optGroup['attr'])) . '>'; + foreach ($optGroup['options'] as $option){ + if (is_array($this->_values) && in_array((string)$option['attr']['value'], $this->_values)) { + $this->_updateAttrArray($option['attr'], array('selected' => 'selected')); + } + $strHtml .= $tabs . "\t\t_getAttrString($option['attr']) . '>' . + $option['text'] . "\n"; + } + $strHtml .= $tabs . "\t\n"; + } + return $strHtml . $tabs . ''; + } + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + $value = array(); + if (is_array($this->_values)) { + foreach ($this->_values as $key => $val) { + for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { + if ((string)$val == (string)$this->_options[$i]['attr']['value']) { + $value[$key] = $this->_options[$i]['text']; + break; + } + } + } + } + $html = empty($value)? ' ': join('
', $value); + if ($this->_persistantFreeze) { + $name = $this->getPrivateName(); + // Only use id attribute if doing single hidden input + if (1 == count($value)) { + $id = $this->getAttribute('id'); + $idAttr = isset($id)? array('id' => $id): array(); + } else { + $idAttr = array(); + } + foreach ($value as $key => $item) { + $html .= '_getAttrString(array( + 'type' => 'hidden', + 'name' => $name, + 'value' => $this->_values[$key] + ) + $idAttr) . ' />'; + } + } + return $html; + } //end func getFrozenHtml + + // }}} + // {{{ exportValue() + + /** + * We check the options and return only the values that _could_ have been + * selected. We also return a scalar value if select is not "multiple" + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (is_null($value)) { + $value = $this->getValue(); + } elseif(!is_array($value)) { + $value = array($value); + } + if (is_array($value) && !empty($this->_optGroups)) { + $cleanValue = null; + foreach ($value as $v) { + foreach ($this->_optGroups as $optGroup){ + for ($i = 0, $optCount = count($optGroup['options']); $i < $optCount; $i++) { + if ($v == $optGroup['options'][$i]['attr']['value']) { + $cleanValue[] = $v; + break; + } + } + } + } + } else { + $cleanValue = $value; + } + if (is_array($cleanValue) && !$this->getMultiple()) { + return $this->_prepareValue($cleanValue[0], $assoc); + } else { + return $this->_prepareValue($cleanValue, $assoc); + } + } + + // }}} + // {{{ onQuickFormEvent() + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' == $event) { + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_submitValues); + // Fix for bug #4465 & #5269 + // XXX: should we push this to element::onQuickFormEvent()? + if (null === $value && (!$caller->isSubmitted() || !$this->getMultiple())) { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (null !== $value) { + $this->setValue($value); + } + return true; + } else { + return parent::onQuickFormEvent($event, $arg, $caller); + } + } + function setHiddenLabel($hiddenLabel){ + $this->_hiddenLabel = $hiddenLabel; + } + /** + * Automatically generates and assigns an 'id' attribute for the element. + * + * Currently used to ensure that labels work on radio buttons and + * checkboxes. Per idea of Alexander Radivanovich. + * Overriden in moodleforms to remove qf_ prefix. + * + * @access private + * @return void + */ + function _generateId() + { + static $idx = 1; + + if (!$this->getAttribute('id')) { + $this->updateAttributes(array('id' => 'id_'. substr(md5(microtime() . $idx++), 0, 6))); + } + } // end func _generateId + /** + * set html for help button + * + * @access public + * @param array $help array of arguments to make a help button + * @param string $function function name to call to get html + */ + function setHelpButton($helpbuttonargs, $function='helpbutton'){ + if (!is_array($helpbuttonargs)){ + $helpbuttonargs=array($helpbuttonargs); + }else{ + $helpbuttonargs=$helpbuttonargs; + } + //we do this to to return html instead of printing it + //without having to specify it in every call to make a button. + if ('helpbutton' == $function){ + $defaultargs=array('', '', 'moodle', true, false, '', true); + $helpbuttonargs=$helpbuttonargs + $defaultargs ; + } + $this->_helpbutton=call_user_func_array($function, $helpbuttonargs); + } + /** + * get html for help button + * + * @access public + * @return string html for help button + */ + function getHelpButton(){ + return $this->_helpbutton; + } + + /** + * Slightly different container template when frozen. Don't want to use a label tag + * with a for attribute in that case for the element label but instead use a div. + * Templates are defined in renderer constructor. + * + * @return string + */ + function getElementTemplateType(){ + if ($this->_flagFrozen){ + return 'static'; + } else { + return 'default'; + } + } +} +?> diff --git a/lib/formslib.php b/lib/formslib.php index dd0cd6ae86..7241e58f29 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -1593,6 +1593,7 @@ MoodleQuickForm::registerElementType('password', "$CFG->libdir/form/password.php MoodleQuickForm::registerElementType('passwordunmask', "$CFG->libdir/form/passwordunmask.php", 'MoodleQuickForm_passwordunmask'); MoodleQuickForm::registerElementType('radio', "$CFG->libdir/form/radio.php", 'MoodleQuickForm_radio'); MoodleQuickForm::registerElementType('select', "$CFG->libdir/form/select.php", 'MoodleQuickForm_select'); +MoodleQuickForm::registerElementType('selectgroups', "$CFG->libdir/form/selectgroups.php", 'MoodleQuickForm_selectgroups'); MoodleQuickForm::registerElementType('text', "$CFG->libdir/form/text.php", 'MoodleQuickForm_text'); MoodleQuickForm::registerElementType('textarea', "$CFG->libdir/form/textarea.php", 'MoodleQuickForm_textarea'); MoodleQuickForm::registerElementType('date_selector', "$CFG->libdir/form/dateselector.php", 'MoodleQuickForm_date_selector'); -- 2.39.5