This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/app/controllers/insert-hyperlink.js
2021-05-26 15:11:12 -04:00

186 lines
4.7 KiB
JavaScript

import { cancel, schedule } from "@ember/runloop";
import Controller from "@ember/controller";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { bind } from "discourse-common/utils/decorators";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import { prefixProtocol } from "discourse/lib/url";
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,
});
schedule("afterRender", () => {
const element = document.querySelector(".insert-link");
element.addEventListener("keydown", this.keyDown);
element
.closest(".modal-inner-container")
.addEventListener("mousedown", this.mouseDown);
});
},
@bind
keyDown(event) {
switch (event.which) {
case 40:
this.highlightRow(event, "down");
break;
case 38:
this.highlightRow(event, "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);
event.preventDefault();
event.stopPropagation();
}
break;
case 27:
// Esc should cancel dropdown first
if (this.searchResults.length) {
this.set("searchResults", []);
event.preventDefault();
event.stopPropagation();
} else {
this.send("closeModal");
}
break;
}
},
@bind
mouseDown(event) {
if (!event.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 = prefixProtocol(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 = discourseDebounce(this, this.triggerSearch, 400);
},
},
});