discourse/app/assets/javascripts/select-kit/mixins/events.js.es6
2017-11-21 18:07:10 +01:00

244 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export default Ember.Mixin.create({
init() {
this._super();
this.keys = {
TAB: 9,
ENTER: 13,
ESC: 27,
UP: 38,
DOWN: 40,
BACKSPACE: 8,
};
},
willDestroyElement() {
this._super();
$(document)
.off("mousedown.select-kit")
.off("touchstart.select-kit");
this.$header()
.off("focus.select-kit")
.off("blur.select-kit")
.off("keypress.select-kit")
.off("keydown.select-kit");
this.$filterInput()
.off("change.select-kit")
.off("keydown.select-kit")
.off("keypress.select-kit")
.off("focus.select-kit")
.off("focusin.select-kit");
},
didInsertElement() {
this._super();
$(document)
.on("mousedown.select-kit, touchstart.select-kit", event => {
if (Ember.isNone(this.get("element"))) return;
if (this.get("element").contains(event.target)) return;
this.didClickOutside(event);
});
this.$header()
.on("blur.select-kit", () => {
if (this.get("isExpanded") === false && this.get("isFocused") === true) {
this.close();
}
})
.on("focus.select-kit", (event) => {
this.set("isFocused", true);
this._destroyEvent(event);
})
.on("keydown.select-kit", (event) => {
const keyCode = event.keyCode || event.which;
if (document.activeElement !== this.$header()[0]) return event;
if (keyCode === this.keys.TAB) this.tabFromHeader(event);
if (keyCode === this.keys.BACKSPACE) this.backspaceFromHeader(event);
if (keyCode === this.keys.ESC) this.escapeFromHeader(event);
if (keyCode === this.keys.ENTER) this.enterFromHeader(event);
if ([this.keys.UP, this.keys.DOWN].includes(keyCode)) this.upAndDownFromHeader(event);
return event;
})
.on("keypress.select-kit", (event) => {
const keyCode = event.keyCode || event.which;
if (keyCode === this.keys.ENTER) { return true; }
this.expand(event);
if (this.get("filterable") === true || this.get("autoFilterable")) {
this.set("renderedFilterOnce", true);
}
Ember.run.schedule("afterRender", () => {
let newVal = this.$filterInput().val();
const start = this.$filterInput()[0].selectionStart;
const end = this.$filterInput()[0].selectionEnd;
if (!Ember.isNone(start) && !Ember.isNone(end)) {
newVal = newVal.substr(0, start) +
String.fromCharCode(keyCode) +
newVal.substr(end, newVal.length);
} else {
newVal = newVal + String.fromCharCode(keyCode);
}
this.$filterInput().focus().val(newVal);
});
return false;
});
this.$filterInput()
.on("change.select-kit", (event) => {
this.send("onFilter", $(event.target).val());
})
.on("focus.select-kit focusin.select-kit", (event) => {
this.set("isFocused", true);
this._destroyEvent(event);
})
.on("keypress.select-kit", (event) => {
event.stopPropagation();
})
.on("keydown.select-kit", (event) => {
const keyCode = event.keyCode || event.which;
if (keyCode === this.keys.TAB) this.tabFromFilter(event);
if (keyCode === this.keys.ESC) this.escapeFromFilter(event);
if (keyCode === this.keys.ENTER) this.enterFromFilter(event);
if ([this.keys.UP, this.keys.DOWN].includes(keyCode)) this.upAndDownFromFilter(event);
});
},
didPressTab(event) {
if (this.get("isExpanded") === false) {
this.unfocus(event);
} else if (this.$highlightedRow().length === 1) {
this._destroyEvent(event);
Ember.run.throttle(this, this._rowClick, this.$highlightedRow(), 150, 150, true);
this.focus(event);
} else {
this._destroyEvent(event);
this.unfocus(event);
}
return true;
},
didPressEscape(event) {
this._destroyEvent(event);
this.unfocus(event);
},
didPressUpAndDownArrows(event) {
this._destroyEvent(event);
const keyCode = event.keyCode || event.which;
const $rows = this.$rows();
if (this.get("isExpanded") === false) {
this.expand(event);
if (this.$selectedRow().length === 1) {
this._highlightRow(this.$selectedRow());
return;
}
}
if ($rows.length <= 0) { return; }
if ($rows.length === 1) {
this._rowSelection($rows, 0);
return;
}
const direction = keyCode === 38 ? -1 : 1;
Ember.run.throttle(this, this._moveHighlight, direction, $rows, 32);
},
didPressBackspace(event) {
this._destroyEvent(event);
this.expand(event);
if (this.$filterInput().is(":visible")) {
this.$filterInput().focus().trigger(event).trigger("change");
}
},
didPressEnter(event) {
this._destroyEvent(event);
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) {
if ($(event.target).parents(".select-kit").length === 1) {
this.close(event);
return false;
}
this.close(event);
return;
},
// make sure we dont propagate a click outside component
// to avoid closing a modal containing the component for example
click(event) {
this._destroyEvent(event);
},
tabFromHeader(event) { this.didPressTab(event); },
tabFromFilter(event) { this.didPressTab(event); },
escapeFromHeader(event) { this.didPressEscape(event); },
escapeFromFilter(event) { this.didPressEscape(event); },
upAndDownFromHeader(event) { this.didPressUpAndDownArrows(event); },
upAndDownFromFilter(event) { this.didPressUpAndDownArrows(event); },
backspaceFromHeader(event) { this.didPressBackspace(event); },
enterFromHeader(event) { this.didPressEnter(event); },
enterFromFilter(event) { this.didPressEnter(event); },
_moveHighlight(direction, $rows) {
const currentIndex = $rows.index(this.$highlightedRow());
let nextIndex = currentIndex + direction;
if (nextIndex < 0) {
nextIndex = $rows.length - 1;
} else if (nextIndex >= $rows.length) {
nextIndex = 0;
}
this._rowSelection($rows, nextIndex);
},
_rowClick($row) { $row.click(); },
_rowSelection($rows, nextIndex) {
const highlightableValue = $rows.eq(nextIndex).attr("data-value");
const $highlightableRow = this.$findRowByValue(highlightableValue);
this._highlightRow($highlightableRow);
},
_highlightRow($row) {
Ember.run.schedule("afterRender", () => {
$row.trigger("mouseover").focus();
this.focus();
});
}
});