mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 07:31:02 +08:00
FIX: select-kit refactoring
- improve mini-tag-chooser keyboard behavior - all multil select now respond to select all and left/right arrows - improve events handling - many minor tweaks
This commit is contained in:
@ -10,7 +10,7 @@ export default DropdownSelectBox.extend({
|
|||||||
headerIcon: "thumbs-o-up",
|
headerIcon: "thumbs-o-up",
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
content.name = `${I18n.t("admin.flags.agree")}...`;
|
content.name = `${I18n.t("admin.flags.agree")}...`;
|
||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import DropdownSelectBox from "select-kit/components/dropdown-select-box";
|
import DropdownSelectBox from "select-kit/components/dropdown-select-box";
|
||||||
import computed from "ember-addons/ember-computed-decorators";
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
|
const { get } = Ember;
|
||||||
|
|
||||||
export default DropdownSelectBox.extend({
|
export default DropdownSelectBox.extend({
|
||||||
classNames: ["delete-flag", "admin-delete-flag-dropdown"],
|
classNames: ["delete-flag", "admin-delete-flag-dropdown"],
|
||||||
@ -8,7 +9,7 @@ export default DropdownSelectBox.extend({
|
|||||||
headerIcon: "trash-o",
|
headerIcon: "trash-o",
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
content.name = `${I18n.t("admin.flags.delete")}...`;
|
content.name = `${I18n.t("admin.flags.delete")}...`;
|
||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
@ -55,7 +56,7 @@ export default DropdownSelectBox.extend({
|
|||||||
|
|
||||||
mutateValue(value) {
|
mutateValue(value) {
|
||||||
const computedContentItem = this.get("computedContent").findBy("value", value);
|
const computedContentItem = this.get("computedContent").findBy("value", value);
|
||||||
Ember.get(computedContentItem, "originalContent.action")();
|
get(computedContentItem, "originalContent.action")();
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -18,9 +18,9 @@ export default MultiSelectComponent.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
computeContentItem(contentItem, name) {
|
computeContentItem(contentItem, name) {
|
||||||
let computedContent = this.baseComputedContentItem(contentItem, name);
|
let computedContentItem = this._super(contentItem, name);
|
||||||
computedContent.locked = contentItem.automatic;
|
computedContentItem.locked = contentItem.automatic;
|
||||||
return computedContent;
|
return computedContentItem;
|
||||||
},
|
},
|
||||||
|
|
||||||
mutateValues(values) {
|
mutateValues(values) {
|
||||||
|
@ -59,7 +59,7 @@ export default ComboBoxComponent.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
|
|
||||||
if (this.get("hasSelection")) {
|
if (this.get("hasSelection")) {
|
||||||
const category = Category.findById(content.value);
|
const category = Category.findById(content.value);
|
||||||
|
@ -68,7 +68,7 @@ export default ComboBoxComponent.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
|
|
||||||
if (this.get("hasSelection")) {
|
if (this.get("hasSelection")) {
|
||||||
const category = Category.findById(content.value);
|
const category = Category.findById(content.value);
|
||||||
|
@ -6,8 +6,8 @@ export default ComboBoxSelectBoxHeaderComponent.extend({
|
|||||||
layoutName: "select-kit/templates/components/category-drop/category-drop-header",
|
layoutName: "select-kit/templates/components/category-drop/category-drop-header",
|
||||||
classNames: "category-drop-header",
|
classNames: "category-drop-header",
|
||||||
|
|
||||||
classNameBindings: ['categoryStyleClass'],
|
classNameBindings: ["categoryStyleClass"],
|
||||||
categoryStyleClass: Ember.computed.alias('site.category_style'),
|
categoryStyleClass: Ember.computed.alias("site.category_style"),
|
||||||
|
|
||||||
@computed("computedContent.value", "computedContent.name")
|
@computed("computedContent.value", "computedContent.name")
|
||||||
category(value, name) {
|
category(value, name) {
|
||||||
|
@ -1,20 +1,15 @@
|
|||||||
import NotificationOptionsComponent from "select-kit/components/notifications-button";
|
import NotificationOptionsComponent from "select-kit/components/notifications-button";
|
||||||
import computed from "ember-addons/ember-computed-decorators";
|
|
||||||
|
|
||||||
export default NotificationOptionsComponent.extend({
|
export default NotificationOptionsComponent.extend({
|
||||||
pluginApiIdentifiers: ["category-notifications-button"],
|
pluginApiIdentifiers: ["category-notifications-button"],
|
||||||
classNames: "category-notifications-button",
|
classNames: "category-notifications-button",
|
||||||
isHidden: Ember.computed.or("category.deleted", "site.isMobileDevice"),
|
isHidden: Ember.computed.or("category.deleted", "site.isMobileDevice"),
|
||||||
|
headerIcon: Ember.computed.alias("iconForSelectedDetails"),
|
||||||
i18nPrefix: "category.notifications",
|
i18nPrefix: "category.notifications",
|
||||||
showFullTitle: false,
|
showFullTitle: false,
|
||||||
allowInitialValueMutation: false,
|
allowInitialValueMutation: false,
|
||||||
|
|
||||||
mutateValue(value) {
|
mutateValue(value) {
|
||||||
this.get("category").setNotification(value);
|
this.get("category").setNotification(value);
|
||||||
},
|
|
||||||
|
|
||||||
@computed("iconForSelectedDetails")
|
|
||||||
headerIcon(iconForSelectedDetails) {
|
|
||||||
return [iconForSelectedDetails];
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import SingleSelectComponent from "select-kit/components/single-select";
|
import SingleSelectComponent from "select-kit/components/single-select";
|
||||||
import { on } from "ember-addons/ember-computed-decorators";
|
import { on, default as computed } from "ember-addons/ember-computed-decorators";
|
||||||
|
|
||||||
export default SingleSelectComponent.extend({
|
export default SingleSelectComponent.extend({
|
||||||
pluginApiIdentifiers: ["combo-box"],
|
pluginApiIdentifiers: ["combo-box"],
|
||||||
@ -12,16 +12,19 @@ export default SingleSelectComponent.extend({
|
|||||||
clearable: false,
|
clearable: false,
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
content.hasSelection = this.get("hasSelection");
|
content.hasSelection = this.get("hasSelection");
|
||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@computed("isExpanded", "caretUpIcon", "caretDownIcon")
|
||||||
|
caretIcon(isExpanded, caretUpIcon, caretDownIcon) {
|
||||||
|
return isExpanded ? caretUpIcon : caretDownIcon;
|
||||||
|
},
|
||||||
|
|
||||||
@on("didReceiveAttrs")
|
@on("didReceiveAttrs")
|
||||||
_setComboBoxOptions() {
|
_setComboBoxOptions() {
|
||||||
this.get("headerComponentOptions").setProperties({
|
this.get("headerComponentOptions").setProperties({
|
||||||
caretUpIcon: this.get("caretUpIcon"),
|
|
||||||
caretDownIcon: this.get("caretDownIcon"),
|
|
||||||
clearable: this.get("clearable"),
|
clearable: this.get("clearable"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,5 @@ export default SelectKitHeaderComponent.extend({
|
|||||||
clearable: Ember.computed.alias("options.clearable"),
|
clearable: Ember.computed.alias("options.clearable"),
|
||||||
caretUpIcon: Ember.computed.alias("options.caretUpIcon"),
|
caretUpIcon: Ember.computed.alias("options.caretUpIcon"),
|
||||||
caretDownIcon: Ember.computed.alias("options.caretDownIcon"),
|
caretDownIcon: Ember.computed.alias("options.caretDownIcon"),
|
||||||
|
shouldDisplayClearableButton: Ember.computed.and("clearable", "computedContent.hasSelection")
|
||||||
@computed("isExpanded", "caretUpIcon", "caretDownIcon")
|
|
||||||
caretIcon(isExpanded, caretUpIcon, caretDownIcon) {
|
|
||||||
return isExpanded === true ? caretUpIcon : caretDownIcon;
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed("clearable", "computedContent.hasSelection")
|
|
||||||
shouldDisplayClearableButton(clearable, hasSelection) {
|
|
||||||
return clearable === true && hasSelection === true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
@ -45,7 +45,7 @@ export default DropdownSelectBoxComponent.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
|
|
||||||
switch (this.get("action")) {
|
switch (this.get("action")) {
|
||||||
case PRIVATE_MESSAGE:
|
case PRIVATE_MESSAGE:
|
||||||
|
@ -21,7 +21,7 @@ export default SingleSelectComponent.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
didClickOutside() {
|
didClickOutside() {
|
||||||
if (this.get("isExpanded") === false) return;
|
if (!this.get("isExpanded")) return;
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -10,6 +10,6 @@ export default SelectKitHeaderComponent.extend({
|
|||||||
|
|
||||||
@computed("options.showFullTitle")
|
@computed("options.showFullTitle")
|
||||||
btnClassName(showFullTitle) {
|
btnClassName(showFullTitle) {
|
||||||
return `btn ${showFullTitle ? 'btn-icon-text' : 'no-text btn-icon'}`;
|
return `btn ${showFullTitle ? "btn-icon-text" : "no-text btn-icon"}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -120,19 +120,19 @@ export default ComboBoxComponent.extend(DatetimeMixin, {
|
|||||||
headerComponent: "future-date-input-selector/future-date-input-selector-header",
|
headerComponent: "future-date-input-selector/future-date-input-selector-header",
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
content.datetime = this._computeDatetimeForValue(this.get("computedValue"));
|
content.datetime = this._computeDatetimeForValue(this.get("computedValue"));
|
||||||
content.name = this.get("selectedComputedContent.name") || content.name;
|
content.name = this.get("selection.name") || content.name;
|
||||||
content.hasSelection = this.get("hasSelection");
|
content.hasSelection = this.get("hasSelection");
|
||||||
content.icons = this._computeIconsForValue(this.get("computedValue"));
|
content.icons = this._computeIconsForValue(this.get("computedValue"));
|
||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
|
|
||||||
computeContentItem(contentItem, name) {
|
computeContentItem(contentItem, name) {
|
||||||
let item = this.baseComputedContentItem(contentItem, name);
|
let computedContentItem = this._super(contentItem, name);
|
||||||
item.datetime = this._computeDatetimeForValue(contentItem.id);
|
computedContentItem.datetime = this._computeDatetimeForValue(contentItem.id);
|
||||||
item.icons = this._computeIconsForValue(contentItem.id);
|
computedContentItem.icons = this._computeIconsForValue(contentItem.id);
|
||||||
return item;
|
return computedContentItem;
|
||||||
},
|
},
|
||||||
|
|
||||||
computeContent() {
|
computeContent() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import MultiSelectComponent from "select-kit/components/multi-select";
|
import MultiSelectComponent from "select-kit/components/multi-select";
|
||||||
|
const { isNone, makeArray } = Ember;
|
||||||
|
|
||||||
export default MultiSelectComponent.extend({
|
export default MultiSelectComponent.extend({
|
||||||
pluginApiIdentifiers: ["list-setting"],
|
pluginApiIdentifiers: ["list-setting"],
|
||||||
@ -11,7 +12,7 @@ export default MultiSelectComponent.extend({
|
|||||||
init() {
|
init() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
if (!Ember.isNone(this.get("settingName"))) {
|
if (!isNone(this.get("settingName"))) {
|
||||||
this.set("nameProperty", this.get("settingName"));
|
this.set("nameProperty", this.get("settingName"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,13 +25,13 @@ export default MultiSelectComponent.extend({
|
|||||||
|
|
||||||
computeContent() {
|
computeContent() {
|
||||||
let content;
|
let content;
|
||||||
if (Ember.isNone(this.get("choices"))) {
|
if (isNone(this.get("choices"))) {
|
||||||
content = this.get("settingValue").split(this.get("tokenSeparator"));;
|
content = this.get("settingValue").split(this.get("tokenSeparator"));;
|
||||||
} else {
|
} else {
|
||||||
content = this.get("choices");
|
content = this.get("choices");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ember.makeArray(content).filter(c => c);
|
return makeArray(content).filter(c => c);
|
||||||
},
|
},
|
||||||
|
|
||||||
mutateValues(values) {
|
mutateValues(values) {
|
||||||
|
@ -13,7 +13,7 @@ export default ComboBox.extend(Tags, {
|
|||||||
classNameBindings: ["noTags"],
|
classNameBindings: ["noTags"],
|
||||||
verticalOffset: 3,
|
verticalOffset: 3,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
noTags: Ember.computed.empty("selectedTags"),
|
noTags: Ember.computed.empty("selection"),
|
||||||
allowAny: true,
|
allowAny: true,
|
||||||
caretUpIcon: Ember.computed.alias("caretIcon"),
|
caretUpIcon: Ember.computed.alias("caretIcon"),
|
||||||
caretDownIcon: Ember.computed.alias("caretIcon"),
|
caretDownIcon: Ember.computed.alias("caretIcon"),
|
||||||
@ -24,6 +24,7 @@ export default ComboBox.extend(Tags, {
|
|||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
this.set("termMatchesForbidden", false);
|
this.set("termMatchesForbidden", false);
|
||||||
|
this.selectionSelector = ".selected-tag";
|
||||||
|
|
||||||
this.set("templateForRow", (rowComponent) => {
|
this.set("templateForRow", (rowComponent) => {
|
||||||
const tag = rowComponent.get("computedContent");
|
const tag = rowComponent.get("computedContent");
|
||||||
@ -36,22 +37,13 @@ export default ComboBox.extend(Tags, {
|
|||||||
this.set("limit", parseInt(this.get("limit") || this.get("siteSettings.max_tags_per_topic")));
|
this.set("limit", parseInt(this.get("limit") || this.get("siteSettings.max_tags_per_topic")));
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("limitReached")
|
@computed("hasReachedLimit")
|
||||||
caretIcon(limitReached) {
|
caretIcon(hasReachedLimit) {
|
||||||
return limitReached ? null : "plus";
|
return hasReachedLimit ? null : "plus";
|
||||||
},
|
|
||||||
|
|
||||||
@computed("selectedTags.[]", "limit")
|
|
||||||
limitReached(selectedTags, limit) {
|
|
||||||
if (selectedTags.length >= limit) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("tags")
|
@computed("tags")
|
||||||
selectedTags(tags) {
|
selection(tags) {
|
||||||
return makeArray(tags);
|
return makeArray(tags);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -62,12 +54,12 @@ export default ComboBox.extend(Tags, {
|
|||||||
didRender() {
|
didRender() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
$(".select-kit-body").on("click.mini-tag-chooser", ".selected-tag", (event) => {
|
this.$(".select-kit-body").on("click.mini-tag-chooser", ".selected-tag", (event) => {
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
this.send("removeTag", $(event.target).attr("data-value"));
|
this.destroyTags($(event.target).attr("data-value"));
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".select-kit-header").on("focus.mini-tag-chooser", ".selected-name", (event) => {
|
this.$(".select-kit-header").on("focus.mini-tag-chooser", ".selected-name", (event) => {
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
this.focus(event);
|
this.focus(event);
|
||||||
});
|
});
|
||||||
@ -76,63 +68,51 @@ export default ComboBox.extend(Tags, {
|
|||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
$(".select-kit-body").off("click.mini-tag-chooser");
|
this.$(".select-kit-body").off("click.mini-tag-chooser");
|
||||||
$(".select-kit-header").off("focus.mini-tag-chooser");
|
this.$(".select-kit-header").off("focus.mini-tag-chooser");
|
||||||
},
|
},
|
||||||
|
|
||||||
didPressEscape(event) {
|
// we are directly mutatings tags to define the current selection
|
||||||
const $lastSelectedTag = $(".selected-tag.selected:last");
|
|
||||||
|
|
||||||
if ($lastSelectedTag && this.get("isExpanded")) {
|
|
||||||
$lastSelectedTag.removeClass("selected");
|
|
||||||
this._destroyEvent(event);
|
|
||||||
} else {
|
|
||||||
this._super(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
backspaceFromFilter(event) {
|
|
||||||
this.didPressBackspace(event);
|
|
||||||
},
|
|
||||||
|
|
||||||
// we are relying on selectedTags and not on value
|
|
||||||
// to define the current selection
|
|
||||||
mutateValue() {},
|
mutateValue() {},
|
||||||
|
|
||||||
didPressBackspace() {
|
didPressTab(event) {
|
||||||
if (!this.get("isExpanded")) {
|
if (this.get("isLoading")) {
|
||||||
this.expand();
|
this._destroyEvent(event);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const $lastSelectedTag = $(".selected-tag:last");
|
if (isEmpty(this.get("filter")) && !this.get("highlighted")) {
|
||||||
|
this.$header().focus();
|
||||||
if (!isEmpty(this.get("filter"))) {
|
this.close(event);
|
||||||
$lastSelectedTag.removeClass("is-highlighted");
|
return true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$lastSelectedTag.length) return;
|
if (this.get("highlighted") && this.get("isExpanded")) {
|
||||||
|
this._destroyEvent(event);
|
||||||
if (!$lastSelectedTag.hasClass("is-highlighted")) {
|
this.focus();
|
||||||
$lastSelectedTag.addClass("is-highlighted");
|
this.select(this.get("highlighted"));
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.send("removeTag", $lastSelectedTag.attr("data-value"));
|
this.close(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("tags.[]", "filter")
|
@computed("tags.[]", "filter", "highlightedSelection.[]")
|
||||||
collectionHeader(tags, filter) {
|
collectionHeader(tags, filter, highlightedSelection) {
|
||||||
if (!isEmpty(tags)) {
|
if (!isEmpty(tags)) {
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
|
// if we have more than x tags we will also filter the selection
|
||||||
if (tags.length >= 20) {
|
if (tags.length >= 20) {
|
||||||
tags = tags.filter(t => t.indexOf(filter) >= 0);
|
tags = tags.filter(t => t.indexOf(filter) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tags.map((tag) => {
|
tags.map((tag) => {
|
||||||
|
const isHighlighted = highlightedSelection.includes(tag);
|
||||||
output += `
|
output += `
|
||||||
<button class="selected-tag" data-value="${tag}">
|
<button aria-label="${tag}" title="${tag}" class="selected-tag ${isHighlighted ? 'is-highlighted' : ''}" data-value="${tag}">
|
||||||
${tag}
|
${tag}
|
||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
@ -143,10 +123,11 @@ export default ComboBox.extend(Tags, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
const joinedTags = this.get("selectedTags").join(", ");
|
|
||||||
|
|
||||||
if (isEmpty(this.get("selectedTags"))) {
|
const joinedTags = this.get("selection").join(", ");
|
||||||
|
|
||||||
|
if (isEmpty(this.get("selection"))) {
|
||||||
content.label = I18n.t("tagging.choose_for_topic");
|
content.label = I18n.t("tagging.choose_for_topic");
|
||||||
} else {
|
} else {
|
||||||
content.label = joinedTags;
|
content.label = joinedTags;
|
||||||
@ -157,45 +138,13 @@ export default ComboBox.extend(Tags, {
|
|||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
_prepareSearch(query) {
|
||||||
removeTag(tag) {
|
|
||||||
let tags = this.get("selectedTags");
|
|
||||||
delete tags[tags.indexOf(tag)];
|
|
||||||
this.set("tags", tags.filter(t => t));
|
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 200));
|
|
||||||
},
|
|
||||||
|
|
||||||
onExpand() {
|
|
||||||
if (isEmpty(this.get("collectionComputedContent"))) {
|
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 200));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onFilter(filter) {
|
|
||||||
filter = isEmpty(filter) ? null : filter;
|
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, filter, 200));
|
|
||||||
},
|
|
||||||
|
|
||||||
onSelect(tag) {
|
|
||||||
if (isEmpty(this.get("selectedTags"))) {
|
|
||||||
this.set("tags", makeArray(tag));
|
|
||||||
} else {
|
|
||||||
this.set("tags", this.get("selectedTags").concat(tag));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 50));
|
|
||||||
|
|
||||||
this.autoHighlight();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
prepareSearch(query) {
|
|
||||||
const data = {
|
const data = {
|
||||||
q: query,
|
q: query,
|
||||||
limit: this.get("siteSettings.max_tag_search_results"),
|
limit: this.get("siteSettings.max_tag_search_results"),
|
||||||
categoryId: this.get("categoryId")
|
categoryId: this.get("categoryId")
|
||||||
};
|
};
|
||||||
if (this.get("selectedTags")) data.selected_tags = this.get("selectedTags").slice(0, 100);
|
if (this.get("selection")) data.selected_tags = this.get("selection").slice(0, 100);
|
||||||
if (!this.get("everyTag")) data.filterForInput = true;
|
if (!this.get("everyTag")) data.filterForInput = true;
|
||||||
|
|
||||||
this.searchTags("/tags/filter/search", data, this._transformJson);
|
this.searchTags("/tags/filter/search", data, this._transformJson);
|
||||||
@ -210,10 +159,42 @@ export default ComboBox.extend(Tags, {
|
|||||||
results = results.sort((a, b) => a.id > b.id);
|
results = results.sort((a, b) => a.id > b.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
results = results.filter(r => !context.get("selectedTags").includes(r.id));
|
results = results.filter(r => !context.get("selection").includes(r.id));
|
||||||
|
|
||||||
return results.map(result => {
|
return results.map(result => {
|
||||||
return { id: result.text, name: result.text, count: result.count };
|
return { id: result.text, name: result.text, count: result.count };
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyTags(tags) {
|
||||||
|
tags = Ember.makeArray(tags);
|
||||||
|
this.get("tags").removeObjects(tags);
|
||||||
|
this._prepareSearch(this.get("filter"));
|
||||||
|
},
|
||||||
|
|
||||||
|
didDeselect(tags) {
|
||||||
|
this.destroyTags(tags);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
onSelect(tag) {
|
||||||
|
this.set("tags", makeArray(this.get("tags")).concat(tag));
|
||||||
|
this._prepareSearch(this.get("filter"));
|
||||||
|
this.autoHighlight();
|
||||||
|
},
|
||||||
|
|
||||||
|
onExpand() {
|
||||||
|
if (isEmpty(this.get("collectionComputedContent"))) {
|
||||||
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, this.get("filter"), 350));
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onFilter(filter) {
|
||||||
|
// we start loading right away so we avoid updating createRow multiple times
|
||||||
|
this.startLoading();
|
||||||
|
|
||||||
|
filter = isEmpty(filter) ? null : filter;
|
||||||
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, filter, 350));
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -2,5 +2,5 @@ import SelectKitHeaderComponent from "select-kit/components/select-kit/select-ki
|
|||||||
|
|
||||||
export default SelectKitHeaderComponent.extend({
|
export default SelectKitHeaderComponent.extend({
|
||||||
layoutName: "select-kit/templates/components/mini-tag-chooser/mini-tag-chooser-header",
|
layoutName: "select-kit/templates/components/mini-tag-chooser/mini-tag-chooser-header",
|
||||||
classNames: "mini-tag-chooser-header",
|
classNames: "mini-tag-chooser-header"
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import SelectKitComponent from "select-kit/components/select-kit";
|
import SelectKitComponent from "select-kit/components/select-kit";
|
||||||
import computed from "ember-addons/ember-computed-decorators";
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
import { on } from "ember-addons/ember-computed-decorators";
|
import { on } from "ember-addons/ember-computed-decorators";
|
||||||
const { get, isNone, isEmpty, makeArray } = Ember;
|
const { get, isNone, isEmpty, makeArray, run } = Ember;
|
||||||
import {
|
import {
|
||||||
applyOnSelectPluginApiCallbacks
|
applyOnSelectPluginApiCallbacks
|
||||||
} from "select-kit/mixins/plugin-api";
|
} from "select-kit/mixins/plugin-api";
|
||||||
@ -17,11 +17,15 @@ export default SelectKitComponent.extend({
|
|||||||
autoFilterable: true,
|
autoFilterable: true,
|
||||||
selectedNameComponent: "multi-select/selected-name",
|
selectedNameComponent: "multi-select/selected-name",
|
||||||
filterIcon: null,
|
filterIcon: null,
|
||||||
|
filterComponent: "multi-select/multi-select-filter",
|
||||||
|
computedValues: null,
|
||||||
|
values: null,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
this.set("computedValues", []);
|
this.set("computedValues", []);
|
||||||
|
|
||||||
if (isNone(this.get("values"))) { this.set("values", []); }
|
if (isNone(this.get("values"))) { this.set("values", []); }
|
||||||
|
|
||||||
this.set("headerComponentOptions", Ember.Object.create({
|
this.set("headerComponentOptions", Ember.Object.create({
|
||||||
@ -37,7 +41,7 @@ export default SelectKitComponent.extend({
|
|||||||
|
|
||||||
@on("didReceiveAttrs")
|
@on("didReceiveAttrs")
|
||||||
_compute() {
|
_compute() {
|
||||||
Ember.run.scheduleOnce("afterRender", () => {
|
run.scheduleOnce("afterRender", () => {
|
||||||
this.willComputeAttributes();
|
this.willComputeAttributes();
|
||||||
let content = this.get("content") || [];
|
let content = this.get("content") || [];
|
||||||
let asyncContent = this.get("asyncContent") || [];
|
let asyncContent = this.get("asyncContent") || [];
|
||||||
@ -51,8 +55,6 @@ export default SelectKitComponent.extend({
|
|||||||
values = this.willComputeValues(values);
|
values = this.willComputeValues(values);
|
||||||
values = this.computeValues(values);
|
values = this.computeValues(values);
|
||||||
values = this._beforeDidComputeValues(values);
|
values = this._beforeDidComputeValues(values);
|
||||||
this._setHeaderComputedContent();
|
|
||||||
this._setCollectionHeaderComputedContent();
|
|
||||||
this.didComputeContent(content);
|
this.didComputeContent(content);
|
||||||
this.didComputeAsyncContent(asyncContent);
|
this.didComputeAsyncContent(asyncContent);
|
||||||
this.didComputeValues(values);
|
this.didComputeValues(values);
|
||||||
@ -62,7 +64,7 @@ export default SelectKitComponent.extend({
|
|||||||
|
|
||||||
@computed("filter", "shouldDisplayCreateRow")
|
@computed("filter", "shouldDisplayCreateRow")
|
||||||
createRowComputedContent(filter, shouldDisplayCreateRow) {
|
createRowComputedContent(filter, shouldDisplayCreateRow) {
|
||||||
if (shouldDisplayCreateRow === true) {
|
if (shouldDisplayCreateRow) {
|
||||||
let content = this.createContentFromInput(filter);
|
let content = this.createContentFromInput(filter);
|
||||||
return this.computeContentItem(content, { created: true });
|
return this.computeContentItem(content, { created: true });
|
||||||
}
|
}
|
||||||
@ -88,13 +90,11 @@ export default SelectKitComponent.extend({
|
|||||||
didComputeValues(values) { return values; },
|
didComputeValues(values) { return values; },
|
||||||
|
|
||||||
mutateAttributes() {
|
mutateAttributes() {
|
||||||
|
run.next(() => {
|
||||||
if (this.get("isDestroyed") || this.get("isDestroying")) return;
|
if (this.get("isDestroyed") || this.get("isDestroying")) return;
|
||||||
|
|
||||||
Ember.run.next(() => {
|
|
||||||
this.mutateContent(this.get("computedContent"));
|
this.mutateContent(this.get("computedContent"));
|
||||||
this.mutateValues(this.get("computedValues"));
|
this.mutateValues(this.get("computedValues"));
|
||||||
this._setCollectionHeaderComputedContent();
|
|
||||||
this._setHeaderComputedContent();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
mutateValues(computedValues) {
|
mutateValues(computedValues) {
|
||||||
@ -139,10 +139,10 @@ export default SelectKitComponent.extend({
|
|||||||
return computedContent;
|
return computedContent;
|
||||||
},
|
},
|
||||||
|
|
||||||
baseHeaderComputedContent() {
|
computeHeaderContent() {
|
||||||
return {
|
return {
|
||||||
title: this.get("title"),
|
title: this.get("title"),
|
||||||
selectedComputedContents: this.get("selectedComputedContents")
|
selection: this.get("selection")
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -153,81 +153,12 @@ export default SelectKitComponent.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("limit", "computedValues.[]")
|
|
||||||
limitReached(limit, computedValues) {
|
|
||||||
if (!limit) return false;
|
|
||||||
return computedValues.length >= limit;
|
|
||||||
},
|
|
||||||
|
|
||||||
validateSelect() {
|
validateSelect() {
|
||||||
return this._super() && !this.get("limitReached");
|
return this._super() && !this.get("hasReachedLimit");
|
||||||
},
|
|
||||||
|
|
||||||
didPressBackspace(event) {
|
|
||||||
this.expand(event);
|
|
||||||
this.keyDown(event);
|
|
||||||
this._destroyEvent(event);
|
|
||||||
},
|
|
||||||
|
|
||||||
didPressEscape(event) {
|
|
||||||
const $highlighted = this.$(".selected-name.is-highlighted");
|
|
||||||
if ($highlighted.length > 0) {
|
|
||||||
$highlighted.removeClass("is-highlighted");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._super(event);
|
|
||||||
},
|
|
||||||
|
|
||||||
keyDown(event) {
|
|
||||||
if (!isEmpty(this.get("filter"))) return;
|
|
||||||
|
|
||||||
const keyCode = event.keyCode || event.which;
|
|
||||||
const $filterInput = this.$filterInput();
|
|
||||||
|
|
||||||
// select all choices
|
|
||||||
if (this.get("hasSelection") && event.metaKey === true && keyCode === 65) {
|
|
||||||
this.$(".choices .selected-name:not(.is-locked)").addClass("is-highlighted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear selection when multiple
|
|
||||||
if (this.$(".selected-name.is-highlighted").length >= 1 && keyCode === this.keys.BACKSPACE) {
|
|
||||||
const highlightedComputedContents = [];
|
|
||||||
$.each(this.$(".selected-name.is-highlighted"), (i, el) => {
|
|
||||||
const computedContent = this._findComputedContentItemByGuid($(el).attr("data-guid"));
|
|
||||||
if (!Ember.isNone(computedContent)) { highlightedComputedContents.push(computedContent); }
|
|
||||||
});
|
|
||||||
this.send("deselect", highlightedComputedContents);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to remove last item from the list
|
|
||||||
if (keyCode === this.keys.BACKSPACE) {
|
|
||||||
let $lastSelectedValue = $(this.$(".choices .selected-name:not(.is-locked)").last());
|
|
||||||
|
|
||||||
if ($lastSelectedValue.length === 0) { return; }
|
|
||||||
|
|
||||||
if ($filterInput.not(":visible") && $lastSelectedValue.length > 0) {
|
|
||||||
$lastSelectedValue.trigger("backspace");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($filterInput.val() === "") {
|
|
||||||
if ($filterInput.is(":focus")) {
|
|
||||||
if ($lastSelectedValue.length > 0) { $lastSelectedValue.trigger("backspace"); }
|
|
||||||
} else {
|
|
||||||
if ($lastSelectedValue.length > 0) {
|
|
||||||
$lastSelectedValue.trigger("backspace");
|
|
||||||
} else {
|
|
||||||
$filterInput.focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("computedValues.[]", "computedContent.[]")
|
@computed("computedValues.[]", "computedContent.[]")
|
||||||
selectedComputedContents(computedValues, computedContent) {
|
selection(computedValues, computedContent) {
|
||||||
const selected = [];
|
const selected = [];
|
||||||
|
|
||||||
computedValues.forEach(v => {
|
computedValues.forEach(v => {
|
||||||
@ -238,88 +169,123 @@ export default SelectKitComponent.extend({
|
|||||||
return selected;
|
return selected;
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("selectedComputedContents.[]")
|
@computed("selection.[]")
|
||||||
hasSelection(selectedComputedContents) { return !Ember.isEmpty(selectedComputedContents); },
|
hasSelection(selection) { return !isEmpty(selection); },
|
||||||
|
|
||||||
|
didPressTab(event) {
|
||||||
|
if (isEmpty(this.get("filter")) && !this.get("highlighted")) {
|
||||||
|
this.$header().focus();
|
||||||
|
this.close(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.get("highlighted") && this.get("isExpanded")) {
|
||||||
|
this._destroyEvent(event);
|
||||||
|
this.focus();
|
||||||
|
this.select(this.get("highlighted"));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
this.close(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
autoHighlight() {
|
autoHighlight() {
|
||||||
Ember.run.schedule("afterRender", () => {
|
run.schedule("afterRender", () => {
|
||||||
if (!this.get("isExpanded")) return;
|
if (!this.get("isExpanded")) return;
|
||||||
if (!this.get("renderedBodyOnce")) return;
|
if (!this.get("renderedBodyOnce")) return;
|
||||||
if (!isNone(this.get("highlightedValue"))) return;
|
if (this.get("highlighted")) return;
|
||||||
|
|
||||||
if (isEmpty(this.get("collectionComputedContent"))) {
|
if (isEmpty(this.get("collectionComputedContent"))) {
|
||||||
if (this.get("createRowComputedContent")) {
|
if (this.get("createRowComputedContent")) {
|
||||||
this.send("highlight", this.get("createRowComputedContent"));
|
this.highlight(this.get("createRowComputedContent"));
|
||||||
} else if (this.get("noneRowComputedContent") && this.get("hasSelection")) {
|
} else if (this.get("noneRowComputedContent") && this.get("hasSelection")) {
|
||||||
this.send("highlight", this.get("noneRowComputedContent"));
|
this.highlight(this.get("noneRowComputedContent"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.send("highlight", this.get("collectionComputedContent.firstObject"));
|
this.highlight(this.get("collectionComputedContent.firstObject"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
didSelect() {
|
select(computedContentItem) {
|
||||||
this.focus();
|
if (!computedContentItem || computedContentItem.__sk_row_type === "noneRow") {
|
||||||
this.autoHighlight();
|
this.clearSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (computedContentItem.__sk_row_type === "createRow") {
|
||||||
|
if (!this.get("computedValues").includes(computedContentItem.value) &&
|
||||||
|
this.validateCreate(computedContentItem.value)) {
|
||||||
|
this.willCreate(computedContentItem);
|
||||||
|
|
||||||
|
computedContentItem.__sk_row_type = null;
|
||||||
|
this.get("computedContent").pushObject(computedContentItem);
|
||||||
|
|
||||||
|
run.schedule("afterRender", () => {
|
||||||
|
this.didCreate(computedContentItem);
|
||||||
|
this._boundaryActionHandler("onCreate");
|
||||||
|
});
|
||||||
|
|
||||||
|
this.select(computedContentItem);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this._boundaryActionHandler("onCreateFailure");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.validateSelect(computedContentItem)) {
|
||||||
|
this.willSelect(computedContentItem);
|
||||||
|
this.clearFilter();
|
||||||
|
this.setProperties({ highlighted: null });
|
||||||
|
this.get("computedValues").pushObject(computedContentItem.value);
|
||||||
|
|
||||||
|
run.next(() => this.mutateAttributes());
|
||||||
|
|
||||||
|
run.schedule("afterRender", () => {
|
||||||
|
this.didSelect(computedContentItem);
|
||||||
|
|
||||||
applyOnSelectPluginApiCallbacks(
|
applyOnSelectPluginApiCallbacks(
|
||||||
this.get("pluginApiIdentifiers"),
|
this.get("pluginApiIdentifiers"),
|
||||||
this.get("computedValue"),
|
computedContentItem.value,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
this._boundaryActionHandler("onSelect", this.get("computedValue"));
|
|
||||||
},
|
|
||||||
|
|
||||||
willDeselect() {
|
|
||||||
this.clearFilter();
|
|
||||||
this.set("highlightedValue", null);
|
|
||||||
},
|
|
||||||
|
|
||||||
didDeselect(rowComputedContentItems) {
|
|
||||||
this.focus();
|
|
||||||
this.autoHighlight();
|
this.autoHighlight();
|
||||||
this._boundaryActionHandler("onDeselect", rowComputedContentItems);
|
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
this._boundaryActionHandler("onSelect", computedContentItem.value);
|
||||||
clearSelection() {
|
});
|
||||||
this.send("deselect", this.get("selectedComputedContents"));
|
|
||||||
this._boundaryActionHandler("onClearSelection");
|
|
||||||
},
|
|
||||||
|
|
||||||
create(computedContentItem) {
|
|
||||||
if (!this.get("computedValues").includes(computedContentItem.value) &&
|
|
||||||
this.validateCreate(computedContentItem.value)) {
|
|
||||||
this.get("computedContent").pushObject(computedContentItem);
|
|
||||||
this._boundaryActionHandler("onCreate");
|
|
||||||
this.send("select", computedContentItem);
|
|
||||||
} else {
|
|
||||||
this._boundaryActionHandler("onCreateFailure");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
select(computedContentItem) {
|
|
||||||
this.willSelect(computedContentItem);
|
|
||||||
|
|
||||||
if (this.validateSelect(computedContentItem)) {
|
|
||||||
this.get("computedValues").pushObject(computedContentItem.value);
|
|
||||||
Ember.run.next(() => this.mutateAttributes());
|
|
||||||
Ember.run.schedule("afterRender", () => this.didSelect(computedContentItem));
|
|
||||||
} else {
|
} else {
|
||||||
this._boundaryActionHandler("onSelectFailure");
|
this._boundaryActionHandler("onSelectFailure");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
deselect(rowComputedContentItems) {
|
deselect(rowComputedContentItems) {
|
||||||
rowComputedContentItems = Ember.makeArray(rowComputedContentItems);
|
|
||||||
const generatedComputedContents = this._filterRemovableComputedContents(makeArray(rowComputedContentItems));
|
|
||||||
this.willDeselect(rowComputedContentItems);
|
this.willDeselect(rowComputedContentItems);
|
||||||
|
rowComputedContentItems = makeArray(rowComputedContentItems);
|
||||||
|
const generatedComputedContents = this._filterRemovableComputedContents(makeArray(rowComputedContentItems));
|
||||||
|
this.set("highlighted", null);
|
||||||
|
this.set("highlightedSelection", []);
|
||||||
this.get("computedValues").removeObjects(rowComputedContentItems.map(r => r.value));
|
this.get("computedValues").removeObjects(rowComputedContentItems.map(r => r.value));
|
||||||
this.get("computedContent").removeObjects(generatedComputedContents);
|
this.get("computedContent").removeObjects(generatedComputedContents);
|
||||||
Ember.run.next(() => this.mutateAttributes());
|
run.next(() => this.mutateAttributes());
|
||||||
Ember.run.schedule("afterRender", () => this.didDeselect(rowComputedContentItems));
|
run.schedule("afterRender", () => {
|
||||||
}
|
this.didDeselect(rowComputedContentItems);
|
||||||
|
this.autoHighlight();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
close(event) {
|
||||||
|
this.clearHighlightSelection();
|
||||||
|
|
||||||
|
this._super(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
unfocus(event) {
|
||||||
|
this.clearHighlightSelection();
|
||||||
|
|
||||||
|
this._super(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
|
const { isEmpty } = Ember;
|
||||||
|
import SelectKitFilterComponent from "select-kit/components/select-kit/select-kit-filter";
|
||||||
|
|
||||||
|
export default SelectKitFilterComponent.extend({
|
||||||
|
layoutName: "select-kit/templates/components/select-kit/select-kit-filter",
|
||||||
|
classNames: ["multi-select-filter"],
|
||||||
|
|
||||||
|
@computed("placeholder", "hasSelection")
|
||||||
|
computedPlaceholder(placeholder, hasSelection) {
|
||||||
|
if (hasSelection) return "";
|
||||||
|
return isEmpty(placeholder) ? "" : I18n.t(placeholder);
|
||||||
|
}
|
||||||
|
});
|
@ -34,12 +34,12 @@ export default SelectKitHeaderComponent.extend({
|
|||||||
$filter.width(availableSpace - parentRightPadding * 4);
|
$filter.width(availableSpace - parentRightPadding * 4);
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("computedContent.selectedComputedContents.[]")
|
@computed("computedContent.selection.[]")
|
||||||
names(selection) {
|
names(selection) {
|
||||||
return Ember.makeArray(selection).map(s => s.name).join(",");
|
return Ember.makeArray(selection).map(s => s.name).join(",");
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("computedContent.selectedComputedContents.[]")
|
@computed("computedContent.selection.[]")
|
||||||
values(selection) {
|
values(selection) {
|
||||||
return Ember.makeArray(selection).map(s => s.value).join(",");
|
return Ember.makeArray(selection).map(s => s.value).join(",");
|
||||||
}
|
}
|
||||||
|
@ -28,20 +28,6 @@ export default Ember.Component.extend({
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
didInsertElement() {
|
|
||||||
this._super();
|
|
||||||
|
|
||||||
$(this.element).on("backspace.selected-name", () => {
|
|
||||||
this._handleBackspace();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
willDestroyElement() {
|
|
||||||
this._super();
|
|
||||||
|
|
||||||
$(this.element).off("backspace.selected-name");
|
|
||||||
},
|
|
||||||
|
|
||||||
label: Ember.computed.or("computedContent.label", "title", "name"),
|
label: Ember.computed.or("computedContent.label", "title", "name"),
|
||||||
|
|
||||||
name: Ember.computed.alias("computedContent.name"),
|
name: Ember.computed.alias("computedContent.name"),
|
||||||
@ -52,19 +38,14 @@ export default Ember.Component.extend({
|
|||||||
return this.getWithDefault("computedContent.locked", false);
|
return this.getWithDefault("computedContent.locked", false);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
click() {
|
@computed("computedContent", "highlightedSelection.[]")
|
||||||
if (this.get("isLocked") === true) return false;
|
isHighlighted(computedContent, highlightedSelection) {
|
||||||
this.sendAction("deselect", [this.get("computedContent")]);
|
return highlightedSelection.includes(this.get("computedContent"));
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleBackspace() {
|
click() {
|
||||||
if (this.get("isLocked") === true) return false;
|
if (this.get("isLocked")) return false;
|
||||||
|
this.sendAction("onClickSelectionItem", [this.get("computedContent")]);
|
||||||
if (this.get("isHighlighted")) {
|
return false;
|
||||||
this.sendAction("deselect", [this.get("computedContent")]);
|
|
||||||
} else {
|
|
||||||
this.set("isHighlighted", true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -13,9 +13,5 @@ export default CategoryRowComponent.extend({
|
|||||||
allowUncategorized: true,
|
allowUncategorized: true,
|
||||||
hideParent: true
|
hideParent: true
|
||||||
}).htmlSafe();
|
}).htmlSafe();
|
||||||
},
|
|
||||||
|
|
||||||
click() {
|
|
||||||
this.sendAction("clearSelection");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -22,7 +22,7 @@ export default DropdownSelectBoxComponent.extend({
|
|||||||
iconForSelectedDetails: Ember.computed.alias("selectedDetails.icon"),
|
iconForSelectedDetails: Ember.computed.alias("selectedDetails.icon"),
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
content.name = I18n.t(`${this.get("i18nPrefix")}.${this.get("selectedDetails.key")}.title`);
|
content.name = I18n.t(`${this.get("i18nPrefix")}.${this.get("selectedDetails.key")}.title`);
|
||||||
content.hasSelection = this.get("hasSelection");
|
content.hasSelection = this.get("hasSelection");
|
||||||
return content;
|
return content;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
|
import DropdownSelectBoxComponent from "select-kit/components/dropdown-select-box";
|
||||||
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
|
|
||||||
export default DropdownSelectBoxComponent.extend({
|
export default DropdownSelectBoxComponent.extend({
|
||||||
classNames: ["period-chooser"],
|
classNames: ["period-chooser"],
|
||||||
@ -8,6 +9,11 @@ export default DropdownSelectBoxComponent.extend({
|
|||||||
value: Ember.computed.alias("period"),
|
value: Ember.computed.alias("period"),
|
||||||
isHidden: Ember.computed.alias("showPeriods"),
|
isHidden: Ember.computed.alias("showPeriods"),
|
||||||
|
|
||||||
|
@computed("isExpanded")
|
||||||
|
caretIcon(isExpanded) {
|
||||||
|
return isExpanded ? "caret-up" : "caret-down";
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
onSelect() {
|
onSelect() {
|
||||||
this.sendAction("action", this.get("computedValue"));
|
this.sendAction("action", this.get("computedValue"));
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
import DropdownSelectBoxHeaderomponent from "select-kit/components/dropdown-select-box/dropdown-select-box-header";
|
import DropdownSelectBoxHeaderomponent from "select-kit/components/dropdown-select-box/dropdown-select-box-header";
|
||||||
import computed from 'ember-addons/ember-computed-decorators';
|
|
||||||
|
|
||||||
export default DropdownSelectBoxHeaderomponent.extend({
|
export default DropdownSelectBoxHeaderomponent.extend({
|
||||||
layoutName: "select-kit/templates/components/period-chooser/period-chooser-header",
|
layoutName: "select-kit/templates/components/period-chooser/period-chooser-header",
|
||||||
classNames: "period-chooser-header",
|
classNames: "period-chooser-header"
|
||||||
|
|
||||||
@computed("isExpanded")
|
|
||||||
caretIcon(isExpanded) {
|
|
||||||
return isExpanded ? "caret-up" : "caret-down";
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ export default DropdownSelectBoxComponent.extend({
|
|||||||
autoHighlight() {},
|
autoHighlight() {},
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
const pinnedGlobally = this.get("topic.pinned_globally");
|
const pinnedGlobally = this.get("topic.pinned_globally");
|
||||||
const pinned = this.get("computedValue");
|
const pinned = this.get("computedValue");
|
||||||
const globally = pinnedGlobally ? "_globally" : "";
|
const globally = pinnedGlobally ? "_globally" : "";
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const { isNone, run } = Ember;
|
const { get, isNone, run, isEmpty, makeArray } = Ember;
|
||||||
import computed from "ember-addons/ember-computed-decorators";
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
import UtilsMixin from "select-kit/mixins/utils";
|
import UtilsMixin from "select-kit/mixins/utils";
|
||||||
import DomHelpersMixin from "select-kit/mixins/dom-helpers";
|
import DomHelpersMixin from "select-kit/mixins/dom-helpers";
|
||||||
@ -7,7 +7,6 @@ import PluginApiMixin from "select-kit/mixins/plugin-api";
|
|||||||
import {
|
import {
|
||||||
applyContentPluginApiCallbacks,
|
applyContentPluginApiCallbacks,
|
||||||
applyHeaderContentPluginApiCallbacks,
|
applyHeaderContentPluginApiCallbacks,
|
||||||
applyOnSelectPluginApiCallbacks,
|
|
||||||
applyCollectionHeaderCallbacks
|
applyCollectionHeaderCallbacks
|
||||||
} from "select-kit/mixins/plugin-api";
|
} from "select-kit/mixins/plugin-api";
|
||||||
|
|
||||||
@ -26,6 +25,7 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
"isLeftAligned",
|
"isLeftAligned",
|
||||||
"isRightAligned",
|
"isRightAligned",
|
||||||
"hasSelection",
|
"hasSelection",
|
||||||
|
"hasReachedLimit",
|
||||||
],
|
],
|
||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
@ -37,13 +37,13 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
renderedFilterOnce: false,
|
renderedFilterOnce: false,
|
||||||
tabindex: 0,
|
tabindex: 0,
|
||||||
none: null,
|
none: null,
|
||||||
highlightedValue: null,
|
highlighted: null,
|
||||||
valueAttribute: "id",
|
valueAttribute: "id",
|
||||||
nameProperty: "name",
|
nameProperty: "name",
|
||||||
autoFilterable: false,
|
autoFilterable: false,
|
||||||
filterable: false,
|
filterable: false,
|
||||||
filter: "",
|
filter: "",
|
||||||
previousFilter: null,
|
previousFilter: "",
|
||||||
filterPlaceholder: "select_kit.filter_placeholder",
|
filterPlaceholder: "select_kit.filter_placeholder",
|
||||||
filterIcon: "search",
|
filterIcon: "search",
|
||||||
headerIcon: null,
|
headerIcon: null,
|
||||||
@ -70,6 +70,7 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
allowContentReplacement: false,
|
allowContentReplacement: false,
|
||||||
collectionHeader: null,
|
collectionHeader: null,
|
||||||
allowAutoSelectFirst: true,
|
allowAutoSelectFirst: true,
|
||||||
|
highlightedSelection: null,
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super();
|
this._super();
|
||||||
@ -78,6 +79,7 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
this.set("headerComponentOptions", Ember.Object.create());
|
this.set("headerComponentOptions", Ember.Object.create());
|
||||||
this.set("rowComponentOptions", Ember.Object.create());
|
this.set("rowComponentOptions", Ember.Object.create());
|
||||||
this.set("computedContent", []);
|
this.set("computedContent", []);
|
||||||
|
this.set("highlightedSelection", []);
|
||||||
|
|
||||||
if (this.site && this.site.isMobileDevice) {
|
if (this.site && this.site.isMobileDevice) {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
@ -99,6 +101,22 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
keyDown(event) {
|
||||||
|
if (!isEmpty(this.get("filter"))) return true;
|
||||||
|
|
||||||
|
const keyCode = event.keyCode || event.which;
|
||||||
|
|
||||||
|
if (event.metaKey === true && keyCode === this.keys.A) {
|
||||||
|
this.didPressSelectAll();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyCode === this.keys.BACKSPACE) {
|
||||||
|
this.didPressBackspace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this.removeObserver(`content.@each.${this.get("nameProperty")}`, this, this._compute);
|
this.removeObserver(`content.@each.${this.get("nameProperty")}`, this, this._compute);
|
||||||
this.removeObserver(`content.[]`, this, this._compute);
|
this.removeObserver(`content.[]`, this, this._compute);
|
||||||
@ -132,28 +150,7 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
},
|
},
|
||||||
didComputeAsyncContent() {},
|
didComputeAsyncContent() {},
|
||||||
|
|
||||||
computeHeaderContent() {
|
|
||||||
return this.baseHeaderComputedContent();
|
|
||||||
},
|
|
||||||
|
|
||||||
computeContentItem(contentItem, options) {
|
computeContentItem(contentItem, options) {
|
||||||
return this.baseComputedContentItem(contentItem, options);
|
|
||||||
},
|
|
||||||
|
|
||||||
computeAsyncContentItem(contentItem, options) {
|
|
||||||
return this.computeContentItem(contentItem, options);
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed("isAsync", "filteredAsyncComputedContent.[]", "filteredComputedContent.[]")
|
|
||||||
collectionComputedContent(isAsync, filteredAsyncComputedContent, filteredComputedContent) {
|
|
||||||
return isAsync ? filteredAsyncComputedContent : filteredComputedContent;
|
|
||||||
},
|
|
||||||
|
|
||||||
validateCreate() { return true; },
|
|
||||||
|
|
||||||
validateSelect() { return true; },
|
|
||||||
|
|
||||||
baseComputedContentItem(contentItem, options) {
|
|
||||||
let originalContent;
|
let originalContent;
|
||||||
options = options || {};
|
options = options || {};
|
||||||
const name = options.name;
|
const name = options.name;
|
||||||
@ -166,13 +163,39 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
originalContent = contentItem;
|
originalContent = contentItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
let computedContentItem = {
|
||||||
value: this._castInteger(this.valueForContentItem(contentItem)),
|
value: this._castInteger(this.valueForContentItem(contentItem)),
|
||||||
name: name || this._nameForContent(contentItem),
|
name: name || this._nameForContent(contentItem),
|
||||||
locked: false,
|
locked: false,
|
||||||
created: options.created || false,
|
created: options.created || false,
|
||||||
|
__sk_row_type: options.created ? "createRow" : null,
|
||||||
originalContent
|
originalContent
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return computedContentItem;
|
||||||
|
},
|
||||||
|
|
||||||
|
computeAsyncContentItem(contentItem, options) {
|
||||||
|
return this.computeContentItem(contentItem, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed("isAsync", "isLoading", "filteredAsyncComputedContent.[]", "filteredComputedContent.[]")
|
||||||
|
collectionComputedContent(isAsync, isLoading, filteredAsyncComputedContent, filteredComputedContent) {
|
||||||
|
if (isAsync) {
|
||||||
|
return isLoading ? [] : filteredAsyncComputedContent;
|
||||||
|
} else {
|
||||||
|
return filteredComputedContent;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
validateCreate() { return !this.get("hasReachedLimit"); },
|
||||||
|
|
||||||
|
validateSelect() { return !this.get("hasReachedLimit"); },
|
||||||
|
|
||||||
|
@computed("limit", "selection.[]")
|
||||||
|
hasReachedLimit(limit, selection) {
|
||||||
|
if (!limit) return false;
|
||||||
|
return selection.length >= limit;
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("shouldFilter", "allowAny", "filter")
|
@computed("shouldFilter", "allowAny", "filter")
|
||||||
@ -182,16 +205,16 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("filter", "collectionComputedContent.[]")
|
@computed("filter", "collectionComputedContent.[]", "isLoading")
|
||||||
noContentRow(filter, collectionComputedContent) {
|
noContentRow(filter, collectionComputedContent, isLoading) {
|
||||||
if (filter.length > 0 && collectionComputedContent.length === 0) {
|
if (filter.length > 0 && collectionComputedContent.length === 0 && !isLoading) {
|
||||||
return I18n.t("select_kit.no_content");
|
return I18n.t("select_kit.no_content");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("limitReached", "limit")
|
@computed("hasReachedLimit", "limit")
|
||||||
maxContentRow(limitReached, limit) {
|
maxContentRow(hasReachedLimit, limit) {
|
||||||
if (limitReached) {
|
if (hasReachedLimit) {
|
||||||
return I18n.t("select_kit.max_content_reached", { count: limit });
|
return I18n.t("select_kit.max_content_reached", { count: limit });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -204,9 +227,9 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("computedValue", "filter", "collectionComputedContent.[]", "limitReached")
|
@computed("computedValue", "filter", "collectionComputedContent.[]", "hasReachedLimit", "isLoading")
|
||||||
shouldDisplayCreateRow(computedValue, filter, collectionComputedContent, limitReached) {
|
shouldDisplayCreateRow(computedValue, filter, collectionComputedContent, hasReachedLimit, isLoading) {
|
||||||
if (limitReached) return false;
|
if (isLoading || hasReachedLimit) return false;
|
||||||
if (collectionComputedContent.map(c => c.value).includes(filter)) return false;
|
if (collectionComputedContent.map(c => c.value).includes(filter)) return false;
|
||||||
if (this.get("allowAny") && filter.length > 0 && this.validateCreate(filter)) return true;
|
if (this.get("allowAny") && filter.length > 0 && this.validateCreate(filter)) return true;
|
||||||
return false;
|
return false;
|
||||||
@ -216,7 +239,9 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
createRowComputedContent(filter, shouldDisplayCreateRow) {
|
createRowComputedContent(filter, shouldDisplayCreateRow) {
|
||||||
if (shouldDisplayCreateRow) {
|
if (shouldDisplayCreateRow) {
|
||||||
let content = this.createContentFromInput(filter);
|
let content = this.createContentFromInput(filter);
|
||||||
return this.computeContentItem(content, { created: true });
|
let computedContentItem = this.computeContentItem(content, { created: true });
|
||||||
|
computedContentItem.__sk_row_type = "createRow";
|
||||||
|
return computedContentItem;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -238,90 +263,100 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
@computed("none")
|
@computed("none")
|
||||||
noneRowComputedContent(none) {
|
noneRowComputedContent(none) {
|
||||||
if (isNone(none)) { return null; }
|
if (isNone(none)) { return null; }
|
||||||
|
let noneRowComputedContent;
|
||||||
|
|
||||||
switch (typeof none) {
|
switch (typeof none) {
|
||||||
case "string":
|
case "string":
|
||||||
return this.computeContentItem(this.noneValue, {
|
noneRowComputedContent = this.computeContentItem(this.noneValue, {
|
||||||
name: (I18n.t(none) || "").htmlSafe()
|
name: (I18n.t(none) || "").htmlSafe()
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return this.computeContentItem(none);
|
noneRowComputedContent = this.computeContentItem(none);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noneRowComputedContent.__sk_row_type = "noneRow";
|
||||||
|
|
||||||
|
return noneRowComputedContent;
|
||||||
},
|
},
|
||||||
|
|
||||||
createContentFromInput(input) { return input; },
|
createContentFromInput(input) { return input; },
|
||||||
|
|
||||||
willSelect() {
|
highlightSelection(items) {
|
||||||
this.clearFilter();
|
this.propertyWillChange("highlightedSelection");
|
||||||
this.set("highlightedValue", null);
|
this.set("highlightedSelection", makeArray(items));
|
||||||
},
|
this.propertyDidChange("highlightedSelection");
|
||||||
didSelect() {
|
|
||||||
this.collapse();
|
|
||||||
this.focus();
|
|
||||||
|
|
||||||
applyOnSelectPluginApiCallbacks(
|
|
||||||
this.get("pluginApiIdentifiers"),
|
|
||||||
this.get("computedValue"),
|
|
||||||
this
|
|
||||||
);
|
|
||||||
|
|
||||||
this._boundaryActionHandler("onSelect", this.get("computedValue"));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
willDeselect() {
|
clearHighlightSelection() {
|
||||||
this.clearFilter();
|
this.highlightSelection([]);
|
||||||
this.set("highlightedValue", null);
|
|
||||||
},
|
|
||||||
didDeselect(rowComputedContentItem) {
|
|
||||||
this.collapse();
|
|
||||||
this.focus();
|
|
||||||
this._boundaryActionHandler("onDeselect", rowComputedContentItem);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
willSelect() {},
|
||||||
|
didSelect() {},
|
||||||
|
|
||||||
|
willCreate() {},
|
||||||
|
didCreate() {},
|
||||||
|
|
||||||
|
willDeselect() {},
|
||||||
|
didDeselect() {},
|
||||||
|
|
||||||
clearFilter() {
|
clearFilter() {
|
||||||
this.$filterInput().val("");
|
this.$filterInput().val("");
|
||||||
this.setProperties({ filter: "" });
|
this.setProperties({ filter: "", previousFilter: "" });
|
||||||
},
|
},
|
||||||
|
|
||||||
startLoading() {
|
startLoading() {
|
||||||
this.set("isLoading", true);
|
this.set("isLoading", true);
|
||||||
|
this.set("highlighted", null);
|
||||||
this._boundaryActionHandler("onStartLoading");
|
this._boundaryActionHandler("onStartLoading");
|
||||||
},
|
},
|
||||||
|
|
||||||
stopLoading() {
|
stopLoading() {
|
||||||
|
this.focus();
|
||||||
this.set("isLoading", false);
|
this.set("isLoading", false);
|
||||||
this._boundaryActionHandler("onStopLoading");
|
this._boundaryActionHandler("onStopLoading");
|
||||||
},
|
},
|
||||||
|
|
||||||
_setCollectionHeaderComputedContent() {
|
@computed("selection.[]", "isExpanded", "filter", "highlightedSelection.[]")
|
||||||
const collectionHeaderComputedContent = applyCollectionHeaderCallbacks(
|
collectionHeaderComputedContent() {
|
||||||
|
return applyCollectionHeaderCallbacks(
|
||||||
this.get("pluginApiIdentifiers"),
|
this.get("pluginApiIdentifiers"),
|
||||||
this.get("collectionHeader"),
|
this.get("collectionHeader"),
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
this.set("collectionHeaderComputedContent", collectionHeaderComputedContent);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_setHeaderComputedContent() {
|
@computed("selection.[]", "isExpanded", "headerIcon")
|
||||||
const headerComputedContent = applyHeaderContentPluginApiCallbacks(
|
headerComputedContent() {
|
||||||
|
return applyHeaderContentPluginApiCallbacks(
|
||||||
this.get("pluginApiIdentifiers"),
|
this.get("pluginApiIdentifiers"),
|
||||||
this.computeHeaderContent(),
|
this.computeHeaderContent(),
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
this.set("headerComputedContent", headerComputedContent);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_boundaryActionHandler(actionName, ...params) {
|
_boundaryActionHandler(actionName, ...params) {
|
||||||
if (Ember.get(this.actions, actionName)) {
|
if (get(this.actions, actionName)) {
|
||||||
run.next(() => this.send(actionName, ...params));
|
run.next(() => this.send(actionName, ...params));
|
||||||
} else if (this.get(actionName)) {
|
} else if (this.get(actionName)) {
|
||||||
run.next(() => this.get(actionName)());
|
run.next(() => this.get(actionName)());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
highlight(computedContent) {
|
||||||
|
this.set("highlighted", computedContent);
|
||||||
|
this._boundaryActionHandler("onHighlight", computedContent);
|
||||||
|
},
|
||||||
|
|
||||||
|
clearSelection() {
|
||||||
|
this.deselect(this.get("selection"));
|
||||||
|
this.focus();
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
toggle() {
|
onToggle() {
|
||||||
this._boundaryActionHandler("onToggle", this);
|
this.clearHighlightSelection();
|
||||||
|
|
||||||
if (this.get("isExpanded")) {
|
if (this.get("isExpanded")) {
|
||||||
this._boundaryActionHandler("onCollapse", this);
|
this._boundaryActionHandler("onCollapse", this);
|
||||||
@ -332,16 +367,29 @@ export default Ember.Component.extend(UtilsMixin, PluginApiMixin, DomHelpersMixi
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
highlight(rowComputedContent) {
|
onClickRow(computedContentItem) {
|
||||||
this.set("highlightedValue", rowComputedContent.value);
|
this.didClickRow(computedContentItem);
|
||||||
this._boundaryActionHandler("onHighlight", rowComputedContent);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
filterComputedContent(filter) {
|
onClickSelectionItem(computedContentItem) {
|
||||||
|
this.didClickSelectionItem(computedContentItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
onClearSelection() {
|
||||||
|
this.clearSelection();
|
||||||
|
},
|
||||||
|
|
||||||
|
onMouseoverRow(computedContentItem) {
|
||||||
|
this.highlight(computedContentItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
onFilterComputedContent(filter) {
|
||||||
if (filter === this.get("previousFilter")) return;
|
if (filter === this.get("previousFilter")) return;
|
||||||
|
|
||||||
|
this.clearHighlightSelection();
|
||||||
|
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
highlightedValue: null,
|
highlighted: null,
|
||||||
renderedFilterOnce: true,
|
renderedFilterOnce: true,
|
||||||
previousFilter: filter,
|
previousFilter: filter,
|
||||||
filter
|
filter
|
||||||
|
@ -7,9 +7,8 @@ export default Ember.Component.extend({
|
|||||||
classNameBindings: ["isFocused", "isHidden"],
|
classNameBindings: ["isFocused", "isHidden"],
|
||||||
isHidden: Ember.computed.not("shouldDisplayFilter"),
|
isHidden: Ember.computed.not("shouldDisplayFilter"),
|
||||||
|
|
||||||
@computed("placeholder", "hasSelection")
|
@computed("placeholder")
|
||||||
computedPlaceholder(placeholder, hasSelection) {
|
computedPlaceholder(placeholder) {
|
||||||
if (hasSelection) return "";
|
|
||||||
return isEmpty(placeholder) ? "" : I18n.t(placeholder);
|
return isEmpty(placeholder) ? "" : I18n.t(placeholder);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import computed from 'ember-addons/ember-computed-decorators';
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
|
const { isEmpty, makeArray } = Ember;
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
layoutName: "select-kit/templates/components/select-kit/select-kit-header",
|
layoutName: "select-kit/templates/components/select-kit/select-kit-header",
|
||||||
@ -33,10 +34,10 @@ export default Ember.Component.extend({
|
|||||||
|
|
||||||
@computed("computedContent.icon", "computedContent.icons")
|
@computed("computedContent.icon", "computedContent.icons")
|
||||||
icons(icon, icons) {
|
icons(icon, icons) {
|
||||||
return Ember.makeArray(icon).concat(icons).filter(i => !Ember.isEmpty(i));
|
return makeArray(icon).concat(icons).filter(i => !isEmpty(i));
|
||||||
},
|
},
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
this.sendAction("toggle");
|
this.sendAction("onToggle");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,9 +2,5 @@ import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-r
|
|||||||
|
|
||||||
export default SelectKitRowComponent.extend({
|
export default SelectKitRowComponent.extend({
|
||||||
layoutName: "select-kit/templates/components/select-kit/select-kit-row",
|
layoutName: "select-kit/templates/components/select-kit/select-kit-row",
|
||||||
classNames: "none",
|
classNames: "none"
|
||||||
|
|
||||||
click() {
|
|
||||||
this.sendAction("clearSelection");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,8 @@ export default Ember.Component.extend(UtilsMixin, {
|
|||||||
"title",
|
"title",
|
||||||
"value:data-value",
|
"value:data-value",
|
||||||
"name:data-name",
|
"name:data-name",
|
||||||
"ariaLabel:aria-label"
|
"ariaLabel:aria-label",
|
||||||
|
"guid:data-guid"
|
||||||
],
|
],
|
||||||
classNameBindings: ["isHighlighted", "isSelected"],
|
classNameBindings: ["isHighlighted", "isSelected"],
|
||||||
|
|
||||||
@ -27,6 +28,9 @@ export default Ember.Component.extend(UtilsMixin, {
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@computed("computedContent")
|
||||||
|
guid(computedContent) { return Ember.guidFor(computedContent); },
|
||||||
|
|
||||||
label: Ember.computed.or("computedContent.label", "title", "name"),
|
label: Ember.computed.or("computedContent.label", "title", "name"),
|
||||||
|
|
||||||
name: Ember.computed.alias("computedContent.name"),
|
name: Ember.computed.alias("computedContent.name"),
|
||||||
@ -39,7 +43,7 @@ export default Ember.Component.extend(UtilsMixin, {
|
|||||||
@on("didReceiveAttrs")
|
@on("didReceiveAttrs")
|
||||||
_setSelectionState() {
|
_setSelectionState() {
|
||||||
this.set("isSelected", this.get("computedValue") === this.get("value"));
|
this.set("isSelected", this.get("computedValue") === this.get("value"));
|
||||||
this.set("isHighlighted", this.get("highlightedValue") === this.get("value"));
|
this.set("isHighlighted", this.get("highlighted.value") === this.get("value"));
|
||||||
},
|
},
|
||||||
|
|
||||||
@on("willDestroyElement")
|
@on("willDestroyElement")
|
||||||
@ -57,14 +61,14 @@ export default Ember.Component.extend(UtilsMixin, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
mouseEnter() {
|
mouseEnter() {
|
||||||
this.set("hoverDebounce", run.debounce(this, this._sendHighlightAction, 32));
|
this.set("hoverDebounce", run.debounce(this, this._sendMouseoverAction, 32));
|
||||||
},
|
},
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
this.sendAction("select", this.get("computedContent"));
|
this.sendAction("onClickRow", this.get("computedContent"));
|
||||||
},
|
},
|
||||||
|
|
||||||
_sendHighlightAction() {
|
_sendMouseoverAction() {
|
||||||
this.sendAction("highlight", this.get("computedContent"));
|
this.sendAction("onMouseoverRow", this.get("computedContent"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import SelectKitComponent from "select-kit/components/select-kit";
|
import SelectKitComponent from "select-kit/components/select-kit";
|
||||||
import { default as computed, on } from 'ember-addons/ember-computed-decorators';
|
import { default as computed, on } from 'ember-addons/ember-computed-decorators';
|
||||||
const { get, isNone, isEmpty, isPresent, run } = Ember;
|
const { get, isNone, isEmpty, isPresent, run, makeArray } = Ember;
|
||||||
|
|
||||||
|
import {
|
||||||
|
applyOnSelectPluginApiCallbacks,
|
||||||
|
} from "select-kit/mixins/plugin-api";
|
||||||
|
|
||||||
export default SelectKitComponent.extend({
|
export default SelectKitComponent.extend({
|
||||||
pluginApiIdentifiers: ["single-select"],
|
pluginApiIdentifiers: ["single-select"],
|
||||||
@ -32,20 +36,15 @@ export default SelectKitComponent.extend({
|
|||||||
this.didComputeAttributes();
|
this.didComputeAttributes();
|
||||||
|
|
||||||
if (this.get("allowInitialValueMutation")) this.mutateAttributes();
|
if (this.get("allowInitialValueMutation")) this.mutateAttributes();
|
||||||
|
|
||||||
this._setCollectionHeaderComputedContent();
|
|
||||||
this._setHeaderComputedContent();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
mutateAttributes() {
|
mutateAttributes() {
|
||||||
|
run.next(() => {
|
||||||
if (this.get("isDestroyed") || this.get("isDestroying")) return;
|
if (this.get("isDestroyed") || this.get("isDestroying")) return;
|
||||||
|
|
||||||
run.next(() => {
|
|
||||||
this.mutateContent(this.get("computedContent"));
|
this.mutateContent(this.get("computedContent"));
|
||||||
this.mutateValue(this.get("computedValue"));
|
this.mutateValue(this.get("computedValue"));
|
||||||
this._setCollectionHeaderComputedContent();
|
|
||||||
this._setHeaderComputedContent();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
mutateContent() {},
|
mutateContent() {},
|
||||||
@ -84,12 +83,12 @@ export default SelectKitComponent.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
baseHeaderComputedContent() {
|
computeHeaderContent() {
|
||||||
return {
|
return {
|
||||||
title: this.get("title"),
|
title: this.get("title"),
|
||||||
icons: Ember.makeArray(this.getWithDefault("headerIcon", [])),
|
icons: makeArray(this.getWithDefault("headerIcon", [])),
|
||||||
value: this.get("selectedComputedContent.value"),
|
value: this.get("selection.value"),
|
||||||
name: this.get("selectedComputedContent.name") || this.get("noneRowComputedContent.name")
|
name: this.get("selection.name") || this.get("noneRowComputedContent.name")
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -120,84 +119,118 @@ export default SelectKitComponent.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
@computed("computedValue", "computedContent.[]")
|
@computed("computedValue", "computedContent.[]")
|
||||||
selectedComputedContent(computedValue, computedContent) {
|
selection(computedValue, computedContent) {
|
||||||
return computedContent.findBy("value", computedValue);
|
return computedContent.findBy("value", computedValue);
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("selectedComputedContent")
|
@computed("selection")
|
||||||
hasSelection(selectedComputedContent) {
|
hasSelection(selection) {
|
||||||
return selectedComputedContent !== this.get("noneRowComputedContent") &&
|
return selection !== this.get("noneRowComputedContent") && !isNone(selection);
|
||||||
!Ember.isNone(selectedComputedContent);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("computedValue", "filter", "collectionComputedContent.[]", "limitReached")
|
@computed("computedValue", "filter", "collectionComputedContent.[]", "hasReachedLimit")
|
||||||
shouldDisplayCreateRow(computedValue, filter) {
|
shouldDisplayCreateRow(computedValue, filter) {
|
||||||
return this._super() && computedValue !== filter;
|
return this._super() && computedValue !== filter;
|
||||||
},
|
},
|
||||||
|
|
||||||
autoHighlight() {
|
autoHighlight() {
|
||||||
run.schedule("afterRender", () => {
|
run.schedule("afterRender", () => {
|
||||||
if (!isNone(this.get("highlightedValue"))) return;
|
if (this.get("shouldDisplayCreateRow")) {
|
||||||
|
this.highlight(this.get("createRowComputedContent"));
|
||||||
const filteredComputedContent = this.get("filteredComputedContent");
|
|
||||||
const displayCreateRow = this.get("shouldDisplayCreateRow");
|
|
||||||
const none = this.get("noneRowComputedContent");
|
|
||||||
|
|
||||||
if (this.get("hasSelection") && isEmpty(this.get("filter"))) {
|
|
||||||
this.send("highlight", this.get("selectedComputedContent"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNone(this.get("highlightedValue")) && !isEmpty(filteredComputedContent)) {
|
if (!isEmpty(this.get("filter")) && !isEmpty(this.get("collectionComputedContent"))) {
|
||||||
this.send("highlight", get(filteredComputedContent, "firstObject"));
|
this.highlight(this.get("collectionComputedContent.firstObject"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayCreateRow && isEmpty(filteredComputedContent)) {
|
if (!this.get("isAsync") && this.get("hasSelection") && isEmpty(this.get("filter"))) {
|
||||||
this.send("highlight", this.get("createRowComputedContent"));
|
this.highlight(get(makeArray(this.get("selection")), "firstObject"));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (!isEmpty(filteredComputedContent)) {
|
|
||||||
this.send("highlight", get(filteredComputedContent, "firstObject"));
|
if (!this.get("isAsync") && !this.get("hasSelection") && isEmpty(this.get("filter")) && !isEmpty(this.get("collectionComputedContent"))) {
|
||||||
|
this.highlight(this.get("collectionComputedContent.firstObject"));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (isEmpty(filteredComputedContent) && isPresent(none) && !displayCreateRow) {
|
|
||||||
this.send("highlight", none);
|
if (isPresent(this.get("noneRowComputedContent"))) {
|
||||||
|
this.highlight(this.get("noneRowComputedContent"));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
select(computedContentItem) {
|
||||||
clearSelection() {
|
if (!computedContentItem || computedContentItem.__sk_row_type === "noneRow") {
|
||||||
this.send("deselect", this.get("selectedComputedContent"));
|
this.clearSelection();
|
||||||
this._boundaryActionHandler("onClearSelection");
|
return;
|
||||||
},
|
}
|
||||||
|
|
||||||
create(computedContentItem) {
|
if (computedContentItem.__sk_row_type === "createRow") {
|
||||||
if (this.get("computedValue") !== computedContentItem.value &&
|
if (this.get("computedValue") !== computedContentItem.value &&
|
||||||
this.validateCreate(computedContentItem.value)) {
|
this.validateCreate(computedContentItem.value)) {
|
||||||
|
this.willCreate(computedContentItem);
|
||||||
|
computedContentItem.__sk_row_type = null;
|
||||||
this.get("computedContent").pushObject(computedContentItem);
|
this.get("computedContent").pushObject(computedContentItem);
|
||||||
|
|
||||||
|
run.schedule("afterRender", () => {
|
||||||
|
this.didCreate(computedContentItem);
|
||||||
this._boundaryActionHandler("onCreate");
|
this._boundaryActionHandler("onCreate");
|
||||||
this.send("select", computedContentItem);
|
});
|
||||||
|
|
||||||
|
this.select(computedContentItem);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
this._boundaryActionHandler("onCreateFailure");
|
this._boundaryActionHandler("onCreateFailure");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
select(rowComputedContentItem) {
|
if (this.validateSelect(computedContentItem)) {
|
||||||
if (this.validateSelect(rowComputedContentItem)) {
|
this.willSelect(computedContentItem);
|
||||||
this.willSelect(rowComputedContentItem);
|
this.clearFilter();
|
||||||
this.set("computedValue", rowComputedContentItem.value);
|
this.setProperties({ highlighted: null, computedValue: computedContentItem.value });
|
||||||
this.mutateAttributes();
|
|
||||||
run.schedule("afterRender", () => this.didSelect(rowComputedContentItem));
|
run.next(() => this.mutateAttributes());
|
||||||
|
|
||||||
|
run.schedule("afterRender", () => {
|
||||||
|
this.didSelect(computedContentItem);
|
||||||
|
|
||||||
|
applyOnSelectPluginApiCallbacks(
|
||||||
|
this.get("pluginApiIdentifiers"),
|
||||||
|
computedContentItem.value,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
this._boundaryActionHandler("onSelect", computedContentItem.value);
|
||||||
|
|
||||||
|
this.autoHighlight();
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this._boundaryActionHandler("onSelectFailure");
|
this._boundaryActionHandler("onSelectFailure");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
deselect(rowComputedContentItem) {
|
deselect(computedContentItem) {
|
||||||
this.willDeselect(rowComputedContentItem);
|
makeArray(computedContentItem).forEach((item) => {
|
||||||
this.set("computedValue", null);
|
this.willDeselect(item);
|
||||||
this.mutateAttributes();
|
|
||||||
run.schedule("afterRender", () => this.didDeselect(rowComputedContentItem));
|
this.clearFilter();
|
||||||
}
|
|
||||||
|
this.setProperties({
|
||||||
|
computedValue: null,
|
||||||
|
highlighted: null,
|
||||||
|
highlightedSelection: []
|
||||||
|
});
|
||||||
|
|
||||||
|
run.next(() => this.mutateAttributes());
|
||||||
|
run.schedule("afterRender", () => {
|
||||||
|
this.didDeselect(item);
|
||||||
|
this._boundaryActionHandler("onDeselect", item);
|
||||||
|
this.autoHighlight();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -58,7 +58,7 @@ export default MultiSelectComponent.extend(Tags, {
|
|||||||
actions: {
|
actions: {
|
||||||
onFilter(filter) {
|
onFilter(filter) {
|
||||||
this.expand();
|
this.expand();
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, filter, 200));
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, filter, 200));
|
||||||
},
|
},
|
||||||
|
|
||||||
onExpand() {
|
onExpand() {
|
||||||
@ -66,15 +66,15 @@ export default MultiSelectComponent.extend(Tags, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onDeselect() {
|
onDeselect() {
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 200));
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, this.get("filter"), 200));
|
||||||
},
|
},
|
||||||
|
|
||||||
onSelect() {
|
onSelect() {
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 50));
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, this.get("filter"), 50));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
prepareSearch(query) {
|
_prepareSearch(query) {
|
||||||
const selectedTags = makeArray(this.get("values")).filter(t => t);
|
const selectedTags = makeArray(this.get("values")).filter(t => t);
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
@ -39,7 +39,7 @@ export default ComboBoxComponent.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
|
|
||||||
if (!content.value) {
|
if (!content.value) {
|
||||||
if (this.get("noTagsSelected")) {
|
if (this.get("noTagsSelected")) {
|
||||||
|
@ -42,25 +42,25 @@ export default MultiSelectComponent.extend(Tags, {
|
|||||||
actions: {
|
actions: {
|
||||||
onFilter(filter) {
|
onFilter(filter) {
|
||||||
this.expand();
|
this.expand();
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, filter, 200));
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, filter, 200));
|
||||||
},
|
},
|
||||||
|
|
||||||
onExpand() {
|
onExpand() {
|
||||||
if (isEmpty(this.get("collectionComputedContent"))) {
|
if (isEmpty(this.get("collectionComputedContent"))) {
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 200));
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, this.get("filter"), 200));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onDeselect() {
|
onDeselect() {
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 200));
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, this.get("filter"), 200));
|
||||||
},
|
},
|
||||||
|
|
||||||
onSelect() {
|
onSelect() {
|
||||||
this.set("searchDebounce", run.debounce(this, this.prepareSearch, this.get("filter"), 50));
|
this.set("searchDebounce", run.debounce(this, this._prepareSearch, this.get("filter"), 50));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
prepareSearch(query) {
|
_prepareSearch(query) {
|
||||||
const data = {
|
const data = {
|
||||||
q: query,
|
q: query,
|
||||||
limit: this.get("siteSettings.max_tag_search_results")
|
limit: this.get("siteSettings.max_tag_search_results")
|
||||||
|
@ -14,7 +14,7 @@ export default DropdownSelectBoxComponent.extend({
|
|||||||
|
|
||||||
mutateValue(value) {
|
mutateValue(value) {
|
||||||
this.sendAction("onPopupMenuAction", value);
|
this.sendAction("onPopupMenuAction", value);
|
||||||
this.setProperties({ value: null, highlightedValue: null });
|
this.setProperties({ value: null, highlighted: null });
|
||||||
},
|
},
|
||||||
|
|
||||||
computeContent(content) {
|
computeContent(content) {
|
||||||
|
@ -8,7 +8,7 @@ export default ComboBoxComponent.extend({
|
|||||||
allowInitialValueMutation: false,
|
allowInitialValueMutation: false,
|
||||||
|
|
||||||
computeHeaderContent() {
|
computeHeaderContent() {
|
||||||
let content = this.baseHeaderComputedContent();
|
let content = this._super();
|
||||||
content.name = I18n.t("topic.controls");
|
content.name = I18n.t("topic.controls");
|
||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
@ -45,7 +45,7 @@ export default ComboBoxComponent.extend({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const refresh = () => this.send("deselect", value);
|
const refresh = () => this.deselect(this.get("selection"));
|
||||||
|
|
||||||
switch(value) {
|
switch(value) {
|
||||||
case "invite":
|
case "invite":
|
||||||
|
@ -6,6 +6,7 @@ export default Ember.Mixin.create({
|
|||||||
|
|
||||||
this._previousScrollParentOverflow = null;
|
this._previousScrollParentOverflow = null;
|
||||||
this._previousCSSContext = null;
|
this._previousCSSContext = null;
|
||||||
|
this.selectionSelector = ".choice";
|
||||||
this.filterInputSelector = ".filter-input";
|
this.filterInputSelector = ".filter-input";
|
||||||
this.rowSelector = ".select-kit-row";
|
this.rowSelector = ".select-kit-row";
|
||||||
this.collectionSelector = ".select-kit-collection";
|
this.collectionSelector = ".select-kit-collection";
|
||||||
@ -58,36 +59,42 @@ export default Ember.Mixin.create({
|
|||||||
this.setProperties({ isFocused: false });
|
this.setProperties({ isFocused: false });
|
||||||
},
|
},
|
||||||
|
|
||||||
// try to focus filter and fallback to header if not present
|
|
||||||
focus() {
|
focus() {
|
||||||
Ember.run.schedule("afterRender", () => {
|
Ember.run.schedule("afterRender", () => {
|
||||||
if ((!this.get("filterable")) || !this.$filterInput().is(":visible")) {
|
this.$header().focus();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// try to focus filter and fallback to header if not present
|
||||||
|
focusFilterOrHeader() {
|
||||||
|
// next so we are sure it finised expand/collapse
|
||||||
|
Ember.run.next(() => {
|
||||||
|
Ember.run.schedule("afterRender", () => {
|
||||||
|
if (!this.$filterInput().is(":visible")) {
|
||||||
this.$header().focus();
|
this.$header().focus();
|
||||||
} else {
|
} else {
|
||||||
this.$filterInput().focus();
|
this.$filterInput().focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
expand() {
|
expand() {
|
||||||
if (this.get("isExpanded") === true) return;
|
if (this.get("isExpanded")) return;
|
||||||
this.setProperties({ isExpanded: true, renderedBodyOnce: true, isFocused: true });
|
this.setProperties({ isExpanded: true, renderedBodyOnce: true, isFocused: true });
|
||||||
this._setCollectionHeaderComputedContent();
|
this.focusFilterOrHeader();
|
||||||
this._setHeaderComputedContent();
|
|
||||||
this.focus();
|
|
||||||
this.autoHighlight();
|
this.autoHighlight();
|
||||||
},
|
},
|
||||||
|
|
||||||
collapse() {
|
collapse() {
|
||||||
this.set("isExpanded", false);
|
this.set("isExpanded", false);
|
||||||
Ember.run.schedule("afterRender", () => this._removeFixedPosition() );
|
Ember.run.schedule("afterRender", () => this._removeFixedPosition() );
|
||||||
this._setHeaderComputedContent();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// lose focus of the component in two steps
|
// lose focus of the component in two steps
|
||||||
// first collapse and keep focus and then remove focus
|
// first collapse and keep focus and then remove focus
|
||||||
unfocus(event) {
|
unfocus(event) {
|
||||||
if (this.get("isExpanded") === true) {
|
if (this.get("isExpanded")) {
|
||||||
this.collapse(event);
|
this.collapse(event);
|
||||||
this.focus(event);
|
this.focus(event);
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,6 +9,9 @@ export default Ember.Mixin.create({
|
|||||||
UP: 38,
|
UP: 38,
|
||||||
DOWN: 40,
|
DOWN: 40,
|
||||||
BACKSPACE: 8,
|
BACKSPACE: 8,
|
||||||
|
LEFT: 37,
|
||||||
|
RIGHT: 39,
|
||||||
|
A: 65
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -55,7 +58,7 @@ export default Ember.Mixin.create({
|
|||||||
|
|
||||||
this.$header()
|
this.$header()
|
||||||
.on("blur.select-kit", () => {
|
.on("blur.select-kit", () => {
|
||||||
if (this.get("isExpanded") === false && this.get("isFocused") === true) {
|
if (!this.get("isExpanded") && this.get("isFocused")) {
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -68,22 +71,27 @@ export default Ember.Mixin.create({
|
|||||||
|
|
||||||
if (document.activeElement !== this.$header()[0]) return event;
|
if (document.activeElement !== this.$header()[0]) return event;
|
||||||
|
|
||||||
if (keyCode === this.keys.TAB) this.tabFromHeader(event);
|
if (keyCode === this.keys.TAB && event.shiftKey) { this.unfocus(event); }
|
||||||
if (keyCode === this.keys.BACKSPACE) this.backspaceFromHeader(event);
|
if (keyCode === this.keys.TAB && !event.shiftKey) this.tabFromHeader(event);
|
||||||
|
if (Ember.isEmpty(this.get("filter")) && keyCode === this.keys.BACKSPACE) this.backspaceFromHeader(event);
|
||||||
if (keyCode === this.keys.ESC) this.escapeFromHeader(event);
|
if (keyCode === this.keys.ESC) this.escapeFromHeader(event);
|
||||||
if (keyCode === this.keys.ENTER) this.enterFromHeader(event);
|
if (keyCode === this.keys.ENTER) this.enterFromHeader(event);
|
||||||
if ([this.keys.UP, this.keys.DOWN].includes(keyCode)) this.upAndDownFromHeader(event);
|
if ([this.keys.UP, this.keys.DOWN].includes(keyCode)) this.upAndDownFromHeader(event);
|
||||||
|
if (Ember.isEmpty(this.get("filter")) &&
|
||||||
|
[this.keys.LEFT, this.keys.RIGHT].includes(keyCode)) {
|
||||||
|
this.leftAndRightFromHeader(event);
|
||||||
|
}
|
||||||
return event;
|
return event;
|
||||||
})
|
})
|
||||||
.on("keypress.select-kit", (event) => {
|
.on("keypress.select-kit", (event) => {
|
||||||
const keyCode = event.keyCode || event.which;
|
const keyCode = event.keyCode || event.which;
|
||||||
|
|
||||||
if (keyCode === this.keys.ENTER) { return true; }
|
if (keyCode === this.keys.ENTER) return true;
|
||||||
if (keyCode === this.keys.TAB) { return true; }
|
if (keyCode === this.keys.TAB) return true;
|
||||||
|
|
||||||
this.expand(event);
|
this.expand(event);
|
||||||
|
|
||||||
if (this.get("filterable") === true || this.get("autoFilterable")) {
|
if (this.get("filterable") || this.get("autoFilterable")) {
|
||||||
this.set("renderedFilterOnce", true);
|
this.set("renderedFilterOnce", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +108,7 @@ export default Ember.Mixin.create({
|
|||||||
|
|
||||||
this.$filterInput()
|
this.$filterInput()
|
||||||
.on("change.select-kit", (event) => {
|
.on("change.select-kit", (event) => {
|
||||||
this.send("filterComputedContent", $(event.target).val());
|
this.send("onFilterComputedContent", $(event.target).val());
|
||||||
})
|
})
|
||||||
.on("keypress.select-kit", (event) => {
|
.on("keypress.select-kit", (event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -108,40 +116,83 @@ export default Ember.Mixin.create({
|
|||||||
.on("keydown.select-kit", (event) => {
|
.on("keydown.select-kit", (event) => {
|
||||||
const keyCode = event.keyCode || event.which;
|
const keyCode = event.keyCode || event.which;
|
||||||
|
|
||||||
if (keyCode === this.keys.BACKSPACE && typeof this.backspaceFromFilter === "function") {
|
if (Ember.isEmpty(this.get("filter")) &&
|
||||||
this.backspaceFromFilter(event);
|
keyCode === this.keys.BACKSPACE &&
|
||||||
|
typeof this.didPressBackspaceFromFilter === "function") {
|
||||||
|
this.didPressBackspaceFromFilter(event);
|
||||||
};
|
};
|
||||||
if (keyCode === this.keys.TAB) this.tabFromFilter(event);
|
|
||||||
|
if (keyCode === this.keys.TAB && event.shiftKey) { this.unfocus(event); }
|
||||||
|
if (keyCode === this.keys.TAB && !event.shiftKey) this.tabFromFilter(event);
|
||||||
if (keyCode === this.keys.ESC) this.escapeFromFilter(event);
|
if (keyCode === this.keys.ESC) this.escapeFromFilter(event);
|
||||||
if (keyCode === this.keys.ENTER) this.enterFromFilter(event);
|
if (keyCode === this.keys.ENTER) this.enterFromFilter(event);
|
||||||
if ([this.keys.UP, this.keys.DOWN].includes(keyCode)) this.upAndDownFromFilter(event);
|
if ([this.keys.UP, this.keys.DOWN].includes(keyCode)) this.upAndDownFromFilter(event);
|
||||||
|
|
||||||
|
if (Ember.isEmpty(this.get("filter")) &&
|
||||||
|
[this.keys.LEFT, this.keys.RIGHT].includes(keyCode)) {
|
||||||
|
this.leftAndRightFromFilter(event);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
didPressTab(event) {
|
didPressTab(event) {
|
||||||
if (this.get("isExpanded") === false) {
|
if (this.$highlightedRow().length && this.get("isExpanded")) {
|
||||||
this.unfocus(event);
|
this.close(event);
|
||||||
} else if (this.$highlightedRow().length === 1) {
|
this.$header().focus();
|
||||||
Ember.run.throttle(this, this._rowClick, this.$highlightedRow(), 150, 150, true);
|
const guid = this.$highlightedRow().attr("data-guid");
|
||||||
this.unfocus(event);
|
this.select(this._findComputedContentItemByGuid(guid));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Ember.isEmpty(this.get("filter"))) {
|
||||||
|
this.close(event);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
this._destroyEvent(event);
|
|
||||||
this.unfocus(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
didPressEnter(event) {
|
||||||
|
if (!this.get("isExpanded")) {
|
||||||
|
this.expand(event);
|
||||||
|
} else if (this.$highlightedRow().length) {
|
||||||
|
this.close(event);
|
||||||
|
this.$header().focus();
|
||||||
|
const guid = this.$highlightedRow().attr("data-guid");
|
||||||
|
this.select(this._findComputedContentItemByGuid(guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
didClickSelectionItem(computedContentItem) {
|
||||||
|
this.focus();
|
||||||
|
this.deselect(computedContentItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
didClickRow(computedContentItem) {
|
||||||
|
this.close(event);
|
||||||
|
this.focus();
|
||||||
|
this.select(computedContentItem);
|
||||||
|
},
|
||||||
|
|
||||||
didPressEscape(event) {
|
didPressEscape(event) {
|
||||||
this._destroyEvent(event);
|
this._destroyEvent(event);
|
||||||
|
|
||||||
|
if (this.get("highlightedSelection").length && this.get("isExpanded")) {
|
||||||
|
this.clearHighlightSelection();
|
||||||
|
} else {
|
||||||
this.unfocus(event);
|
this.unfocus(event);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
didPressUpAndDownArrows(event) {
|
didPressUpAndDownArrows(event) {
|
||||||
this._destroyEvent(event);
|
this._destroyEvent(event);
|
||||||
|
|
||||||
|
this.clearHighlightSelection();
|
||||||
|
|
||||||
const keyCode = event.keyCode || event.which;
|
const keyCode = event.keyCode || event.which;
|
||||||
|
|
||||||
const $rows = this.$rows();
|
const $rows = this.$rows();
|
||||||
|
|
||||||
if (this.get("isExpanded") === false) {
|
if (this.get("isExpanded") === false) {
|
||||||
@ -151,9 +202,12 @@ export default Ember.Mixin.create({
|
|||||||
this._highlightRow(this.$selectedRow());
|
this._highlightRow(this.$selectedRow());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($rows.length <= 0) { return; }
|
if (!$rows.length) { return; }
|
||||||
|
|
||||||
if ($rows.length === 1) {
|
if ($rows.length === 1) {
|
||||||
this._rowSelection($rows, 0);
|
this._rowSelection($rows, 0);
|
||||||
return;
|
return;
|
||||||
@ -164,28 +218,43 @@ export default Ember.Mixin.create({
|
|||||||
Ember.run.throttle(this, this._moveHighlight, direction, $rows, 32);
|
Ember.run.throttle(this, this._moveHighlight, direction, $rows, 32);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
didPressBackspaceFromFilter(event) { this.didPressBackspace(event); },
|
||||||
didPressBackspace(event) {
|
didPressBackspace(event) {
|
||||||
this._destroyEvent(event);
|
if (!this.get("isExpanded")) {
|
||||||
|
this.expand();
|
||||||
|
if (event) event.stopImmediatePropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.expand(event);
|
if (!this.get("selection").length) return;
|
||||||
|
|
||||||
if (this.$filterInput().is(":visible")) {
|
if (!Ember.isEmpty(this.get("filter"))) {
|
||||||
this.$filterInput().focus().trigger(event).trigger("change");
|
this.clearHighlightSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.get("highlightedSelection").length) {
|
||||||
|
// try to highlight the last non locked item from the current selection
|
||||||
|
Ember.makeArray(this.get("selection")).slice().reverse().some(selection => {
|
||||||
|
if (!Ember.get(selection, "locked")) {
|
||||||
|
this.highlightSelection(selection);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (event) event.stopImmediatePropagation();
|
||||||
|
} else {
|
||||||
|
this.deselect(this.get("highlightedSelection"));
|
||||||
|
if (event) event.stopImmediatePropagation();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
didPressEnter(event) {
|
didPressSelectAll() {
|
||||||
this._destroyEvent(event);
|
this.highlightSelection(Ember.makeArray(this.get("selection")));
|
||||||
|
|
||||||
if (this.get("isExpanded") === false) {
|
|
||||||
this.expand(event);
|
|
||||||
} else if (this.$highlightedRow().length === 1) {
|
|
||||||
Ember.run.throttle(this, this._rowClick, this.$highlightedRow(), 150, true);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
didClickOutside(event) {
|
didClickOutside(event) {
|
||||||
if ($(event.target).parents(".select-kit").length === 1) {
|
if (this.get("isExpanded") && $(event.target).parents(".select-kit").length) {
|
||||||
this.close(event);
|
this.close(event);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -200,6 +269,38 @@ export default Ember.Mixin.create({
|
|||||||
this._destroyEvent(event);
|
this._destroyEvent(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
didPressLeftAndRightArrows(event) {
|
||||||
|
if (!this.get("isExpanded")) {
|
||||||
|
this.expand();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Ember.isEmpty(this.get("selection"))) return;
|
||||||
|
|
||||||
|
const keyCode = event.keyCode || event.which;
|
||||||
|
|
||||||
|
if (keyCode === this.keys.LEFT) {
|
||||||
|
const prev = this.get("highlightedSelection.lastObject");
|
||||||
|
const indexOfPrev = this.get("selection").indexOf(prev);
|
||||||
|
|
||||||
|
if (this.get("selection")[indexOfPrev - 1]) {
|
||||||
|
this.highlightSelection(this.get("selection")[indexOfPrev - 1]);
|
||||||
|
} else {
|
||||||
|
this.highlightSelection(this.get("selection.lastObject"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const prev = this.get("highlightedSelection.firstObject");
|
||||||
|
const indexOfNext= this.get("selection").indexOf(prev);
|
||||||
|
|
||||||
|
if (this.get("selection")[indexOfNext + 1]) {
|
||||||
|
this.highlightSelection(this.get("selection")[indexOfNext + 1]);
|
||||||
|
} else {
|
||||||
|
this.highlightSelection(this.get("selection.firstObject"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
tabFromHeader(event) { this.didPressTab(event); },
|
tabFromHeader(event) { this.didPressTab(event); },
|
||||||
tabFromFilter(event) { this.didPressTab(event); },
|
tabFromFilter(event) { this.didPressTab(event); },
|
||||||
|
|
||||||
@ -209,6 +310,9 @@ export default Ember.Mixin.create({
|
|||||||
upAndDownFromHeader(event) { this.didPressUpAndDownArrows(event); },
|
upAndDownFromHeader(event) { this.didPressUpAndDownArrows(event); },
|
||||||
upAndDownFromFilter(event) { this.didPressUpAndDownArrows(event); },
|
upAndDownFromFilter(event) { this.didPressUpAndDownArrows(event); },
|
||||||
|
|
||||||
|
leftAndRightFromHeader(event) { this.didPressLeftAndRightArrows(event); },
|
||||||
|
leftAndRightFromFilter(event) { this.didPressLeftAndRightArrows(event); },
|
||||||
|
|
||||||
backspaceFromHeader(event) { this.didPressBackspace(event); },
|
backspaceFromHeader(event) { this.didPressBackspace(event); },
|
||||||
|
|
||||||
enterFromHeader(event) { this.didPressEnter(event); },
|
enterFromHeader(event) { this.didPressEnter(event); },
|
||||||
@ -227,8 +331,6 @@ export default Ember.Mixin.create({
|
|||||||
this._rowSelection($rows, nextIndex);
|
this._rowSelection($rows, nextIndex);
|
||||||
},
|
},
|
||||||
|
|
||||||
_rowClick($row) { $row.click(); },
|
|
||||||
|
|
||||||
_rowSelection($rows, nextIndex) {
|
_rowSelection($rows, nextIndex) {
|
||||||
const highlightableValue = $rows.eq(nextIndex).attr("data-value");
|
const highlightableValue = $rows.eq(nextIndex).attr("data-value");
|
||||||
const $highlightableRow = this.$findRowByValue(highlightableValue);
|
const $highlightableRow = this.$findRowByValue(highlightableValue);
|
||||||
|
@ -22,17 +22,18 @@ export default Ember.Mixin.create({
|
|||||||
data
|
data
|
||||||
}).then(json => {
|
}).then(json => {
|
||||||
self.set("asyncContent", callback(self, json));
|
self.set("asyncContent", callback(self, json));
|
||||||
|
self.autoHighlight();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
popupAjaxError(error);
|
popupAjaxError(error);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
self.stopLoading();
|
self.stopLoading();
|
||||||
self.autoHighlight();
|
self.focusFilterOrHeader();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
validateCreate(term) {
|
validateCreate(term) {
|
||||||
if (this.get("limitReached") || !this.site.get("can_create_tag")) {
|
if (this.get("hasReachedLimit") || !this.site.get("can_create_tag")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +48,9 @@ export default Ember.Mixin.create({
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.get("asyncContent").map(c => get(c, "id")).includes(term)) {
|
const inCollection = this.get("collectionComputedContent").map(c => get(c, "id")).includes(term);
|
||||||
|
const inSelection = this.get("selection").map(s => s.toLowerCase()).includes(term);
|
||||||
|
if (inCollection || inSelection) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,12 +36,20 @@ export default Ember.Mixin.create({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_findComputedContentItemByGuid(guid) {
|
_findComputedContentItemByGuid(guid) {
|
||||||
return this.get("computedContent").find(c => {
|
if (guidFor(this.get("createRowComputedContent")) === guid) {
|
||||||
|
return this.get("createRowComputedContent");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guidFor(this.get("noneRowComputedContent")) === guid) {
|
||||||
|
return this.get("noneRowComputedContent");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.get("collectionComputedContent").find(c => {
|
||||||
return guidFor(c) === guid;
|
return guidFor(c) === guid;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_filterRemovableComputedContents(computedContent) {
|
_filterRemovableComputedContents(computedContent) {
|
||||||
return computedContent.filter(c => c.created === true);
|
return computedContent.filter(c => c.created);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
{{#if shouldDisplayClearableButton}}
|
{{#if shouldDisplayClearableButton}}
|
||||||
<button class="btn-clear" {{action clearSelection bubbles=false}}>
|
<button class="btn-clear" {{action onClearSelection bubbles=false}}>
|
||||||
{{d-icon 'times'}}
|
{{d-icon 'times'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
{{#if options.showFullTitle}}
|
{{#if options.showFullTitle}}
|
||||||
<span class="d-button-label selected-name">
|
<span class="d-button-label selected-name">
|
||||||
{{label}}
|
{{{label}}}
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if shouldDisplayClearableButton}}
|
{{#if shouldDisplayClearableButton}}
|
||||||
<button class="btn-clear" {{action clearSelection bubbles=false}}>
|
<button class="btn-clear" {{action onClearSelection bubbles=false}}>
|
||||||
{{d-icon 'times'}}
|
{{d-icon 'times'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -1 +1,3 @@
|
|||||||
{{input class="selected-name" value=label readonly="readonly"}}
|
{{input class="selected-name" value=label readonly="readonly" tabindex="-1"}}
|
||||||
|
|
||||||
|
{{d-icon caretIcon class="caret-icon"}}
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
tabindex=tabindex
|
tabindex=tabindex
|
||||||
isFocused=isFocused
|
isFocused=isFocused
|
||||||
isExpanded=isExpanded
|
isExpanded=isExpanded
|
||||||
|
highlightedSelection=highlightedSelection
|
||||||
|
onClickSelectionItem=(action "onClickSelectionItem")
|
||||||
computedContent=headerComputedContent
|
computedContent=headerComputedContent
|
||||||
deselect=(action "deselect")
|
onToggle=(action "onToggle")
|
||||||
toggle=(action "toggle")
|
|
||||||
clearSelection=(action "clearSelection")
|
|
||||||
options=headerComponentOptions
|
options=headerComponentOptions
|
||||||
}}
|
}}
|
||||||
{{component filterComponent
|
{{component filterComponent
|
||||||
@ -16,12 +16,13 @@
|
|||||||
isLoading=isLoading
|
isLoading=isLoading
|
||||||
shouldDisplayFilter=shouldDisplayFilter
|
shouldDisplayFilter=shouldDisplayFilter
|
||||||
isFocused=isFocused
|
isFocused=isFocused
|
||||||
filterComputedContent=(action "filterComputedContent")
|
onFilterComputedContent=(action "onFilterComputedContent")
|
||||||
}}
|
}}
|
||||||
{{/component}}
|
{{/component}}
|
||||||
|
|
||||||
<div class="select-kit-body">
|
<div class="select-kit-body">
|
||||||
{{#if renderedBodyOnce}}
|
{{#if renderedBodyOnce}}
|
||||||
|
{{#unless isLoading}}
|
||||||
{{component collectionComponent
|
{{component collectionComponent
|
||||||
collectionHeaderComputedContent=collectionHeaderComputedContent
|
collectionHeaderComputedContent=collectionHeaderComputedContent
|
||||||
hasSelection=hasSelection
|
hasSelection=hasSelection
|
||||||
@ -34,16 +35,15 @@
|
|||||||
templateForRow=templateForRow
|
templateForRow=templateForRow
|
||||||
templateForNoneRow=templateForNoneRow
|
templateForNoneRow=templateForNoneRow
|
||||||
templateForCreateRow=templateForCreateRow
|
templateForCreateRow=templateForCreateRow
|
||||||
clearSelection=(action "clearSelection")
|
onClickRow=(action "onClickRow")
|
||||||
select=(action "select")
|
onMouseoverRow=(action "onMouseoverRow")
|
||||||
highlight=(action "highlight")
|
highlighted=highlighted
|
||||||
create=(action "create")
|
|
||||||
highlightedValue=highlightedValue
|
|
||||||
computedValue=computedValue
|
computedValue=computedValue
|
||||||
rowComponentOptions=rowComponentOptions
|
rowComponentOptions=rowComponentOptions
|
||||||
noContentRow=noContentRow
|
noContentRow=noContentRow
|
||||||
maxContentRow=maxContentRow
|
maxContentRow=maxContentRow
|
||||||
}}
|
}}
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<div class="choices">
|
<div class="choices">
|
||||||
{{#each computedContent.selectedComputedContents as |selectedComputedContent|}}
|
{{#each computedContent.selection as |selection|}}
|
||||||
{{component selectedNameComponent
|
{{component selectedNameComponent
|
||||||
deselect=deselect
|
onClickSelectionItem=onClickSelectionItem
|
||||||
computedContent=selectedComputedContent}}
|
highlightedSelection=highlightedSelection
|
||||||
|
computedContent=selection}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
<span class="filter choice" tabindex="-1">
|
<span class="filter choice" tabindex="-1">
|
||||||
{{yield}}
|
{{yield}}
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
{{component noneRowComponent
|
{{component noneRowComponent
|
||||||
computedContent=noneRowComputedContent
|
computedContent=noneRowComputedContent
|
||||||
templateForRow=templateForNoneRow
|
templateForRow=templateForNoneRow
|
||||||
highlightedValue=highlightedValue
|
highlighted=highlighted
|
||||||
clearSelection=clearSelection
|
onMouseoverRow=onMouseoverRow
|
||||||
highlight=highlight
|
|
||||||
computedValue=computedValue
|
computedValue=computedValue
|
||||||
options=rowComponentOptions
|
options=rowComponentOptions
|
||||||
|
onClickRow=onClickRow
|
||||||
}}
|
}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -21,11 +21,11 @@
|
|||||||
{{#if createRowComputedContent}}
|
{{#if createRowComputedContent}}
|
||||||
{{component createRowComponent
|
{{component createRowComponent
|
||||||
computedContent=createRowComputedContent
|
computedContent=createRowComputedContent
|
||||||
highlightedValue=highlightedValue
|
highlighted=highlighted
|
||||||
computedValue=computedValue
|
computedValue=computedValue
|
||||||
templateForRow=templateForCreateRow
|
templateForRow=templateForCreateRow
|
||||||
highlight=highlight
|
onMouseoverRow=onMouseoverRow
|
||||||
select=create
|
onClickRow=onClickRow
|
||||||
options=rowComponentOptions
|
options=rowComponentOptions
|
||||||
}}
|
}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -43,11 +43,11 @@
|
|||||||
{{#each collectionComputedContent as |computedContent|}}
|
{{#each collectionComputedContent as |computedContent|}}
|
||||||
{{component rowComponent
|
{{component rowComponent
|
||||||
computedContent=computedContent
|
computedContent=computedContent
|
||||||
highlightedValue=highlightedValue
|
highlighted=highlighted
|
||||||
computedValue=computedValue
|
computedValue=computedValue
|
||||||
templateForRow=templateForRow
|
templateForRow=templateForRow
|
||||||
select=select
|
onClickRow=onClickRow
|
||||||
highlight=highlight
|
onMouseoverRow=onMouseoverRow
|
||||||
options=rowComponentOptions
|
options=rowComponentOptions
|
||||||
}}
|
}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
tabindex=-1
|
tabindex=-1
|
||||||
class="filter-input"
|
class="filter-input"
|
||||||
placeholder=computedPlaceholder
|
placeholder=computedPlaceholder
|
||||||
key-up=filterComputedContent
|
key-up=onFilterComputedContent
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
autocorrect="off"
|
autocorrect="off"
|
||||||
autocapitalize="off"
|
autocapitalize="off"
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{{component headerComponent
|
{{component headerComponent
|
||||||
|
caretIcon=caretIcon
|
||||||
tabindex=tabindex
|
tabindex=tabindex
|
||||||
isFocused=isFocused
|
isFocused=isFocused
|
||||||
isExpanded=isExpanded
|
isExpanded=isExpanded
|
||||||
computedContent=headerComputedContent
|
computedContent=headerComputedContent
|
||||||
deselect=(action "deselect")
|
onToggle=(action "onToggle")
|
||||||
toggle=(action "toggle")
|
onClearSelection=(action "onClearSelection")
|
||||||
clearSelection=(action "clearSelection")
|
|
||||||
options=headerComponentOptions
|
options=headerComponentOptions
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
shouldDisplayFilter=shouldDisplayFilter
|
shouldDisplayFilter=shouldDisplayFilter
|
||||||
placeholder=filterPlaceholder
|
placeholder=filterPlaceholder
|
||||||
isFocused=isFocused
|
isFocused=isFocused
|
||||||
filterComputedContent=(action "filterComputedContent")
|
onFilterComputedContent=(action "onFilterComputedContent")
|
||||||
}}
|
}}
|
||||||
|
|
||||||
{{#if renderedBodyOnce}}
|
{{#if renderedBodyOnce}}
|
||||||
@ -34,11 +34,9 @@
|
|||||||
templateForRow=templateForRow
|
templateForRow=templateForRow
|
||||||
templateForNoneRow=templateForNoneRow
|
templateForNoneRow=templateForNoneRow
|
||||||
templateForCreateRow=templateForCreateRow
|
templateForCreateRow=templateForCreateRow
|
||||||
clearSelection=(action "clearSelection")
|
onClickRow=(action "onClickRow")
|
||||||
select=(action "select")
|
onMouseoverRow=(action "onMouseoverRow")
|
||||||
highlight=(action "highlight")
|
highlighted=highlighted
|
||||||
create=(action "create")
|
|
||||||
highlightedValue=highlightedValue
|
|
||||||
computedValue=computedValue
|
computedValue=computedValue
|
||||||
rowComponentOptions=rowComponentOptions
|
rowComponentOptions=rowComponentOptions
|
||||||
noContentRow=noContentRow
|
noContentRow=noContentRow
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
&.combo-box {
|
&.combo-box {
|
||||||
&.category-chooser {
|
&.category-chooser {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
|
||||||
|
.combo-box-header {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.select-kit-row {
|
.select-kit-row {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
display: -ms-flexbox;
|
display: -ms-flexbox;
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
&.future-date-input-selector {
|
&.future-date-input-selector {
|
||||||
min-width: 50%;
|
min-width: 50%;
|
||||||
|
|
||||||
|
.future-date-input-selector-header {
|
||||||
|
.btn-clear {
|
||||||
|
line-height: $line-height-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.future-date-input-selector-datetime {
|
.future-date-input-selector-datetime {
|
||||||
color: lighten($primary, 40%);
|
color: lighten($primary, 40%);
|
||||||
font-size: $font-down-1;
|
font-size: $font-down-1;
|
||||||
|
@ -72,6 +72,7 @@ componentTest('interactions', {
|
|||||||
assert.equal(this.get('categories').length, 3);
|
assert.equal(this.get('categories').length, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.get('subject').expand();
|
||||||
this.get('subject').keyboard().backspace();
|
this.get('subject').keyboard().backspace();
|
||||||
this.get('subject').keyboard().backspace();
|
this.get('subject').keyboard().backspace();
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ componentTest('interactions', {
|
|||||||
assert.equal(listSetting.header().value(), 'bold,italic,underline');
|
assert.equal(listSetting.header().value(), 'bold,italic,underline');
|
||||||
});
|
});
|
||||||
|
|
||||||
listSetting.fillInFilter('strike');
|
listSetting.expand().fillInFilter('strike');
|
||||||
|
|
||||||
andThen(() => {
|
andThen(() => {
|
||||||
assert.equal(listSetting.highlightedRow().value(), 'strike');
|
assert.equal(listSetting.highlightedRow().value(), 'strike');
|
||||||
|
@ -66,6 +66,7 @@ componentTest('interactions', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.get('subject').selectRowByValue(3);
|
this.get('subject').selectRowByValue(3);
|
||||||
|
this.get('subject').expand();
|
||||||
|
|
||||||
andThen(() => {
|
andThen(() => {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
Reference in New Issue
Block a user