4 * Text field for selecting a value from a large list of possible values, with
5 * auto-completion and optionally with a select dropdown for selecting common
8 * HTMLComboboxField implements most of the same functionality and should be
9 * used instead, if possible.
11 * If one of 'options-messages', 'options', or 'options-message' is provided
12 * and non-empty, the select dropdown will be shown. An 'other' key will be
13 * appended using message 'htmlform-selectorother-other' if not already
16 * Besides the parameters recognized by HTMLTextField, the following are
18 * options-messages - As for HTMLSelectField
19 * options - As for HTMLSelectField
20 * options-message - As for HTMLSelectField
21 * autocomplete-data - Associative array mapping display text to values.
22 * autocomplete-data-messages - Like autocomplete, but keys are message names.
23 * require-match - Boolean, if true the value must be in the options or the
25 * other-message - Message to use instead of htmlform-selectorother-other for
26 * the 'other' message.
27 * other - Raw text to use for the 'other' message
29 * The old name of autocomplete-data[-messages] was autocomplete[-messages] which is still
30 * recognized but deprecated since MediaWiki 1.29 since it conflicts with how autocomplete is
31 * used in HTMLTextField.
33 class HTMLAutoCompleteSelectField
extends HTMLTextField
{
34 protected $autocompleteData = [];
36 public function __construct( $params ) {
38 'require-match' => false,
41 // FIXME B/C, remove in 1.30
43 array_key_exists( 'autocomplete', $params )
44 && !array_key_exists( 'autocomplete-data', $params )
46 $params['autocomplete-data'] = $params['autocomplete'];
47 unset( $params['autocomplete'] );
50 array_key_exists( 'autocomplete-messages', $params )
51 && !array_key_exists( 'autocomplete-data-messages', $params )
53 $params['autocomplete-data-messages'] = $params['autocomplete-messages'];
54 unset( $params['autocomplete-messages'] );
57 parent
::__construct( $params );
59 if ( array_key_exists( 'autocomplete-data-messages', $this->mParams
) ) {
60 foreach ( $this->mParams
['autocomplete-data-messages'] as $key => $value ) {
61 $key = $this->msg( $key )->plain();
62 $this->autocompleteData
[$key] = strval( $value );
64 } elseif ( array_key_exists( 'autocomplete-data', $this->mParams
) ) {
65 foreach ( $this->mParams
['autocomplete-data'] as $key => $value ) {
66 $this->autocompleteData
[$key] = strval( $value );
69 if ( !is_array( $this->autocompleteData
) ||
!$this->autocompleteData
) {
70 throw new MWException( 'HTMLAutoCompleteSelectField called without any autocompletions' );
74 if ( $this->mOptions
&& !in_array( 'other', $this->mOptions
, true ) ) {
75 if ( isset( $params['other-message'] ) ) {
76 $msg = $this->getMessage( $params['other-message'] )->text();
77 } elseif ( isset( $params['other'] ) ) {
78 $msg = $params['other'];
80 $msg = wfMessage( 'htmlform-selectorother-other' )->text();
82 $this->mOptions
[$msg] = 'other';
86 public function loadDataFromRequest( $request ) {
87 if ( $request->getCheck( $this->mName
) ) {
88 $val = $request->getText( $this->mName
. '-select', 'other' );
90 if ( $val === 'other' ) {
91 $val = $request->getText( $this->mName
);
92 if ( isset( $this->autocompleteData
[$val] ) ) {
93 $val = $this->autocompleteData
[$val];
99 return $this->getDefault();
103 public function validate( $value, $alldata ) {
104 $p = parent
::validate( $value, $alldata );
110 $validOptions = HTMLFormField
::flattenOptions( $this->getOptions() ?
: [] );
112 if ( in_array( strval( $value ), $validOptions, true ) ) {
114 } elseif ( in_array( strval( $value ), $this->autocompleteData
, true ) ) {
116 } elseif ( $this->mParams
['require-match'] ) {
117 return $this->msg( 'htmlform-select-badoption' );
123 // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
124 public function getAttributes( array $list ) {
127 'data-autocomplete' => FormatJson
::encode( array_keys( $this->autocompleteData
) ),
128 ] + parent
::getAttributes( $list );
130 if ( $this->getOptions() ) {
131 $attribs['data-hide-if'] = FormatJson
::encode(
132 [ '!==', $this->mName
. '-select', 'other' ]
139 public function getInputHTML( $value ) {
140 $oldClass = $this->mClass
;
141 $this->mClass
= (array)$this->mClass
;
143 $valInSelect = false;
146 if ( $this->getOptions() ) {
147 if ( $value !== false ) {
148 $value = strval( $value );
149 $valInSelect = in_array(
150 $value, HTMLFormField
::flattenOptions( $this->getOptions() ), true
154 $selected = $valInSelect ?
$value : 'other';
155 $select = new XmlSelect( $this->mName
. '-select', $this->mID
. '-select', $selected );
156 $select->addOptions( $this->getOptions() );
157 $select->setAttribute( 'class', 'mw-htmlform-select-or-other' );
159 if ( !empty( $this->mParams
['disabled'] ) ) {
160 $select->setAttribute( 'disabled', 'disabled' );
163 if ( isset( $this->mParams
['tabindex'] ) ) {
164 $select->setAttribute( 'tabindex', $this->mParams
['tabindex'] );
167 $ret = $select->getHTML() . "<br />\n";
169 $this->mClass
[] = 'mw-htmlform-hide-if';
172 if ( $valInSelect ) {
175 $key = array_search( strval( $value ), $this->autocompleteData
, true );
176 if ( $key !== false ) {
181 $this->mClass
[] = 'mw-htmlform-autocomplete';
182 $ret .= parent
::getInputHTML( $valInSelect ?
'' : $value );
183 $this->mClass
= $oldClass;
189 * Get the OOUI version of this input.
190 * @param string $value
193 public function getInputOOUI( $value ) {
194 // To be implemented, for now override the function from HTMLTextField