mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 01:06:35 -04:00
Create a rough draft of the editor web component
This commit is contained in:
parent
d558f08a74
commit
1db71805d3
1 changed files with 68 additions and 40 deletions
|
@ -334,7 +334,7 @@ function onBlur(): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fieldContainsInlineContent(field: HTMLDivElement): boolean {
|
function fieldContainsInlineContent(field: Element): boolean {
|
||||||
if (field.childNodes.length === 0) {
|
if (field.childNodes.length === 0) {
|
||||||
// for now, for all practical purposes, empty fields are in block mode
|
// for now, for all practical purposes, empty fields are in block mode
|
||||||
return false;
|
return false;
|
||||||
|
@ -437,41 +437,73 @@ function onCutOrCopy(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createField(
|
class EditingArea extends HTMLElement {
|
||||||
index: number,
|
connectedCallback() {
|
||||||
label: string,
|
this.setAttribute("contenteditable", "true");
|
||||||
color: string,
|
}
|
||||||
content: string
|
}
|
||||||
): [HTMLDivElement, HTMLDivElement] {
|
|
||||||
const name = document.createElement("div");
|
|
||||||
name.id = `name${index}`;
|
|
||||||
name.className = "fname";
|
|
||||||
|
|
||||||
const fieldname = document.createElement("span");
|
customElements.define("editing-area", EditingArea);
|
||||||
fieldname.className = "fieldname";
|
|
||||||
fieldname.innerText = label;
|
|
||||||
name.appendChild(fieldname);
|
|
||||||
|
|
||||||
const field = document.createElement("div");
|
class EditorField extends HTMLElement {
|
||||||
field.id = `f${index}`;
|
labelContainer: HTMLDivElement
|
||||||
field.className = "field";
|
label: HTMLSpanElement
|
||||||
field.setAttribute("contenteditable", "true");
|
editingContainer: HTMLDivElement
|
||||||
field.style.color = color;
|
editingArea: EditingArea
|
||||||
field.addEventListener("keydown", onKey);
|
editingShadow: ShadowRoot
|
||||||
field.addEventListener("keyup", onKeyUp);
|
|
||||||
field.addEventListener("input", onInput);
|
|
||||||
field.addEventListener("focus", onFocus);
|
|
||||||
field.addEventListener("blur", onBlur);
|
|
||||||
field.addEventListener("paste", onPaste);
|
|
||||||
field.addEventListener("copy", onCutOrCopy);
|
|
||||||
field.addEventListener("oncut", onCutOrCopy);
|
|
||||||
field.innerHTML = content;
|
|
||||||
|
|
||||||
if (fieldContainsInlineContent(field)) {
|
connectedCallback() {
|
||||||
field.appendChild(document.createElement("br"));
|
this.labelContainer = this.appendChild(document.createElement("div"));
|
||||||
|
this.labelContainer.className = "fname";
|
||||||
|
|
||||||
|
this.label = this.labelContainer.appendChild(document.createElement("span"));
|
||||||
|
this.label.className = "fieldname";
|
||||||
|
|
||||||
|
this.editingContainer = this.appendChild(document.createElement("div"));
|
||||||
|
this.editingContainer.className = "field";
|
||||||
|
this.editingContainer.addEventListener("keydown", onKey);
|
||||||
|
this.editingContainer.addEventListener("keyup", onKeyUp);
|
||||||
|
this.editingContainer.addEventListener("input", onInput);
|
||||||
|
this.editingContainer.addEventListener("focus", onFocus);
|
||||||
|
this.editingContainer.addEventListener("blur", onBlur);
|
||||||
|
this.editingContainer.addEventListener("paste", onPaste);
|
||||||
|
this.editingContainer.addEventListener("copy", onCutOrCopy);
|
||||||
|
this.editingContainer.addEventListener("oncut", onCutOrCopy);
|
||||||
|
|
||||||
|
const editingShadow = this.editingContainer.attachShadow({ mode: "open" });
|
||||||
|
this.editingArea = editingShadow.appendChild(document.createElement("editing-area")) as EditingArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [name, field];
|
initialize(index: number, label: string, color: string, content: string): void {
|
||||||
|
this.labelContainer.id = `name${index}`;
|
||||||
|
this.label.innerText = label;
|
||||||
|
|
||||||
|
this.editingContainer.id = `f${index}`;
|
||||||
|
|
||||||
|
this.editingArea.style.color = color;
|
||||||
|
this.editingArea.innerHTML = content;
|
||||||
|
if (fieldContainsInlineContent(this.editingArea)) {
|
||||||
|
this.editingArea.appendChild(document.createElement("br"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldContent(): string {
|
||||||
|
return this.editingArea.innerHTML;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("editor-field", EditorField);
|
||||||
|
|
||||||
|
function adjustFieldAmount(amount: number): void {
|
||||||
|
const fieldsContainer = document.getElementById("fields");
|
||||||
|
|
||||||
|
while (fieldsContainer.childElementCount < amount) {
|
||||||
|
fieldsContainer.appendChild(document.createElement("editor-field"))
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fieldsContainer.childElementCount > amount) {
|
||||||
|
fieldsContainer.removeChild(fieldsContainer.lastElementChild);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFields(fields: [string, string][]): void {
|
function setFields(fields: [string, string][]): void {
|
||||||
|
@ -481,17 +513,13 @@ function setFields(fields: [string, string][]): void {
|
||||||
.getComputedStyle(document.documentElement)
|
.getComputedStyle(document.documentElement)
|
||||||
.getPropertyValue("--text-fg");
|
.getPropertyValue("--text-fg");
|
||||||
|
|
||||||
const elements = fields.flatMap(([name, fieldcontent], index: number) =>
|
adjustFieldAmount(fields.length);
|
||||||
createField(index, name, color, fieldcontent)
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldsContainer = document.getElementById("fields");
|
const fieldsContainer = document.getElementById("fields");
|
||||||
// can be replaced with ParentNode.replaceChildren in Chrome 86+
|
const children = [...fieldsContainer.children]
|
||||||
while (fieldsContainer.firstChild) {
|
for (const [index, child] of children.entries()) {
|
||||||
fieldsContainer.removeChild(fieldsContainer.firstChild);
|
const [name, fieldContent] = fields[index];
|
||||||
}
|
(child as EditorField).initialize(index, name, color, fieldContent);
|
||||||
for (const element of elements) {
|
|
||||||
fieldsContainer.appendChild(element);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeDisableButtons();
|
maybeDisableButtons();
|
||||||
|
|
Loading…
Reference in a new issue