2013-11-19 12:55:50 +00:00
|
|
|
<?php
|
2013-11-19 13:08:16 +00:00
|
|
|
|
2013-11-19 12:55:50 +00:00
|
|
|
/**
|
|
|
|
|
* Select dropdown field, with an additional "other" textbox.
|
2015-11-08 15:21:58 +00:00
|
|
|
*
|
|
|
|
|
* HTMLComboboxField implements the same functionality using a single form field
|
|
|
|
|
* and should be used instead.
|
2020-07-10 19:23:59 +00:00
|
|
|
*
|
|
|
|
|
* @stable to extend
|
2013-11-19 12:55:50 +00:00
|
|
|
*/
|
|
|
|
|
class HTMLSelectOrOtherField extends HTMLTextField {
|
Apply ID and class more consistently in HTMLSelect(Or|And)OtherField
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
2022-06-06 13:30:53 +00:00
|
|
|
private const FIELD_CLASS = 'mw-htmlform-select-or-other';
|
2020-07-10 19:23:59 +00:00
|
|
|
|
2020-07-23 09:41:58 +00:00
|
|
|
/**
|
2020-07-10 19:23:59 +00:00
|
|
|
* @stable to call
|
2020-07-23 09:41:58 +00:00
|
|
|
* @inheritDoc
|
2020-07-10 19:23:59 +00:00
|
|
|
*/
|
2016-11-04 10:40:42 +00:00
|
|
|
public function __construct( $params ) {
|
2014-02-18 20:28:06 +00:00
|
|
|
parent::__construct( $params );
|
|
|
|
|
$this->getOptions();
|
|
|
|
|
if ( !in_array( 'other', $this->mOptions, true ) ) {
|
2013-11-19 13:08:16 +00:00
|
|
|
$msg =
|
2017-10-06 22:17:58 +00:00
|
|
|
$params['other'] ?? wfMessage( 'htmlform-selectorother-other' )->text();
|
2014-04-10 15:31:25 +00:00
|
|
|
// Have 'other' always as first element
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->mOptions = [ $msg => 'other' ] + $this->mOptions;
|
2013-11-19 12:55:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 10:40:42 +00:00
|
|
|
public function getInputHTML( $value ) {
|
2013-11-19 12:55:50 +00:00
|
|
|
$valInSelect = false;
|
|
|
|
|
|
|
|
|
|
if ( $value !== false ) {
|
2014-03-05 20:15:41 +00:00
|
|
|
$value = strval( $value );
|
|
|
|
|
$valInSelect = in_array(
|
|
|
|
|
$value, HTMLFormField::flattenOptions( $this->getOptions() ), true
|
|
|
|
|
);
|
2013-11-19 12:55:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$selected = $valInSelect ? $value : 'other';
|
|
|
|
|
|
Apply ID and class more consistently in HTMLSelect(Or|And)OtherField
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
2022-06-06 13:30:53 +00:00
|
|
|
$select = new XmlSelect( $this->mName, false, $selected );
|
2014-02-18 20:28:06 +00:00
|
|
|
$select->addOptions( $this->getOptions() );
|
2013-11-19 12:55:50 +00:00
|
|
|
|
Apply ID and class more consistently in HTMLSelect(Or|And)OtherField
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
2022-06-06 13:30:53 +00:00
|
|
|
$tbAttribs = [ 'size' => $this->getSize() ];
|
2013-11-19 12:55:50 +00:00
|
|
|
|
2013-11-19 13:08:16 +00:00
|
|
|
if ( !empty( $this->mParams['disabled'] ) ) {
|
2013-11-19 12:55:50 +00:00
|
|
|
$select->setAttribute( 'disabled', 'disabled' );
|
2013-11-19 13:08:16 +00:00
|
|
|
$tbAttribs['disabled'] = 'disabled';
|
2013-11-19 12:55:50 +00:00
|
|
|
}
|
|
|
|
|
|
2013-05-02 18:27:44 +00:00
|
|
|
if ( isset( $this->mParams['tabindex'] ) ) {
|
|
|
|
|
$select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
|
|
|
|
|
$tbAttribs['tabindex'] = $this->mParams['tabindex'];
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-19 12:55:50 +00:00
|
|
|
$select = $select->getHTML();
|
|
|
|
|
|
2013-11-19 13:08:16 +00:00
|
|
|
if ( isset( $this->mParams['maxlength'] ) ) {
|
|
|
|
|
$tbAttribs['maxlength'] = $this->mParams['maxlength'];
|
2013-11-19 12:55:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$textbox = Html::input( $this->mName . '-other', $valInSelect ? '' : $value, 'text', $tbAttribs );
|
|
|
|
|
|
Apply ID and class more consistently in HTMLSelect(Or|And)OtherField
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
2022-06-06 13:30:53 +00:00
|
|
|
$wrapperAttribs = [
|
|
|
|
|
'id' => $this->mID,
|
|
|
|
|
'class' => self::FIELD_CLASS
|
|
|
|
|
];
|
|
|
|
|
if ( $this->mClass !== '' ) {
|
|
|
|
|
$wrapperAttribs['class'] .= ' ' . $this->mClass;
|
|
|
|
|
}
|
|
|
|
|
return Html::rawElement(
|
|
|
|
|
'div',
|
|
|
|
|
$wrapperAttribs,
|
|
|
|
|
"$select<br />\n$textbox"
|
|
|
|
|
);
|
2013-11-19 12:55:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-06-05 12:13:14 +00:00
|
|
|
protected function shouldInfuseOOUI() {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function getOOUIModules() {
|
|
|
|
|
return [ 'mediawiki.widgets.SelectWithInputWidget' ];
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-04 10:40:42 +00:00
|
|
|
public function getInputOOUI( $value ) {
|
2017-06-05 12:13:14 +00:00
|
|
|
$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;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 05:29:03 +00:00
|
|
|
$disabled = false;
|
|
|
|
|
if ( isset( $this->mParams[ 'disabled' ] ) && $this->mParams[ 'disabled' ] ) {
|
|
|
|
|
$disabled = true;
|
|
|
|
|
}
|
|
|
|
|
|
Apply ID and class more consistently in HTMLSelect(Or|And)OtherField
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
2022-06-06 13:30:53 +00:00
|
|
|
$inputClasses = [ self::FIELD_CLASS ];
|
|
|
|
|
if ( $this->mClass !== '' ) {
|
|
|
|
|
$inputClasses = array_merge( $inputClasses, explode( ' ', $this->mClass ) );
|
|
|
|
|
}
|
2017-06-05 12:13:14 +00:00
|
|
|
return $this->getInputWidget( [
|
2017-09-25 18:49:51 +00:00
|
|
|
'id' => $this->mID,
|
Apply ID and class more consistently in HTMLSelect(Or|And)OtherField
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
2022-06-06 13:30:53 +00:00
|
|
|
'classes' => $inputClasses,
|
2018-07-25 05:29:03 +00:00
|
|
|
'disabled' => $disabled,
|
2017-06-05 12:13:14 +00:00
|
|
|
'textinput' => $textAttribs,
|
|
|
|
|
'dropdowninput' => $dropdownAttribs,
|
2019-07-22 22:53:14 +00:00
|
|
|
'required' => $this->mParams[ 'required' ] ?? false,
|
2017-06-05 12:13:14 +00:00
|
|
|
'or' => true,
|
|
|
|
|
] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getInputWidget( $params ) {
|
2017-10-15 01:41:58 +00:00
|
|
|
return new MediaWiki\Widget\SelectWithInputWidget( $params );
|
2015-07-26 23:22:56 +00:00
|
|
|
}
|
|
|
|
|
|
2013-11-19 12:55:50 +00:00
|
|
|
/**
|
2014-04-20 21:33:05 +00:00
|
|
|
* @param WebRequest $request
|
2013-11-19 12:55:50 +00:00
|
|
|
*
|
2014-04-20 21:33:05 +00:00
|
|
|
* @return string
|
2013-11-19 12:55:50 +00:00
|
|
|
*/
|
2016-11-04 10:40:42 +00:00
|
|
|
public function loadDataFromRequest( $request ) {
|
2013-11-19 12:55:50 +00:00
|
|
|
if ( $request->getCheck( $this->mName ) ) {
|
|
|
|
|
$val = $request->getText( $this->mName );
|
|
|
|
|
|
2014-03-05 20:15:41 +00:00
|
|
|
if ( $val === 'other' ) {
|
2013-11-19 12:55:50 +00:00
|
|
|
$val = $request->getText( $this->mName . '-other' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $val;
|
|
|
|
|
} else {
|
|
|
|
|
return $this->getDefault();
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-11-19 13:08:16 +00:00
|
|
|
}
|