Rename editingContainer -> editingArea; editingArea -> editable

* Custom elements are now namespaces with `anki-`
* The element names are inspired by summernote, which have the same
  naming scheme of "editingArea > editable"
This commit is contained in:
Henrik Giesel 2021-01-29 20:32:21 +01:00
parent 2e72de4af0
commit 61346cf1f7
2 changed files with 42 additions and 42 deletions

View file

@ -1,4 +1,4 @@
editing-area { anki-editable {
display: block; display: block;
overflow-wrap: break-word; overflow-wrap: break-word;
overflow: auto; overflow: auto;

View file

@ -1,7 +1,7 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
let currentField: EditingContainer | null = null; let currentField: EditingArea | null = null;
let changeTimer: number | null = null; let changeTimer: number | null = null;
let currentNoteId: number | null = null; let currentNoteId: number | null = null;
@ -33,7 +33,7 @@ function saveNow(keepFocus: boolean): void {
saveField("key"); saveField("key");
} else { } else {
// triggers onBlur, which saves // triggers onBlur, which saves
currentField.blurEditingArea(); currentField.blurEditable();
} }
} }
@ -52,7 +52,7 @@ interface Selection {
function onKey(evt: KeyboardEvent): void { function onKey(evt: KeyboardEvent): void {
// esc clears focus, allowing dialog to close // esc clears focus, allowing dialog to close
if (evt.code === "Escape") { if (evt.code === "Escape") {
currentField.blurEditingArea(); currentField.blurEditable();
return; return;
} }
@ -91,7 +91,7 @@ function onKeyUp(evt: KeyboardEvent): void {
if ( if (
nodeIsElement(anchor) && nodeIsElement(anchor) &&
anchor.tagName === "DIV" && anchor.tagName === "DIV" &&
!(anchor instanceof EditingContainer) && !(anchor instanceof EditingArea) &&
anchor.childElementCount === 1 && anchor.childElementCount === 1 &&
anchor.children[0].tagName === "BR" anchor.children[0].tagName === "BR"
) { ) {
@ -249,12 +249,12 @@ function clearChangeTimer(): void {
} }
function onFocus(evt: FocusEvent): void { function onFocus(evt: FocusEvent): void {
const elem = evt.currentTarget as EditingContainer; const elem = evt.currentTarget as EditingArea;
if (currentField === elem) { if (currentField === elem) {
// anki window refocused; current element unchanged // anki window refocused; current element unchanged
return; return;
} }
elem.focusEditingArea(); elem.focusEditable();
currentField = elem; currentField = elem;
pycmd(`focus:${currentField.ord}`); pycmd(`focus:${currentField.ord}`);
enableButtons(); enableButtons();
@ -280,19 +280,19 @@ function onFocus(evt: FocusEvent): void {
} }
function focusField(n: number): void { function focusField(n: number): void {
const field = document.getElementById(`f${n}`) as EditingContainer; const field = document.getElementById(`f${n}`) as EditingArea;
if (field) { if (field) {
field.focusEditingArea(); field.focusEditable();
} }
} }
function focusIfField(x: number, y: number): boolean { function focusIfField(x: number, y: number): boolean {
const elements = document.elementsFromPoint(x, y); const elements = document.elementsFromPoint(x, y);
for (let i = 0; i < elements.length; i++) { for (let i = 0; i < elements.length; i++) {
let elem = elements[i] as EditingContainer; let elem = elements[i] as EditingArea;
if (elem instanceof EditingContainer) { if (elem instanceof EditingArea) {
elem.focusEditingArea(); elem.focusEditable();
// the focus event may not fire if the window is not active, so make sure // the focus event may not fire if the window is not active, so make sure
// the current field is set // the current field is set
currentField = elem; currentField = elem;
@ -309,7 +309,7 @@ function onPaste(): void {
function caretToEnd(): void { function caretToEnd(): void {
const range = document.createRange(); const range = document.createRange();
range.selectNodeContents(currentField.editingArea); range.selectNodeContents(currentField.editable);
range.collapse(false); range.collapse(false);
const selection = currentField.getSelection(); const selection = currentField.getSelection();
selection.removeAllRanges(); selection.removeAllRanges();
@ -379,7 +379,7 @@ function enableButtons(): void {
// disable the buttons if a field is not currently focused // disable the buttons if a field is not currently focused
function maybeDisableButtons(): void { function maybeDisableButtons(): void {
if (document.activeElement instanceof EditingContainer) { if (document.activeElement instanceof EditingArea) {
enableButtons(); enableButtons();
} else { } else {
disableButtons(); disableButtons();
@ -423,7 +423,7 @@ function onCutOrCopy(): boolean {
return true; return true;
} }
class EditingArea extends HTMLElement { class Editable extends HTMLElement {
set fieldHTML(content: string) { set fieldHTML(content: string) {
this.innerHTML = content; this.innerHTML = content;
@ -443,10 +443,10 @@ class EditingArea extends HTMLElement {
} }
} }
customElements.define("editing-area", EditingArea); customElements.define("anki-editable", Editable);
class EditingContainer extends HTMLDivElement { class EditingArea extends HTMLDivElement {
editingArea: EditingArea; editable: Editable;
baseStyle: HTMLStyleElement; baseStyle: HTMLStyleElement;
constructor() { constructor() {
@ -456,15 +456,15 @@ class EditingContainer extends HTMLDivElement {
const rootStyle = document.createElement("link"); const rootStyle = document.createElement("link");
rootStyle.setAttribute("rel", "stylesheet"); rootStyle.setAttribute("rel", "stylesheet");
rootStyle.setAttribute("href", "./_anki/css/editing-area.css"); rootStyle.setAttribute("href", "./_anki/css/editable.css");
this.shadowRoot.appendChild(rootStyle); this.shadowRoot.appendChild(rootStyle);
this.baseStyle = document.createElement("style"); this.baseStyle = document.createElement("style");
this.baseStyle.setAttribute("rel", "stylesheet"); this.baseStyle.setAttribute("rel", "stylesheet");
this.shadowRoot.appendChild(this.baseStyle); this.shadowRoot.appendChild(this.baseStyle);
this.editingArea = document.createElement("editing-area") as EditingArea; this.editable = document.createElement("anki-editable") as Editable;
this.shadowRoot.appendChild(this.editingArea); this.shadowRoot.appendChild(this.editable);
} }
get ord(): number { get ord(): number {
@ -472,11 +472,11 @@ class EditingContainer extends HTMLDivElement {
} }
set fieldHTML(content: string) { set fieldHTML(content: string) {
this.editingArea.fieldHTML = content; this.editable.fieldHTML = content;
} }
get fieldHTML(): string { get fieldHTML(): string {
return this.editingArea.fieldHTML; return this.editable.fieldHTML;
} }
connectedCallback(): void { connectedCallback(): void {
@ -490,7 +490,7 @@ class EditingContainer extends HTMLDivElement {
this.addEventListener("oncut", onCutOrCopy); this.addEventListener("oncut", onCutOrCopy);
const baseStyleSheet = this.baseStyle.sheet as CSSStyleSheet; const baseStyleSheet = this.baseStyle.sheet as CSSStyleSheet;
baseStyleSheet.insertRule("editing-area {}", 0); baseStyleSheet.insertRule("anki-editable {}", 0);
} }
disconnectedCallback(): void { disconnectedCallback(): void {
@ -506,7 +506,7 @@ class EditingContainer extends HTMLDivElement {
initialize(color: string, content: string): void { initialize(color: string, content: string): void {
this.setBaseColor(color); this.setBaseColor(color);
this.editingArea.fieldHTML = content; this.editable.fieldHTML = content;
} }
setBaseColor(color: string): void { setBaseColor(color: string): void {
@ -524,28 +524,28 @@ class EditingContainer extends HTMLDivElement {
} }
isRightToLeft(): boolean { isRightToLeft(): boolean {
return this.editingArea.style.direction === "rtl"; return this.editable.style.direction === "rtl";
} }
getSelection(): Selection { getSelection(): Selection {
return this.shadowRoot.getSelection(); return this.shadowRoot.getSelection();
} }
focusEditingArea(): void { focusEditable(): void {
this.editingArea.focus(); this.editable.focus();
} }
blurEditingArea(): void { blurEditable(): void {
this.editingArea.blur(); this.editable.blur();
} }
} }
customElements.define("editing-container", EditingContainer, { extends: "div" }); customElements.define("anki-editing-area", EditingArea, { extends: "div" });
class EditorField extends HTMLDivElement { class EditorField extends HTMLDivElement {
labelContainer: HTMLDivElement; labelContainer: HTMLDivElement;
label: HTMLSpanElement; label: HTMLSpanElement;
editingContainer: EditingContainer; editingArea: EditingArea;
constructor() { constructor() {
super(); super();
@ -557,10 +557,10 @@ class EditorField extends HTMLDivElement {
this.label.className = "fieldname"; this.label.className = "fieldname";
this.labelContainer.appendChild(this.label); this.labelContainer.appendChild(this.label);
this.editingContainer = document.createElement("div", { this.editingArea = document.createElement("div", {
is: "editing-container", is: "anki-editing-area",
}) as EditingContainer; }) as EditingArea;
this.appendChild(this.editingContainer); this.appendChild(this.editingArea);
} }
static get observedAttributes(): string[] { static get observedAttributes(): string[] {
@ -574,28 +574,28 @@ class EditorField extends HTMLDivElement {
attributeChangedCallback(name: string, _oldValue: string, newValue: string): void { attributeChangedCallback(name: string, _oldValue: string, newValue: string): void {
switch (name) { switch (name) {
case "ord": case "ord":
this.editingContainer.setAttribute("ord", newValue); this.editingArea.setAttribute("ord", newValue);
} }
} }
initialize(label: string, color: string, content: string): void { initialize(label: string, color: string, content: string): void {
this.label.innerText = label; this.label.innerText = label;
this.editingContainer.initialize(color, content); this.editingArea.initialize(color, content);
} }
setBaseStyling(fontFamily: string, fontSize: string, direction: string): void { setBaseStyling(fontFamily: string, fontSize: string, direction: string): void {
this.editingContainer.setBaseStyling(fontFamily, fontSize, direction); this.editingArea.setBaseStyling(fontFamily, fontSize, direction);
} }
} }
customElements.define("editor-field", EditorField, { extends: "div" }); customElements.define("anki-editor-field", EditorField, { extends: "div" });
function adjustFieldAmount(amount: number): void { function adjustFieldAmount(amount: number): void {
const fieldsContainer = document.getElementById("fields"); const fieldsContainer = document.getElementById("fields");
while (fieldsContainer.childElementCount < amount) { while (fieldsContainer.childElementCount < amount) {
const newField = document.createElement("div", { const newField = document.createElement("div", {
is: "editor-field", is: "anki-editor-field",
}) as EditorField; }) as EditorField;
newField.ord = fieldsContainer.childElementCount; newField.ord = fieldsContainer.childElementCount;
fieldsContainer.appendChild(newField); fieldsContainer.appendChild(newField);
@ -634,7 +634,7 @@ function setFields(fields: [string, string][]): void {
function setBackgrounds(cols: ("dupe" | "")[]) { function setBackgrounds(cols: ("dupe" | "")[]) {
forEditorField(cols, (field, value) => forEditorField(cols, (field, value) =>
field.editingContainer.classList.toggle("dupe", value === "dupe") field.editingArea.classList.toggle("dupe", value === "dupe")
); );
document document
.querySelector("#dupes") .querySelector("#dupes")