diff --git a/app/assets/javascripts/discourse/components/category-select-box.js.es6 b/app/assets/javascripts/discourse/components/category-select-box.js.es6 index e0ec28846e5..f5926a5ca77 100644 --- a/app/assets/javascripts/discourse/components/category-select-box.js.es6 +++ b/app/assets/javascripts/discourse/components/category-select-box.js.es6 @@ -1,8 +1,8 @@ import SelectBoxComponent from "discourse/components/select-box"; -import { categoryBadgeHTML } from 'discourse/helpers/category-link'; -import { observes, on } from 'ember-addons/ember-computed-decorators'; -import PermissionType from 'discourse/models/permission-type'; -import Category from 'discourse/models/category'; +import { categoryBadgeHTML } from "discourse/helpers/category-link"; +import { observes, on } from "ember-addons/ember-computed-decorators"; +import PermissionType from "discourse/models/permission-type"; +import Category from "discourse/models/category"; export default SelectBoxComponent.extend({ classNames: ["category-select-box"], @@ -13,9 +13,9 @@ export default SelectBoxComponent.extend({ castInteger: true, - width: '100%', + width: "100%", - @on("willInsertElement") + @on("init") @observes("selectedContent") _setHeaderText: function() { let headerText; @@ -30,7 +30,7 @@ export default SelectBoxComponent.extend({ headerText = this.get("selectedContent.text"); } - this.set("headerText", headerText); + this.set("headerText", Handlebars.escapeExpression(headerText)); }, // original method is kept for compatibility diff --git a/app/assets/javascripts/discourse/components/select-box.js.es6 b/app/assets/javascripts/discourse/components/select-box.js.es6 index 60a3a0bcc0c..8c2cce699b8 100644 --- a/app/assets/javascripts/discourse/components/select-box.js.es6 +++ b/app/assets/javascripts/discourse/components/select-box.js.es6 @@ -1,17 +1,17 @@ import { on, observes } from "ember-addons/ember-computed-decorators"; -import { iconHTML } from 'discourse-common/lib/icon-library'; +import { iconHTML } from "discourse-common/lib/icon-library"; export default Ember.Component.extend({ layoutName: "components/select-box", classNames: "select-box", - - width: 220, - classNameBindings: ["expanded:is-expanded"], expanded: false, focused: false, + filterFocused: false, + renderBody: false, + wrapper: true, tabindex: 0, caretUpIcon: "caret-up", @@ -39,13 +39,11 @@ export default Ember.Component.extend({ selectBoxHeaderComponent: "select-box/select-box-header", selectBoxCollectionComponent: "select-box/select-box-collection", + width: 220, maxCollectionHeight: 200, - maxWidth: 200, verticalOffset: 0, horizontalOffset: 0, - renderBody: false, - castInteger: false, filterFunction: function() { @@ -71,6 +69,30 @@ export default Ember.Component.extend({ }; }.property(), + applyDirection() { + this.$().removeClass("is-reversed"); + + const offsetTop = this.$()[0].getBoundingClientRect().top; + const windowHeight = $(window).height(); + const headerHeight = this.$(".select-box-header").outerHeight(); + const filterHeight = this.$(".select-box-filter").outerHeight(); + + if (windowHeight - (offsetTop + this.get("maxCollectionHeight") + filterHeight + headerHeight) < 0) { + this.$().addClass("is-reversed"); + this.$(".select-box-body").css({ + left: this.get("horizontalOffset"), + top: "", + bottom: headerHeight + this.get("verticalOffset") + }); + } else { + this.$(".select-box-body").css({ + left: this.get("horizontalOffset"), + top: headerHeight + this.get("verticalOffset"), + bottom: "" + }); + } + }, + init() { this._super(); @@ -82,12 +104,101 @@ export default Ember.Component.extend({ this.set("filterable", false); } + this.set("headerText", Handlebars.escapeExpression(this.get("headerText"))); + this.setProperties({ componentId: this.elementId, filteredContent: [] }); }, + @on("willDestroyElement") + _unbindEvents: function() { + $(window).off("resize.select-box"); + $(document).off("click.select-box", "keydown.select-box"); + this.$(".select-box-offscreen").off( + "focusin.select-box", + "focusout.select-box", + "keydown.select-box" + ); + this.$(".filter-query").off("focusin.select-box", "focusout.select-box"); + }, + + @on("didRender") + _configureSelectBoxDOM: function() { + this.$().css("width", this.get("width")); + this.$(".select-box-header").css("height", this.$().css("height")); + this.$(".select-box-filter").css("height", this.$().css("height")); + + if (this.get("expanded")) { + this.$(".select-box-body").css("width", this.$().css("width")); + this.$(".select-box-collection").css("max-height", this.get("maxCollectionHeight")); + + this._bindTab(); + + Ember.run.schedule("afterRender", () => { + this.applyDirection(); + + if (this.get("wrapper")) { + this._positionSelectBoxWrapper(); + } + }); + } else { + $(document).off("keydown.select-box"); + + if (this.get("wrapper")) { + this.$(".select-box-wrapper").hide(); + } + } + }, + + @on("didInsertElement") + _bindEvents: function() { + $(document).on("click.select-box", (event) => { + const clickOutside = $(event.target).parents(".select-box").attr("id") !== this.$().attr("id"); + if (this.get("expanded") && clickOutside) { + this.setProperties({ expanded: false, focused: false }); + } + }); + + this.$(".select-box-offscreen").on("focusin.select-box", () => { + this.set("focused", true); + }); + this.$(".select-box-offscreen").on("focusout.select-box", () => { + this.set("focused", false); + }); + + this.$(".filter-query").on("focusin.select-box", () => { + this.set("filterFocused", true); + }); + this.$(".filter-query").on("focusout.select-box", () => { + this.set("filterFocused", false); + }); + + this.$(".select-box-offscreen").on("keydown.select-box", (event) => { + const keyCode = event.keyCode || event.which; + + if (keyCode === 13 || keyCode === 40) { + this.setProperties({expanded: true, focused: false}); + return false; + } + + if (keyCode === 27) { + this.$(".select-box-offscreen").blur(); + return false; + } + + if (keyCode >= 65 && keyCode <= 90) { + this.setProperties({expanded: true, focused: false}); + Ember.run.schedule("afterRender", () => { + this.$(".filter-query").focus().val(String.fromCharCode(keyCode)); + }); + } + }); + + $(window).on("resize.select-box", () => this.set("expanded", false) ); + }, + @observes("value") _valueChanged: function() { if (Ember.isNone(this.get("value"))) { @@ -115,41 +226,13 @@ export default Ember.Component.extend({ if (Ember.isNone(this.get("lastHoveredId"))) { this.set("lastHoveredId", this.get("value")); } + + if (this.get("filterable")) { + Ember.run.schedule("afterRender", () => this.$(".filter-query").focus()); + } }; }, - @on("willDestroyElement") - _unbindEvents: function() { - $(document).off("click.select-box"); - $(document).off("keydown.select-box"); - this.$(".select-box-offscreen").off("focusin.select-box"); - this.$(".select-box-offscreen").off("focusout.select-box"); - this.$(".select-box-offscreen").off("keydown.select-box"); - $(window).off("resize.select-box"); - }, - - @on("didRender") - _configureSelectBoxDOM: function() { - this.$().css("width", this.get("width")); - this.$(".select-box-header").css("height", this.$().height()); - this.$(".select-box-filter").css("height", this.$().height()); - - if (this.get("expanded")) { - this.$(".select-box-body").css('width', this.$().width()); - this.$(".select-box-collection").css("max-height", this.get("maxCollectionHeight")); - - this._bindTab(); - - Ember.run.schedule('afterRender', () => { - this.applyDirection(); - this._positionSelectBoxWrapper(); - }); - } else { - $(document).off("keydown.select-box"); - this.$(".select-box-wrapper").hide(); - } - }, - @observes("content.[]", "value") @on("didReceiveAttrs") _contentChanged: function() { @@ -162,59 +245,13 @@ export default Ember.Component.extend({ this.set("filteredContent", this._remapContent(this.get("content"))); this._setSelectedContent(this.get("content")); - if (this.get("dynamicHeaderText") === true) { + if (this.get("dynamicHeaderText")) { if (!Ember.isNone(this.get("selectedContent.text"))) { this.set("headerText", this.get("selectedContent.text")); } } }, - @on("didInsertElement") - _bindEvents: function() { - $(document).on("click.select-box", (event) => { - const clickOutside = $(event.target).parents(".select-box").attr("id") !== this.$().attr("id"); - if (this.get("expanded") && clickOutside) { - this.setProperties({ - expanded: false, - focused: false - }); - } - }); - - this.$(".select-box-offscreen").on("focusin.select-box", () => { - this.set("focused", true); - }); - - this.$(".select-box-offscreen").on("keydown.select-box", (event) => { - const keyCode = event.keyCode || event.which; - - if(keyCode === 13 || keyCode === 40) { - this.setProperties({expanded: true, focused: false}); - return false; - } - - if(keyCode === 27) { - this.$(".select-box-offscreen").blur(); - return false; - } - - if (keyCode >= 65 && keyCode <= 90) { - this.setProperties({expanded: true, focused: false}); - Ember.run.schedule("afterRender", () => { - this.$(".filter-query").focus().val(String.fromCharCode(keyCode)); - }); - } - }); - - this.$(".select-box-offscreen").on("focusout.select-box", () => { - this.set("focused", false); - }); - - $(window).on("resize.select-box", () => { - this.set("expanded", false); - }); - }, - actions: { onToggle() { this.toggleProperty("expanded"); @@ -225,7 +262,7 @@ export default Ember.Component.extend({ }, onSelectRow(id) { - if(this.get("castInteger") === true) { + if (this.get("castInteger")) { id = parseInt(id, 10); } @@ -256,7 +293,7 @@ export default Ember.Component.extend({ _normalizeContent(content) { let id = content[this.get("idKey")]; - if(this.get("castInteger") === true) { + if (this.get("castInteger")) { id = parseInt(id, 10); } @@ -286,28 +323,4 @@ export default Ember.Component.extend({ height: headerHeight + this.$(".select-box-body").outerHeight() }); }, - - applyDirection() { - this.$().removeClass("is-reversed"); - - const offsetTop = this.$()[0].getBoundingClientRect().top; - const windowHeight = $(window).height(); - const headerHeight = this.$(".select-box-header").outerHeight(); - const filterHeight = this.$(".select-box-filter").outerHeight(); - - if (windowHeight - (offsetTop + this.get("maxCollectionHeight") + filterHeight + headerHeight) < 0) { - this.$().addClass("is-reversed"); - this.$(".select-box-body").css({ - left: this.get("horizontalOffset"), - top: "", - bottom: headerHeight + this.get("verticalOffset") - }); - } else { - this.$(".select-box-body").css({ - left: this.get("horizontalOffset"), - top: headerHeight + this.get("verticalOffset"), - bottom: "" - }); - } - }, }); diff --git a/app/assets/javascripts/discourse/components/select-box/select-box-filter.js.es6 b/app/assets/javascripts/discourse/components/select-box/select-box-filter.js.es6 index 8c87886c961..50c8474e5b4 100644 --- a/app/assets/javascripts/discourse/components/select-box/select-box-filter.js.es6 +++ b/app/assets/javascripts/discourse/components/select-box/select-box-filter.js.es6 @@ -1,3 +1,5 @@ export default Ember.Component.extend({ - classNames: "select-box-filter" + classNames: "select-box-filter", + + classNameBindings: ["focused:is-focused"] }); diff --git a/app/assets/javascripts/discourse/templates/components/select-box.hbs b/app/assets/javascripts/discourse/templates/components/select-box.hbs index ac6e74e2b9b..89fadee0bd2 100644 --- a/app/assets/javascripts/discourse/templates/components/select-box.hbs +++ b/app/assets/javascripts/discourse/templates/components/select-box.hbs @@ -22,8 +22,9 @@ {{#if filterable}} {{component selectBoxFilterComponent onFilterChange=(action "onFilterChange") - filterIcon=filterIcon - filterPlaceholder=filterPlaceholder + icon=filterIcon + focused=filterFocused + placeholder=filterPlaceholder }} {{/if}} @@ -40,4 +41,6 @@ {{/if}} -
+{{#if wrapper}} + +{{/if}} diff --git a/app/assets/javascripts/discourse/templates/components/select-box/select-box-filter.hbs b/app/assets/javascripts/discourse/templates/components/select-box/select-box-filter.hbs index 3ec68be715c..3ba9d155040 100644 --- a/app/assets/javascripts/discourse/templates/components/select-box/select-box-filter.hbs +++ b/app/assets/javascripts/discourse/templates/components/select-box/select-box-filter.hbs @@ -1,7 +1,7 @@ {{input tabindex="-1" class="filter-query" - placeholder=filterPlaceholder + placeholder=placeholder key-up=onFilterChange autocomplete="off" autocorrect="off" @@ -9,6 +9,6 @@ spellcheck=false }} -{{#if filterIcon}} - {{d-icon filterIcon}} +{{#if icon}} + {{d-icon icon class="filter-icon"}} {{/if}} diff --git a/app/assets/javascripts/discourse/templates/components/select-box/select-box-header.hbs b/app/assets/javascripts/discourse/templates/components/select-box/select-box-header.hbs index c0bf0a71cef..14184521797 100644 --- a/app/assets/javascripts/discourse/templates/components/select-box/select-box-header.hbs +++ b/app/assets/javascripts/discourse/templates/components/select-box/select-box-header.hbs @@ -1,15 +1,9 @@ -