3 namespace MediaWiki\HTMLForm\Field
;
5 use InvalidArgumentException
;
6 use MediaWiki\HTMLForm\HTMLFormField
;
7 use MediaWiki\Json\FormatJson
;
8 use MediaWiki\Xml\XmlSelect
;
11 * Text field for selecting a value from a large list of possible values, with
12 * auto-completion and optionally with a select dropdown for selecting common
15 * HTMLComboboxField implements most of the same functionality and should be
16 * used instead, if possible.
18 * If one of 'options-messages', 'options', or 'options-message' is provided
19 * and non-empty, the select dropdown will be shown. An 'other' key will be
20 * appended using message 'htmlform-selectorother-other' if not already
23 * Besides the parameters recognized by HTMLTextField, the following are
25 * options-messages - As for HTMLSelectField
26 * options - As for HTMLSelectField
27 * options-message - As for HTMLSelectField
28 * autocomplete-data - Associative array mapping display text to values.
29 * autocomplete-data-messages - Like autocomplete, but keys are message names.
30 * require-match - Boolean, if true the value must be in the options or the
32 * other-message - Message to use instead of htmlform-selectorother-other for
33 * the 'other' message.
34 * other - Raw text to use for the 'other' message
38 class HTMLAutoCompleteSelectField
extends HTMLTextField
{
40 protected $autocompleteData = [];
46 public function __construct( $params ) {
48 'require-match' => false,
51 parent
::__construct( $params );
53 if ( array_key_exists( 'autocomplete-data-messages', $this->mParams
) ) {
54 foreach ( $this->mParams
['autocomplete-data-messages'] as $key => $value ) {
55 $key = $this->msg( $key )->plain();
56 $this->autocompleteData
[$key] = strval( $value );
58 } elseif ( array_key_exists( 'autocomplete-data', $this->mParams
) ) {
59 foreach ( $this->mParams
['autocomplete-data'] as $key => $value ) {
60 $this->autocompleteData
[$key] = strval( $value );
63 if ( !is_array( $this->autocompleteData
) ||
!$this->autocompleteData
) {
64 throw new InvalidArgumentException( 'HTMLAutoCompleteSelectField called without any autocompletions' );
68 if ( $this->mOptions
&& !in_array( 'other', $this->mOptions
, true ) ) {
69 if ( isset( $params['other-message'] ) ) {
70 $msg = $this->getMessage( $params['other-message'] )->text();
71 } elseif ( isset( $params['other'] ) ) {
72 $msg = $params['other'];
74 $msg = wfMessage( 'htmlform-selectorother-other' )->text();
76 $this->mOptions
[$msg] = 'other';
80 public function loadDataFromRequest( $request ) {
81 if ( $request->getCheck( $this->mName
) ) {
82 $val = $request->getText( $this->mName
. '-select', 'other' );
84 if ( $val === 'other' ) {
85 $val = $request->getText( $this->mName
);
86 if ( isset( $this->autocompleteData
[$val] ) ) {
87 $val = $this->autocompleteData
[$val];
93 return $this->getDefault();
97 public function validate( $value, $alldata ) {
98 $p = parent
::validate( $value, $alldata );
104 $validOptions = HTMLFormField
::flattenOptions( $this->getOptions() ?
: [] );
107 in_array( strval( $value ), $validOptions, true ) ||
108 in_array( strval( $value ), $this->autocompleteData
, true )
111 } elseif ( $this->mParams
['require-match'] ) {
112 return $this->msg( 'htmlform-select-badoption' );
118 // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
119 public function getAttributes( array $list ) {
122 'data-autocomplete' => FormatJson
::encode( array_keys( $this->autocompleteData
) ),
123 ] + parent
::getAttributes( $list );
125 if ( $this->getOptions() ) {
126 $attribs['data-cond-state'] = FormatJson
::encode( [
127 'hide' => [ '!==', $this->mName
. '-select', 'other' ],
134 public function getInputHTML( $value ) {
135 $oldClass = $this->mClass
;
136 $classes = (array)$this->mClass
;
138 $valInSelect = false;
141 if ( $this->getOptions() ) {
142 if ( $value !== false ) {
143 $value = strval( $value );
144 $valInSelect = in_array(
145 $value, HTMLFormField
::flattenOptions( $this->getOptions() ), true
149 $selected = $valInSelect ?
$value : 'other';
150 $select = new XmlSelect( $this->mName
. '-select', $this->mID
. '-select', $selected );
151 $select->addOptions( $this->getOptions() );
153 if ( !empty( $this->mParams
['disabled'] ) ) {
154 $select->setAttribute( 'disabled', 'disabled' );
157 if ( isset( $this->mParams
['tabindex'] ) ) {
158 $select->setAttribute( 'tabindex', $this->mParams
['tabindex'] );
161 $ret = $select->getHTML() . "<br />\n";
163 $classes[] = 'mw-htmlform-hide-if';
166 if ( $valInSelect ) {
169 $key = array_search( strval( $value ), $this->autocompleteData
, true );
170 if ( $key !== false ) {
175 $classes[] = 'mw-htmlform-autocomplete';
176 $this->mClass
= implode( ' ', $classes );
177 $ret .= parent
::getInputHTML( $valInSelect ?
'' : $value );
178 $this->mClass
= $oldClass;
184 * Get the OOUI version of this input.
185 * @param string $value
188 public function getInputOOUI( $value ) {
189 // To be implemented, for now override the function from HTMLTextField
194 /** @deprecated class alias since 1.42 */
195 class_alias( HTMLAutoCompleteSelectField
::class, 'HTMLAutoCompleteSelectField' );