From 9df32864f6e5ec77634787e5281e4ced035f46a2 Mon Sep 17 00:00:00 2001 From: Kohei Yoshino Date: Wed, 20 Dec 2023 00:00:36 -0500 Subject: [PATCH] Bug 1870891 - Replace native (FIELD_TYPE_SINGLE_SELECT and FIELD_TYPE_MULTI_SELECT only) # inline: (boolean) output field as a table-cell instead of as a stand-alone div (default: false) # no_indent: (boolean) don't indent the field (left-padding) (default: false) # full_width: (boolean) the field takes up the complete page width (default: false) @@ -91,13 +90,6 @@ ELSIF field_type == constants.FIELD_TYPE_MULTI_SELECT || field_type == constants ELSE; has_value = value != ""; END; -IF !select_size.defined; - IF field_type == constants.FIELD_TYPE_SINGLE_SELECT; - select_size = 0; - ELSE; - select_size = 5; - END; -END; # switch to view mode if edit-only and the current user cannot edit IF !editable && edit_only; edit_only = 0; @@ -271,37 +263,38 @@ END; [% END %] [% ELSE %] - + [% END %] [% CASE constants.FIELD_TYPE_MULTI_SELECT %] [%# multi value select %] - + [% CASE constants.FIELD_TYPE_FREETEXT %] [%# normal input field %] diff --git a/extensions/BugModal/template/en/default/bug_modal/flags.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/flags.html.tmpl index f85d571ba0..4c427399fd 100644 --- a/extensions/BugModal/template/en/default/bug_modal/flags.html.tmpl +++ b/extensions/BugModal/template/en/default/bug_modal/flags.html.tmpl @@ -130,7 +130,7 @@ - + [% IF (t.is_requestable && t.is_requesteeble) || (f && f.requestee) %] diff --git a/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl index e2ce154c0d..f55403f434 100644 --- a/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl +++ b/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl @@ -64,6 +64,7 @@ "extensions/BugModal/web/comments.js", "extensions/ComponentWatching/web/js/overlay.js", "js/bugzilla-readable-status-min.js", + "js/components/select.js", "js/field.js", "js/comments.js" ); diff --git a/extensions/BugModal/template/en/default/bug_modal/tracking_flags.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/tracking_flags.html.tmpl index 21678f6920..cd2484e78d 100644 --- a/extensions/BugModal/template/en/default/bug_modal/tracking_flags.html.tmpl +++ b/extensions/BugModal/template/en/default/bug_modal/tracking_flags.html.tmpl @@ -92,7 +92,7 @@ [% BLOCK tf_select %] [% RETURN UNLESS flag %] - + [% END %] diff --git a/extensions/BugModal/web/bug_modal.css b/extensions/BugModal/web/bug_modal.css index fce485a3b2..f9e962a65c 100644 --- a/extensions/BugModal/web/bug_modal.css +++ b/extensions/BugModal/web/bug_modal.css @@ -1411,27 +1411,7 @@ a.lightbox-icon.markdown { #component { width: auto !important; -} - -#component-description { - overflow: auto; - overscroll-behavior: contain; - margin: 4px 0; - max-height: 150px; - font-size: var(--font-size-small); - overflow-wrap: anywhere; -} - -#component-description > :first-child { - margin-top: 0; -} - -#component-description > :last-child { - margin-bottom: 0; -} - -#component-description ul { - padding: 0 0 0 16px; + min-width: 160px; } #component-tip { diff --git a/extensions/BugModal/web/bug_modal.js b/extensions/BugModal/web/bug_modal.js index 4e4580f794..199c92e383 100644 --- a/extensions/BugModal/web/bug_modal.js +++ b/extensions/BugModal/web/bug_modal.js @@ -619,7 +619,7 @@ $(function() { // // dirty field tracking - $('#changeform select').each(function() { + $('#changeform bz-select').each(function() { var that = $(this); var dirty = $('#' + that.attr('id') + '-dirty'); if (!dirty) return; @@ -627,15 +627,15 @@ $(function() { // store the option that had the selected attribute when we // initially loaded - var value = that.find('option[selected]').map(function() { return this.value; }).toArray(); + var value = that.find('bz-option[selected]').map(function() { return this.value; }).toArray(); if (value.length === 0 && !that.attr('multiple')) - value = that.find('option:first').map(function() { return this.value; }).toArray(); + value = that.find('bz-option:first').map(function() { return this.value; }).toArray(); that.data('preselected', value); // if the user hasn't touched a field, override the browser's choice // with Bugzilla's if (!dirty.val()) - that.val(value); + that.val(value[0]); }); // edit/save mode button @@ -702,7 +702,7 @@ $(function() { `); } else { $select.insertAdjacentHTML('beforeend', ` - + ${name} `); } } @@ -1002,7 +1002,7 @@ $(function() { other.val(that.val()); }); - // bug flag value ` element alternative that shows a searchbar for easier data input. This + * partially implements the {@link HTMLSelectElement} DOM API and the `combobox` WAI-ARIA role. + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement + * @see https://w3c.github.io/aria/#combobox + * @see https://www.w3.org/WAI/ARIA/apg/patterns/combobox/ + */ +class BzSelectElement extends HTMLElement { + /** + * Make it the custom element part of the outer form. + * @type {boolean} + */ + static formAssociated = true; + + /** + * A list of attributes to be captured with {@link attributeChangedCallback}. + * @type {string[]} + */ + static get observedAttributes() { + return ['name', 'disabled', 'required', 'aria-required', 'aria-invalid', 'aria-errormessage']; + } + + /** + * Whether to allow selecting multiple options. This component doesn’t support multiple selection, + * so the value is fixed with `false`. + * @type {boolean} + */ + multiple = false; + + /** + * The `type` property. This component doesn’t support multiple selection, so the value is fixed. + * @type {string} + */ + type = 'select-one'; + + /** + * The internal field ID. + * @type {string} + */ + #id; + + /** + * The internal field label. + * @type {string} + */ + #label; + + /** + * A reference to the element with the `combobox` role. + * @type {HTMLElement} + */ + #combobox; + + /** + * A reference to the label element inside the {@link #combobox}, + * @type {HTMLElement} + */ + #comboboxLabel; + + /** + * A reference to the `` element that shows the dropdown list. + * @type {HTMLDialogElement} + */ + #dialog; + + /** + * A reference to the `` element that serves as a searchbar. + * @type {HTMLInputElement} + */ + #searchBar; + + /** + * A reference to the ` +
+ +
+ +
+ `; + + this.#combobox = this.shadowRoot.querySelector('[role="combobox"]'); + this.#comboboxLabel = this.#combobox.querySelector('.label'); + this.#dialog = this.shadowRoot.querySelector('dialog'); + this.#searchBar = this.shadowRoot.querySelector('[role="search"]'); + this.#clearButton = this.shadowRoot.querySelector('button.clear'); + this.#listbox = this.shadowRoot.querySelector('[role="listbox"]'); + this.#slot = this.shadowRoot.querySelector('slot'); + this.#noMatchMessage = this.shadowRoot.querySelector('.no-match'); + + this.#combobox.addEventListener('click', (event) => this.#onComboboxClick(event)); + this.#combobox.addEventListener('keydown', (event) => this.#onComboboxKeyDown(event)); + this.#dialog.addEventListener('click', (event) => this.#onDialogClick(event)); + this.#dialog.addEventListener('keydown', (event) => this.#onDialogKeyDown(event)); + this.#dialog.addEventListener('close', () => this.#onDialogClose(event)); + this.#searchBar.addEventListener('input', () => this.#onSearchbarInput(event)); + this.#clearButton.addEventListener('click', (event) => this.#onClearButtonClick(event)); + this.#listbox.addEventListener('mouseover', (event) => this.#onListboxMouseOver(event)); + this.#slot.addEventListener('slotchange', () => this.#onSlotChange()); + + this.#setProps(); + } + + /** + * Called whenever attributes are changed. Sync the values with corresponding properties. + * @param {string} name Attribute name. + * @param {string} oldValue Old attribute value. + * @param {string} value New attribute value. + */ + attributeChangedCallback(name, oldValue, value) { + this.#props[name] = value; + this.#setProps(); + } + + /** + * Called whenever the {@link #combobox} is clicked. Show the dropdown list. + */ + #onComboboxClick() { + this.#showDropdown(); + } + + /** + * Called whenever a key is pressed on the {@link #combobox}. Mimic the native `