/** * Renders a dropdown list, including support for multiple choices. * * Configuration options: * * In addition to the standard pieform element configuration options, the select element * can take these. Each one must include an "options", "optgroups", or "optionurl" * parameter, because otherwise it won't have any options. * * - "options" (array): The list of items in the menu. A little confusingly, the array key * for each array entry is used as the "value" attribute for the <option> tag. Each array * value should usually be a string, in which case it will be displayed as the text between * the <option> tags. Or for more advanced functionality each array value can be an array * with these keys: * --- "value": The string to display inside the <option> tags * --- "disabled" (boolean default false): Set to true to disable this option * --- "style": CSS styling to set on this option * --- "label": sets a "label" attribute on the <option> tag * * - "optgroups" (array of arrays): Provide this INSTEAD of "options" if you want to use * optgroups. This should be an array of arrays. Each entry in the array represents an * optgroup (the key is ignored). Each optgroup array should contain an item with the * key "label", which will be the user-displayed label, and an item with the key "options", * which should be a list of options to go in that outgroup, with the same format as a * standard "options" array. * * - "multiple" (boolean, default false): Indicates whether to allow multiple items to be selected * * - "collapseifoneoption" (boolean, default true): If there's only one option, print it as a string * instead of as a menu. * * - "allowother" (boolean, default false): Says to add an "other" free text field to the menu. If there * is a menu option with value "other", then selecting this will display the free text * field. If there is no menu option with value "other", one will be added to the option * list. * * - "width" (deprecated): How wide to make this select element in pixels. Better to do this with CSS. * * - "height" (deprecated): How tall to make this select element in pixels. Better to do this with CSS. * * @todo Currently, putting a junk defaultvalue/value for a multiple select * does not trigger any kind of error, it should perhaps trigger a * Pieform::info * * @param Pieform $form The form to render the element for * @param array $element The element to render * @return string The HTML for the element */ function pieform_element_select(Pieform $form, $element) { if (!empty($element['multiple'])) { $element['name'] .= '[]'; } if (!empty($element['allowother']) and !isset($element['options']['other'])) { $element['options']['other'] = get_string('element.select.other', 'pieforms'); } $optionsavailable = true; $options = pieform_element_select_get_options($element); if (empty($options)) { $optionsavailable = false; Pieform::info('Select elements should have at least one option'); } if (!empty($element['collapseifoneoption']) && is_array($options) && count($options) == 1) { foreach ($options as $key => $value) { if (is_array($value)) { $value = $value['value']; } $result = Pieform::hsc($value) . '<input type="hidden" id="' . $form->make_id($element, true) . '" name="' . Pieform::hsc($element['name']) . '" value="' . Pieform::hsc($key) . '">'; } return $result; } $result = '<select' . $form->element_attributes($element) . (!empty($element['multiple']) ? ' multiple="multiple"' : '') . (!empty($element['allowother']) ? ' onChange="pieform_select_other(this);"' : '') . (!empty($element['width']) ? ' style="width: ' . $element['width'] . 'px;' : ' style="') . (!empty($element['height']) ? ' height: ' . $element['height'] . 'px;"' : '"') . ">\n"; if (!$optionsavailable) { $result .= "\t<option></option>\n</select>"; return $result; } $values = $form->get_value($element); $optionselected = false; if (!empty($element['allowother'])) { $use_other = $values; foreach ($element['options'] as $key => $value) { if (!is_array($values) && $key == $values || is_array($values) && in_array($key, $values)) { unset($use_other); break; } } if (isset($use_other)) { $values = 'other'; } } if (empty($element['optgroups'])) { $result .= pieform_element_select_render_options($element['options'], $values, $optionselected, $element); } else { foreach ($element['optgroups'] as $optgroup) { $result .= "\t<optgroup label=\"" . hsc($optgroup['label']) . '">' . "\n" . pieform_element_select_render_options($optgroup['options'], $values, $optionselected, $element) . "\t</optgroup>\n"; } } if (!$optionselected && !is_array($values) && $values !== null) { Pieform::info('Invalid value for select "' . $element['name'] . '"'); } $result .= '</select>'; if (!empty($element['allowother'])) { $other_attrib = array('name' => $element['name'] . '_other', 'id' => $element['id'] . '_other'); if (isset($use_other)) { $other_value = ' value="' . hsc($use_other) . '"'; } else { $other_attrib['class'] = 'hidden'; $other_value = ''; } $result .= '<label for="' . $element['id'] . '_other" class="accessible-hidden">' . get_string('licenseotherurl') . '</label>' . '<input type="text"' . $form->element_attributes($other_attrib) . $other_value . ">\n"; } return $result; }