class Editor extends List { constructor(container, limitsByType) { super(container); this.limitsByType_ = new Map(limitsByType || [ [EditorNode, [0, Number.POSITIVE_INFINITY]], [EditorGroup, [0, Number.POSITIVE_INFINITY]], [EditorLink, [0, Number.POSITIVE_INFINITY]], [EditorLabel, [0, 1]], ]); this.container_.classList.add('editor'); // Needs to accept focus to receive keydown, but shouldn't be in the normal // tab flow. this.container_.tabIndex = 99999; this.container_.addEventListener('keydown', e => { this.onKeyDown(e); }); this.container_.focus(); } clear() { this.container_.innerHTML = ''; } serialize(type) { // Doesn't have a type, only used as part of other objects let ret = []; for (let entry of this.getEntries(type)) { ret.push(entry.serialize()); } return ret; } unserialize(ser) { for (let entry of ser) { this.container_.appendChild(EditorEntryBase.unserialize(entry)); } } mayAdd(type) { let limits = this.limitsByType_.get(type); if (!limits) { return false; } return this.getEntries(type).length < limits[1]; } mayDelete(type) { let limits = this.limitsByType_.get(type); if (!limits) { return false; } return this.getEntries(type).length > limits[0]; } addNodeAfter() { if (this.mayAdd(EditorNode)) { EditorNode.addAfter(this.container_, this.getSelected()); } } addNodeBefore() { if (this.mayAdd(EditorNode)) { EditorNode.addBefore(this.container_, this.getSelected()); } } addLabelBefore() { if (this.mayAdd(EditorLabel)) { EditorLabel.addBefore(this.container_, this.getSelected()); } } addLabelAfter() { if (this.mayAdd(EditorLabel)) { EditorLabel.addAfter(this.container_, this.getSelected()); } } addLinkBefore() { if (this.mayAdd(EditorLink)) { EditorLink.addBefore(this.container_, this.getSelected()); } } addLinkAfter() { if (this.mayAdd(EditorLink)) { EditorLink.addAfter(this.container_, this.getSelected()); } } addLinkBefore() { if (this.mayAdd(EditorLink)) { EditorLink.addBefore(this.container_, this.getSelected()); } } addGroupAfter() { if (this.mayAdd(EditorGroup)) { EditorGroup.addAfter(this.container_, this.getSelected()); } } addGroupBefore() { if (this.mayAdd(EditorGroup)) { EditorGroup.addBefore(this.container_, this.getSelected()); } } onKeyDown(e) { switch (e.key) { case 'a': this.addLabelAfter(); e.stopPropagation(); e.preventDefault(); return; case 'A': this.addLabelBefore(); e.stopPropagation(); e.preventDefault(); return; case 'g': this.addGroupAfter(); e.stopPropagation(); e.preventDefault(); return; case 'G': this.addGroupBefore(); e.stopPropagation(); e.preventDefault(); return; case 'i': this.addLinkAfter(); e.stopPropagation(); e.preventDefault(); return; case 'I': this.addLinkBefore(); e.stopPropagation(); e.preventDefault(); return; case 'n': this.addNodeAfter(); e.stopPropagation(); e.preventDefault(); return; case 'N': this.addNodeBefore(); e.stopPropagation(); e.preventDefault(); return; } super.onKeyDown(e); } }