select-box minor fixes

This commit is contained in:
Joffrey JAFFEUX 2017-08-25 19:56:57 +02:00 committed by GitHub
parent 075cc1a8bb
commit 14f06c2740
10 changed files with 188 additions and 173 deletions

View File

@ -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

View File

@ -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: ""
});
}
},
});

View File

@ -1,3 +1,5 @@
export default Ember.Component.extend({
classNames: "select-box-filter"
classNames: "select-box-filter",
classNameBindings: ["focused:is-focused"]
});

View File

@ -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}}
</div>
<div class="select-box-wrapper"></div>
{{#if wrapper}}
<div class="select-box-wrapper"></div>
{{/if}}

View File

@ -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}}

View File

@ -1,15 +1,9 @@
<div class="wrapper">
{{#if icon}}
<div class="icon">
{{d-icon icon}}
</div>
{{/if}}
{{#if icon}}
{{d-icon icon class="icon"}}
{{/if}}
<span class="current-selection">
{{text}}
</span>
<span class="current-selection">
{{{text}}}
</span>
<div class="caret-icon">
{{d-icon caretIcon}}
</div>
</div>
{{d-icon caretIcon class="caret-icon"}}

View File

@ -72,7 +72,7 @@
{{#if model.showCategoryChooser}}
<div class="category-input">
{{category-select-box valueAttribute="id" value=model.categoryId scopedCategoryId=scopedCategoryId tabindex="3"}}
{{category-select-box value=model.categoryId scopedCategoryId=scopedCategoryId tabindex="3"}}
{{popup-input-tip validation=categoryValidation}}
</div>
{{#if model.archetype.hasOptions}}

View File

@ -1,11 +1,8 @@
.category-select-box.select-box {
height: 34px;
.category-select-box {
.select-box-row {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
line-height: 14px;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;

View File

@ -2,9 +2,7 @@
border-radius: 3px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
display: inline-block;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
@ -39,6 +37,16 @@
.collection, {
border-radius: 0 0 3px 3px;
}
.select-box-header {
border-radius: 3px 3px 0 0;
}
&.is-reversed {
.select-box-header {
border-radius: 0 0 3px 3px;
}
}
}
&.is-highlighted {
@ -62,8 +70,7 @@
}
.d-icon {
color: dark-light-choose(scale-color($header_primary, $lightness: 50%), $header_primary);
font-size: 14px;
opacity: 0.7;
}
.select-box-header {
@ -74,6 +81,9 @@
box-sizing: border-box;
cursor: pointer;
outline: none;
display: flex;
align-items: center;
justify-content: space-between;
&.is-focused {
border: 1px solid $tertiary;
@ -142,24 +152,22 @@
}
.select-box .select-box-header {
.wrapper {
height: inherit;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
padding-left: 10px;
padding-right: 10px;
}
height: inherit;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
padding-left: 10px;
padding-right: 10px;
.current-selection {
text-align: left;
@ -169,6 +177,7 @@
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: inherit;
}
.icon {
@ -218,10 +227,6 @@
margin: 5px;
min-height: 1px;
.d-icon {
margin-right: 5px;
}
.text {
margin: 0;
}
@ -246,7 +251,8 @@
justify-content: space-between;
padding: 0 10px;
input, input:focus {
.filter-query, .filter-query:focus, .filter-query:active {
background: none;
margin: 0;
-webkit-box-flex: 1;
-ms-flex: 1;

View File

@ -87,7 +87,7 @@ componentTest('customisable icon', {
template: '{{select-box icon="shower"}}',
test(assert) {
assert.equal(find(".select-box-header .icon").html().trim(), "<i class=\"fa fa-shower d-icon d-icon-shower\"></i>", "it has a the correct icon");
assert.equal(find(".select-box-header .icon").hasClass("d-icon-shower"), true, "it has a the correct icon");
}
});