/**
* Dropdown of values in an array
*
* @param $name select name
* @param $elements array of elements to display
* @param $options array of possible options:
* - value : integer / preselected value (default 0)
* - used : array / Already used items ID: not to display in dropdown (default empty)
* - readonly : boolean / used as a readonly item (default false)
* - on_change : string / value to transmit to "onChange"
* - multiple : boolean / can select several values (default false)
* - size : integer / number of rows for the select (default = 1)
* - display : boolean / display or return string
* - other : boolean or string if not false, then we can use an "other" value
* if it is a string, then the default value will be this string
* - rand : specific rand if needed (default is generated one)
* - width : specific width needed (default not set)
* - emptylabel : empty label if empty displayed (default self::EMPTY_VALUE)
* - display_emptychoice : display empty choice (default false)
* - tooltip : string / message to add as tooltip on the dropdown (default '')
* - option_tooltips : array / message to add as tooltip on the dropdown options. Use the same keys as for the $elements parameter, but none is mandotary. Missing keys will just be ignored and no tooltip will be added. To add a tooltip on an option group, is the '__optgroup_label' key inside the array describing option tooltips : 'optgroupname1' => array('__optgroup_label' => 'tooltip for option group') (default empty)
*
* Permit to use optgroup defining items in arrays
* array('optgroupname' => array('key1' => 'val1',
* 'key2' => 'val2'),
* 'optgroupname2' => array('key3' => 'val3',
* 'key4' => 'val4'))
**/
static function showFromArray($name, array $elements, $options = array())
{
$param['value'] = '';
$param['values'] = array('');
$param['tooltip'] = '';
$param['option_tooltips'] = array();
$param['used'] = array();
$param['readonly'] = false;
$param['on_change'] = '';
$param['width'] = '';
$param['multiple'] = false;
$param['size'] = 1;
$param['display'] = true;
$param['other'] = false;
$param['rand'] = mt_rand();
$param['emptylabel'] = self::EMPTY_VALUE;
$param['display_emptychoice'] = false;
if (is_array($options) && count($options)) {
if (isset($options['value']) && strlen($options['value'])) {
$options['values'] = array($options['value']);
unset($options['value']);
}
foreach ($options as $key => $val) {
$param[$key] = $val;
}
}
if ($param['other'] !== false) {
$other_select_option = $name . '_other_value';
$param['on_change'] .= "displayOtherSelectOptions(this, \"{$other_select_option}\");";
// If $param['other'] is a string, then we must highlight "other" option
if (is_string($param['other'])) {
if (!$param["multiple"]) {
$param['values'] = array($other_select_option);
} else {
$param['values'][] = $other_select_option;
}
}
}
$param['option_tooltips'] = Html::entities_deep($param['option_tooltips']);
if ($param["display_emptychoice"]) {
$elements = array(0 => $param['emptylabel']) + $elements;
}
if ($param["multiple"]) {
$field_name = $name . "[]";
} else {
$field_name = $name;
}
$output = '';
// readonly mode
$field_id = Html::cleanId("dropdown_" . $name . $param['rand']);
if ($param['readonly']) {
$to_display = array();
foreach ($param['values'] as $value) {
$output .= "<input type='hidden' name='{$field_name}' value='{$value}'>";
if (isset($elements[$value])) {
$to_display[] = $elements[$value];
}
}
$output .= implode('<br>', $to_display);
} else {
$output .= "<select name='{$field_name}' id='{$field_id}'";
if ($param['tooltip']) {
$output .= ' title="' . Html::entities_deep($param['tooltip']) . '"';
}
if (!empty($param["on_change"])) {
$output .= " onChange='" . $param["on_change"] . "'";
}
if (is_int($param["size"]) && $param["size"] > 0) {
$output .= " size='" . $param["size"] . "'";
}
if ($param["multiple"]) {
$output .= " multiple";
}
$output .= '>';
$max_option_size = 0;
foreach ($elements as $key => $val) {
// optgroup management
if (is_array($val)) {
$opt_goup = Html::entities_deep($key);
if ($max_option_size < strlen($opt_goup)) {
$max_option_size = strlen($opt_goup);
}
$output .= "<optgroup label=\"{$opt_goup}\"";
$optgroup_tooltips = false;
if (isset($param['option_tooltips'][$key])) {
if (is_array($param['option_tooltips'][$key])) {
if (isset($param['option_tooltips'][$key]['__optgroup_label'])) {
$output .= ' title="' . $param['option_tooltips'][$key]['__optgroup_label'] . '"';
}
$optgroup_tooltips = $param['option_tooltips'][$key];
} else {
$output .= ' title="' . $param['option_tooltips'][$key] . '"';
}
}
$output .= ">";
foreach ($val as $key2 => $val2) {
if (!isset($param['used'][$key2])) {
$output .= "<option value='" . $key2 . "'";
// Do not use in_array : trouble with 0 and empty value
foreach ($param['values'] as $value) {
if (strcmp($key2, $value) === 0) {
$output .= " selected";
break;
}
}
if ($optgroup_tooltips && isset($optgroup_tooltips[$key2])) {
$output .= ' title="' . $optgroup_tooltips[$key2] . '"';
}
$output .= ">" . $val2 . "</option>";
if ($max_option_size < strlen($val2)) {
$max_option_size = strlen($val2);
}
}
}
$output .= "</optgroup>";
} else {
if (!isset($param['used'][$key])) {
$output .= "<option value='" . $key . "'";
// Do not use in_array : trouble with 0 and empty value
foreach ($param['values'] as $value) {
if (strcmp($key, $value) === 0) {
$output .= " selected";
break;
}
}
if (isset($param['option_tooltips'][$key])) {
$output .= ' title="' . $param['option_tooltips'][$key] . '"';
}
$output .= ">" . $val . "</option>";
if ($max_option_size < strlen($val)) {
$max_option_size = strlen($val);
}
}
}
}
if ($param['other'] !== false) {
$output .= "<option value='{$other_select_option}'";
if (is_string($param['other'])) {
$output .= " selected";
}
$output .= ">" . __('Other...') . "</option>";
}
$output .= "</select>";
if ($param['other'] !== false) {
$output .= "<input name='{$other_select_option}' id='{$other_select_option}' type='text'";
if (is_string($param['other'])) {
$output .= " value=\"" . $param['other'] . "\"";
} else {
$output .= " style=\"display: none\"";
}
$output .= ">";
}
}
// Width set on select
$output .= Html::jsAdaptDropdown($field_id, array('width' => $param["width"]));
if ($param["multiple"]) {
// Hack for All / None because select2 does not provide it
$select = __('All');
$deselect = __('None');
$output .= "<div class='invisible' id='selectallbuttons_{$field_id}'>";
$output .= "<div class='select2-actionable-menu'>";
$output .= "<a class='vsubmit floatleft' " . "onclick=\"selectAll('{$field_id}');\$('#{$field_id}').select2('close');\">{$select}" . "</a> ";
$output .= "<a class='vsubmit floatright' onclick=\"deselectAll('{$field_id}');\">{$deselect}" . "</a>";
$output .= "</div></div>";
$js = "\n var multichecksappend{$field_id} = false;\n \$('#{$field_id}').on('select2-open', function() {\n if (!multichecksappend{$field_id}) {\n \$('#select2-drop').append(\$('#selectallbuttons_{$field_id}').html());\n multichecksappend{$field_id} = true;\n }\n });";
$output .= Html::scriptBlock($js);
}
$output .= Ajax::commonDropdownUpdateItem($param, false);
if ($param['display']) {
echo $output;
return $param['rand'];
}
return $output;
}