2019-07-03 01:42:17 +00:00
|
|
|
<!--# include file="List.js" -->
|
|
|
|
|
|
|
|
|
|
class Editor extends List {
|
2019-07-10 08:14:53 +00:00
|
|
|
constructor(container, limitsByType) {
|
2019-07-03 01:42:17 +00:00
|
|
|
super(container);
|
|
|
|
|
|
2019-07-10 08:14:53 +00:00
|
|
|
this.limitsByType_ = new Map(limitsByType || [
|
|
|
|
|
[EditorNode, [0, Number.POSITIVE_INFINITY]],
|
|
|
|
|
[EditorGroup, [0, Number.POSITIVE_INFINITY]],
|
|
|
|
|
[EditorLink, [0, Number.POSITIVE_INFINITY]],
|
|
|
|
|
[EditorLabel, [0, 1]],
|
2019-07-10 21:32:52 +00:00
|
|
|
[EditorHelp, [0, Number.POSITIVE_INFINITY]],
|
2019-07-10 08:14:53 +00:00
|
|
|
]);
|
2019-07-03 01:42:17 +00:00
|
|
|
|
|
|
|
|
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 = '';
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-10 08:14:53 +00:00
|
|
|
serialize(type) {
|
2019-07-03 01:42:17 +00:00
|
|
|
// Doesn't have a type, only used as part of other objects
|
|
|
|
|
let ret = [];
|
2019-07-10 08:14:53 +00:00
|
|
|
for (let entry of this.getEntries(type)) {
|
2019-07-03 01:42:17 +00:00
|
|
|
ret.push(entry.serialize());
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unserialize(ser) {
|
|
|
|
|
for (let entry of ser) {
|
2019-07-10 21:32:52 +00:00
|
|
|
let elem = EditorEntryBase.unserialize(entry);
|
|
|
|
|
if (elem) {
|
|
|
|
|
this.container_.appendChild(elem);
|
|
|
|
|
} else {
|
|
|
|
|
console.log('failed to unserialize', entry);
|
|
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-10 08:14:53 +00:00
|
|
|
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];
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-11 04:25:06 +00:00
|
|
|
addNodeAfter(...rest) {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorNode)) {
|
2019-07-11 04:25:06 +00:00
|
|
|
EditorNode.addAfter(this.container_, this.getSelected(), ...rest);
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-11 04:25:06 +00:00
|
|
|
addNodeBefore(...rest) {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorNode)) {
|
2019-07-11 04:25:06 +00:00
|
|
|
EditorNode.addBefore(this.container_, this.getSelected(), ...rest);
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-10 04:09:54 +00:00
|
|
|
addLabelBefore() {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorLabel)) {
|
2019-07-10 04:09:54 +00:00
|
|
|
EditorLabel.addBefore(this.container_, this.getSelected());
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-10 04:09:54 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-10 04:09:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addLabelAfter() {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorLabel)) {
|
2019-07-10 04:09:54 +00:00
|
|
|
EditorLabel.addAfter(this.container_, this.getSelected());
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-10 04:09:54 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-10 04:09:54 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-03 01:42:17 +00:00
|
|
|
addLinkAfter() {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorLink)) {
|
2019-07-11 04:40:43 +00:00
|
|
|
EditorLink.addAfter(this.container_, this.getSelected(),
|
|
|
|
|
this.queryEntries('.highlight', EditorNode));
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addLinkBefore() {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorLink)) {
|
2019-07-11 04:40:43 +00:00
|
|
|
EditorLink.addBefore(this.container_, this.getSelected(),
|
|
|
|
|
this.queryEntries('.highlight', EditorNode));
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addGroupAfter() {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorGroup)) {
|
2019-07-11 04:25:06 +00:00
|
|
|
EditorGroup.addAfter(this.container_, this.getSelected(),
|
|
|
|
|
this.queryEntries('.highlight', EditorNode));
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addGroupBefore() {
|
2019-07-10 08:14:53 +00:00
|
|
|
if (this.mayAdd(EditorGroup)) {
|
2019-07-11 04:25:06 +00:00
|
|
|
EditorGroup.addBefore(this.container_, this.getSelected(),
|
|
|
|
|
this.queryEntries('.highlight', EditorNode));
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
2019-07-10 21:32:52 +00:00
|
|
|
|
|
|
|
|
addHelpAfter() {
|
|
|
|
|
if (this.mayAdd(EditorHelp)) {
|
|
|
|
|
EditorHelp.addAfter(this.container_, this.getSelected());
|
2019-07-11 19:58:22 +00:00
|
|
|
return true;
|
2019-07-10 21:32:52 +00:00
|
|
|
}
|
2019-07-11 19:58:22 +00:00
|
|
|
return false;
|
2019-07-10 21:32:52 +00:00
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
|
|
|
|
|
onKeyDown(e) {
|
|
|
|
|
switch (e.key) {
|
2019-07-10 04:09:54 +00:00
|
|
|
case 'a':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addLabelAfter()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-10 04:09:54 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 'A':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addLabelBefore()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-10 04:09:54 +00:00
|
|
|
return;
|
|
|
|
|
|
2019-07-03 01:42:17 +00:00
|
|
|
case 'g':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addGroupAfter()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 'G':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addGroupBefore()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 'i':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addLinkAfter()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 'I':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addLinkBefore()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 'n':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addNodeAfter()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 'N':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addNodeBefore()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
return;
|
2019-07-10 21:32:52 +00:00
|
|
|
|
|
|
|
|
case '?':
|
2019-07-11 19:58:22 +00:00
|
|
|
if (this.addHelpAfter()) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
2019-07-10 21:32:52 +00:00
|
|
|
return;
|
2019-07-11 04:28:55 +00:00
|
|
|
|
|
|
|
|
case 'Escape':
|
2019-07-11 19:50:35 +00:00
|
|
|
case '`':
|
2019-07-11 04:40:43 +00:00
|
|
|
if (!this.container_.parentElement.xArchObj) {
|
|
|
|
|
for (let entry of this.queryEntries('.highlight')) {
|
|
|
|
|
entry.getElement().classList.toggle('highlight', false);
|
|
|
|
|
}
|
2019-07-11 04:44:33 +00:00
|
|
|
this.container_.setAttribute('data-arch-refresh', '');
|
2019-07-11 04:40:43 +00:00
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
return;
|
2019-07-11 04:28:55 +00:00
|
|
|
}
|
2019-07-03 01:42:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
super.onKeyDown(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-10 04:09:54 +00:00
|
|
|
|
|
|
|
|
<!--# include file="EditorEntryBase.js" -->
|
|
|
|
|
<!--# include file="EditorGroup.js" -->
|
2019-07-10 21:32:52 +00:00
|
|
|
<!--# include file="EditorHelp.js" -->
|
2019-07-10 04:09:54 +00:00
|
|
|
<!--# include file="EditorLabel.js" -->
|
|
|
|
|
<!--# include file="EditorLink.js" -->
|
|
|
|
|
<!--# include file="EditorNode.js" -->
|