183 lines
4.6 KiB
JavaScript
183 lines
4.6 KiB
JavaScript
import { isEmpty } from "@ember/utils";
|
|
import { cancel, debounce, scheduleOnce } from "@ember/runloop";
|
|
import Controller from "@ember/controller";
|
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
|
import { searchForTerm } from "discourse/lib/search";
|
|
|
|
export default Controller.extend(ModalFunctionality, {
|
|
_debounced: null,
|
|
_activeSearch: null,
|
|
|
|
onShow() {
|
|
this.setProperties({
|
|
linkUrl: "",
|
|
linkText: "",
|
|
searchResults: [],
|
|
searchLoading: false,
|
|
selectedRow: -1
|
|
});
|
|
|
|
scheduleOnce("afterRender", () => {
|
|
const element = document.querySelector(".insert-link");
|
|
|
|
element.addEventListener("keydown", e => this.keyDown(e));
|
|
|
|
element
|
|
.closest(".modal-inner-container")
|
|
.addEventListener("mousedown", e => this.mouseDown(e));
|
|
|
|
document.querySelector("input.link-url").focus();
|
|
});
|
|
},
|
|
|
|
keyDown(e) {
|
|
switch (e.which) {
|
|
case 40:
|
|
this.highlightRow(e, "down");
|
|
break;
|
|
case 38:
|
|
this.highlightRow(e, "up");
|
|
break;
|
|
case 13:
|
|
// override Enter behaviour when a row is selected
|
|
if (this.selectedRow > -1) {
|
|
const selected = document.querySelectorAll(
|
|
".internal-link-results .search-link"
|
|
)[this.selectedRow];
|
|
this.selectLink(selected);
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
break;
|
|
case 27:
|
|
// Esc should cancel dropdown first
|
|
if (this.searchResults.length) {
|
|
this.set("searchResults", []);
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
mouseDown(e) {
|
|
if (!e.target.closest(".inputs")) {
|
|
this.set("searchResults", []);
|
|
}
|
|
},
|
|
|
|
highlightRow(e, direction) {
|
|
const index =
|
|
direction === "down" ? this.selectedRow + 1 : this.selectedRow - 1;
|
|
|
|
if (index > -1 && index < this.searchResults.length) {
|
|
document
|
|
.querySelectorAll(".internal-link-results .search-link")
|
|
[index].focus();
|
|
this.set("selectedRow", index);
|
|
} else {
|
|
this.set("selectedRow", -1);
|
|
document.querySelector("input.link-url").focus();
|
|
}
|
|
|
|
e.preventDefault();
|
|
},
|
|
|
|
selectLink(el) {
|
|
this.setProperties({
|
|
linkUrl: el.href,
|
|
searchResults: [],
|
|
selectedRow: -1
|
|
});
|
|
|
|
if (!this.linkText && el.dataset.title) {
|
|
this.set("linkText", el.dataset.title);
|
|
}
|
|
|
|
document.querySelector("input.link-text").focus();
|
|
},
|
|
|
|
triggerSearch() {
|
|
if (this.linkUrl.length > 3 && this.linkUrl.indexOf("http") === -1) {
|
|
this.set("searchLoading", true);
|
|
this._activeSearch = searchForTerm(this.linkUrl, {
|
|
typeFilter: "topic"
|
|
});
|
|
this._activeSearch
|
|
.then(results => {
|
|
if (results && results.topics && results.topics.length > 0) {
|
|
this.set("searchResults", results.topics);
|
|
} else {
|
|
this.set("searchResults", []);
|
|
}
|
|
})
|
|
.finally(() => {
|
|
this.set("searchLoading", false);
|
|
this._activeSearch = null;
|
|
});
|
|
} else {
|
|
this.abortSearch();
|
|
}
|
|
},
|
|
|
|
abortSearch() {
|
|
if (this._activeSearch) {
|
|
this._activeSearch.abort();
|
|
}
|
|
this.setProperties({
|
|
searchResults: [],
|
|
searchLoading: false
|
|
});
|
|
},
|
|
|
|
onClose() {
|
|
const element = document.querySelector(".insert-link");
|
|
element.removeEventListener("keydown", this.keyDown);
|
|
element
|
|
.closest(".modal-inner-container")
|
|
.removeEventListener("mousedown", this.mouseDown);
|
|
|
|
cancel(this._debounced);
|
|
},
|
|
|
|
actions: {
|
|
ok() {
|
|
const origLink = this.linkUrl;
|
|
const linkUrl =
|
|
origLink.indexOf("://") === -1 ? `http://${origLink}` : origLink;
|
|
const sel = this.toolbarEvent.selected;
|
|
|
|
if (isEmpty(linkUrl)) {
|
|
return;
|
|
}
|
|
|
|
const linkText = this.linkText || "";
|
|
|
|
if (linkText.length) {
|
|
this.toolbarEvent.addText(`[${linkText}](${linkUrl})`);
|
|
} else {
|
|
if (sel.value) {
|
|
this.toolbarEvent.addText(`[${sel.value}](${linkUrl})`);
|
|
} else {
|
|
this.toolbarEvent.addText(`[${origLink}](${linkUrl})`);
|
|
this.toolbarEvent.selectText(sel.start + 1, origLink.length);
|
|
}
|
|
}
|
|
this.send("closeModal");
|
|
},
|
|
cancel() {
|
|
this.send("closeModal");
|
|
},
|
|
linkClick(e) {
|
|
if (!e.metaKey && !e.ctrlKey) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
this.selectLink(e.target.closest(".search-link"));
|
|
}
|
|
},
|
|
search() {
|
|
this._debounced = debounce(this, this.triggerSearch, 400);
|
|
}
|
|
}
|
|
});
|