Working label as an editor entry type
This commit is contained in:
53
Editor.js
53
Editor.js
@@ -1,16 +1,15 @@
|
||||
<!--# include file="List.js" -->
|
||||
|
||||
class Editor extends List {
|
||||
static NODE = 1;
|
||||
static GROUP = 2;
|
||||
static LINK = 3;
|
||||
static LABEL = 4;
|
||||
|
||||
constructor(container, allowedTypes) {
|
||||
constructor(container, limitsByType) {
|
||||
super(container);
|
||||
|
||||
this.allowedTypes_ = new Set(allowedTypes ||
|
||||
[Editor.NODE, Editor.GROUP, Editor.LINK]);
|
||||
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
|
||||
@@ -24,10 +23,10 @@ class Editor extends List {
|
||||
this.container_.innerHTML = '';
|
||||
}
|
||||
|
||||
serialize() {
|
||||
serialize(type) {
|
||||
// Doesn't have a type, only used as part of other objects
|
||||
let ret = [];
|
||||
for (let entry of this.getEntries()) {
|
||||
for (let entry of this.getEntries(type)) {
|
||||
ret.push(entry.serialize());
|
||||
}
|
||||
return ret;
|
||||
@@ -39,60 +38,72 @@ class Editor extends List {
|
||||
}
|
||||
}
|
||||
|
||||
isAllowed(type) {
|
||||
return this.mayAdd() && this.allowedTypes_.has(type);
|
||||
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.isAllowed(Editor.NODE)) {
|
||||
if (this.mayAdd(EditorNode)) {
|
||||
EditorNode.addAfter(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addNodeBefore() {
|
||||
if (this.isAllowed(Editor.NODE)) {
|
||||
if (this.mayAdd(EditorNode)) {
|
||||
EditorNode.addBefore(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addLabelBefore() {
|
||||
if (this.isAllowed(Editor.LABEL)) {
|
||||
if (this.mayAdd(EditorLabel)) {
|
||||
EditorLabel.addBefore(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addLabelAfter() {
|
||||
if (this.isAllowed(Editor.LABEL)) {
|
||||
if (this.mayAdd(EditorLabel)) {
|
||||
EditorLabel.addAfter(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addLinkBefore() {
|
||||
if (this.isAllowed(Editor.LINK)) {
|
||||
if (this.mayAdd(EditorLink)) {
|
||||
EditorLink.addBefore(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addLinkAfter() {
|
||||
if (this.isAllowed(Editor.LINK)) {
|
||||
if (this.mayAdd(EditorLink)) {
|
||||
EditorLink.addAfter(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addLinkBefore() {
|
||||
if (this.isAllowed(Editor.LINK)) {
|
||||
if (this.mayAdd(EditorLink)) {
|
||||
EditorLink.addBefore(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addGroupAfter() {
|
||||
if (this.isAllowed(Editor.GROUP)) {
|
||||
if (this.mayAdd(EditorGroup)) {
|
||||
EditorGroup.addAfter(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
addGroupBefore() {
|
||||
if (this.isAllowed(Editor.GROUP)) {
|
||||
if (this.mayAdd(EditorGroup)) {
|
||||
EditorGroup.addBefore(this.container_, this.getSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ class EditorGroup extends EditorEntryBase {
|
||||
this.elem_.classList.add('group');
|
||||
|
||||
let nodeList = document.createElement('div');
|
||||
this.nodes_ = new Editor(nodeList, [Editor.NODE, Editor.LABEL]);
|
||||
this.nodes_.setMinEntries(1);
|
||||
this.nodes_ = new Editor(nodeList, [
|
||||
[EditorNode, [1, Number.POSITIVE_INFINITY]],
|
||||
[EditorLabel, [0, 1]],
|
||||
]);
|
||||
this.nodes_.addNodeAfter();
|
||||
this.elem_.appendChild(nodeList);
|
||||
}
|
||||
@@ -21,7 +23,7 @@ class EditorGroup extends EditorEntryBase {
|
||||
return {
|
||||
type: 'group',
|
||||
label: this.getLabel(),
|
||||
members: this.nodes_.serialize(),
|
||||
members: this.nodes_.serialize(EditorNode),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,18 +47,22 @@ class EditorGroup extends EditorEntryBase {
|
||||
}
|
||||
|
||||
getNodes() {
|
||||
return this.nodes_.getEntries();
|
||||
return this.nodes_.getEntries(EditorNode);
|
||||
}
|
||||
|
||||
getLabel() {
|
||||
// TODO
|
||||
return '';
|
||||
let label = this.nodes_.getEntries(EditorLabel)[0];
|
||||
return label ? label.getLabel() : null;
|
||||
}
|
||||
|
||||
setLabel(label) {
|
||||
// TODO
|
||||
//this.input_.value = label;
|
||||
//this.input_.setAttribute('data-arch-value', this.input_.value);
|
||||
let obj = this.nodes_.getEntries(EditorLabel)[0];
|
||||
if (obj) {
|
||||
obj.setLabel(label);
|
||||
} else {
|
||||
this.nodes_.addLabelBefore();
|
||||
this.setLabel(label);
|
||||
}
|
||||
}
|
||||
|
||||
getElement() {
|
||||
@@ -79,8 +85,8 @@ class EditorGroup extends EditorEntryBase {
|
||||
|
||||
static unserialize(ser) {
|
||||
let group = new EditorGroup();
|
||||
group.setLabel(ser.label);
|
||||
group.nodes_.clear();
|
||||
group.setLabel(ser.label);
|
||||
group.nodes_.unserialize(ser.members);
|
||||
return group.getElement();
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@ class EditorLink extends EditorEntryBase {
|
||||
this.elem_.classList.add('link');
|
||||
|
||||
let nodeList = document.createElement('div');
|
||||
this.nodes_ = new Editor(nodeList, [Editor.NODE]);
|
||||
this.nodes_.setMinEntries(2);
|
||||
this.nodes_.setMaxEntries(2);
|
||||
this.nodes_ = new Editor(nodeList, [
|
||||
[EditorNode, [2, 2]],
|
||||
[EditorLabel, [0, 1]],
|
||||
]);
|
||||
this.nodes_.addNodeAfter();
|
||||
this.nodes_.addNodeAfter();
|
||||
this.elem_.appendChild(nodeList);
|
||||
@@ -49,21 +50,26 @@ class EditorLink extends EditorEntryBase {
|
||||
};
|
||||
|
||||
getFrom() {
|
||||
return this.nodes_.getEntries()[0];
|
||||
return this.nodes_.getEntries(EditorNode)[0];
|
||||
}
|
||||
|
||||
getTo() {
|
||||
return this.nodes_.getEntries()[1];
|
||||
return this.nodes_.getEntries(EditorNode)[1];
|
||||
}
|
||||
|
||||
getLabel() {
|
||||
// TODO
|
||||
return '';
|
||||
let label = this.nodes_.getEntries(EditorLabel)[0];
|
||||
return label ? label.getLabel() : null;
|
||||
}
|
||||
|
||||
setLabel(label) {
|
||||
// TODO
|
||||
//this.input_.setAttribute('data-arch-value', this.input_.value);
|
||||
let obj = this.nodes_.getEntries(EditorLabel)[0];
|
||||
if (obj) {
|
||||
obj.setLabel(label);
|
||||
} else {
|
||||
this.nodes_.addLabelBefore();
|
||||
this.setLabel(label);
|
||||
}
|
||||
}
|
||||
|
||||
getElement() {
|
||||
@@ -86,8 +92,8 @@ class EditorLink extends EditorEntryBase {
|
||||
|
||||
static unserialize(ser) {
|
||||
let link = new EditorLink();
|
||||
link.setLabel(ser.label);
|
||||
link.nodes_.clear();
|
||||
link.setLabel(ser.label);
|
||||
link.nodes_.unserialize([ser.from, ser.to]);
|
||||
return link.getElement();
|
||||
}
|
||||
|
||||
29
List.js
29
List.js
@@ -1,30 +1,19 @@
|
||||
class List {
|
||||
constructor(container) {
|
||||
this.container_ = container;
|
||||
this.minEntries_ = 0;
|
||||
this.maxEntries_ = Number.MAX_SAFE_INTEGER;
|
||||
}
|
||||
|
||||
setMinEntries(min) {
|
||||
this.minEntries_ = min;
|
||||
}
|
||||
|
||||
setMaxEntries(max) {
|
||||
this.maxEntries_ = max;
|
||||
}
|
||||
|
||||
getEntries() {
|
||||
getEntries(type) {
|
||||
let ret = [];
|
||||
for (let elem of this.container_.children) {
|
||||
if (type && !(elem.xArchObj instanceof type)) {
|
||||
continue;
|
||||
}
|
||||
ret.push(elem.xArchObj);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
mayAdd() {
|
||||
return this.container_.children.length < this.maxEntries_;
|
||||
}
|
||||
|
||||
getSelected() {
|
||||
let iter = document.activeElement;
|
||||
while (iter) {
|
||||
@@ -36,12 +25,13 @@ class List {
|
||||
return null;
|
||||
}
|
||||
|
||||
mayDelete(type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
deleteSelected() {
|
||||
if (this.container_.children.length <= this.minEntries_) {
|
||||
return;
|
||||
}
|
||||
let sel = this.getSelected();
|
||||
if (sel) {
|
||||
if (sel && this.mayDelete(sel.xArchObj.constructor)) {
|
||||
sel.xArchObj.remove();
|
||||
}
|
||||
}
|
||||
@@ -49,6 +39,7 @@ class List {
|
||||
deleteSelectedAndAfter() {
|
||||
let sel = this.getSelected();
|
||||
if (sel) {
|
||||
// TODO: fix to obey mayDelete()
|
||||
while (this.container_.lastElementChild != sel &&
|
||||
this.container_.children.length > this.minEntries_) {
|
||||
this.container_.lastElementChild.xArchObj.remove();
|
||||
|
||||
@@ -173,10 +173,9 @@ body {
|
||||
|
||||
.gridGroupLabel {
|
||||
width: calc(100% - 10px);
|
||||
height: 100%;
|
||||
height: calc(100% - 10px);
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
padding-top: 3px;
|
||||
overflow: hidden;
|
||||
overflow-wrap: anywhere;
|
||||
z-index: 1;
|
||||
|
||||
Reference in New Issue
Block a user