diff --git a/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js b/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js index a315b60e72d..8bbd791ab4f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js @@ -113,10 +113,12 @@ acceptance("Category Edit", function (needs) { const allowedTagChooser = selectKit("#category-allowed-tags"); await allowedTagChooser.expand(); await allowedTagChooser.selectRowByValue("monkey"); + await allowedTagChooser.collapse(); const allowedTagGroupChooser = selectKit("#category-allowed-tag-groups"); await allowedTagGroupChooser.expand(); await allowedTagGroupChooser.selectRowByValue("TagGroup1"); + await allowedTagGroupChooser.collapse(); await click("#save-category"); @@ -129,6 +131,7 @@ acceptance("Category Edit", function (needs) { await allowedTagChooser.expand(); await allowedTagChooser.deselectItemByValue("monkey"); + await allowedTagChooser.collapse(); await allowedTagGroupChooser.expand(); await allowedTagGroupChooser.deselectItemByValue("TagGroup1"); diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-categories-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-categories-test.js index 653dbe67f98..df1ea13aa07 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-categories-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-categories-test.js @@ -39,10 +39,16 @@ acceptance("User Preferences - Categories", function (needs) { ".tracking-controls__regular-categories .category-selector" ); + await trackedCategoriesSelector.collapse(); + await regularCategoriesSelector.expand(); await regularCategoriesSelector.deselectItemByValue("4"); + + await regularCategoriesSelector.collapse(); await trackedCategoriesSelector.expand(); await trackedCategoriesSelector.selectRowByValue("4"); + await trackedCategoriesSelector.collapse(); + await click(".save-changes"); assert.deepEqual(putRequestData, { @@ -63,6 +69,7 @@ acceptance("User Preferences - Categories", function (needs) { await categorySelector.expand(); // User has `regular_category_ids` set to [4] in fixtures await categorySelector.selectRowByValue(4); + await categorySelector.collapse(); await click(".save-changes"); assert.deepEqual(putRequestData, { diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js index 176516da4e3..ee0ce91298c 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-tracking-test.js @@ -173,17 +173,25 @@ acceptance("User Preferences - Tracking", function (needs) { assert.notOk( trackedCategoriesSelector.rowByValue("4").exists(), - "category that is set to regular is not available for selection" + "category that is set to regular is not available for selection under tracked" ); const regularCategoriesSelector = selectKit( ".tracking-controls__regular-categories .category-selector" ); - + await trackedCategoriesSelector.collapse(); await regularCategoriesSelector.expand(); await regularCategoriesSelector.deselectItemByValue("4"); + + assert.ok( + regularCategoriesSelector.rowByValue("4").exists(), + "category is no longer selected under regular" + ); + + await regularCategoriesSelector.collapse(); await trackedCategoriesSelector.expand(); await trackedCategoriesSelector.selectRowByValue("4"); + await trackedCategoriesSelector.collapse(); await click(".save-changes"); assert.deepEqual(putRequestData, { diff --git a/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js b/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js index 4824aea118a..d8e51b0dd3e 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/select-kit/mini-tag-chooser-test.js @@ -58,9 +58,8 @@ module( await this.subject.fillInFilter("baz"); await this.subject.selectRowByValue("monkey"); - const error = query(".select-kit-error").innerText; assert.strictEqual( - error, + query(".select-kit-error").innerText, I18n.t("select_kit.max_content_reached", { count: this.siteSettings.max_tags_per_topic, }) diff --git a/app/assets/javascripts/select-kit/addon/components/multi-select.js b/app/assets/javascripts/select-kit/addon/components/multi-select.js index e15d96d9fe7..b2fc0ca1d1e 100644 --- a/app/assets/javascripts/select-kit/addon/components/multi-select.js +++ b/app/assets/javascripts/select-kit/addon/components/multi-select.js @@ -75,6 +75,7 @@ export default SelectKitComponent.extend({ }, select(value, item) { + this.selectKit.set("multiSelectInFocus", true); if (this.selectKit.hasSelection && this.selectKit.options.maximum === 1) { this.selectKit.deselectByValue( this.getValue(this.selectedContent.firstObject) diff --git a/app/assets/javascripts/select-kit/addon/components/select-kit.js b/app/assets/javascripts/select-kit/addon/components/select-kit.js index 75f2e876e30..2db4e681421 100644 --- a/app/assets/javascripts/select-kit/addon/components/select-kit.js +++ b/app/assets/javascripts/select-kit/addon/components/select-kit.js @@ -94,6 +94,7 @@ export default Component.extend( noneItem: null, newItem: null, filter: null, + multiSelectInFocus: null, modifyContent: bind(this, this._modifyContentWrapper), modifySelection: bind(this, this._modifySelectionWrapper), @@ -441,6 +442,7 @@ export default Component.extend( items = makeArray(items); if (this.multiSelect) { + this.selectKit.set("multiSelectInFocus", true); items = items.filter( (i) => i !== this.newItem && diff --git a/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-body.js b/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-body.js index a6a8437fe6b..b6a232a6994 100644 --- a/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-body.js +++ b/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-body.js @@ -1,5 +1,5 @@ import Component from "@ember/component"; -import { bind } from "@ember/runloop"; +import { bind } from "discourse-common/utils/decorators"; import { computed } from "@ember/object"; export default Component.extend({ @@ -10,55 +10,41 @@ export default Component.extend({ return false; }), - rootEventType: "click", - - init() { - this._super(...arguments); - - this.handleRootMouseDownHandler = bind(this, this.handleRootMouseDown); - }, - didInsertElement() { this._super(...arguments); - this.element.style.position = "relative"; - - document.addEventListener( - this.rootEventType, - this.handleRootMouseDownHandler, - true - ); + this.element.addEventListener("focusout", this._handleFocusOut, true); }, willDestroyElement() { this._super(...arguments); - - document.removeEventListener( - this.rootEventType, - this.handleRootMouseDownHandler, - true - ); + this.element.removeEventListener("focusout", this._handleFocusOut, true); }, - handleRootMouseDown(event) { + @bind + _handleFocusOut(event) { if (!this.selectKit.isExpanded) { return; } - const headerElement = document.querySelector( - `#${this.selectKit.uniqueID}-header` - ); - - if (headerElement && headerElement.contains(event.target)) { + if (!this.selectKit.mainElement()) { return; } - if (this.element.contains(event.target)) { + if (this.selectKit.mainElement().contains(event.relatedTarget)) { return; } - if (this.selectKit.mainElement()) { - this.selectKit.close(event); + // We have to use a custom flag for multi-selects to keep UI visible. + // We can't rely on event.relatedTarget for these cases because, + // when adding/removing items in a multi-select, the DOM element + // has already been removed by this point, and therefore + // event.relatedTarget is going to be null. + if (this.selectKit.multiSelectInFocus) { + this.selectKit.set("multiSelectInFocus", false); + return; } + + this.selectKit.close(event); }, }); diff --git a/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-header.js b/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-header.js index 5bd78815f7b..ea2744afe1a 100644 --- a/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-header.js +++ b/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-header.js @@ -122,7 +122,10 @@ export default Component.extend(UtilsMixin, { event.stopPropagation(); event.preventDefault(); // prevents the space to trigger a scroll page-next this.selectKit.open(event); - } else if (event.key === "Escape") { + } else if ( + event.key === "Escape" || + (event.shiftKey && event.key === "Tab") + ) { event.stopPropagation(); if (this.selectKit.isExpanded) { this.selectKit.close(event); diff --git a/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-row.js b/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-row.js index 9f0df11e103..dc739fb55d1 100644 --- a/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-row.js +++ b/app/assets/javascripts/select-kit/addon/components/select-kit/select-kit-row.js @@ -41,7 +41,6 @@ export default Component.extend(UtilsMixin, { if (!this.site.mobileView) { this.element.addEventListener("mouseenter", this.handleMouseEnter); this.element.addEventListener("focus", this.handleMouseEnter); - this.element.addEventListener("blur", this.handleBlur); } }, @@ -49,9 +48,8 @@ export default Component.extend(UtilsMixin, { this._super(...arguments); if (!this.site.mobileView) { - this.element.removeEventListener("mouseenter", this.handleBlur); + this.element.removeEventListener("mouseenter", this.handleMouseEnter); this.element.removeEventListener("focus", this.handleMouseEnter); - this.element.removeEventListener("blur", this.handleMouseEnter); } }, @@ -134,20 +132,6 @@ export default Component.extend(UtilsMixin, { return false; }, - @action - handleBlur(event) { - if ( - (!this.isDestroying || !this.isDestroyed) && - event.target && - this.selectKit.mainElement() - ) { - if (!this.selectKit.mainElement().contains(event.target)) { - this.selectKit.close(event); - } - } - return false; - }, - click(event) { event.preventDefault(); event.stopPropagation();