diff --git a/qt/aqt/data/web/css/editing-area.scss b/qt/aqt/data/web/css/editing-area.scss
new file mode 100644
index 000000000..c171e820c
--- /dev/null
+++ b/qt/aqt/data/web/css/editing-area.scss
@@ -0,0 +1,11 @@
+editing-area {
+ display: block;
+ overflow-wrap: break-word;
+ overflow: auto;
+ padding: 5px;
+
+ &:empty::after {
+ content: "\a";
+ white-space: pre;
+ }
+}
diff --git a/qt/aqt/data/web/css/editor.scss b/qt/aqt/data/web/css/editor.scss
index af714c161..d9e90e1d6 100644
--- a/qt/aqt/data/web/css/editor.scss
+++ b/qt/aqt/data/web/css/editor.scss
@@ -22,14 +22,6 @@
.field {
border: 1px solid var(--border);
background: var(--frame-bg);
- padding: 5px;
- overflow-wrap: break-word;
- overflow: auto;
-
- &:empty::after {
- content: "\A";
- white-space: pre;
- }
}
.fname {
diff --git a/qt/aqt/data/web/js/editor.ts b/qt/aqt/data/web/js/editor.ts
index 952347063..2c156f5ad 100644
--- a/qt/aqt/data/web/js/editor.ts
+++ b/qt/aqt/data/web/js/editor.ts
@@ -356,14 +356,9 @@ function saveField(type: "blur" | "key"): void {
return;
}
- const fieldText =
- fieldContainsInlineContent(currentField) &&
- currentField.innerHTML.endsWith("
")
- ? // trim trailing
- currentField.innerHTML.slice(0, -4)
- : currentField.innerHTML;
-
- pycmd(`${type}:${currentFieldOrdinal()}:${currentNoteId}:${fieldText}`);
+ pycmd(
+ `${type}:${currentFieldOrdinal()}:${currentNoteId}:${currentField.fieldHTML}`
+ );
}
function currentFieldOrdinal(): string {
@@ -441,64 +436,104 @@ class EditingArea extends HTMLElement {
connectedCallback() {
this.setAttribute("contenteditable", "true");
}
+
+ initialize(color: string): void {
+ this.style.color = color;
+ }
+
+ set fieldHTML(content: string) {
+ this.innerHTML = content;
+
+ if (fieldContainsInlineContent(this)) {
+ this.appendChild(document.createElement("br"));
+ }
+ }
+
+ get fieldHTML(): string {
+ return fieldContainsInlineContent(this) && this.innerHTML.endsWith("
")
+ ? this.innerHTML.slice(0, -4) // trim trailing
+ : this.innerHTML;
+ }
}
customElements.define("editing-area", EditingArea);
-class EditorField extends HTMLElement {
- labelContainer: HTMLDivElement
- label: HTMLSpanElement
- editingContainer: HTMLDivElement
- editingArea: EditingArea
- editingShadow: ShadowRoot
+class EditingContainer extends HTMLDivElement {
+ editingArea: EditingArea;
- connectedCallback() {
+ connectedCallback(): void {
+ this.className = "field";
+
+ this.addEventListener("keydown", onKey);
+ this.addEventListener("keyup", onKeyUp);
+ this.addEventListener("input", onInput);
+ this.addEventListener("focus", onFocus);
+ this.addEventListener("blur", onBlur);
+ this.addEventListener("paste", onPaste);
+ this.addEventListener("copy", onCutOrCopy);
+ this.addEventListener("oncut", onCutOrCopy);
+
+ const editingShadow = this.attachShadow({ mode: "open" });
+
+ const style = editingShadow.appendChild(document.createElement("link"));
+ style.setAttribute("rel", "stylesheet");
+ style.setAttribute("href", "./_anki/css/editing-area.css");
+
+ this.editingArea = editingShadow.appendChild(
+ document.createElement("editing-area")
+ ) as EditingArea;
+ }
+
+ initialize(index: number, color: string, content: string): void {
+ this.id = `f${index}`;
+ this.editingArea.initialize(color);
+ this.editingArea.fieldHTML = content;
+ }
+
+ set fieldHTML(content: string) {
+ this.editingArea.fieldHTML = content;
+ }
+
+ get fieldHTML(): string {
+ return this.editingArea.fieldHTML;
+ }
+}
+
+customElements.define("editing-container", EditingContainer, { extends: "div" });
+
+class EditorField extends HTMLDivElement {
+ labelContainer: HTMLDivElement;
+ label: HTMLSpanElement;
+ editingContainer: EditingContainer;
+
+ connectedCallback(): void {
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;
+ this.editingContainer = this.appendChild(
+ document.createElement("div", { is: "editing-container" })
+ ) as EditingContainer;
}
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;
+ this.editingContainer.initialize(index, color, content);
}
}
-customElements.define("editor-field", EditorField);
+customElements.define("editor-field", EditorField, { extends: "div" });
function adjustFieldAmount(amount: number): void {
const fieldsContainer = document.getElementById("fields");
while (fieldsContainer.childElementCount < amount) {
- fieldsContainer.appendChild(document.createElement("editor-field"))
+ fieldsContainer.appendChild(
+ document.createElement("div", { is: "editor-field" })
+ );
}
while (fieldsContainer.childElementCount > amount) {
@@ -516,10 +551,10 @@ function setFields(fields: [string, string][]): void {
adjustFieldAmount(fields.length);
const fieldsContainer = document.getElementById("fields");
- const children = [...fieldsContainer.children]
+ const children = [...fieldsContainer.children] as EditorField[];
for (const [index, child] of children.entries()) {
const [name, fieldContent] = fields[index];
- (child as EditorField).initialize(index, name, color, fieldContent);
+ child.initialize(index, name, color, fieldContent);
}
maybeDisableButtons();