FEATURE: support for multi-combo-box
This commit is contained in:
parent
3093074398
commit
0da529010a
10
.eslintrc
10
.eslintrc
|
@ -43,11 +43,11 @@
|
|||
"asyncRender":true,
|
||||
"selectDropdown":true,
|
||||
"selectBox":true,
|
||||
"expandSelectBox":true,
|
||||
"collapseSelectBox":true,
|
||||
"selectBoxSelectRow":true,
|
||||
"selectBoxSelectNoneRow":true,
|
||||
"selectBoxFillInFilter":true,
|
||||
"expandSelectBoxKit":true,
|
||||
"collapseSelectBoxKit":true,
|
||||
"selectBoxKitSelectRow":true,
|
||||
"selectBoxKitSelectNoneRow":true,
|
||||
"selectBoxKitFillInFilter":true,
|
||||
"asyncTestDiscourse":true,
|
||||
"fixture":true,
|
||||
"find":true,
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
export default Ember.Component.extend({
|
||||
tagName: 'div',
|
||||
|
||||
_init: function(){
|
||||
this.$("input").select2({
|
||||
multiple: true,
|
||||
width: '100%',
|
||||
query: function(opts) {
|
||||
opts.callback({
|
||||
results: this.get("available").filter(function(o) {
|
||||
return -1 !== o.name.toLowerCase().indexOf(opts.term.toLowerCase());
|
||||
}).map(this._format)
|
||||
});
|
||||
}.bind(this)
|
||||
}).on("change", function(evt) {
|
||||
if (evt.added){
|
||||
this.triggerAction({
|
||||
action: "groupAdded",
|
||||
actionContext: this.get("available").findBy("id", evt.added.id)
|
||||
});
|
||||
} else if (evt.removed) {
|
||||
this.triggerAction({
|
||||
action:"groupRemoved",
|
||||
actionContext: evt.removed.id
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this._refreshOnReset();
|
||||
}.on("didInsertElement"),
|
||||
|
||||
_format(item) {
|
||||
return {
|
||||
"text": item.name,
|
||||
"id": item.id,
|
||||
"locked": item.automatic
|
||||
};
|
||||
},
|
||||
|
||||
_refreshOnReset: function() {
|
||||
this.$("input").select2("data", this.get("selected").map(this._format));
|
||||
}.observes("selected")
|
||||
});
|
|
@ -1,52 +0,0 @@
|
|||
/**
|
||||
Provide a nice GUI for a pipe-delimited list in the site settings.
|
||||
|
||||
@param settingValue is a reference to SiteSetting.value.
|
||||
@param choices is a reference to SiteSetting.choices
|
||||
**/
|
||||
export default Ember.Component.extend({
|
||||
|
||||
_select2FormatSelection: function(selectedObject, jqueryWrapper, htmlEscaper) {
|
||||
var text = selectedObject.text;
|
||||
if (text.length <= 6) {
|
||||
jqueryWrapper.closest('li.select2-search-choice').css({"border-bottom": '7px solid #'+text});
|
||||
}
|
||||
return htmlEscaper(text);
|
||||
},
|
||||
|
||||
_initializeSelect2: function(){
|
||||
var options = {
|
||||
multiple: false,
|
||||
separator: "|",
|
||||
tokenSeparators: ["|"],
|
||||
tags : this.get("choices") || [],
|
||||
width: 'off',
|
||||
dropdownCss: this.get("choices") ? {} : {display: 'none'},
|
||||
selectOnBlur: this.get("choices") ? false : true
|
||||
};
|
||||
|
||||
var settingName = this.get('settingName');
|
||||
if (typeof settingName === 'string' && settingName.indexOf('colors') > -1) {
|
||||
options.formatSelection = this._select2FormatSelection;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.$("input").select2(options).on("change", function(obj) {
|
||||
self.set("settingValue", obj.val.join("|"));
|
||||
self.refreshSortables();
|
||||
});
|
||||
|
||||
this.refreshSortables();
|
||||
}.on('didInsertElement'),
|
||||
|
||||
refreshOnReset: function() {
|
||||
this.$("input").select2("val", this.get("settingValue").split("|"));
|
||||
}.observes("settingValue"),
|
||||
|
||||
refreshSortables: function() {
|
||||
var self = this;
|
||||
this.$("ul.select2-choices").sortable().on('sortupdate', function() {
|
||||
self.$("input").select2("onSortEnd");
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1 +0,0 @@
|
|||
<input type="text">
|
|
@ -1,3 +0,0 @@
|
|||
<div class="input-setting-list">
|
||||
<input type="text" value="{{unbound settingValue}}">
|
||||
</div>
|
|
@ -0,0 +1,45 @@
|
|||
import MultiComboBoxComponent from "select-box-kit/components/multi-combo-box";
|
||||
|
||||
export default MultiComboBoxComponent.extend({
|
||||
classNames: "admin-group-selector",
|
||||
selected: null,
|
||||
available: null,
|
||||
allowAny: false,
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super();
|
||||
|
||||
this.set("value", this.get("selected").map(s => this._valueForContent(s)));
|
||||
this.set("content", this.get("available"));
|
||||
},
|
||||
|
||||
formatRowContent(content) {
|
||||
let formatedContent = this._super(content);
|
||||
formatedContent.locked = content.automatic;
|
||||
return formatedContent;
|
||||
},
|
||||
|
||||
didUpdateAttrs() {
|
||||
this._super();
|
||||
|
||||
this.set("highlightedValue", null);
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.autoHighlightFunction();
|
||||
});
|
||||
},
|
||||
|
||||
selectValuesFunction(values) {
|
||||
values.forEach(value => {
|
||||
this.triggerAction({
|
||||
action: "groupAdded",
|
||||
actionContext: this.get("content").findBy("id", parseInt(value, 10))
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
deselectValuesFunction(values) {
|
||||
values.forEach(value => {
|
||||
this.triggerAction({ action: "groupRemoved", actionContext: value });
|
||||
});
|
||||
}
|
||||
});
|
|
@ -8,10 +8,10 @@ export default DropdownSelectBoxComponent.extend({
|
|||
|
||||
@on("didReceiveAttrs")
|
||||
_setComponentOptions() {
|
||||
this.set("headerComponentOptions", Ember.Object.create({
|
||||
this.get("headerComponentOptions").setProperties({
|
||||
shouldDisplaySelectedName: false,
|
||||
icon: `${iconHTML('bars')}${iconHTML('caret-down')}`.htmlSafe(),
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
@computed
|
||||
|
@ -38,11 +38,8 @@ export default DropdownSelectBoxComponent.extend({
|
|||
return items;
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
this.get(value)();
|
||||
this.set("value", null);
|
||||
}
|
||||
selectValueFunction(value) {
|
||||
this.get(value)();
|
||||
this.set("value", null);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,24 +12,24 @@ export default ComboBoxComponent.extend({
|
|||
castInteger: true,
|
||||
allowUncategorized: null,
|
||||
|
||||
filterFunction(computedContent) {
|
||||
const _matchFunction = (filter, text) => {
|
||||
return text.toLowerCase().indexOf(filter) > -1;
|
||||
};
|
||||
filteredContentFunction(computedContent, computedValue, filter) {
|
||||
if (isEmpty(filter)) { return computedContent; }
|
||||
|
||||
return (selectBox) => {
|
||||
const filter = selectBox.get("filter").toLowerCase();
|
||||
return _.filter(computedContent, c => {
|
||||
const category = Category.findById(get(c, "value"));
|
||||
const text = get(c, "name");
|
||||
if (category && category.get("parentCategory")) {
|
||||
const categoryName = category.get("parentCategory.name");
|
||||
return _matchFunction(filter, text) || _matchFunction(filter, categoryName);
|
||||
} else {
|
||||
return _matchFunction(filter, text);
|
||||
}
|
||||
});
|
||||
const _matchFunction = (f, text) => {
|
||||
return text.toLowerCase().indexOf(f) > -1;
|
||||
};
|
||||
const lowerFilter = filter.toLowerCase();
|
||||
|
||||
return computedContent.filter(c => {
|
||||
const category = Category.findById(get(c, "value"));
|
||||
const text = get(c, "name");
|
||||
if (category && category.get("parentCategory")) {
|
||||
const categoryName = category.get("parentCategory.name");
|
||||
return _matchFunction(lowerFilter, text) || _matchFunction(lowerFilter, categoryName);
|
||||
} else {
|
||||
return _matchFunction(lowerFilter, text);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@computed("rootNone", "rootNoneLabel")
|
||||
|
|
|
@ -7,11 +7,7 @@ export default NotificationOptionsComponent.extend({
|
|||
value: Ember.computed.alias("category.notification_level"),
|
||||
headerComponent: "category-notifications-button/category-notifications-button-header",
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
this.get("category").setNotification(value);
|
||||
this.blur();
|
||||
}
|
||||
selectValueFunction(value) {
|
||||
this.get("category").setNotification(value);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,10 +12,10 @@ export default SelectBoxKitComponent.extend({
|
|||
|
||||
@on("didReceiveAttrs")
|
||||
_setComboBoxOptions() {
|
||||
this.set("headerComponentOptions", Ember.Object.create({
|
||||
this.get("headerComponentOptions").setProperties({
|
||||
caretUpIcon: this.get("caretUpIcon"),
|
||||
caretDownIcon: this.get("caretDownIcon"),
|
||||
clearable: this.get("clearable"),
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -9,16 +9,11 @@ export default SelectBoxKitComponent.extend({
|
|||
headerComponent: "dropdown-select-box/dropdown-select-box-header",
|
||||
rowComponent: "dropdown-select-box/dropdown-select-box-row",
|
||||
|
||||
clickOutside() {
|
||||
this.close();
|
||||
},
|
||||
clickOutside() { this.close(); },
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
this.set("value", value);
|
||||
didSelectValue() {
|
||||
this._super();
|
||||
|
||||
this.blur();
|
||||
}
|
||||
this.blur();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,10 +5,7 @@ export default NotificationOptionsComponent.extend({
|
|||
value: Ember.computed.alias("group.group_user.notification_level"),
|
||||
i18nPrefix: "groups.notifications",
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
this.get("group").setNotification(value, this.get("user.id"));
|
||||
}
|
||||
selectValueFunction(value) {
|
||||
this.get("group").setNotification(value, this.get("user.id"));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import MultiComboBoxComponent from "select-box-kit/components/multi-combo-box";
|
||||
import { observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default MultiComboBoxComponent.extend({
|
||||
classNames: "list-setting",
|
||||
tokenSeparator: "|",
|
||||
settingValue: "",
|
||||
choices: null,
|
||||
filterable: true,
|
||||
|
||||
init() {
|
||||
const valuesFromString = this.get("settingValue").split(this.get("tokenSeparator"));
|
||||
this.set("value", valuesFromString.reject(v => Ember.isEmpty(v)));
|
||||
|
||||
if (Ember.isNone(this.get("choices"))) {
|
||||
this.set("content", valuesFromString);
|
||||
} else {
|
||||
this.set("content", this.get("choices"));
|
||||
}
|
||||
|
||||
if (!Ember.isNone(this.get("settingName"))) {
|
||||
this.set("nameProperty", this.get("settingName"));
|
||||
}
|
||||
|
||||
if (Ember.isEmpty(this.get("content"))) {
|
||||
this.set("rowComponent", null);
|
||||
this.set("noContentLabel", null);
|
||||
}
|
||||
|
||||
this._super();
|
||||
|
||||
if (this.get("nameProperty").indexOf("color") > -1) {
|
||||
this.set("headerComponentOptions", Ember.Object.create({
|
||||
selectedNameComponent: "multi-combo-box/selected-color"
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
@observes("value.[]")
|
||||
setSettingValue() {
|
||||
this.set("settingValue", this.get("value").join(this.get("tokenSeparator")));
|
||||
},
|
||||
|
||||
@observes("content.[]")
|
||||
setChoices() { this.set("choices", this.get("content")); },
|
||||
|
||||
_handleTabOnKeyDown(event) {
|
||||
if (this.$highlightedRow().length === 1) {
|
||||
this._super(event);
|
||||
} else {
|
||||
this.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,20 +1,32 @@
|
|||
// Experimental
|
||||
import SelectBoxKitComponent from "select-box-kit/components/select-box-kit";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
const { get, isNone } = Ember;
|
||||
const { get, isNone, isEmpty } = Ember;
|
||||
|
||||
export default SelectBoxKitComponent.extend({
|
||||
classNames: "multi-combobox",
|
||||
classNames: "multi-combo-box",
|
||||
headerComponent: "multi-combo-box/multi-combo-box-header",
|
||||
filterComponent: null,
|
||||
headerText: "select_box.default_header_text",
|
||||
value: [],
|
||||
allowAny: true,
|
||||
allowValueMutation: false,
|
||||
autoSelectFirst: false,
|
||||
autoFilterable: true,
|
||||
selectedNameComponent: "multi-combo-box/selected-name",
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
|
||||
if (isNone(this.get("value"))) { this.set("value", []); }
|
||||
|
||||
this.set("headerComponentOptions", Ember.Object.create({
|
||||
selectedNameComponent: this.get("selectedNameComponent")
|
||||
}));
|
||||
},
|
||||
|
||||
@computed("filter")
|
||||
templateForCreateRow() {
|
||||
return (rowComponent) => {
|
||||
return `Create: ${rowComponent.get("content.name")}`;
|
||||
return I18n.t("select_box.create", { content: rowComponent.get("content.name")});
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -22,78 +34,207 @@ export default SelectBoxKitComponent.extend({
|
|||
const keyCode = event.keyCode || event.which;
|
||||
const $filterInput = this.$filterInput();
|
||||
|
||||
if (keyCode === 8) {
|
||||
let $lastSelectedValue = $(this.$(".choices .selected-name").last());
|
||||
if (this.get("isFocused") === true && this.get("isExpanded") === false && keyCode === this.keys.BACKSPACE) {
|
||||
this.expand();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($lastSelectedValue.is(":focus") || $(document.activeElement).is($lastSelectedValue)) {
|
||||
this.send("onDeselect", $lastSelectedValue.data("value"));
|
||||
// select all choices
|
||||
if (event.metaKey === true && keyCode === 65 && isEmpty(this.get("filter"))) {
|
||||
this.$(".choices .selected-name:not(.is-locked)").addClass("is-highlighted");
|
||||
return;
|
||||
}
|
||||
|
||||
// clear selection when multiple
|
||||
if (Ember.isEmpty(this.get("filter")) && this.$(".selected-name.is-highlighted").length >= 1 && keyCode === this.keys.BACKSPACE) {
|
||||
const highlightedValues = [];
|
||||
$.each(this.$(".selected-name.is-highlighted"), (i, el) => {
|
||||
highlightedValues.push($(el).attr("data-value"));
|
||||
});
|
||||
|
||||
this.send("onDeselect", highlightedValues);
|
||||
return;
|
||||
}
|
||||
|
||||
// try to remove last item from the list
|
||||
if (Ember.isEmpty(this.get("filter")) && keyCode === this.keys.BACKSPACE) {
|
||||
let $lastSelectedValue = $(this.$(".choices .selected-name:not(.is-locked)").last());
|
||||
|
||||
if ($lastSelectedValue.length === 0) { return; }
|
||||
|
||||
if ($lastSelectedValue.hasClass("is-highlighted") || $(document.activeElement).is($lastSelectedValue)) {
|
||||
this.send("onDeselect", this.get("selectedContent.lastObject.value"));
|
||||
$filterInput.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if ($filterInput.not(":visible") && $lastSelectedValue.length > 0) {
|
||||
$lastSelectedValue.click();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($filterInput.val() === "") {
|
||||
if ($filterInput.is(":focus")) {
|
||||
if ($lastSelectedValue.length > 0) {
|
||||
$lastSelectedValue.focus();
|
||||
}
|
||||
if ($lastSelectedValue.length > 0) { $lastSelectedValue.click(); }
|
||||
} else {
|
||||
if ($lastSelectedValue.length > 0) {
|
||||
$lastSelectedValue.focus();
|
||||
$lastSelectedValue.click();
|
||||
} else {
|
||||
$filterInput.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$filterInput.focus();
|
||||
this._super(event);
|
||||
}
|
||||
},
|
||||
|
||||
@computed("none")
|
||||
computedNone(none) {
|
||||
if (!isNone(none)) {
|
||||
this.set("none", { name: I18n.t(none), value: "" });
|
||||
}
|
||||
},
|
||||
|
||||
@computed("value.[]")
|
||||
computedValue(value) {
|
||||
return value.map(v => this._castInteger(v));
|
||||
},
|
||||
computedValue(value) { return value.map(v => this._castInteger(v)); },
|
||||
|
||||
@computed("computedValue.[]", "computedContent.[]")
|
||||
selectedContent(computedValue, computedContent) {
|
||||
@computed("value.[]", "computedContent.[]")
|
||||
selectedContent(value, computedContent) {
|
||||
const contents = [];
|
||||
computedValue.forEach(cv => {
|
||||
contents.push(computedContent.findBy("value", cv));
|
||||
value.forEach(v => {
|
||||
const content = computedContent.findBy("value", v);
|
||||
if (!isNone(content)) { contents.push(content); }
|
||||
});
|
||||
return contents;
|
||||
},
|
||||
|
||||
filterFunction(content) {
|
||||
return (selectBox, computedValue) => {
|
||||
const filter = selectBox.get("filter").toLowerCase();
|
||||
return _.filter(content, c => {
|
||||
return !computedValue.includes(get(c, "value")) &&
|
||||
get(c, "name").toLowerCase().indexOf(filter) > -1;
|
||||
});
|
||||
};
|
||||
filteredContentFunction(computedContent, computedValue, filter) {
|
||||
computedContent = computedContent.filter(c => {
|
||||
return !computedValue.includes(get(c, "value"));
|
||||
});
|
||||
|
||||
if (isEmpty(filter)) { return computedContent; }
|
||||
|
||||
const lowerFilter = filter.toLowerCase();
|
||||
return computedContent.filter(c => {
|
||||
return get(c, "name").toLowerCase().indexOf(lowerFilter) > -1;
|
||||
});
|
||||
},
|
||||
|
||||
willCreateContent() {
|
||||
this.set("highlightedValue", null);
|
||||
},
|
||||
|
||||
didCreateContent() {
|
||||
this.clearFilter();
|
||||
this.autoHighlightFunction();
|
||||
},
|
||||
|
||||
createContentFunction(input) {
|
||||
if (!this.get("content").includes(input)) {
|
||||
this.get("content").pushObject(input);
|
||||
this.get("value").pushObject(input);
|
||||
}
|
||||
},
|
||||
|
||||
deselectValuesFunction(values) {
|
||||
const contents = this._computeRemovableContentsForValues(values);
|
||||
this.get("value").removeObjects(values);
|
||||
this.get("content").removeObjects(contents);
|
||||
},
|
||||
|
||||
highlightValueFunction(value) {
|
||||
this.set("highlightedValue", value);
|
||||
},
|
||||
|
||||
selectValuesFunction(values) {
|
||||
this.get("value").pushObjects(values);
|
||||
},
|
||||
|
||||
willSelectValues() {
|
||||
this.expand();
|
||||
this.set("highlightedValue", null);
|
||||
},
|
||||
|
||||
didSelectValues() {
|
||||
this.focus();
|
||||
this.clearFilter();
|
||||
this.autoHighlightFunction();
|
||||
},
|
||||
|
||||
willDeselectValues() {
|
||||
this.set("highlightedValue", null);
|
||||
},
|
||||
|
||||
didDeselectValues() {
|
||||
this.autoHighlightFunction();
|
||||
},
|
||||
|
||||
willHighlightValue() {},
|
||||
|
||||
didHighlightValue() {},
|
||||
|
||||
autoHighlightFunction() {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
if (this.get("isExpanded") === false) { return; }
|
||||
if (this.get("renderedBodyOnce") === false) { return; }
|
||||
if (!isNone(this.get("highlightedValue"))) { return; }
|
||||
|
||||
if (isEmpty(this.get("filteredContent"))) {
|
||||
if (!isEmpty(this.get("filter"))) {
|
||||
this.send("onHighlight", this.get("filter"));
|
||||
} else if (this.get("none") && !isEmpty(this.get("selectedContent"))) {
|
||||
this.send("onHighlight", this.noneValue);
|
||||
}
|
||||
} else {
|
||||
this.send("onHighlight", this.get("filteredContent.firstObject.value"));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
onClearSelection() {
|
||||
this.send("onSelect", []);
|
||||
const values = this.get("selectedContent").map(c => get(c, "value"));
|
||||
this.send("onDeselect", values);
|
||||
},
|
||||
|
||||
onSelect(value) {
|
||||
this.setProperties({ filter: "", highlightedValue: null });
|
||||
this.get("value").pushObject(value);
|
||||
onHighlight(value) {
|
||||
value = this._originalValueForValue(value);
|
||||
this.willHighlightValue(value);
|
||||
this.set("highlightedValue", value);
|
||||
this.highlightValueFunction(value);
|
||||
this.didHighlightValue(value);
|
||||
},
|
||||
|
||||
onDeselect(value) {
|
||||
this.defaultOnDeselect(value);
|
||||
this.get("value").removeObject(value);
|
||||
onCreateContent(input) {
|
||||
this.willCreateContent(input);
|
||||
this.createContentFunction(input);
|
||||
this.didCreateContent(input);
|
||||
},
|
||||
|
||||
onSelect(values) {
|
||||
values = Ember.makeArray(values).map(v => this._originalValueForValue(v));
|
||||
this.willSelectValues(values);
|
||||
this.selectValuesFunction(values);
|
||||
this.didSelectValues(values);
|
||||
},
|
||||
|
||||
onDeselect(values) {
|
||||
values = Ember.makeArray(this._computeRemovableValues(values));
|
||||
this.willDeselectValues(values);
|
||||
this.deselectValuesFunction(values);
|
||||
this.didSelectValues(values);
|
||||
}
|
||||
},
|
||||
|
||||
_computeRemovableContentsForValues(values) {
|
||||
const removableContents = [];
|
||||
values.forEach(v => {
|
||||
if (!this.get("_initialValues").includes(v)) {
|
||||
const content = this._contentForValue(v);
|
||||
if (!isNone(content)) { removableContents.push(content); }
|
||||
}
|
||||
});
|
||||
return removableContents;
|
||||
},
|
||||
|
||||
_computeRemovableValues(values) {
|
||||
return Ember.makeArray(values)
|
||||
.map(v => this._originalValueForValue(v))
|
||||
.filter(v => {
|
||||
return get(this._computedContentForValue(v), "locked") !== true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,37 +4,27 @@ import SelectBoxKitHeaderComponent from "select-box-kit/components/select-box-ki
|
|||
|
||||
export default SelectBoxKitHeaderComponent.extend({
|
||||
attributeBindings: ["names:data-name"],
|
||||
classNames: "multi-combobox-header",
|
||||
classNames: "multi-combo-box-header",
|
||||
layoutName: "select-box-kit/templates/components/multi-combo-box/multi-combo-box-header",
|
||||
|
||||
@computed("filter", "selectedContent.[]", "isFocused", "selectBoxIsExpanded")
|
||||
shouldDisplayFilterPlaceholder(filter, selectedContent, isFocused) {
|
||||
if (Ember.isEmpty(selectedContent)) {
|
||||
if (filter.length > 0) { return false; }
|
||||
if (isFocused === true) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
selectedNameComponent: Ember.computed.alias("options.selectedNameComponent"),
|
||||
|
||||
@on("didRender")
|
||||
_positionFilter() {
|
||||
this.$(".filter").width(0);
|
||||
if (this.get("shouldDisplayFilter") === false) { return; }
|
||||
|
||||
const $filter = this.$(".filter");
|
||||
$filter.width(0);
|
||||
|
||||
const leftHeaderOffset = this.$().offset().left;
|
||||
const leftFilterOffset = this.$(".filter").offset().left;
|
||||
const leftFilterOffset = $filter.offset().left;
|
||||
const offset = leftFilterOffset - leftHeaderOffset;
|
||||
const width = this.$().outerWidth(false);
|
||||
const availableSpace = width - offset;
|
||||
|
||||
// TODO: avoid magic number 8
|
||||
// TODO: make sure the filter doesn’t end up being very small
|
||||
this.$(".filter").width(availableSpace - 8);
|
||||
const $choices = $filter.parent(".choices");
|
||||
const parentRightPadding = parseInt($choices.css("padding-right") , 10);
|
||||
$filter.width(availableSpace - parentRightPadding * 4);
|
||||
},
|
||||
|
||||
@computed("selectedContent.[]")
|
||||
names(selectedContent) {
|
||||
return selectedContent.map(sc => sc.name).join(",");
|
||||
}
|
||||
names(selectedContent) { return selectedContent.map(sc => sc.name).join(","); }
|
||||
});
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
import SelectedNameComponent from "select-box-kit/components/multi-combo-box/selected-name";
|
||||
|
||||
export default SelectedNameComponent.extend({
|
||||
didRender() {
|
||||
const name = this.get("content.name");
|
||||
this.$().css("border-bottom", Handlebars.Utils.escapeExpression(`7px solid #${name}`));
|
||||
}
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
export default Ember.Component.extend({
|
||||
attributeBindings: ["tabindex","content.name:data-name", "content.value:data-value"],
|
||||
classNames: "selected-name",
|
||||
classNameBindings: ["isHighlighted", "isLocked"],
|
||||
layoutName: "select-box-kit/templates/components/multi-combo-box/selected-name",
|
||||
tagName: "li",
|
||||
tabindex: -1,
|
||||
|
||||
isLocked: Ember.computed("content.locked", function() {
|
||||
return this.getWithDefault("content.locked", false);
|
||||
}),
|
||||
|
||||
click() {
|
||||
if (this.get("isLocked") === true) { return false; }
|
||||
|
||||
this.toggleProperty("isHighlighted");
|
||||
return false;
|
||||
}
|
||||
});
|
|
@ -22,15 +22,15 @@ export default DropdownSelectBoxComponent.extend({
|
|||
|
||||
@on("didReceiveAttrs", "didUpdateAttrs")
|
||||
_setComponentOptions() {
|
||||
this.set("headerComponentOptions", Ember.Object.create({
|
||||
this.get("headerComponentOptions").setProperties({
|
||||
i18nPrefix: this.get("i18nPrefix"),
|
||||
showFullTitle: this.get("showFullTitle"),
|
||||
}));
|
||||
});
|
||||
|
||||
this.set("rowComponentOptions", Ember.Object.create({
|
||||
this.get("rowComponentOptions").setProperties({
|
||||
i18nPrefix: this.get("i18nPrefix"),
|
||||
i18nPostfix: this.get("i18nPostfix")
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
@computed("computedValue")
|
||||
|
|
|
@ -11,7 +11,7 @@ export default DropdownSelectBoxHeaderComponent.extend({
|
|||
|
||||
@computed("_selectedDetails.icon", "_selectedDetails.key")
|
||||
icon(icon, key) {
|
||||
return iconHTML(icon, {class: key}).htmlSafe();
|
||||
return iconHTML(icon, { class: key }).htmlSafe();
|
||||
},
|
||||
|
||||
@computed("_selectedDetails.key", "i18nPrefix")
|
||||
|
@ -20,5 +20,7 @@ export default DropdownSelectBoxHeaderComponent.extend({
|
|||
},
|
||||
|
||||
@computed("selectedContent.firstObject.value")
|
||||
_selectedDetails(value) { return buttonDetails(value); }
|
||||
_selectedDetails(value) {
|
||||
return buttonDetails(value);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -48,17 +48,13 @@ export default DropdownSelectBoxComponent.extend({
|
|||
];
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
selectValueFunction(value) {
|
||||
const topic = this.get("topic");
|
||||
|
||||
const topic = this.get("topic");
|
||||
|
||||
if (value === "unpinned") {
|
||||
topic.clearPin();
|
||||
} else {
|
||||
topic.rePin();
|
||||
}
|
||||
if (value === "unpinned") {
|
||||
topic.clearPin();
|
||||
} else {
|
||||
topic.rePin();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const { get, isNone, isEmpty, isPresent } = Ember;
|
||||
import { on, observes } from "ember-addons/ember-computed-decorators";
|
||||
import { on } from "ember-addons/ember-computed-decorators";
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import UtilsMixin from "select-box-kit/mixins/utils";
|
||||
import DomHelpersMixin from "select-box-kit/mixins/dom-helpers";
|
||||
|
@ -22,7 +22,8 @@ export default Ember.Component.extend(UtilsMixin, DomHelpersMixin, KeyboardMixin
|
|||
isExpanded: false,
|
||||
isFocused: false,
|
||||
isHidden: false,
|
||||
renderBody: false,
|
||||
renderedBodyOnce: false,
|
||||
renderedFilterOnce: false,
|
||||
tabindex: 0,
|
||||
scrollableParentSelector: ".modal-body",
|
||||
value: null,
|
||||
|
@ -37,10 +38,12 @@ export default Ember.Component.extend(UtilsMixin, DomHelpersMixin, KeyboardMixin
|
|||
filterPlaceholder: "select_box.filter_placeholder",
|
||||
filterIcon: "search",
|
||||
rowComponent: "select-box-kit/select-box-kit-row",
|
||||
rowComponentOptions: null,
|
||||
noneRowComponent: "select-box-kit/select-box-kit-none-row",
|
||||
createRowComponent: "select-box-kit/select-box-kit-create-row",
|
||||
filterComponent: "select-box-kit/select-box-kit-filter",
|
||||
headerComponent: "select-box-kit/select-box-kit-header",
|
||||
headerComponentOptions: null,
|
||||
collectionComponent: "select-box-kit/select-box-kit-collection",
|
||||
collectionHeight: 200,
|
||||
verticalOffset: 0,
|
||||
|
@ -50,126 +53,92 @@ export default Ember.Component.extend(UtilsMixin, DomHelpersMixin, KeyboardMixin
|
|||
allowAny: false,
|
||||
allowValueMutation: true,
|
||||
autoSelectFirst: true,
|
||||
content: null,
|
||||
_initialValues: null,
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
|
||||
this.noneValue = "__none__";
|
||||
this._previousScrollParentOverflow = "auto";
|
||||
this._previousCSSContext = {};
|
||||
this.set("headerComponentOptions", Ember.Object.create());
|
||||
this.set("rowComponentOptions", Ember.Object.create());
|
||||
|
||||
if ($(window).outerWidth(false) <= 420) {
|
||||
this.setProperties({ filterable: false, autoFilterable: false });
|
||||
}
|
||||
|
||||
this._previousScrollParentOverflow = "auto";
|
||||
this._previousCSSContext = {};
|
||||
if (isNone(this.get("content"))) { this.set("content", []); }
|
||||
this.set("value", this._castInteger(this.get("value")));
|
||||
|
||||
this.setInitialValues();
|
||||
},
|
||||
|
||||
click(event) {
|
||||
event.stopPropagation();
|
||||
setInitialValues() {
|
||||
this.set("_initialValues", this.getWithDefault("content", []).map((c) => {
|
||||
return this._valueForContent(c);
|
||||
}));
|
||||
},
|
||||
|
||||
close() {
|
||||
this.setProperties({ isExpanded: false, isFocused: false });
|
||||
@computed("computedContent.[]", "computedValue.[]", "filter")
|
||||
filteredContent(computedContent, computedValue, filter) {
|
||||
return this.filteredContentFunction(computedContent, computedValue, filter);
|
||||
},
|
||||
|
||||
focus() {
|
||||
Ember.run.schedule("afterRender", () => this.$offscreenInput().select() );
|
||||
filteredContentFunction(computedContent, computedValue, filter) {
|
||||
if (isEmpty(filter)) { return computedContent; }
|
||||
|
||||
const lowerFilter = filter.toLowerCase();
|
||||
return computedContent.filter(c => {
|
||||
return get(c, "name").toLowerCase().indexOf(lowerFilter) > -1;
|
||||
});
|
||||
},
|
||||
|
||||
blur() {
|
||||
Ember.run.schedule("afterRender", () => this.$offscreenInput().blur() );
|
||||
},
|
||||
formatRowContent(content) {
|
||||
let originalContent;
|
||||
|
||||
clickOutside(event) {
|
||||
if ($(event.target).parents(".select-box-kit").length === 1) {
|
||||
this.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.get("isExpanded") === true) {
|
||||
this.set("isExpanded", false);
|
||||
this.focus();
|
||||
if (typeof content === "string" || typeof content === "number") {
|
||||
originalContent = {};
|
||||
originalContent[this.get("valueAttribute")] = content;
|
||||
originalContent[this.get("nameProperty")] = content;
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
createFunction(input) {
|
||||
return (selectedBox) => {
|
||||
const formatedContent = selectedBox.formatContent(input);
|
||||
formatedContent.meta.generated = true;
|
||||
return formatedContent;
|
||||
};
|
||||
},
|
||||
|
||||
filterFunction(content) {
|
||||
return selectBox => {
|
||||
const filter = selectBox.get("filter").toLowerCase();
|
||||
return _.filter(content, c => {
|
||||
return get(c, "name").toLowerCase().indexOf(filter) > -1;
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
nameForContent(content) {
|
||||
if (isNone(content)) {
|
||||
return null;
|
||||
originalContent = content;
|
||||
}
|
||||
|
||||
if (typeof content === "object") {
|
||||
return get(content, this.get("nameProperty"));
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
valueForContent(content) {
|
||||
switch (typeof content) {
|
||||
case "string":
|
||||
case "number":
|
||||
return this._castInteger(content);
|
||||
default:
|
||||
return this._castInteger(get(content, this.get("valueAttribute")));
|
||||
}
|
||||
},
|
||||
|
||||
formatContent(content) {
|
||||
return {
|
||||
value: this.valueForContent(content),
|
||||
name: this.nameForContent(content),
|
||||
originalContent: content,
|
||||
meta: { generated: false }
|
||||
value: this._castInteger(this._valueForContent(content)),
|
||||
name: this._nameForContent(content),
|
||||
locked: false,
|
||||
originalContent
|
||||
};
|
||||
},
|
||||
|
||||
formatContents(contents) {
|
||||
return contents.map(content => this.formatContent(content));
|
||||
return contents.map(content => this.formatRowContent(content));
|
||||
},
|
||||
|
||||
@computed("filter", "filterable", "autoFilterable")
|
||||
computedFilterable(filter, filterable, autoFilterable) {
|
||||
if (filterable === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (filter.length > 0 && autoFilterable === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@computed("filter", "filterable", "autoFilterable", "renderedFilterOnce")
|
||||
shouldDisplayFilter(filter, filterable, autoFilterable, renderedFilterOnce) {
|
||||
if (renderedFilterOnce === true || filterable === true) { return true; }
|
||||
if (filter.length > 0 && autoFilterable === true) { return true; }
|
||||
return false;
|
||||
},
|
||||
|
||||
@computed("computedFilterable", "filter", "allowAny")
|
||||
shouldDisplayCreateRow(computedFilterable, filter, allow) {
|
||||
return computedFilterable === true && filter.length > 0 && allow === true;
|
||||
@computed("filter")
|
||||
shouldDisplayCreateRow(filter) {
|
||||
if (this.get("allowAny") === true && filter.length > 0) { return true; }
|
||||
return false;
|
||||
},
|
||||
|
||||
@computed("filter", "allowAny")
|
||||
createRowContent(filter, allow) {
|
||||
if (allow === true) {
|
||||
@computed("filter", "shouldDisplayCreateRow")
|
||||
createRowContent(filter, shouldDisplayCreateRow) {
|
||||
if (shouldDisplayCreateRow === true && !this.get("value").includes(filter)) {
|
||||
return Ember.Object.create({ value: filter, name: filter });
|
||||
}
|
||||
},
|
||||
|
||||
@computed("content.[]")
|
||||
@computed("content.[]", "value.[]")
|
||||
computedContent(content) {
|
||||
this._mutateValue();
|
||||
return this.formatContents(content || []);
|
||||
|
@ -178,10 +147,10 @@ export default Ember.Component.extend(UtilsMixin, DomHelpersMixin, KeyboardMixin
|
|||
@computed("value", "none", "computedContent.firstObject.value")
|
||||
computedValue(value, none, firstContentValue) {
|
||||
if (isNone(value) && isNone(none) && this.get("autoSelectFirst") === true) {
|
||||
return this._castInteger(firstContentValue);
|
||||
return firstContentValue;
|
||||
}
|
||||
|
||||
return this._castInteger(value);
|
||||
return value;
|
||||
},
|
||||
|
||||
@computed
|
||||
|
@ -195,90 +164,51 @@ export default Ember.Component.extend(UtilsMixin, DomHelpersMixin, KeyboardMixin
|
|||
|
||||
@computed("none")
|
||||
computedNone(none) {
|
||||
if (isNone(none)) {
|
||||
return null;
|
||||
}
|
||||
if (isNone(none)) { return null; }
|
||||
|
||||
switch (typeof none) {
|
||||
case "string":
|
||||
return Ember.Object.create({ name: I18n.t(none), value: "" });
|
||||
return Ember.Object.create({ name: I18n.t(none), value: this.noneValue });
|
||||
default:
|
||||
return this.formatContent(none);
|
||||
return this.formatRowContent(none);
|
||||
}
|
||||
},
|
||||
|
||||
@computed("computedValue", "computedContent.[]")
|
||||
selectedContent(computedValue, computedContent) {
|
||||
if (isNone(computedValue)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [ computedContent.findBy("value", this._castInteger(computedValue)) ];
|
||||
},
|
||||
|
||||
@on("didRender")
|
||||
_configureSelectBoxDOM() {
|
||||
if (this.get("isExpanded") === true) {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$collection().css("max-height", this.get("collectionHeight"));
|
||||
this._applyDirection();
|
||||
this._positionWrapper();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@on("willDestroyElement")
|
||||
_cleanHandlers() {
|
||||
$(window).off("resize.select-box-kit");
|
||||
this._removeFixedPosition();
|
||||
if (isNone(computedValue)) { return []; }
|
||||
return [ computedContent.findBy("value", computedValue) ];
|
||||
},
|
||||
|
||||
@on("didInsertElement")
|
||||
_setupResizeListener() {
|
||||
$(window).on("resize.select-box-kit", () => this.set("isExpanded", false) );
|
||||
$(window).on("resize.select-box-kit", () => this.collapse() );
|
||||
},
|
||||
|
||||
@observes("filter", "filteredContent.[]", "shouldDisplayCreateRow")
|
||||
_setHighlightedValue() {
|
||||
const filteredContent = this.get("filteredContent");
|
||||
const display = this.get("shouldDisplayCreateRow");
|
||||
const none = this.get("computedNone");
|
||||
|
||||
if (isNone(this.get("highlightedValue")) && !isEmpty(filteredContent)) {
|
||||
this.set("highlightedValue", get(filteredContent, "firstObject.value"));
|
||||
return;
|
||||
}
|
||||
autoHighlightFunction() {
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
if (!isNone(this.get("highlightedValue"))) { return; }
|
||||
|
||||
if (display === true && isEmpty(filteredContent)) {
|
||||
this.set("highlightedValue", this.get("filter"));
|
||||
}
|
||||
else if (!isEmpty(filteredContent)) {
|
||||
this.set("highlightedValue", get(filteredContent, "firstObject.value"));
|
||||
}
|
||||
else if (isEmpty(filteredContent) && isPresent(none) && display === false) {
|
||||
this.set("highlightedValue", get(none, "value"));
|
||||
}
|
||||
},
|
||||
const filteredContent = this.get("filteredContent");
|
||||
const display = this.get("shouldDisplayCreateRow");
|
||||
const none = this.get("computedNone");
|
||||
|
||||
@observes("isExpanded")
|
||||
_isExpandedChanged() {
|
||||
if (this.get("isExpanded") === true) {
|
||||
this._applyFixedPosition();
|
||||
if (isNone(this.get("highlightedValue")) && !isEmpty(filteredContent)) {
|
||||
this.send("onHighlight", get(filteredContent, "firstObject.value"));
|
||||
return;
|
||||
}
|
||||
|
||||
this.setProperties({
|
||||
highlightedValue: this.get("computedValue"),
|
||||
renderBody: true,
|
||||
isFocused: true
|
||||
});
|
||||
} else {
|
||||
this._removeFixedPosition();
|
||||
}
|
||||
},
|
||||
|
||||
@computed("filter", "computedFilterable", "computedContent.[]", "computedValue.[]")
|
||||
filteredContent(filter, computedFilterable, computedContent, computedValue) {
|
||||
if (computedFilterable === false) { return computedContent; }
|
||||
return this.filterFunction(computedContent)(this, computedValue);
|
||||
if (display === true && isEmpty(filteredContent)) {
|
||||
this.send("onHighlight", this.get("filter"));
|
||||
}
|
||||
else if (!isEmpty(filteredContent)) {
|
||||
this.send("onHighlight", get(filteredContent, "firstObject.value"));
|
||||
}
|
||||
else if (isEmpty(filteredContent) && isPresent(none) && display === false) {
|
||||
this.send("onHighlight", get(none, "value"));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@computed("scrollableParentSelector")
|
||||
|
@ -286,191 +216,100 @@ export default Ember.Component.extend(UtilsMixin, DomHelpersMixin, KeyboardMixin
|
|||
return this.$().parents(scrollableParentSelector).first();
|
||||
},
|
||||
|
||||
willFilterContent() {
|
||||
this.expand();
|
||||
this.set("highlightedValue", null);
|
||||
},
|
||||
didFilterContent() {
|
||||
this.set("renderedFilterOnce", true);
|
||||
this.autoHighlightFunction();
|
||||
},
|
||||
|
||||
willCreateContent() { },
|
||||
createContentFunction(input) {
|
||||
this.get("content").pushObject(input);
|
||||
this.send("onSelect", input);
|
||||
},
|
||||
didCreateContent() {
|
||||
this.clearFilter();
|
||||
this.autoHighlightFunction();
|
||||
},
|
||||
|
||||
willHighlightValue() {},
|
||||
highlightValueFunction(value) {
|
||||
this.set("highlightedValue", value);
|
||||
},
|
||||
didHighlightValue() {},
|
||||
|
||||
willSelectValue() {
|
||||
this.clearFilter();
|
||||
this.set("highlightedValue", null);
|
||||
},
|
||||
selectValueFunction(value) {
|
||||
this.set("value", value);
|
||||
},
|
||||
didSelectValue() {
|
||||
this.collapse();
|
||||
this.focus();
|
||||
},
|
||||
|
||||
willDeselectValue() {
|
||||
this.set("highlightedValue", null);
|
||||
},
|
||||
unsetValueFunction() {
|
||||
this.set("value", null);
|
||||
},
|
||||
didDeselectValue() {
|
||||
this.focus();
|
||||
},
|
||||
|
||||
actions: {
|
||||
onToggle() {
|
||||
this.toggleProperty("isExpanded");
|
||||
|
||||
if (this.get("isExpanded") === true) { this.focus(); }
|
||||
},
|
||||
|
||||
onCreateContent(input) {
|
||||
const content = this.createFunction(input)(this);
|
||||
this.get("computedContent").pushObject(content);
|
||||
this.send("onSelect", content.value);
|
||||
},
|
||||
|
||||
onFilterChange(filter) {
|
||||
this.set("filter", filter);
|
||||
},
|
||||
|
||||
onHighlight(value) {
|
||||
this.set("highlightedValue", value);
|
||||
this.get("isExpanded") === true ? this.collapse() : this.expand();
|
||||
},
|
||||
|
||||
onClearSelection() {
|
||||
this.send("onSelect", null);
|
||||
this.send("onDeselect", this.get("value"));
|
||||
},
|
||||
|
||||
onHighlight(value) {
|
||||
value = this._originalValueForValue(value);
|
||||
this.willHighlightValue(value);
|
||||
this.set("highlightedValue", value);
|
||||
this.highlightValueFunction(value);
|
||||
this.didHighlightValue(value);
|
||||
},
|
||||
|
||||
onCreateContent(input) {
|
||||
this.willCreateContent(input);
|
||||
this.createContentFunction(input);
|
||||
this.didCreateContent(input);
|
||||
},
|
||||
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
this.set("value", value);
|
||||
if (value === "") { value = null; }
|
||||
this.willSelectValue(value);
|
||||
this.selectValueFunction(value);
|
||||
this.didSelectValue(value);
|
||||
},
|
||||
|
||||
onDeselect() {
|
||||
this.defaultOnDeselect();
|
||||
this.set("value", null);
|
||||
}
|
||||
onDeselect(value) {
|
||||
value = this._originalValueForValue(value);
|
||||
this.willDeselectValue(value);
|
||||
this.unsetValueFunction(value);
|
||||
this.didSelectValue(value);
|
||||
},
|
||||
|
||||
onFilterChange(_filter) {
|
||||
this.willFilterContent(_filter);
|
||||
this.set("filter", _filter);
|
||||
this.didFilterContent(_filter);
|
||||
},
|
||||
},
|
||||
|
||||
defaultOnSelect(value) {
|
||||
if (value === "") { value = null; }
|
||||
|
||||
this.setProperties({
|
||||
highlightedValue: null,
|
||||
isExpanded: false,
|
||||
filter: ""
|
||||
});
|
||||
|
||||
this.focus();
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
defaultOnDeselect(value) {
|
||||
const content = this.get("computedContent").findBy("value", value);
|
||||
if (!isNone(content) && get(content, "meta.generated") === true) {
|
||||
this.get("computedContent").removeObject(content);
|
||||
}
|
||||
},
|
||||
|
||||
_applyDirection() {
|
||||
let options = { left: "auto", bottom: "auto", top: "auto" };
|
||||
|
||||
const dHeader = $(".d-header")[0];
|
||||
const dHeaderBounds = dHeader ? dHeader.getBoundingClientRect() : {top: 0, height: 0};
|
||||
const dHeaderHeight = dHeaderBounds.top + dHeaderBounds.height;
|
||||
const headerHeight = this.$header().outerHeight(false);
|
||||
const headerWidth = this.$header().outerWidth(false);
|
||||
const bodyHeight = this.$body().outerHeight(false);
|
||||
const windowWidth = $(window).width();
|
||||
const windowHeight = $(window).height();
|
||||
const boundingRect = this.get("element").getBoundingClientRect();
|
||||
const offsetTop = boundingRect.top;
|
||||
const offsetBottom = boundingRect.bottom;
|
||||
|
||||
if (this.get("fullWidthOnMobile") && windowWidth <= 420) {
|
||||
const margin = 10;
|
||||
const relativeLeft = this.$().offset().left - $(window).scrollLeft();
|
||||
options.left = margin - relativeLeft;
|
||||
options.width = windowWidth - margin * 2;
|
||||
options.maxWidth = options.minWidth = "unset";
|
||||
} else {
|
||||
const bodyWidth = this.$body().outerWidth(false);
|
||||
|
||||
if ($("html").css("direction") === "rtl") {
|
||||
const horizontalSpacing = boundingRect.right;
|
||||
const hasHorizontalSpace = horizontalSpacing - (this.get("horizontalOffset") + bodyWidth) > 0;
|
||||
if (hasHorizontalSpace) {
|
||||
this.setProperties({ isLeftAligned: true, isRightAligned: false });
|
||||
options.left = bodyWidth + this.get("horizontalOffset");
|
||||
} else {
|
||||
this.setProperties({ isLeftAligned: false, isRightAligned: true });
|
||||
options.right = - (bodyWidth - headerWidth + this.get("horizontalOffset"));
|
||||
}
|
||||
} else {
|
||||
const horizontalSpacing = boundingRect.left;
|
||||
const hasHorizontalSpace = (windowWidth - (this.get("horizontalOffset") + horizontalSpacing + bodyWidth) > 0);
|
||||
if (hasHorizontalSpace) {
|
||||
this.setProperties({ isLeftAligned: true, isRightAligned: false });
|
||||
options.left = this.get("horizontalOffset");
|
||||
} else {
|
||||
this.setProperties({ isLeftAligned: false, isRightAligned: true });
|
||||
options.right = this.get("horizontalOffset");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const componentHeight = this.get("verticalOffset") + bodyHeight + headerHeight;
|
||||
const hasBelowSpace = windowHeight - offsetBottom - componentHeight > 0;
|
||||
const hasAboveSpace = offsetTop - componentHeight - dHeaderHeight > 0;
|
||||
if (hasBelowSpace || (!hasBelowSpace && !hasAboveSpace)) {
|
||||
this.setProperties({ isBelow: true, isAbove: false });
|
||||
options.top = headerHeight + this.get("verticalOffset");
|
||||
} else {
|
||||
this.setProperties({ isBelow: false, isAbove: true });
|
||||
options.bottom = headerHeight + this.get("verticalOffset");
|
||||
}
|
||||
|
||||
this.$body().css(options);
|
||||
},
|
||||
|
||||
_applyFixedPosition() {
|
||||
const width = this.$().outerWidth(false);
|
||||
const height = this.$header().outerHeight(false);
|
||||
|
||||
if (this.get("scrollableParent").length === 0) { return; }
|
||||
|
||||
const $placeholder = $(`<div class='select-box-kit-fixed-placeholder-${this.elementId}'></div>`);
|
||||
|
||||
this._previousScrollParentOverflow = this.get("scrollableParent").css("overflow");
|
||||
this.get("scrollableParent").css({ overflow: "hidden" });
|
||||
|
||||
this._previousCSSContext = {
|
||||
minWidth: this.$().css("min-width"),
|
||||
maxWidth: this.$().css("max-width")
|
||||
};
|
||||
|
||||
const componentStyles = {
|
||||
position: "fixed",
|
||||
"margin-top": -this.get("scrollableParent").scrollTop(),
|
||||
width,
|
||||
minWidth: "unset",
|
||||
maxWidth: "unset"
|
||||
};
|
||||
|
||||
if ($("html").css("direction") === "rtl") {
|
||||
componentStyles.marginRight = -width;
|
||||
} else {
|
||||
componentStyles.marginLeft = -width;
|
||||
}
|
||||
|
||||
$placeholder.css({ display: "inline-block", width, height, "vertical-align": "middle" });
|
||||
|
||||
this.$().before($placeholder).css(componentStyles);
|
||||
},
|
||||
|
||||
_removeFixedPosition() {
|
||||
if (this.get("scrollableParent").length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(`.select-box-kit-fixed-placeholder-${this.elementId}`).remove();
|
||||
|
||||
const css = _.extend(
|
||||
this._previousCSSContext,
|
||||
{
|
||||
top: "auto",
|
||||
left: "auto",
|
||||
"margin-left": "auto",
|
||||
"margin-right": "auto",
|
||||
"margin-top": "auto",
|
||||
position: "relative"
|
||||
}
|
||||
);
|
||||
this.$().css(css);
|
||||
|
||||
this.get("scrollableParent").css({
|
||||
overflow: this._previousScrollParentOverflow
|
||||
});
|
||||
},
|
||||
|
||||
_positionWrapper() {
|
||||
const headerHeight = this.$header().outerHeight(false);
|
||||
|
||||
this.$(".select-box-kit-wrapper").css({
|
||||
width: this.$().width(),
|
||||
height: headerHeight + this.$body().outerHeight(false)
|
||||
});
|
||||
clearFilter() {
|
||||
this.$filterInput().val("");
|
||||
this.setProperties({ filter: "" });
|
||||
},
|
||||
|
||||
@on("didReceiveAttrs")
|
||||
|
|
|
@ -2,5 +2,5 @@ export default Ember.Component.extend({
|
|||
layoutName: "select-box-kit/templates/components/select-box-kit/select-box-kit-filter",
|
||||
classNames: "select-box-kit-filter",
|
||||
classNameBindings: ["isFocused", "isHidden"],
|
||||
isHidden: Ember.computed.not("filterable"),
|
||||
isHidden: Ember.computed.not("shouldDisplayFilter")
|
||||
});
|
||||
|
|
|
@ -8,12 +8,15 @@ export default Ember.Component.extend(UtilsMixin, {
|
|||
layoutName: "select-box-kit/templates/components/select-box-kit/select-box-kit-row",
|
||||
classNames: "select-box-kit-row",
|
||||
tagName: "li",
|
||||
tabIndex: -1,
|
||||
attributeBindings: [
|
||||
"tabIndex",
|
||||
"title",
|
||||
"content.value:data-value",
|
||||
"content.name:data-name"
|
||||
],
|
||||
classNameBindings: ["isHighlighted", "isSelected"],
|
||||
clicked: false,
|
||||
|
||||
title: Ember.computed.alias("content.name"),
|
||||
|
||||
|
@ -23,17 +26,15 @@ export default Ember.Component.extend(UtilsMixin, {
|
|||
@on("didReceiveAttrs")
|
||||
_setSelectionState() {
|
||||
const contentValue = this.get("content.value");
|
||||
|
||||
this.set("isSelected", this.get("value") === contentValue);
|
||||
this.set("isHighlighted", this._castInteger(this.get("highlightedValue")) === this._castInteger(contentValue));
|
||||
this.set("isHighlighted", this.get("highlightedValue") === contentValue);
|
||||
},
|
||||
|
||||
@on("willDestroyElement")
|
||||
_clearDebounce() {
|
||||
const hoverDebounce = this.get("hoverDebounce");
|
||||
|
||||
if (isPresent(hoverDebounce)) {
|
||||
run.cancel(hoverDebounce);
|
||||
}
|
||||
if (isPresent(hoverDebounce)) { run.cancel(hoverDebounce); }
|
||||
},
|
||||
|
||||
@computed("content.originalContent.icon", "content.originalContent.iconClass")
|
||||
|
@ -50,7 +51,14 @@ export default Ember.Component.extend(UtilsMixin, {
|
|||
},
|
||||
|
||||
click() {
|
||||
this.sendAction("onSelect", this.get("content.value"));
|
||||
this._sendOnSelectAction();
|
||||
},
|
||||
|
||||
_sendOnSelectAction() {
|
||||
if (this.get("clicked") === false) {
|
||||
this.set("clicked", true);
|
||||
this.sendAction("onSelect", this.get("content.value"));
|
||||
}
|
||||
},
|
||||
|
||||
_sendOnHighlightAction() {
|
||||
|
|
|
@ -6,11 +6,7 @@ export default NotificationOptionsComponent.extend({
|
|||
showFullTitle: false,
|
||||
headerComponent: "tag-notifications-button/tag-notifications-button-header",
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
this.sendAction("action", value);
|
||||
this.blur();
|
||||
}
|
||||
selectValueFunction(value) {
|
||||
this.sendAction("action", value);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -39,38 +39,34 @@ export default ComboBoxComponent.extend({
|
|||
return content;
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
value = this.defaultOnSelect(value);
|
||||
selectValueFunction(value) {
|
||||
const topic = this.get("topic");
|
||||
|
||||
const topic = this.get("topic");
|
||||
// In case it"s not a valid topic
|
||||
if (!topic.get("id")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// In case it"s not a valid topic
|
||||
if (!topic.get("id")) {
|
||||
return;
|
||||
}
|
||||
this.set("value", value);
|
||||
|
||||
this.set("value", value);
|
||||
const refresh = () => this.send("onDeselect", value);
|
||||
|
||||
const refresh = () => this.set("value", null);
|
||||
|
||||
switch(value) {
|
||||
case "invite":
|
||||
this.attrs.showInvite();
|
||||
refresh();
|
||||
break;
|
||||
case "bookmark":
|
||||
topic.toggleBookmark().then(() => refresh() );
|
||||
break;
|
||||
case "share":
|
||||
this.appEvents.trigger("share:url", topic.get("shareUrl"), $("#topic-footer-buttons"));
|
||||
refresh();
|
||||
break;
|
||||
case "flag":
|
||||
this.attrs.showFlagTopic();
|
||||
refresh();
|
||||
break;
|
||||
}
|
||||
switch(value) {
|
||||
case "invite":
|
||||
this.attrs.showInvite();
|
||||
refresh();
|
||||
break;
|
||||
case "bookmark":
|
||||
topic.toggleBookmark().then(() => refresh() );
|
||||
break;
|
||||
case "share":
|
||||
this.appEvents.trigger("share:url", topic.get("shareUrl"), $("#topic-footer-buttons"));
|
||||
refresh();
|
||||
break;
|
||||
case "flag":
|
||||
this.attrs.showFlagTopic();
|
||||
refresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,17 +24,11 @@ export default NotificationOptionsComponent.extend({
|
|||
this.appEvents.off("topic-notifications-button:changed");
|
||||
},
|
||||
|
||||
actions: {
|
||||
onSelect(value) {
|
||||
if (value !== this.get("computedValue")) {
|
||||
this.get("topic.details").updateNotifications(value);
|
||||
}
|
||||
|
||||
this.set("value", value);
|
||||
|
||||
this.defaultOnSelect(value);
|
||||
|
||||
this.blur();
|
||||
selectValueFunction(value) {
|
||||
if (value !== this.get("value")) {
|
||||
this.get("topic.details").updateNotifications(value);
|
||||
}
|
||||
|
||||
this.set("value", value);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { on } from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
init() {
|
||||
this._super();
|
||||
|
@ -8,46 +10,237 @@ export default Ember.Mixin.create({
|
|||
this.collectionSelector = ".select-box-kit-collection";
|
||||
this.headerSelector = ".select-box-kit-header";
|
||||
this.bodySelector = ".select-box-kit-body";
|
||||
this.wrapperSelector = ".select-box-kit-wrapper";
|
||||
},
|
||||
|
||||
$findRowByValue(value) {
|
||||
return this.$(`${this.rowSelector}[data-value='${value}']`);
|
||||
$findRowByValue(value) { return this.$(`${this.rowSelector}[data-value='${value}']`); },
|
||||
|
||||
$header() { return this.$(this.headerSelector); },
|
||||
|
||||
$body() { return this.$(this.bodySelector); },
|
||||
|
||||
$collection() { return this.$(this.collectionSelector); },
|
||||
|
||||
$rows(withHidden) {
|
||||
|
||||
if (withHidden === true) {
|
||||
return this.$(`${this.rowSelector}:not(.no-content)`);
|
||||
} else {
|
||||
return this.$(`${this.rowSelector}:not(.no-content):not(.is-hidden)`);
|
||||
}
|
||||
},
|
||||
|
||||
$header() {
|
||||
return this.$(this.headerSelector);
|
||||
$highlightedRow() { return this.$rows().filter(".is-highlighted"); },
|
||||
|
||||
$selectedRow() { return this.$rows().filter(".is-selected"); },
|
||||
|
||||
$offscreenInput() { return this.$(this.offscreenInputSelector); },
|
||||
|
||||
$filterInput() { return this.$(this.filterInputSelector); },
|
||||
|
||||
@on("didRender")
|
||||
_ajustPosition() {
|
||||
$(`.select-box-kit-fixed-placeholder-${this.elementId}`).remove();
|
||||
this.$collection().css("max-height", this.get("collectionHeight"));
|
||||
this._applyFixedPosition();
|
||||
this._applyDirection();
|
||||
this._positionWrapper();
|
||||
},
|
||||
|
||||
$body() {
|
||||
return this.$(this.bodySelector);
|
||||
@on("willDestroyElement")
|
||||
_clearState() {
|
||||
$(window).off("resize.select-box-kit");
|
||||
$(`.select-box-kit-fixed-placeholder-${this.elementId}`).remove();
|
||||
},
|
||||
|
||||
$collection() {
|
||||
return this.$(this.collectionSelector);
|
||||
// make sure we don’t propagate a click outside component
|
||||
// to avoid closing a modal containing the component for example
|
||||
click(event) { this._killEvent(event); },
|
||||
|
||||
// use to collapse and remove focus
|
||||
close() {
|
||||
this.collapse();
|
||||
this.setProperties({ isFocused: false });
|
||||
},
|
||||
|
||||
$rows() {
|
||||
return this.$(this.rowSelector);
|
||||
// force the component in a known default state
|
||||
focus() {
|
||||
Ember.run.schedule("afterRender", () => this.$offscreenInput().focus() );
|
||||
},
|
||||
|
||||
$highlightedRow() {
|
||||
return this.$rows().filter(".is-highlighted");
|
||||
expand() {
|
||||
if (this.get("isExpanded") === true) { return; }
|
||||
this.setProperties({ isExpanded: true, renderedBodyOnce: true, isFocused: true });
|
||||
this.focus();
|
||||
this.autoHighlightFunction();
|
||||
},
|
||||
|
||||
$selectedRow() {
|
||||
return this.$rows().filter(".is-selected");
|
||||
collapse() {
|
||||
this.set("isExpanded", false);
|
||||
Ember.run.schedule("afterRender", () => this._removeFixedPosition() );
|
||||
},
|
||||
|
||||
$offscreenInput() {
|
||||
return this.$(this.offscreenInputSelector);
|
||||
// make sure we close/unfocus the component when clicked outside
|
||||
clickOutside(event) {
|
||||
if ($(event.target).parents(".select-box-kit").length === 1) {
|
||||
this.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
this.unfocus();
|
||||
return;
|
||||
},
|
||||
|
||||
$filterInput() {
|
||||
return this.$(this.filterInputSelector);
|
||||
// lose focus of the component in two steps
|
||||
// first collapase and keep focus and then remove focus
|
||||
unfocus() {
|
||||
this.set("highlightedValue", null);
|
||||
|
||||
if (this.get("isExpanded") === true) {
|
||||
this.collapse();
|
||||
this.focus();
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
blur() {
|
||||
Ember.run.schedule("afterRender", () => this.$offscreenInput().blur() );
|
||||
},
|
||||
|
||||
_killEvent(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
_applyDirection() {
|
||||
let options = { left: "auto", bottom: "auto", top: "auto" };
|
||||
|
||||
const dHeader = $(".d-header")[0];
|
||||
const dHeaderBounds = dHeader ? dHeader.getBoundingClientRect() : {top: 0, height: 0};
|
||||
const dHeaderHeight = dHeaderBounds.top + dHeaderBounds.height;
|
||||
const headerHeight = this.$header().outerHeight(false);
|
||||
const headerWidth = this.$header().outerWidth(false);
|
||||
const bodyHeight = this.$body().outerHeight(false);
|
||||
const windowWidth = $(window).width();
|
||||
const windowHeight = $(window).height();
|
||||
const boundingRect = this.get("element").getBoundingClientRect();
|
||||
const offsetTop = boundingRect.top;
|
||||
const offsetBottom = boundingRect.bottom;
|
||||
|
||||
if (this.get("fullWidthOnMobile") && windowWidth <= 420) {
|
||||
const margin = 10;
|
||||
const relativeLeft = this.$().offset().left - $(window).scrollLeft();
|
||||
options.left = margin - relativeLeft;
|
||||
options.width = windowWidth - margin * 2;
|
||||
options.maxWidth = options.minWidth = "unset";
|
||||
} else {
|
||||
const bodyWidth = this.$body().outerWidth(false);
|
||||
|
||||
if ($("html").css("direction") === "rtl") {
|
||||
const horizontalSpacing = boundingRect.right;
|
||||
const hasHorizontalSpace = horizontalSpacing - (this.get("horizontalOffset") + bodyWidth) > 0;
|
||||
if (hasHorizontalSpace) {
|
||||
this.setProperties({ isLeftAligned: true, isRightAligned: false });
|
||||
options.left = bodyWidth + this.get("horizontalOffset");
|
||||
} else {
|
||||
this.setProperties({ isLeftAligned: false, isRightAligned: true });
|
||||
options.right = - (bodyWidth - headerWidth + this.get("horizontalOffset"));
|
||||
}
|
||||
} else {
|
||||
const horizontalSpacing = boundingRect.left;
|
||||
const hasHorizontalSpace = (windowWidth - (this.get("horizontalOffset") + horizontalSpacing + bodyWidth) > 0);
|
||||
if (hasHorizontalSpace) {
|
||||
this.setProperties({ isLeftAligned: true, isRightAligned: false });
|
||||
options.left = this.get("horizontalOffset");
|
||||
} else {
|
||||
this.setProperties({ isLeftAligned: false, isRightAligned: true });
|
||||
options.right = this.get("horizontalOffset");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const componentHeight = this.get("verticalOffset") + bodyHeight + headerHeight;
|
||||
const hasBelowSpace = windowHeight - offsetBottom - componentHeight > 0;
|
||||
const hasAboveSpace = offsetTop - componentHeight - dHeaderHeight > 0;
|
||||
if (hasBelowSpace || (!hasBelowSpace && !hasAboveSpace)) {
|
||||
this.setProperties({ isBelow: true, isAbove: false });
|
||||
options.top = headerHeight + this.get("verticalOffset");
|
||||
} else {
|
||||
this.setProperties({ isBelow: false, isAbove: true });
|
||||
options.bottom = headerHeight + this.get("verticalOffset");
|
||||
}
|
||||
|
||||
this.$body().css(options);
|
||||
},
|
||||
|
||||
_applyFixedPosition() {
|
||||
if (this.get("scrollableParent").length === 0) { return; }
|
||||
|
||||
const width = this.$().outerWidth(false);
|
||||
const height = this.$().outerHeight(false);
|
||||
const $placeholder = $(`<div class='select-box-kit-fixed-placeholder-${this.elementId}'></div>`);
|
||||
|
||||
this._previousScrollParentOverflow = this.get("scrollableParent").css("overflow");
|
||||
this.get("scrollableParent").css({ overflow: "hidden" });
|
||||
|
||||
this._previousCSSContext = {
|
||||
minWidth: this.$().css("min-width"),
|
||||
maxWidth: this.$().css("max-width")
|
||||
};
|
||||
|
||||
const componentStyles = {
|
||||
position: "fixed",
|
||||
"margin-top": -this.get("scrollableParent").scrollTop(),
|
||||
width,
|
||||
minWidth: "unset",
|
||||
maxWidth: "unset"
|
||||
};
|
||||
|
||||
if ($("html").css("direction") === "rtl") {
|
||||
componentStyles.marginRight = -width;
|
||||
} else {
|
||||
componentStyles.marginLeft = -width;
|
||||
}
|
||||
|
||||
$placeholder.css({ display: "inline-block", width, height, "vertical-align": "middle" });
|
||||
|
||||
this.$().before($placeholder).css(componentStyles);
|
||||
},
|
||||
|
||||
_removeFixedPosition() {
|
||||
$(`.select-box-kit-fixed-placeholder-${this.elementId}`).remove();
|
||||
|
||||
if (this.get("scrollableParent").length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.element || this.isDestroying || this.isDestroyed) { return; }
|
||||
|
||||
const css = jQuery.extend(
|
||||
this._previousCSSContext,
|
||||
{
|
||||
top: "auto",
|
||||
left: "auto",
|
||||
"margin-left": "auto",
|
||||
"margin-right": "auto",
|
||||
"margin-top": "auto",
|
||||
position: "relative"
|
||||
}
|
||||
);
|
||||
this.$().css(css);
|
||||
|
||||
this.get("scrollableParent").css({
|
||||
overflow: this._previousScrollParentOverflow
|
||||
});
|
||||
},
|
||||
|
||||
_positionWrapper() {
|
||||
const headerHeight = this.$header().outerHeight(false);
|
||||
|
||||
this.$(this.wrapperSelector).css({
|
||||
width: this.$().outerWidth(false),
|
||||
height: headerHeight + this.$body().outerHeight(false)
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
const { isEmpty } = Ember;
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
init() {
|
||||
this._super();
|
||||
|
@ -35,9 +33,13 @@ export default Ember.Mixin.create({
|
|||
.off("focus.select-box-kit")
|
||||
.off("focusin.select-box-kit")
|
||||
.off("blur.select-box-kit")
|
||||
.off("keypress.select-box-kit")
|
||||
.off("keydown.select-box-kit");
|
||||
|
||||
this.$filterInput().off("keydown.select-box-kit");
|
||||
this.$filterInput()
|
||||
.off("change.select-box-kit")
|
||||
.off("keypress.select-box-kit")
|
||||
.off("keydown.select-box-kit");
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
|
@ -70,58 +72,67 @@ export default Ember.Mixin.create({
|
|||
.on("keydown.select-box-kit", (event) => {
|
||||
const keyCode = event.keyCode || event.which;
|
||||
|
||||
if (keyCode === this.keys.TAB) { this._handleTabOnKeyDown(event); }
|
||||
if (keyCode === this.keys.ESC) { this._handleEscOnKeyDown(event); }
|
||||
if (keyCode === this.keys.UP || keyCode === this.keys.DOWN) {
|
||||
this._handleArrowKey(keyCode, event);
|
||||
}
|
||||
if (keyCode === this.keys.BACKSPACE) {
|
||||
this.expand();
|
||||
|
||||
if (this.$filterInput().is(":visible")) {
|
||||
this.$filterInput().focus().trigger(event).trigger("change");
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.on("keypress.select-box-kit", (event) => {
|
||||
const keyCode = event.keyCode || event.which;
|
||||
|
||||
switch (keyCode) {
|
||||
case this.keys.UP:
|
||||
case this.keys.DOWN:
|
||||
if (this.get("isExpanded") === false) {
|
||||
this.set("isExpanded", true);
|
||||
}
|
||||
|
||||
Ember.run.schedule("actions", () => {
|
||||
this._handleArrowKey(keyCode);
|
||||
});
|
||||
|
||||
this._killEvent(event);
|
||||
|
||||
return;
|
||||
case this.keys.ENTER:
|
||||
if (this.get("isExpanded") === false) {
|
||||
this.set("isExpanded", true);
|
||||
} else {
|
||||
this.send("onSelect", this.$highlightedRow().data("value"));
|
||||
this.expand();
|
||||
} else if (this.$highlightedRow().length === 1) {
|
||||
this.$highlightedRow().click();
|
||||
}
|
||||
|
||||
this._killEvent(event);
|
||||
|
||||
return;
|
||||
case this.keys.TAB:
|
||||
if (this.get("isExpanded") === false) {
|
||||
return true;
|
||||
} else {
|
||||
this.send("onSelect", this.$highlightedRow().data("value"));
|
||||
return;
|
||||
}
|
||||
case this.keys.ESC:
|
||||
this.close();
|
||||
this._killEvent(event);
|
||||
return;
|
||||
return false;
|
||||
case this.keys.BACKSPACE:
|
||||
this._killEvent(event);
|
||||
return;
|
||||
return event;
|
||||
}
|
||||
|
||||
if (this._isSpecialKey(keyCode) === false && event.metaKey === false) {
|
||||
this.setProperties({
|
||||
isExpanded: true,
|
||||
filter: String.fromCharCode(keyCode)
|
||||
});
|
||||
this.expand();
|
||||
|
||||
Ember.run.schedule("afterRender", () => this.$filterInput().focus() );
|
||||
if (this.get("filterable") === true || this.get("autoFilterable")) {
|
||||
this.set("renderedFilterOnce", true);
|
||||
}
|
||||
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
this.$filterInput()
|
||||
.focus()
|
||||
.val(this.$filterInput().val() + String.fromCharCode(keyCode));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.$filterInput()
|
||||
.on(`keydown.select-box-kit`, (event) => {
|
||||
.on("change.select-box-kit", (event) => {
|
||||
this.send("onFilterChange", $(event.target).val());
|
||||
})
|
||||
.on("keydown.select-box-kit", (event) => {
|
||||
const keyCode = event.keyCode || event.which;
|
||||
|
||||
if (keyCode === this.keys.TAB) { this._handleTabOnKeyDown(event); }
|
||||
if (keyCode === this.keys.ESC) { this._handleEscOnKeyDown(event); }
|
||||
if (keyCode === this.keys.UP || keyCode === this.keys.DOWN) {
|
||||
this._handleArrowKey(keyCode, event);
|
||||
}
|
||||
})
|
||||
.on("keypress.select-box-kit", (event) => {
|
||||
const keyCode = event.keyCode || event.which;
|
||||
|
||||
if ([
|
||||
|
@ -133,67 +144,75 @@ export default Ember.Mixin.create({
|
|||
return true;
|
||||
}
|
||||
|
||||
if (keyCode === this.keys.TAB && this.get("isExpanded") === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._isSpecialKey(keyCode) === true) {
|
||||
this.$offscreenInput().focus().trigger(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
},
|
||||
|
||||
_handleArrowKey(keyCode) {
|
||||
if (isEmpty(this.get("filteredContent"))) {
|
||||
_handleEscOnKeyDown(event) {
|
||||
this.unfocus();
|
||||
this._killEvent(event);
|
||||
},
|
||||
|
||||
_handleTabOnKeyDown(event) {
|
||||
if (this.get("isExpanded") === false) {
|
||||
this.unfocus();
|
||||
return true;
|
||||
} else if (this.$highlightedRow().length === 1) {
|
||||
this._killEvent(event);
|
||||
this.$highlightedRow().click();
|
||||
this.focus();
|
||||
} else {
|
||||
this.unfocus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_handleArrowKey(keyCode, event) {
|
||||
if (this.get("isExpanded") === false) { this.expand(); }
|
||||
this._killEvent(event);
|
||||
const $rows = this.$rows();
|
||||
|
||||
if ($rows.length <= 0) { return; }
|
||||
if ($rows.length === 1) {
|
||||
this._rowSelection($rows, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
switch (keyCode) {
|
||||
case 38:
|
||||
Ember.run.throttle(this, this._handleUpArrow, 32);
|
||||
break;
|
||||
default:
|
||||
Ember.run.throttle(this, this._handleDownArrow, 32);
|
||||
}
|
||||
});
|
||||
const direction = keyCode === 38 ? -1 : 1;
|
||||
|
||||
Ember.run.throttle(this, this._moveHighlight, direction, $rows, 32);
|
||||
},
|
||||
|
||||
_moveHighlight(direction) {
|
||||
const $rows = this.$rows();
|
||||
_moveHighlight(direction, $rows) {
|
||||
const currentIndex = $rows.index(this.$highlightedRow());
|
||||
let nextIndex = currentIndex + direction;
|
||||
|
||||
let nextIndex = 0;
|
||||
|
||||
if (currentIndex < 0) {
|
||||
if (nextIndex < 0) {
|
||||
nextIndex = $rows.length - 1;
|
||||
} else if (nextIndex >= $rows.length) {
|
||||
nextIndex = 0;
|
||||
} else if (currentIndex + direction < $rows.length) {
|
||||
nextIndex = currentIndex + direction;
|
||||
}
|
||||
|
||||
this._rowSelection($rows, nextIndex);
|
||||
},
|
||||
|
||||
_handleDownArrow() { this._moveHighlight(1); },
|
||||
|
||||
_handleUpArrow() { this._moveHighlight(-1); },
|
||||
|
||||
_rowSelection($rows, nextIndex) {
|
||||
const highlightableValue = $rows.eq(nextIndex).data("value");
|
||||
const highlightableValue = $rows.eq(nextIndex).attr("data-value");
|
||||
const $highlightableRow = this.$findRowByValue(highlightableValue);
|
||||
this.send("onHighlight", highlightableValue);
|
||||
|
||||
Ember.run.schedule("afterRender", () => {
|
||||
const $collection = this.$collection();
|
||||
const currentOffset = $collection.offset().top +
|
||||
$collection.outerHeight(false);
|
||||
const nextBottom = $highlightableRow.offset().top +
|
||||
$highlightableRow.outerHeight(false);
|
||||
const nextOffset = $collection.scrollTop() + nextBottom - currentOffset;
|
||||
|
||||
if (nextIndex === 0) {
|
||||
$collection.scrollTop(0);
|
||||
} else if (nextBottom > currentOffset) {
|
||||
$collection.scrollTop(nextOffset);
|
||||
}
|
||||
$highlightableRow.trigger("mouseover").focus();
|
||||
this.focus();
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -1,9 +1,57 @@
|
|||
const { get, isNone } = Ember;
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
_nameForContent(content) {
|
||||
if (isNone(content)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof content === "object") {
|
||||
return get(content, this.get("nameProperty"));
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
_castInteger(value) {
|
||||
if (this.get("castInteger") === true && Ember.isPresent(value)) {
|
||||
return parseInt(value, 10);
|
||||
}
|
||||
|
||||
return Ember.isNone(value) ? value : value.toString();
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
_valueForContent(content) {
|
||||
switch (typeof content) {
|
||||
case "string":
|
||||
case "number":
|
||||
return content;
|
||||
default:
|
||||
return get(content, this.get("valueAttribute"));
|
||||
}
|
||||
},
|
||||
|
||||
_contentForValue(value) {
|
||||
return this.get("content").find(c => {
|
||||
if (this._valueForContent(c) === value) { return true; }
|
||||
});
|
||||
},
|
||||
|
||||
_computedContentForValue(value) {
|
||||
const searchedValue = value.toString();
|
||||
return this.get("computedContent").find(c => {
|
||||
if (c.value.toString() === searchedValue) { return true; }
|
||||
});
|
||||
},
|
||||
|
||||
_originalValueForValue(value) {
|
||||
if (isNone(value)) { return null; }
|
||||
if (value === this.noneValue) { return this.noneValue; }
|
||||
|
||||
const computedContent = this._computedContentForValue(value);
|
||||
|
||||
if (isNone(computedContent)) { return value; }
|
||||
|
||||
return get(computedContent.originalContent, this.get("valueAttribute"));
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,30 +1,13 @@
|
|||
<ul class="choices">
|
||||
{{#each selectedContent as |selectedContent|}}
|
||||
<li tabindex="-1" data-value={{selectedContent.value}} data-name={{selectedContent.name}} class="selected-name">
|
||||
<span class="delete-icon" {{action onDeselect selectedContent.value bubbles=false}}>
|
||||
{{d-icon "times"}}
|
||||
</span>
|
||||
<span class="name">
|
||||
{{selectedContent.name}}
|
||||
</span>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if shouldDisplayFilterPlaceholder}}
|
||||
<li class="choice-placeholder">
|
||||
{{text}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{component selectedNameComponent onDeselect=onDeselect content=selectedContent}}
|
||||
{{/each}}
|
||||
|
||||
<li class="filter">
|
||||
{{input
|
||||
class="select-box-kit-filter-input"
|
||||
key-up=onFilterChange
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
spellcheck=false
|
||||
value=filter
|
||||
{{component "select-box-kit/select-box-kit-filter"
|
||||
onFilterChange=onFilterChange
|
||||
shouldDisplayFilter=shouldDisplayFilter
|
||||
isFocused=isFocused
|
||||
filter=filter
|
||||
}}
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<span class="name">
|
||||
{{#unless isLocked}}
|
||||
<span class="delete-icon" {{action onDeselect content.value bubbles=false}}>
|
||||
{{d-icon "times"}}
|
||||
</span>
|
||||
{{/unless}}
|
||||
|
||||
{{content.name}}
|
||||
</span>
|
|
@ -19,6 +19,7 @@
|
|||
onToggle=(action "onToggle")
|
||||
onFilterChange=(action "onFilterChange")
|
||||
onClearSelection=(action "onClearSelection")
|
||||
shouldDisplayFilter=shouldDisplayFilter
|
||||
options=headerComponentOptions
|
||||
}}
|
||||
|
||||
|
@ -26,16 +27,14 @@
|
|||
{{component filterComponent
|
||||
onFilterChange=(action "onFilterChange")
|
||||
icon=filterIcon
|
||||
filter=filter
|
||||
filterable=computedFilterable
|
||||
shouldDisplayFilter=shouldDisplayFilter
|
||||
isFocused=isFocused
|
||||
placeholder=(i18n filterPlaceholder)
|
||||
tabindex=tabindex
|
||||
filter=filter
|
||||
}}
|
||||
|
||||
{{#if renderBody}}
|
||||
{{#if renderedBodyOnce}}
|
||||
{{component collectionComponent
|
||||
shouldDisplayCreateRow=shouldDisplayCreateRow
|
||||
none=computedNone
|
||||
createRowContent=createRowContent
|
||||
selectedContent=selectedContent
|
||||
|
@ -43,13 +42,9 @@
|
|||
rowComponent=rowComponent
|
||||
noneRowComponent=noneRowComponent
|
||||
createRowComponent=createRowComponent
|
||||
iconForRow=iconForRow
|
||||
templateForRow=templateForRow
|
||||
templateForNoneRow=templateForNoneRow
|
||||
templateForCreateRow=templateForCreateRow
|
||||
shouldHighlightRow=shouldHighlightRow
|
||||
shouldSelectRow=shouldSelectRow
|
||||
titleForRow=titleForRow
|
||||
onClearSelection=(action "onClearSelection")
|
||||
onSelect=(action "onSelect")
|
||||
onHighlight=(action "onHighlight")
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
{{component noneRowComponent
|
||||
content=none
|
||||
templateForRow=templateForNoneRow
|
||||
titleForRow=titleForRow
|
||||
iconForRow=iconForRow
|
||||
highlightedValue=highlightedValue
|
||||
onClearSelection=onClearSelection
|
||||
onHighlight=onHighlight
|
||||
|
@ -14,12 +12,11 @@
|
|||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if shouldDisplayCreateRow}}
|
||||
{{#if createRowContent}}
|
||||
{{component createRowComponent
|
||||
content=createRowContent
|
||||
templateForRow=templateForCreateRow
|
||||
titleForRow=titleForRow
|
||||
iconForRow=iconForRow
|
||||
highlightedValue=highlightedValue
|
||||
onHighlight=onHighlight
|
||||
onCreateContent=onCreateContent
|
||||
|
@ -33,7 +30,6 @@
|
|||
content=content
|
||||
templateForRow=templateForRow
|
||||
titleForRow=titleForRow
|
||||
iconForRow=iconForRow
|
||||
highlightedValue=highlightedValue
|
||||
onSelect=onSelect
|
||||
onHighlight=onHighlight
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{{input
|
||||
tabindex=tabindex
|
||||
tabindex=-1
|
||||
class="select-box-kit-filter-input"
|
||||
placeholder=placeholder
|
||||
key-down=onFilterChange
|
||||
key-up=onFilterChange
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
|
|
|
@ -215,9 +215,8 @@ $mobile-breakpoint: 700px;
|
|||
.select-box-kit {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.select-box-kit-header {
|
||||
height: 28px;
|
||||
.select-box-kit.multi-combo-box {
|
||||
width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,6 +619,10 @@ section.details {
|
|||
text-align: left;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.select-box-kit {
|
||||
width: inherit;
|
||||
}
|
||||
}
|
||||
.long-value {
|
||||
width: 800px;
|
||||
|
@ -701,7 +704,7 @@ section.details {
|
|||
|
||||
.ace_editor {
|
||||
pointer-events:none;
|
||||
|
||||
|
||||
.ace_cursor {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
|
|
@ -89,14 +89,6 @@
|
|||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-highlighted {
|
||||
background: $tertiary-low;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $highlight-medium;
|
||||
}
|
||||
}
|
||||
|
||||
.select-box-kit-collection {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
.select-box-kit {
|
||||
&.multi-combo-box {
|
||||
&.list-setting {
|
||||
.select-box-kit-row.create {
|
||||
.square {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
.select-box-kit {
|
||||
&.multi-combo-box {
|
||||
width: 300px;
|
||||
background: $secondary;
|
||||
border: 1px solid dark-light-diff($primary, $secondary, 90%, -60%);
|
||||
border-radius: 0;
|
||||
|
||||
.select-box-kit-body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select-box-kit-row {
|
||||
margin: 5px;
|
||||
min-height: 1px;
|
||||
padding: 5px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.select-box-kit-filter {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.multi-combo-box-header {
|
||||
background: $secondary;
|
||||
border: 0;
|
||||
border-bottom: 1px solid transparent;
|
||||
|
||||
&.is-focused {
|
||||
box-shadow: $tertiary 0px 0px 6px 0px;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
.multi-combo-box-header {
|
||||
background: #e9e9e9;
|
||||
border-color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-highlighted {
|
||||
.multi-combo-box-header {
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid transparent;
|
||||
box-shadow: $tertiary 0px 0px 6px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-expanded {
|
||||
.select-box-kit-wrapper {
|
||||
display: block;
|
||||
border: 1px solid $tertiary;
|
||||
box-shadow: $tertiary 0px 0px 6px 0px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.multi-combo-box-header {
|
||||
border-bottom: 1px solid $primary-low;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.select-box-kit-body {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.choices {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
flex: 1;
|
||||
min-height: 36px;
|
||||
box-sizing: border-box;
|
||||
|
||||
li {
|
||||
display: inline-flex;
|
||||
box-sizing: border-box;
|
||||
padding: 0 5px;
|
||||
margin-bottom: 4px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.filter {
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
white-space: nowrap;
|
||||
min-width: 50px;
|
||||
padding: 0;
|
||||
|
||||
.select-box-kit-filter-input, .select-box-kit-filter-input:focus {
|
||||
border: none;
|
||||
background: none;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
min-width: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.selected-name {
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
color: $primary;
|
||||
cursor: default;
|
||||
border: 1px solid $primary-medium;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 2px $secondary inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||
background-clip: padding-box;
|
||||
-webkit-touch-callout: none;
|
||||
user-select: none;
|
||||
background-color: $primary-low;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
line-height: normal;
|
||||
|
||||
.name {
|
||||
padding: 0 5px;
|
||||
line-height: 22px
|
||||
}
|
||||
|
||||
&.is-highlighted {
|
||||
border-color: $danger;
|
||||
}
|
||||
|
||||
.d-icon {
|
||||
margin-right: 5px;
|
||||
color: $primary-medium;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
|
||||
&:hover {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
.multi-combobox {
|
||||
width: 300px;
|
||||
background: $secondary;
|
||||
border: 1px solid dark-light-diff($primary, $secondary, 90%, -60%);
|
||||
|
||||
.select-box-kit-body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select-box-kit-row {
|
||||
margin: 5px;
|
||||
min-height: 1px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.select-box-kit-filter {
|
||||
border-top: 1px solid $primary-low;
|
||||
}
|
||||
|
||||
.select-box-kit-header {
|
||||
background: $secondary;
|
||||
border-bottom: 1px solid transparent;
|
||||
|
||||
&.is-focused {
|
||||
border-bottom: 1px solid $primary-low;
|
||||
box-shadow: $tertiary 0px 0px 6px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
.select-box-kit-header {
|
||||
background: #e9e9e9;
|
||||
border-color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-highlighted {
|
||||
.select-box-kit-header {
|
||||
border: 1px solid $tertiary;
|
||||
box-shadow: $tertiary 0px 0px 6px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-expanded {
|
||||
.select-box-kit-wrapper {
|
||||
display: block;
|
||||
border: 1px solid $tertiary;
|
||||
box-shadow: $tertiary 0px 0px 6px 0px;
|
||||
}
|
||||
|
||||
.select-box-kit-header {
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.select-box-kit-body {
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.choices {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.choice-placeholder {
|
||||
padding: 0 5px;
|
||||
margin: 2px 0;
|
||||
border: 1px solid transparent;
|
||||
display: inline-flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.filter {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.select-box-kit-filter-input, .select-box-kit-filter-input:focus {
|
||||
border: none;
|
||||
background: none;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
min-width: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.selected-name {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 0 5px;
|
||||
margin: 2px 0;
|
||||
color: $primary;
|
||||
cursor: default;
|
||||
border: 1px solid $primary-medium;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 2px $secondary inset, 0 1px 0 rgba(0,0,0,0.05);
|
||||
background-clip: padding-box;
|
||||
-webkit-touch-callout: none;
|
||||
user-select: none;
|
||||
background-color: $primary-low;
|
||||
|
||||
&:focus {
|
||||
border-color: $primary;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.d-icon {
|
||||
margin-right: 5px;
|
||||
color: $primary-medium;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
|
||||
&:hover {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
}
|
||||
|
||||
.select-box-kit {
|
||||
border: 1px solid transparent;
|
||||
min-width: 220px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
@ -65,6 +66,9 @@
|
|||
}
|
||||
|
||||
.select-box-kit-header {
|
||||
border: 1px solid transparent;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
-webkit-transition: all .25s;
|
||||
-o-transition: all .25s;
|
||||
transition: all .25s;
|
||||
|
@ -138,10 +142,13 @@
|
|||
|
||||
.select-box-kit-row {
|
||||
cursor: pointer;
|
||||
line-height: normal;
|
||||
outline: none;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
|
@ -172,10 +179,6 @@
|
|||
&.is-selected.is-highlighted {
|
||||
background: $tertiary-low;
|
||||
}
|
||||
|
||||
&.none:not(.is-highlighted) {
|
||||
background: $primary-low;
|
||||
}
|
||||
}
|
||||
|
||||
.select-box-kit-collection {
|
||||
|
@ -255,8 +258,8 @@
|
|||
|
||||
.select-box-kit-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
background: none;
|
||||
display: none;
|
||||
-webkit-box-sizing: border-box;
|
||||
|
|
|
@ -1155,6 +1155,7 @@ en:
|
|||
default_header_text: Select...
|
||||
no_content: No matches found
|
||||
filter_placeholder: Search...
|
||||
create: "Create {{content}}"
|
||||
|
||||
emoji_picker:
|
||||
filter_placeholder: Search for emoji
|
||||
|
|
|
@ -44,8 +44,8 @@ QUnit.test("suspend, then unsuspend a user", assert => {
|
|||
andThen(() => {
|
||||
assert.equal(find('.perform-suspend[disabled]').length, 1, 'disabled by default');
|
||||
|
||||
expandSelectBox('.suspend-until .combobox');
|
||||
selectBoxSelectRow('tomorrow', { selector: '.suspend-until .combobox'});
|
||||
expandSelectBoxKit('.suspend-until .combobox');
|
||||
selectBoxKitSelectRow('tomorrow', { selector: '.suspend-until .combobox'});
|
||||
});
|
||||
|
||||
fillIn('.suspend-reason', "for breaking the rules");
|
||||
|
|
|
@ -11,7 +11,7 @@ QUnit.test("does not display uncategorized if not allowed", assert => {
|
|||
visit("/");
|
||||
click('#create-topic');
|
||||
|
||||
expandSelectBox('.category-chooser');
|
||||
('.category-chooser');
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(selectBox('.category-chooser').rowByIndex(0).name() !== 'uncategorized');
|
||||
|
|
|
@ -75,9 +75,9 @@ QUnit.test("Subcategory list settings", assert => {
|
|||
|
||||
click('.edit-category-general');
|
||||
|
||||
expandSelectBox('.edit-category-tab-general .category-chooser');
|
||||
expandSelectBoxKit('.edit-category-tab-general .category-chooser');
|
||||
|
||||
selectBoxSelectRow(3, {selector: '.edit-category-tab-general .category-chooser'});
|
||||
selectBoxKitSelectRow(3, {selector: '.edit-category-tab-general .category-chooser'});
|
||||
|
||||
click('.edit-category-settings');
|
||||
andThen(() => {
|
||||
|
|
|
@ -257,8 +257,8 @@ QUnit.test("update in filter through advanced search ui", assert => {
|
|||
fillIn('.search input.full-page-search', 'none');
|
||||
click('.search-advanced-btn');
|
||||
|
||||
expandSelectBox('.search-advanced-options .select-box-kit#in');
|
||||
selectBoxSelectRow('bookmarks', { selector: '.search-advanced-options .select-box-kit#in' });
|
||||
expandSelectBoxKit('.search-advanced-options .select-box-kit#in');
|
||||
selectBoxKitSelectRow('bookmarks', { selector: '.search-advanced-options .select-box-kit#in' });
|
||||
fillIn('.search-advanced-options .select-box-kit#in', 'bookmarks');
|
||||
|
||||
andThen(() => {
|
||||
|
@ -271,8 +271,8 @@ QUnit.test("update status through advanced search ui", assert => {
|
|||
visit("/search");
|
||||
fillIn('.search input.full-page-search', 'none');
|
||||
click('.search-advanced-btn');
|
||||
expandSelectBox('.search-advanced-options .select-box-kit#status');
|
||||
selectBoxSelectRow('closed', { selector: '.search-advanced-options .select-box-kit#status' });
|
||||
expandSelectBoxKit('.search-advanced-options .select-box-kit#status');
|
||||
selectBoxKitSelectRow('closed', { selector: '.search-advanced-options .select-box-kit#status' });
|
||||
fillIn('.search-advanced-options .select-box-kit#status', 'closed');
|
||||
|
||||
andThen(() => {
|
||||
|
@ -286,8 +286,8 @@ QUnit.test("update post time through advanced search ui", assert => {
|
|||
fillIn('.search input.full-page-search', 'none');
|
||||
click('.search-advanced-btn');
|
||||
fillIn('#search-post-date', '2016-10-05');
|
||||
expandSelectBox('.search-advanced-options .select-box-kit#postTime');
|
||||
selectBoxSelectRow('after', { selector: '.search-advanced-options .select-box-kit#postTime' });
|
||||
expandSelectBoxKit('.search-advanced-options .select-box-kit#postTime');
|
||||
selectBoxKitSelectRow('after', { selector: '.search-advanced-options .select-box-kit#postTime' });
|
||||
fillIn('.search-advanced-options .select-box-kit#postTime', 'after');
|
||||
|
||||
andThen(() => {
|
||||
|
|
|
@ -89,7 +89,7 @@ QUnit.test("Search with context", assert => {
|
|||
QUnit.test("Right filters are shown to anonymous users", assert => {
|
||||
visit("/search?expanded=true");
|
||||
|
||||
expandSelectBox(".select-box-kit#in");
|
||||
expandSelectBoxKit(".select-box-kit#in");
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(exists('.select-box-kit#in .select-box-kit-row[data-value=first]'));
|
||||
|
@ -115,7 +115,7 @@ QUnit.test("Right filters are shown to logged-in users", assert => {
|
|||
Discourse.reset();
|
||||
visit("/search?expanded=true");
|
||||
|
||||
expandSelectBox(".select-box-kit#in");
|
||||
expandSelectBoxKit(".select-box-kit#in");
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(exists('.select-box-kit#in .select-box-kit-row[data-value=first]'));
|
||||
|
|
|
@ -28,8 +28,8 @@ QUnit.test("Updating topic notification level", assert => {
|
|||
);
|
||||
});
|
||||
|
||||
expandSelectBox(notificationOptions);
|
||||
selectBoxSelectRow("3", { selector: notificationOptions});
|
||||
expandSelectBoxKit(notificationOptions);
|
||||
selectBoxKitSelectRow("3", { selector: notificationOptions});
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(
|
||||
|
|
|
@ -53,9 +53,9 @@ QUnit.test("Updating the topic title and category", assert => {
|
|||
|
||||
fillIn('#edit-title', 'this is the new title');
|
||||
|
||||
expandSelectBox('.title-wrapper .category-chooser');
|
||||
expandSelectBoxKit('.title-wrapper .category-chooser');
|
||||
|
||||
selectBoxSelectRow(4, {selector: '.title-wrapper .category-chooser'});
|
||||
selectBoxKitSelectRow(4, {selector: '.title-wrapper .category-chooser'});
|
||||
|
||||
click('#topic-title .submit-edit');
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ componentTest('default', {
|
|||
assert.equal($selectBox.el.find(".d-icon-bars").length, 1);
|
||||
assert.equal($selectBox.el.find(".d-icon-caret-down").length, 1);
|
||||
|
||||
expandSelectBox('.categories-admin-dropdown');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal($selectBox.rowByValue("create").name(), "New Category");
|
||||
|
|
|
@ -6,7 +6,7 @@ componentTest('with value', {
|
|||
template: '{{category-chooser value=2}}',
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').header.name(), "feature");
|
||||
|
@ -18,7 +18,7 @@ componentTest('with excludeCategoryId', {
|
|||
template: '{{category-chooser excludeCategoryId=2}}',
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').rowByValue(2).el.length, 0);
|
||||
|
@ -30,7 +30,7 @@ componentTest('with scopedCategoryId', {
|
|||
template: '{{category-chooser scopedCategoryId=2}}',
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').rowByIndex(0).name(), "feature");
|
||||
|
@ -48,7 +48,7 @@ componentTest('with allowUncategorized=null', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').header.name(), "Select a category…");
|
||||
|
@ -64,7 +64,7 @@ componentTest('with allowUncategorized=null rootNone=true', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').header.name(), "Select a category…");
|
||||
|
@ -81,7 +81,7 @@ componentTest('with disallowed uncategorized, rootNone and rootNoneLabel', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').header.name(), "Select a category…");
|
||||
|
@ -97,7 +97,7 @@ componentTest('with allowed uncategorized', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').header.name(), "uncategorized");
|
||||
|
@ -113,7 +113,7 @@ componentTest('with allowed uncategorized and rootNone', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').header.name(), "(no category)");
|
||||
|
@ -130,7 +130,7 @@ componentTest('with allowed uncategorized rootNone and rootNoneLabel', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.category-chooser');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.category-chooser').header.name(), "root none label");
|
||||
|
|
|
@ -8,7 +8,7 @@ componentTest('default', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').header.name(), "hello");
|
||||
|
@ -25,7 +25,7 @@ componentTest('with valueAttribute', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').rowByValue(0).name(), "hello");
|
||||
|
@ -41,7 +41,7 @@ componentTest('with nameProperty', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').rowByValue(0).name(), "hello");
|
||||
|
@ -57,7 +57,7 @@ componentTest('with an array as content', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').rowByValue('evil').name(), "evil");
|
||||
|
@ -75,7 +75,7 @@ componentTest('with value and none as a string', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').noneRow.name(), 'none');
|
||||
|
@ -85,7 +85,7 @@ componentTest('with value and none as a string', {
|
|||
assert.equal(this.get('value'), 'trout');
|
||||
});
|
||||
|
||||
selectBoxSelectRow('', {selector: '.combobox' });
|
||||
selectBoxKitSelectRow('__none__', {selector: '.combobox' });
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(this.get('value'), null);
|
||||
|
@ -102,7 +102,7 @@ componentTest('with value and none as an object', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').noneRow.name(), 'none');
|
||||
|
@ -112,7 +112,7 @@ componentTest('with value and none as an object', {
|
|||
assert.equal(this.get('value'), 'evil');
|
||||
});
|
||||
|
||||
selectBoxSelectNoneRow({ selector: '.combobox' });
|
||||
selectBoxKitSelectNoneRow({ selector: '.combobox' });
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(this.get('value'), null);
|
||||
|
@ -130,7 +130,7 @@ componentTest('with no value and none as an object', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').header.name(), 'none');
|
||||
|
@ -148,7 +148,7 @@ componentTest('with no value and none string', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').header.name(), 'none');
|
||||
|
@ -164,7 +164,7 @@ componentTest('with no value and no none', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').header.name(), 'evil', 'it sets the first row as value');
|
||||
|
@ -180,15 +180,15 @@ componentTest('with no value and no none', {
|
|||
// },
|
||||
//
|
||||
// test(assert) {
|
||||
// expandSelectBox();
|
||||
// ();
|
||||
//
|
||||
// andThen(() => assert.equal(find(".select-box-kit-filter-input").length, 1, "it has a search input"));
|
||||
//
|
||||
// selectBoxFillInFilter("regis");
|
||||
// selectBoxKitFillInFilter("regis");
|
||||
//
|
||||
// andThen(() => assert.equal(selectBox().rows.length, 1, "it filters results"));
|
||||
//
|
||||
// selectBoxFillInFilter("");
|
||||
// selectBoxKitFillInFilter("");
|
||||
//
|
||||
// andThen(() => {
|
||||
// assert.equal(
|
||||
|
@ -207,17 +207,17 @@ componentTest('with no value and no none', {
|
|||
// },
|
||||
//
|
||||
// test(assert) {
|
||||
// expandSelectBox();
|
||||
// ();
|
||||
//
|
||||
// selectBoxFillInFilter("rob");
|
||||
// selectBoxKitFillInFilter("rob");
|
||||
//
|
||||
// andThen(() => assert.equal(selectBox().rows.length, 1) );
|
||||
//
|
||||
// collapseSelectBox();
|
||||
// collapseSelectBoxKit();
|
||||
//
|
||||
// andThen(() => assert.notOk(selectBox().isExpanded) );
|
||||
//
|
||||
// expandSelectBox();
|
||||
// ();
|
||||
//
|
||||
// andThen(() => assert.equal(selectBox().rows.length, 1) );
|
||||
// }
|
||||
|
@ -232,7 +232,7 @@ componentTest('with empty string as value', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox('.combobox');
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox('.combobox').header.name(), 'evil', 'it sets the first row as value');
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import componentTest from 'helpers/component-test';
|
||||
|
||||
moduleForComponent('list-setting', {integration: true});
|
||||
|
||||
componentTest('default', {
|
||||
template: '{{list-setting settingValue=settingValue choices=choices}}',
|
||||
|
||||
beforeEach() {
|
||||
this.set('settingValue', 'bold|italic');
|
||||
this.set('choices', ['bold', 'italic', 'underline']);
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.propEqual(selectBox().header.name(), 'bold,italic');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
componentTest('with only setting value', {
|
||||
template: '{{list-setting settingValue=settingValue}}',
|
||||
|
||||
beforeEach() {
|
||||
this.set('settingValue', 'bold|italic');
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.propEqual(selectBox().header.name(), 'bold,italic');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
componentTest('interactions', {
|
||||
template: '{{list-setting settingValue=settingValue choices=choices}}',
|
||||
|
||||
beforeEach() {
|
||||
this.set('settingValue', 'bold|italic');
|
||||
this.set('choices', ['bold', 'italic', 'underline']);
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBoxKit();
|
||||
|
||||
selectBoxKitSelectRow('underline');
|
||||
|
||||
andThen(() => {
|
||||
assert.propEqual(selectBox().header.name(), 'bold,italic,underline');
|
||||
});
|
||||
|
||||
selectBoxKitFillInFilter('strike');
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().highlightedRow.name(), 'strike');
|
||||
});
|
||||
|
||||
selectBox().keyboard.enter();
|
||||
|
||||
andThen(() => {
|
||||
assert.propEqual(selectBox().header.name(), 'bold,italic,underline,strike');
|
||||
});
|
||||
|
||||
selectBox().keyboard.backspace();
|
||||
selectBox().keyboard.backspace();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(this.get('choices').length, 3, 'it removes the created content from original list');
|
||||
});
|
||||
}
|
||||
});
|
|
@ -11,7 +11,99 @@ componentTest('with objects and values', {
|
|||
|
||||
test(assert) {
|
||||
andThen(() => {
|
||||
assert.propEqual(selectBox(".multi-combobox").header.name(), 'hello,world');
|
||||
assert.propEqual(selectBox().header.name(), 'hello,world');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
componentTest('interactions', {
|
||||
template: '{{multi-combo-box none=none content=items value=value}}',
|
||||
|
||||
beforeEach() {
|
||||
I18n.translations[I18n.locale].js.test = {none: 'none'};
|
||||
this.set('items', [{id: 1, name: 'regis'}, {id: 2, name: 'sam'}, {id: 3, name: 'robin'}]);
|
||||
this.set('value', [1, 2]);
|
||||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().highlightedRow.name(), 'robin', 'it highlights the first content row');
|
||||
});
|
||||
|
||||
this.set('none', 'test.none');
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().noneRow.el.length, 1);
|
||||
assert.equal(selectBox().highlightedRow.name(), 'robin', 'it highlights the first content row');
|
||||
});
|
||||
|
||||
selectBoxKitSelectRow(3);
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().highlightedRow.name(), 'none', 'it highlights none row if no content');
|
||||
});
|
||||
|
||||
selectBoxKitFillInFilter('joffrey');
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().highlightedRow.name(), 'joffrey', 'it highlights create row when filling filter');
|
||||
});
|
||||
|
||||
selectBox().keyboard.enter();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().highlightedRow.name(), 'none', 'it highlights none row after creating content and no content left');
|
||||
});
|
||||
|
||||
selectBox().keyboard.backspace();
|
||||
|
||||
andThen(() => {
|
||||
const $lastSelectedName = selectBox().header.el.find('.selected-name').last();
|
||||
assert.equal($lastSelectedName.attr('data-name'), 'joffrey');
|
||||
assert.ok($lastSelectedName.hasClass('is-highlighted'), 'it highlights the last selected name when using backspace');
|
||||
});
|
||||
|
||||
selectBox().keyboard.backspace();
|
||||
|
||||
andThen(() => {
|
||||
const $lastSelectedName = selectBox().header.el.find('.selected-name').last();
|
||||
assert.equal($lastSelectedName.attr('data-name'), 'robin', 'it removes the previous highlighted selected content');
|
||||
assert.notOk(exists(selectBox().rowByValue('joffrey').el), 'generated content shouldn’t appear in content when removed');
|
||||
});
|
||||
|
||||
selectBox().keyboard.selectAll();
|
||||
|
||||
andThen(() => {
|
||||
const $highlightedSelectedNames = selectBox().header.el.find('.selected-name.is-highlighted');
|
||||
assert.equal($highlightedSelectedNames.length, 3, 'it highlights each selected name');
|
||||
});
|
||||
|
||||
selectBox().keyboard.backspace();
|
||||
|
||||
andThen(() => {
|
||||
const $selectedNames = selectBox().header.el.find('.selected-name');
|
||||
assert.equal($selectedNames.length, 0, 'it removed all selected content');
|
||||
});
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(this.$(".select-box-kit").hasClass("is-focused"));
|
||||
assert.ok(this.$(".select-box-kit").hasClass("is-expanded"));
|
||||
});
|
||||
|
||||
selectBox().keyboard.escape();
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(this.$(".select-box-kit").hasClass("is-focused"));
|
||||
assert.notOk(this.$(".select-box-kit").hasClass("is-expanded"));
|
||||
});
|
||||
|
||||
selectBox().keyboard.escape();
|
||||
|
||||
andThen(() => {
|
||||
assert.notOk(this.$(".select-box-kit").hasClass("is-focused"));
|
||||
assert.notOk(this.$(".select-box-kit").hasClass("is-expanded"));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -23,7 +23,7 @@ componentTest('updating the content refreshes the list', {
|
|||
test(assert) {
|
||||
andThen(() => assert.notOk(selectBox().isHidden) );
|
||||
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => assert.equal(selectBox().selectedRow.name(), "Pinned") );
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ componentTest('updating the content refreshes the list', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().rowByValue(1).name(), "robin");
|
||||
|
@ -29,7 +29,7 @@ componentTest('accepts a value by reference', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(
|
||||
|
@ -38,7 +38,7 @@ componentTest('accepts a value by reference', {
|
|||
);
|
||||
});
|
||||
|
||||
selectBoxSelectRow(1);
|
||||
selectBoxKitSelectRow(1);
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(this.get("value"), 1, "it mutates the value");
|
||||
|
@ -58,7 +58,7 @@ componentTest('default search icon', {
|
|||
template: '{{select-box-kit filterable=true}}',
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(exists(selectBox().filter.icon), "it has a the correct icon");
|
||||
|
@ -70,7 +70,7 @@ componentTest('with no search icon', {
|
|||
template: '{{select-box-kit filterable=true filterIcon=null}}',
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().filter.icon().length, 0, "it has no icon");
|
||||
|
@ -82,7 +82,7 @@ componentTest('custom search icon', {
|
|||
template: '{{select-box-kit filterable=true filterIcon="shower"}}',
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(selectBox().filter.icon().hasClass("d-icon-shower"), "it has a the correct icon");
|
||||
|
@ -93,11 +93,11 @@ componentTest('custom search icon', {
|
|||
componentTest('select-box is expandable', {
|
||||
template: '{{select-box-kit}}',
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => assert.ok(selectBox().isExpanded) );
|
||||
|
||||
collapseSelectBox();
|
||||
collapseSelectBoxKit();
|
||||
|
||||
andThen(() => assert.notOk(selectBox().isExpanded) );
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ componentTest('accepts custom value/name keys', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().selectedRow.name(), "robin");
|
||||
|
@ -130,7 +130,7 @@ componentTest('doesn’t render collection content before first expand', {
|
|||
test(assert) {
|
||||
assert.notOk(exists(find(".select-box-kit-collection")));
|
||||
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(exists(find(".select-box-kit-collection")));
|
||||
|
@ -146,7 +146,7 @@ componentTest('supports options to limit size', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
const height = find(".select-box-kit-collection").height();
|
||||
|
@ -163,11 +163,11 @@ componentTest('dynamic headerText', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => assert.equal(selectBox().header.name(), "robin") );
|
||||
|
||||
selectBoxSelectRow(2);
|
||||
selectBoxKitSelectRow(2);
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().header.name(), "regis", "it changes header text");
|
||||
|
@ -186,7 +186,7 @@ componentTest('supports custom row template', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => assert.equal(selectBox().rowByValue(1).el.html().trim(), "<b>robin</b>") );
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ componentTest('supports converting select value to integer', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => assert.equal(selectBox().selectedRow.name(), "régis") );
|
||||
|
||||
|
@ -224,7 +224,7 @@ componentTest('supports keyboard events', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
selectBox().keyboard.down();
|
||||
|
||||
|
@ -251,7 +251,7 @@ componentTest('supports keyboard events', {
|
|||
assert.notOk(selectBox().isExpanded, "it collapses the select box when selecting a row");
|
||||
});
|
||||
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
selectBox().keyboard.escape();
|
||||
|
||||
|
@ -259,18 +259,13 @@ componentTest('supports keyboard events', {
|
|||
assert.notOk(selectBox().isExpanded, "it collapses the select box");
|
||||
});
|
||||
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
selectBoxFillInFilter("regis");
|
||||
|
||||
// andThen(() => {
|
||||
// assert.equal(selectBox().highlightedRow.title(), "regis", "it highlights the first result");
|
||||
// });
|
||||
selectBoxKitFillInFilter("regis");
|
||||
|
||||
selectBox().keyboard.tab();
|
||||
|
||||
andThen(() => {
|
||||
// assert.equal(selectBox().selectedRow.title(), "regis", "it selects the row when pressing tab");
|
||||
assert.notOk(selectBox().isExpanded, "it collapses the select box when selecting a row");
|
||||
});
|
||||
}
|
|
@ -17,7 +17,7 @@ componentTest('default', {
|
|||
},
|
||||
|
||||
test(assert) {
|
||||
expandSelectBox();
|
||||
expandSelectBoxKit();
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(selectBox().header.name(), "Topic Controls");
|
||||
|
@ -26,7 +26,7 @@ componentTest('default', {
|
|||
assert.equal(selectBox().selectedRow.el.length, 0, "it doesn’t preselect first row");
|
||||
});
|
||||
|
||||
selectBoxSelectRow("share");
|
||||
selectBoxKitSelectRow("share");
|
||||
|
||||
andThen(() => {
|
||||
assert.equal(this.get("value"), null, "it resets the value");
|
||||
|
|
|
@ -10,7 +10,7 @@ function checkSelectBoxIsNotCollapsed(selectBoxSelector) {
|
|||
}
|
||||
}
|
||||
|
||||
Ember.Test.registerAsyncHelper('expandSelectBox', function(app, selectBoxSelector) {
|
||||
Ember.Test.registerAsyncHelper('expandSelectBoxKit', function(app, selectBoxSelector) {
|
||||
selectBoxSelector = selectBoxSelector || '.select-box-kit';
|
||||
|
||||
checkSelectBoxIsNotExpanded(selectBoxSelector);
|
||||
|
@ -18,7 +18,7 @@ Ember.Test.registerAsyncHelper('expandSelectBox', function(app, selectBoxSelecto
|
|||
click(selectBoxSelector + ' .select-box-kit-header');
|
||||
});
|
||||
|
||||
Ember.Test.registerAsyncHelper('collapseSelectBox', function(app, selectBoxSelector) {
|
||||
Ember.Test.registerAsyncHelper('collapseSelectBoxKit', function(app, selectBoxSelector) {
|
||||
selectBoxSelector = selectBoxSelector || '.select-box-kit';
|
||||
|
||||
checkSelectBoxIsNotCollapsed(selectBoxSelector);
|
||||
|
@ -26,7 +26,7 @@ Ember.Test.registerAsyncHelper('collapseSelectBox', function(app, selectBoxSelec
|
|||
click(selectBoxSelector + ' .select-box-kit-header');
|
||||
});
|
||||
|
||||
Ember.Test.registerAsyncHelper('selectBoxSelectRow', function(app, rowValue, options) {
|
||||
Ember.Test.registerAsyncHelper('selectBoxKitSelectRow', function(app, rowValue, options) {
|
||||
options = options || {};
|
||||
options.selector = options.selector || '.select-box-kit';
|
||||
|
||||
|
@ -35,7 +35,7 @@ Ember.Test.registerAsyncHelper('selectBoxSelectRow', function(app, rowValue, opt
|
|||
click(options.selector + " .select-box-kit-row[data-value='" + rowValue + "']");
|
||||
});
|
||||
|
||||
Ember.Test.registerAsyncHelper('selectBoxSelectNoneRow', function(app, options) {
|
||||
Ember.Test.registerAsyncHelper('selectBoxKitSelectNoneRow', function(app, options) {
|
||||
options = options || {};
|
||||
options.selector = options.selector || '.select-box-kit';
|
||||
|
||||
|
@ -44,7 +44,7 @@ Ember.Test.registerAsyncHelper('selectBoxSelectNoneRow', function(app, options)
|
|||
click(options.selector + " .select-box-kit-row.none");
|
||||
});
|
||||
|
||||
Ember.Test.registerAsyncHelper('selectBoxFillInFilter', function(app, filter, options) {
|
||||
Ember.Test.registerAsyncHelper('selectBoxKitFillInFilter', function(app, filter, options) {
|
||||
options = options || {};
|
||||
options.selector = options.selector || '.select-box-kit';
|
||||
|
||||
|
@ -52,7 +52,6 @@ Ember.Test.registerAsyncHelper('selectBoxFillInFilter', function(app, filter, op
|
|||
|
||||
var filterQuerySelector = options.selector + ' .select-box-kit-filter-input';
|
||||
fillIn(filterQuerySelector, filter);
|
||||
triggerEvent(filterQuerySelector, 'keyup');
|
||||
});
|
||||
|
||||
function selectBox(selector) { // eslint-disable-line no-unused-vars
|
||||
|
@ -88,23 +87,26 @@ function selectBox(selector) { // eslint-disable-line no-unused-vars
|
|||
}
|
||||
|
||||
function keyboardHelper() {
|
||||
function createEvent(target, keyCode) {
|
||||
function createEvent(target, keyCode, options) {
|
||||
target = target || ".select-box-kit-filter-input";
|
||||
selector = find(selector).find(target);
|
||||
|
||||
andThen(function() {
|
||||
var event = jQuery.Event('keydown');
|
||||
var event = jQuery.Event(options.type);
|
||||
event.keyCode = keyCode;
|
||||
if (options && options.metaKey === true) { event.metaKey = true; }
|
||||
find(selector).trigger(event);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
down: function(target) { createEvent(target, 40); },
|
||||
up: function(target) { createEvent(target, 38); },
|
||||
escape: function(target) { createEvent(target, 27); },
|
||||
enter: function(target) { createEvent(target, 13); },
|
||||
tab: function(target) { createEvent(target, 9); }
|
||||
down: function(target) { createEvent(target, 40, {type: 'keydown'}); },
|
||||
up: function(target) { createEvent(target, 38, {type: 'keydown'}); },
|
||||
escape: function(target) { createEvent(target, 27, {type: 'keydown'}); },
|
||||
enter: function(target) { createEvent(target, 13, {type: 'keypress'}); },
|
||||
tab: function(target) { createEvent(target, 9, {type: 'keydown'}); },
|
||||
backspace: function(target) { createEvent(target, 8, {type: 'keydown'}); },
|
||||
selectAll: function(target) { createEvent(target, 65, {metaKey: true, type: 'keydown'}); },
|
||||
};
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
//= require sinon-qunit-1.0.0
|
||||
|
||||
//= require helpers/assertions
|
||||
//= require helpers/select-box-helper
|
||||
//= require helpers/select-box-kit-helper
|
||||
|
||||
//= require helpers/qunit-helpers
|
||||
//= require_tree ./fixtures
|
||||
|
|
Loading…
Reference in New Issue