Implement HTMLComboboxField
authorBartosz Dziewoński <matma.rex@gmail.com>
Sun, 8 Nov 2015 15:21:58 +0000 (16:21 +0100)
committerBartosz Dziewoński <matma.rex@gmail.com>
Thu, 12 Nov 2015 08:48:27 +0000 (09:48 +0100)
It's a dropdown select with the ability to add custom options, or a
text field with input suggestions, whichever you prefer.

This is meant to be a replacement for HTMLSelectOrOtherField and
HTMLAutoCompleteSelectField.

In regular HTML mode, it uses HTML5 `<datalist>` element with no
custom JavaScript. This is supported by a wide range of browsers
(IE 10+, modern Firefox and Chrome, Opera 12+).

In OOUI mode, it uses a ComboBoxInputWidget.

Depends on: I14b40884f185fb4e5

Bug: T118119
Change-Id: I954d3d24ed4efe90be9596a1bd9586ba3aee1e23

autoload.php
includes/XmlSelect.php
includes/htmlform/HTMLAutoCompleteSelectField.php
includes/htmlform/HTMLComboboxField.php [new file with mode: 0644]
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLSelectOrOtherField.php

index 15f1b10..3ebf44b 100644 (file)
@@ -491,6 +491,7 @@ $wgAutoloadLocalClasses = array(
        'HTMLCacheUpdateJob' => __DIR__ . '/includes/jobqueue/jobs/HTMLCacheUpdateJob.php',
        'HTMLCheckField' => __DIR__ . '/includes/htmlform/HTMLCheckField.php',
        'HTMLCheckMatrix' => __DIR__ . '/includes/htmlform/HTMLCheckMatrix.php',
+       'HTMLComboboxField' => __DIR__ . '/includes/htmlform/HTMLComboboxField.php',
        'HTMLEditTools' => __DIR__ . '/includes/htmlform/HTMLEditTools.php',
        'HTMLFileCache' => __DIR__ . '/includes/cache/HTMLFileCache.php',
        'HTMLFloatField' => __DIR__ . '/includes/htmlform/HTMLFloatField.php',
index 78f4764..9d37b95 100644 (file)
  */
 
 /**
- * Class for generating HTML <select> elements.
+ * Class for generating HTML <select> or <datalist> elements.
  */
 class XmlSelect {
        protected $options = array();
        protected $default = false;
+       protected $tagName = 'select';
        protected $attributes = array();
 
        public function __construct( $name = false, $id = false, $default = false ) {
@@ -49,6 +50,13 @@ class XmlSelect {
                $this->default = $default;
        }
 
+       /**
+        * @param string|array $tagName
+        */
+       public function setTagName( $tagName ) {
+               $this->tagName = $tagName;
+       }
+
        /**
         * @param string $name
         * @param string $value
@@ -127,6 +135,6 @@ class XmlSelect {
                        $contents .= self::formatOptions( $options, $this->default );
                }
 
-               return Html::rawElement( 'select', $this->attributes, rtrim( $contents ) );
+               return Html::rawElement( $this->tagName, $this->attributes, rtrim( $contents ) );
        }
 }
index 55cd5d0..fc19d9a 100644 (file)
@@ -5,6 +5,9 @@
  * auto-completion and optionally with a select dropdown for selecting common
  * options.
  *
+ * HTMLComboboxField implements most of the same functionality and should be
+ * used instead, if possible.
+ *
  * If one of 'options-messages', 'options', or 'options-message' is provided
  * and non-empty, the select dropdown will be shown. An 'other' key will be
  * appended using message 'htmlform-selectorother-other' if not already
@@ -22,7 +25,6 @@
  *   other-message - Message to use instead of htmlform-selectorother-other for
  *      the 'other' message.
  *   other - Raw text to use for the 'other' message
- *
  */
 class HTMLAutoCompleteSelectField extends HTMLTextField {
        protected $autocomplete = array();
diff --git a/includes/htmlform/HTMLComboboxField.php b/includes/htmlform/HTMLComboboxField.php
new file mode 100644 (file)
index 0000000..e5679bb
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * A combo box field.
+ *
+ * You can think of it as a dropdown select with the ability to add custom options,
+ * or as a text field with input suggestions (autocompletion).
+ *
+ * When JavaScript is not supported or enabled, it uses HTML5 `<datalist>` element.
+ *
+ * Besides the parameters recognized by HTMLTextField, the following are
+ * recognized:
+ *   options-messages - As for HTMLSelectField
+ *   options - As for HTMLSelectField
+ *   options-message - As for HTMLSelectField
+ */
+class HTMLComboboxField extends HTMLTextField {
+       // FIXME Ewww, this shouldn't be adding any attributes not requested in $list :(
+       public function getAttributes( array $list, array $mappings = null ) {
+               $attribs = array(
+                       'type' => 'text',
+                       'list' => $this->mName . '-datalist',
+               ) + parent::getAttributes( $list, $mappings );
+
+               return $attribs;
+       }
+
+       function getInputHTML( $value ) {
+               $datalist = new XmlSelect( false, $this->mName . '-datalist' );
+               $datalist->setTagName( 'datalist' );
+               $datalist->addOptions( $this->getOptions() );
+
+               return parent::getInputHTML( $value ) . $datalist->getHTML();
+       }
+
+       function getInputOOUI( $value ) {
+               $disabled = false;
+               $allowedParams = array( 'tabindex' );
+               $attribs = $this->getAttributes( $allowedParams, array( 'tabindex' => 'tabIndex' ) );
+
+               if ( $this->mClass !== '' ) {
+                       $attribs['classes'] = array( $this->mClass );
+               }
+
+               if ( !empty( $this->mParams['disabled'] ) ) {
+                       $disabled = true;
+               }
+
+               return new OOUI\ComboBoxInputWidget( array(
+                       'name' => $this->mName,
+                       'id' => $this->mID,
+                       'options' => $this->getOptionsOOUI(),
+                       'value' => strval( $value ),
+                       'disabled' => $disabled,
+               ) + $attribs );
+       }
+}
index 2b9a49a..ac81ef2 100644 (file)
@@ -128,6 +128,7 @@ class HTMLForm extends ContextSource {
                'textwithbutton' => 'HTMLTextFieldWithButton',
                'textarea' => 'HTMLTextAreaField',
                'select' => 'HTMLSelectField',
+               'combobox' => 'HTMLComboboxField',
                'radio' => 'HTMLRadioField',
                'multiselect' => 'HTMLMultiSelectField',
                'limitselect' => 'HTMLSelectLimitField',
index 3e7acdf..81a29d0 100644 (file)
@@ -2,6 +2,9 @@
 
 /**
  * Select dropdown field, with an additional "other" textbox.
+ *
+ * HTMLComboboxField implements the same functionality using a single form field
+ * and should be used instead.
  */
 class HTMLSelectOrOtherField extends HTMLTextField {
        function __construct( $params ) {