[ 'option.attr' => null, 'option.disable' => 'disable', 'option.id' => null, 'option.key' => 'value', 'option.key.toHtml' => true, 'option.label' => null, 'option.label.toHtml' => true, 'option.text' => 'text', 'option.text.toHtml' => true, 'option.class' => 'class', 'option.onclick' => 'onclick', ], ]; /** * Generates a yes/no radio list. * * @param string $name The value of the HTML name attribute * @param array $attribs Additional HTML attributes for the `` tag. This * can be an array of attributes, or an array of options. Treated as options * if it is the last argument passed. Valid options are: * Format options, see {@see JHtml::$formatOptions}. * Selection options, see {@see JHtmlSelect::options()}. * list.attr, string|array: Additional attributes for the select * element. * id, string: Value to use as the select element id attribute. * Defaults to the same as the name. * list.select, string|array: Identifies one or more option elements * to be selected, based on the option key values. * @param string $optKey The name of the object variable for the option value. If * set to null, the index of the value array is used. * @param string $optText The name of the object variable for the option text. * @param mixed $selected The key that is selected (accepts an array or a string). * @param mixed $idtag Value of the field id or null by default * @param boolean $translate True to translate * * @return string HTML for the select list. * * @since 3.7.2 */ public static function smartlist($data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false) { $innerList = self::genericlist($data, $name, $attribs, $optKey, $optText, $selected, $idtag, $translate); // Joomla 3: Use Chosen if (version_compare(JVERSION, '3.999.999', 'le')) { HTMLHelper::_('formbehavior.chosen'); return $innerList; } // Joomla 4: Use the joomla-field-fancy-select using choices.js try { \Joomla\CMS\Factory::getApplication()->getDocument()->getWebAssetManager() ->usePreset('choicesjs') ->useScript('webcomponent.field-fancy-select'); } catch (Exception $e) { return $innerList; } $j4Attr = array_filter([ 'class' => $attribs['class'] ?? null, 'placeholder' => $attribs['placeholder'] ?? null, ], function ($x) { return !empty($x); }); $dataAttribute = ''; if (isset($attribs['dataAttribute'])) { $dataAttribute = is_string($attribs['dataAttribute']) ? $attribs['dataAttribute'] : ''; } if ((bool) ($attribs['allowCustom'] ?? false)) { $dataAttribute .= ' allow-custom new-item-prefix="#new#"'; } $remoteSearchUrl = $attribs['remoteSearchURL'] ?? null; $remoteSearch = ((bool) ($attribs['remoteSearch'] ?? false)) && !empty($remoteSearchUrl); $termKey = $attribs['termKey'] ?? 'like'; $minTermLength = $attribs['minTermLength'] ?? 3; if ($remoteSearch) { $dataAttribute .= ' remote-search'; $j4Attr['url'] = $remoteSearchUrl; $j4Attr['term-key'] = $termKey; $j4Attr['min-term-length'] = $minTermLength; } if (isset($attribs['required'])) { $j4Attr['class'] = ($j4Attr['class'] ?? '') . ' required'; $dataAttribute .= ' required'; } if (isset($attribs['readonly'])) { return $innerList; } return sprintf("%s", ArrayHelper::toString($j4Attr), $dataAttribute, $innerList); } /** * Generates an HTML selection list. * * @param array $data An array of objects, arrays, or scalars. * @param string $name The value of the HTML name attribute. * @param mixed $attribs Additional HTML attributes for the `' . $options['format.eol']; } /** * Generates a grouped HTML selection list from nested arrays. * * @param array $data An array of groups, each of which is an array of options. * @param string $name The value of the HTML name attribute * @param array $options Options, an array of key/value pairs. Valid options are: * Format options, {@see HTMLHelper::$formatOptions}. * Selection options. See {@see HTMLHelper::options()}. * group.id: The property in each group to use as the group id * attribute. Defaults to none. * group.label: The property in each group to use as the group * label. Defaults to "text". If set to null, the data array index key is * used. * group.items: The property in each group to use as the array of * items in the group. Defaults to "items". If set to null, group.id and * group. label are forced to null and the data element is assumed to be a * list of selections. * id: Value to use as the select element id attribute. Defaults to * the same as the name. * list.attr: Attributes for the select element. Can be a string or * an array of key/value pairs. Defaults to none. * list.select: either the value of one selected option or an array * of selected options. Default: none. * list.translate: Boolean. If set, text and labels are translated via * Text::_(). * * @return string HTML for the select list * * @throws RuntimeException If a group has contents that cannot be processed. */ public static function groupedlist(array $data, string $name, array $options = []): string { // Set default options and overwrite with anything passed in $options = array_merge( HTMLHelper::$formatOptions, [ 'format.depth' => 0, 'group.items' => 'items', 'group.label' => 'text', 'group.label.toHtml' => true, 'id' => false, ], $options ); // Apply option rules if ($options['group.items'] === null) { $options['group.label'] = null; } $attribs = ''; if (isset($options['list.attr'])) { if (is_array($options['list.attr'])) { $attribs = ArrayHelper::toString($options['list.attr']); } else { $attribs = $options['list.attr']; } if ($attribs !== '') { $attribs = ' ' . $attribs; } } $id = $options['id'] !== false ? $options['id'] : $name; $id = str_replace(['[', ']', ' '], '', $id); // Disable groups in the options. $options['groups'] = false; $baseIndent = str_repeat($options['format.indent'], $options['format.depth']++); $html = $baseIndent . '' . $options['format.eol']; $groupIndent = str_repeat($options['format.indent'], $options['format.depth']++); foreach ($data as $dataKey => $group) { $label = $dataKey; $id = ''; $noGroup = is_int($dataKey); if ($options['group.items'] == null) { // Sub-list is an associative array $subList = $group; } elseif (is_array($group)) { // Sub-list is in an element of an array. $subList = $group[$options['group.items']]; if (isset($group[$options['group.label']])) { $label = $group[$options['group.label']]; $noGroup = false; } if (isset($options['group.id']) && isset($group[$options['group.id']])) { $id = $group[$options['group.id']]; $noGroup = false; } } elseif (is_object($group)) { // Sub-list is in a property of an object $subList = $group->{$options['group.items']}; if (isset($group->{$options['group.label']})) { $label = $group->{$options['group.label']}; $noGroup = false; } if (isset($options['group.id']) && isset($group->{$options['group.id']})) { $id = $group->{$options['group.id']}; $noGroup = false; } } else { throw new RuntimeException('Invalid group contents.', 1); } if ($noGroup) { $html .= static::options($subList, $options); } else { $html .= $groupIndent . '' . $options['format.eol'] . static::options($subList, $options) . $groupIndent . '' . $options['format.eol']; } } return $html . ($baseIndent . '' . $options['format.eol']); } /** * Generates a selection list of integers. * * @param integer $start The start integer * @param integer $end The end integer * @param integer $inc The increment * @param string $name The value of the HTML name attribute * @param mixed $attribs Additional HTML attributes for the `` tag * @param mixed $optKey The key that is selected * @param string $optText The name of the object variable for the option value * @param mixed $selected The name of the object variable for the option text * @param boolean $idtag Value of the field id or null by default * @param boolean $translate True if options will be translated * * @return string HTML for the select list */ public static function radiolist($data, $name, $attribs = null, $optKey = 'value', $optText = 'text', $selected = null, $idtag = false, $translate = false) { $forSelect = false; if (isset($attribs['forSelect'])) { $forSelect = (bool) ($attribs['forSelect']); unset($attribs['forSelect']); } if (is_array($attribs)) { $attribs = ArrayHelper::toString($attribs); } $id_text = empty($idtag) ? $name : $idtag; $html = ''; foreach ($data as $optionObject) { $optionValue = $optionObject->$optKey; $labelText = $translate ? \Joomla\CMS\Language\Text::_($optionObject->$optText) : $optionObject->$optText; $id = ($optionObject->id ?? null); $extra = ''; $id = $id ? $optionObject->id : $id_text . $optionValue; if (is_array($selected)) { foreach ($selected as $val) { $k2 = is_object($val) ? $val->$optKey : $val; if ($optionValue == $k2) { $extra .= ' selected="selected" '; break; } } } else { $extra .= ((string) $optionValue === (string) $selected ? ' checked="checked" ' : ''); } if ($forSelect) { $html .= "\n\t" . ''; $html .= "\n\t" . ''; } else { $html .= "\n\t" . ''; } } return $html . "\n"; } /** * Creates two radio buttons styled with FEF to appear as a YES/NO switch * * @param string $name Name of the field * @param mixed $selected Selected field * @param array $attribs Additional attributes to add to the switch * * @return string The HTML for the switch */ public static function booleanswitch(string $name, $selected, array $attribs = []): string { if (empty($attribs)) { $attribs = ['class' => 'akeeba-toggle']; } elseif (isset($attribs['class'])) { $attribs['class'] .= ' akeeba-toggle'; } else { $attribs['class'] = 'akeeba-toggle'; } $temp = ''; foreach ($attribs as $key => $value) { $temp .= $key . ' = "' . $value . '"'; } $attribs = $temp; $checked_1 = $selected ? '' : 'checked '; $checked_2 = $selected ? 'checked ' : ''; $html = '
'; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '
'; return $html; } }