There were several inconsistencies in how ID vs cssclass vs own classes were applied, both within the same widget + mode, between different modes for the same widget, and different widgets. So uniform all of them according to the plan detailed on phabricator. Include HTMLSelectAndOtherField as well (that wasn't mentioned on phab) for consistency. Also remove the select-or-other class from HTMLAutoCompleteSelectField (which was only applied in HTML mode), since the widget is not technically a SelectOrOther. Adjust the logic in selectorother.js so that it works fine in HTML mode, and disable it for OOUI mode since SelectWithInputWidget does that already (and the field is autoinfused). Also, in HTMLAutoCompleteSelectField, don't assign an array to $this->mClass. This happens to be working right now, but it violates the type definition of the property. Luckily, according to codesearch this change seems to be backwards-compatible because these fields are not commonly used, and nobody seems to be passing cssclass to them. Bug: T309883 Change-Id: If950f131d1c4bc1645de6021781045dccfc61966
179 lines
4.2 KiB
PHP
179 lines
4.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Select dropdown field, with an additional "other" textbox.
|
|
*
|
|
* HTMLComboboxField implements the same functionality using a single form field
|
|
* and should be used instead.
|
|
*
|
|
* @stable to extend
|
|
*/
|
|
class HTMLSelectOrOtherField extends HTMLTextField {
|
|
private const FIELD_CLASS = 'mw-htmlform-select-or-other';
|
|
|
|
/**
|
|
* @stable to call
|
|
* @inheritDoc
|
|
*/
|
|
public function __construct( $params ) {
|
|
parent::__construct( $params );
|
|
$this->getOptions();
|
|
if ( !in_array( 'other', $this->mOptions, true ) ) {
|
|
$msg =
|
|
$params['other'] ?? wfMessage( 'htmlform-selectorother-other' )->text();
|
|
// Have 'other' always as first element
|
|
$this->mOptions = [ $msg => 'other' ] + $this->mOptions;
|
|
}
|
|
}
|
|
|
|
public function getInputHTML( $value ) {
|
|
$valInSelect = false;
|
|
|
|
if ( $value !== false ) {
|
|
$value = strval( $value );
|
|
$valInSelect = in_array(
|
|
$value, HTMLFormField::flattenOptions( $this->getOptions() ), true
|
|
);
|
|
}
|
|
|
|
$selected = $valInSelect ? $value : 'other';
|
|
|
|
$select = new XmlSelect( $this->mName, false, $selected );
|
|
$select->addOptions( $this->getOptions() );
|
|
|
|
$tbAttribs = [ 'size' => $this->getSize() ];
|
|
|
|
if ( !empty( $this->mParams['disabled'] ) ) {
|
|
$select->setAttribute( 'disabled', 'disabled' );
|
|
$tbAttribs['disabled'] = 'disabled';
|
|
}
|
|
|
|
if ( isset( $this->mParams['tabindex'] ) ) {
|
|
$select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
|
|
$tbAttribs['tabindex'] = $this->mParams['tabindex'];
|
|
}
|
|
|
|
$select = $select->getHTML();
|
|
|
|
if ( isset( $this->mParams['maxlength'] ) ) {
|
|
$tbAttribs['maxlength'] = $this->mParams['maxlength'];
|
|
}
|
|
|
|
$textbox = Html::input( $this->mName . '-other', $valInSelect ? '' : $value, 'text', $tbAttribs );
|
|
|
|
$wrapperAttribs = [
|
|
'id' => $this->mID,
|
|
'class' => self::FIELD_CLASS
|
|
];
|
|
if ( $this->mClass !== '' ) {
|
|
$wrapperAttribs['class'] .= ' ' . $this->mClass;
|
|
}
|
|
return Html::rawElement(
|
|
'div',
|
|
$wrapperAttribs,
|
|
"$select<br />\n$textbox"
|
|
);
|
|
}
|
|
|
|
protected function shouldInfuseOOUI() {
|
|
return true;
|
|
}
|
|
|
|
protected function getOOUIModules() {
|
|
return [ 'mediawiki.widgets.SelectWithInputWidget' ];
|
|
}
|
|
|
|
public function getInputOOUI( $value ) {
|
|
$this->mParent->getOutput()->addModuleStyles( 'mediawiki.widgets.SelectWithInputWidget.styles' );
|
|
|
|
$valInSelect = false;
|
|
if ( $value !== false ) {
|
|
$value = strval( $value );
|
|
$valInSelect = in_array(
|
|
$value, HTMLFormField::flattenOptions( $this->getOptions() ), true
|
|
);
|
|
}
|
|
|
|
# DropdownInput
|
|
$dropdownAttribs = [
|
|
'name' => $this->mName,
|
|
'options' => $this->getOptionsOOUI(),
|
|
'value' => $valInSelect ? $value : 'other',
|
|
];
|
|
|
|
$allowedParams = [
|
|
'disabled',
|
|
'tabindex',
|
|
];
|
|
|
|
$dropdownAttribs += OOUI\Element::configFromHtmlAttributes(
|
|
$this->getAttributes( $allowedParams )
|
|
);
|
|
|
|
# TextInput
|
|
$textAttribs = [
|
|
'name' => $this->mName . '-other',
|
|
'size' => $this->getSize(),
|
|
'value' => $valInSelect ? '' : $value,
|
|
];
|
|
|
|
$allowedParams = [
|
|
'required',
|
|
'autofocus',
|
|
'multiple',
|
|
'disabled',
|
|
'tabindex',
|
|
'maxlength',
|
|
];
|
|
|
|
$textAttribs += OOUI\Element::configFromHtmlAttributes(
|
|
$this->getAttributes( $allowedParams )
|
|
);
|
|
|
|
if ( $this->mPlaceholder !== '' ) {
|
|
$textAttribs['placeholder'] = $this->mPlaceholder;
|
|
}
|
|
|
|
$disabled = false;
|
|
if ( isset( $this->mParams[ 'disabled' ] ) && $this->mParams[ 'disabled' ] ) {
|
|
$disabled = true;
|
|
}
|
|
|
|
$inputClasses = [ self::FIELD_CLASS ];
|
|
if ( $this->mClass !== '' ) {
|
|
$inputClasses = array_merge( $inputClasses, explode( ' ', $this->mClass ) );
|
|
}
|
|
return $this->getInputWidget( [
|
|
'id' => $this->mID,
|
|
'classes' => $inputClasses,
|
|
'disabled' => $disabled,
|
|
'textinput' => $textAttribs,
|
|
'dropdowninput' => $dropdownAttribs,
|
|
'required' => $this->mParams[ 'required' ] ?? false,
|
|
'or' => true,
|
|
] );
|
|
}
|
|
|
|
public function getInputWidget( $params ) {
|
|
return new MediaWiki\Widget\SelectWithInputWidget( $params );
|
|
}
|
|
|
|
/**
|
|
* @param WebRequest $request
|
|
*
|
|
* @return string
|
|
*/
|
|
public function loadDataFromRequest( $request ) {
|
|
if ( $request->getCheck( $this->mName ) ) {
|
|
$val = $request->getText( $this->mName );
|
|
|
|
if ( $val === 'other' ) {
|
|
$val = $request->getText( $this->mName . '-other' );
|
|
}
|
|
|
|
return $val;
|
|
} else {
|
|
return $this->getDefault();
|
|
}
|
|
}
|
|
}
|