Remove mootools as dependency.

This commit is contained in:
Paulo Veiga
2021-12-14 17:06:09 +00:00
parent 25b86f3cff
commit 75a153d1d5
47 changed files with 255 additions and 1107 deletions

View File

@ -8,12 +8,6 @@
"airbnb-base",
"plugin:cypress/recommended"
],
"globals":{
"Class": "readonly",
"$": "readonly",
"$msg": "readonly",
"_": "readonly"
},
"plugins": ["only-warn"],
"rules": {
"no-underscore-dangle": "off",

View File

@ -34,8 +34,7 @@
"@wisemapping/core-js": "^0.0.1",
"@wisemapping/web2d": "^0.0.1",
"jest": "^27.4.3",
"jquery": "^3.6.0",
"mootools": "1.4.5"
"jquery": "^3.6.0"
},
"devDependencies": {
"@babel/core": "^7.14.6",

View File

@ -16,6 +16,7 @@
* limitations under the License.
*/
import { $assert, $defined } from "@wisemapping/core-js";
import EventBus from "./layout/EventBus";
class CommandContext {
constructor(designer) {
@ -31,7 +32,7 @@ class CommandContext {
}
const designerTopics = this._designer.getModel().getTopics();
const result = designerTopics.filter((topic) => topicsIds.contains(topic.getId()));
const result = designerTopics.filter((topic) => topicsIds.includes(topic.getId()));
if (result.length !== topicsIds.length) {
const ids = designerTopics.map((topic) => topic.getId());
@ -98,7 +99,7 @@ class CommandContext {
}
const designerRel = this._designer.getModel().getRelationships();
return designerRel.filter((rel) => relIds.contains(rel.getId()));
return designerRel.filter((rel) => relIds.includes(rel.getId()));
}
/** */

View File

@ -78,10 +78,10 @@ class ControlPoint {
this._createControlPoint();
this._endPoint = [];
this._orignalCtrlPoint = [];
this._orignalCtrlPoint[0] = this._controls[0].clone();
this._orignalCtrlPoint[1] = this._controls[1].clone();
this._endPoint[0] = this._line.getLine().getFrom().clone();
this._endPoint[1] = this._line.getLine().getTo().clone();
this._orignalCtrlPoint[0] = { ...this._controls[0] };
this._orignalCtrlPoint[1] = { ...this._controls[1] };
this._endPoint[0] = { ...this._line.getLine().getFrom() };
this._endPoint[1] = { ...this._line.getLine().getTo() };
}
redraw() {

View File

@ -240,7 +240,7 @@ class DesignerKeyboard extends Keyboard {
$(document).on('keypress', (event) => {
let keyCode;
// Firefox doesn't skip special keys for keypress event...
if (event.key && excludes.contains(event.key.toLowerCase())) {
if (event.key && excludes.includes(event.key.toLowerCase())) {
return;
}
// Sometimes Firefox doesn't contain keyCode value

View File

@ -81,8 +81,8 @@ class DesignerModel extends Events {
* @return {Array.<mindplot.Relationship, mindplot.Topic>} all topics and relationships
*/
getEntities() {
const result = [].append(this._topics);
result.append(this._relationships);
let result = [].concat(this._topics);
result = result.concat(this._relationships);
return result;
}
@ -92,7 +92,7 @@ class DesignerModel extends Events {
*/
removeTopic(topic) {
$assert(topic, 'topic can not be null');
this._topics.erase(topic);
this._topics = this._topics.filter((t) => t !== topic);
}
/**
@ -101,7 +101,7 @@ class DesignerModel extends Events {
*/
removeRelationship(rel) {
$assert(rel, 'rel can not be null');
this._relationships.erase(rel);
this._relationships = this._relationships.filter((r) => r !== rel);
}
/**

View File

@ -59,8 +59,8 @@ class DragConnector {
// - Nodes that are collapsed
// - It's not part of the branch dragged itself
topics = topics.filter((topic) => {
let result = draggedNode != topic;
result = result && topic != draggedNode;
let result = draggedNode !== topic;
result = result && topic !== draggedNode;
result = result && !topic.areChildrenShrunken() && !topic.isCollapsed();
result = result && !draggedNode.isChildTopic(topic);
return result;

View File

@ -25,16 +25,24 @@ class Events {
return string.replace(/^on([A-Z])/, (full, first) => first.toLowerCase());
}
addEvent(type, fn, internal) {
type = Events._removeOn(type);
addEvent(typeName, fn, internal) {
const type = Events._removeOn(typeName);
this.$events[type] = (this.$events[type] || []).include(fn);
if (internal) fn.internal = true;
// Add function had not been added yet
const funByType = this.$events[type] ? this.$events[type] : [];
if (!funByType.includes(fn)) {
funByType.push(fn);
this.$events[type] = funByType;
}
// Mark reference ...
// eslint-disable-next-line no-param-reassign
fn.internal = Boolean(internal);
return this;
}
fireEvent(type, args, delay) {
type = Events._removeOn(type);
fireEvent(typeName, args, delay) {
const type = Events._removeOn(typeName);
const events = this.$events[type];
if (!events) return this;
@ -42,16 +50,15 @@ class Events {
events.forEach(((fn) => {
if (delay) {
fn.delay(delay, this, args);
}
else {
} else {
fn.apply(this, args);
}
}).bind(this));
}));
return this;
}
removeEvent(type, fn) {
type = Events._removeOn(type);
removeEvent(typeName, fn) {
const type = Events._removeOn(typeName);
const events = this.$events[type];
if (events && !fn.internal) {
const index = events.indexOf(fn);

View File

@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// eslint-disable-next-line max-classes-per-file
import { $assert, $defined } from '@wisemapping/core-js';
import * as web2d from '@wisemapping/web2d';
import IconGroupRemoveTip from './IconGroupRemoveTip';
@ -22,14 +23,6 @@ import IconGroupRemoveTip from './IconGroupRemoveTip';
import Icon from './Icon';
class IconGroup {
/** @lends IconGroup */
/**
* @constructs
* @param topicId
* @param iconSize
* @throws will throw an error if topicId is null or undefined
* @throws will throw an error if iconSize is null or undefined
*/
constructor(topicId, iconSize) {
$assert($defined(topicId), 'topicId can not be null');
$assert($defined(iconSize), 'iconSize can not be null');
@ -43,7 +36,7 @@ class IconGroup {
coordSizeWidth: 0,
coordSizeHeight: 100,
});
this._removeTip = new IconGroup.RemoveTip(this._group, topicId);
this._removeTip = new IconGroupRemoveTip(this._group, topicId);
this.seIconSize(iconSize, iconSize);
this._registerListeners();
@ -76,10 +69,10 @@ class IconGroup {
}
/**
* @param icon the icon to be added to the icon group
* @param {Boolean} remove
* @throws will throw an error if icon is not defined
*/
* @param icon the icon to be added to the icon group
* @param {Boolean} remove
* @throws will throw an error if icon is not defined
*/
addIcon(icon, remove) {
$defined(icon, 'icon is not defined');
@ -111,7 +104,7 @@ class IconGroup {
});
if (result == null) {
throw new Error(`Icon can no be found:${iconModel.getId()}, Icons:${this._icons}`);
throw new Error(`Icon can no be found:${iconModel.getId()} Icons:${this._icons}`);
}
return result;
@ -131,7 +124,7 @@ class IconGroup {
this._removeTip.close(0);
this._group.removeChild(icon.getImage());
this._icons.erase(icon);
this._icons = this._icons.filter((i) => i !== icon);
this._resize(this._icons.length);
const me = this;
@ -164,7 +157,6 @@ class IconGroup {
this._group.setCoordSize(iconsLength * iconSize, iconSize);
}
// eslint-disable-next-line class-methods-use-this
_positionIcon(icon, order) {
const iconSize = Icon.SIZE + IconGroup.ICON_PADDING * 2;
icon.getImage().setPosition(
@ -181,6 +173,4 @@ class IconGroup {
*/
IconGroup.ICON_PADDING = 5;
IconGroup.RemoveTip = IconGroupRemoveTip;
export default IconGroup;

View File

@ -22,7 +22,7 @@ export default class RemoveTip {
$assert(icon, 'icon can not be null');
// Nothing to do ...
if (this._activeIcon != icon) {
if (this._activeIcon !== icon) {
// If there is an active icon, close it first ...
if (this._activeIcon) {
this.close(0);
@ -82,10 +82,10 @@ export default class RemoveTip {
me._closeTimeoutId = null;
};
if (!$defined(delay) || delay == 0) {
if (!$defined(delay) || delay === 0) {
close();
} else {
this._closeTimeoutId = close.delay(delay);
this._closeTimeoutId = $(close).delay(delay);
}
}
}

View File

@ -1,10 +1,14 @@
class Options {
setOptions() {
const options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
setOptions(...args) {
this.options = { ...this.options, ...args };
const { options } = this;
if (this.addEvent) {
for (const option in options) {
if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
if (typeof (options[option]) != 'function' || !(/^on[A-Z]/).test(option) ){
continue;
}
this.addEvent(option, options[option]);
delete options[option];
}

View File

@ -65,11 +65,11 @@ class Relationship extends ConnectionLine {
// Position the line ...
if ($defined(model.getSrcCtrlPoint())) {
const srcPoint = model.getSrcCtrlPoint().clone();
const srcPoint = { ...model.getSrcCtrlPoint() };
this.setSrcControlPoint(srcPoint);
}
if ($defined(model.getDestCtrlPoint())) {
const destPoint = model.getDestCtrlPoint().clone();
const destPoint = { ...model.getDestCtrlPoint() };
this.setDestControlPoint(destPoint);
}
}

View File

@ -355,7 +355,7 @@ class Topic extends NodeGraph {
/** */
deleteRelationship(relationship) {
this._relationships.erase(relationship);
this._relationships = this._relationships.filter((r) => r !== relationship);
}
/** */
@ -1186,7 +1186,7 @@ class Topic extends NodeGraph {
/** */
removeChild(child) {
const children = this.getChildren();
children.erase(child);
this._children = children.filter((c) => c !== child);
}
/** */

View File

@ -75,7 +75,7 @@ class AddTopicCommand extends Command {
// Delete disconnected the nodes. Create a copy of the topics ...
const clonedModel = [];
this._models.forEach((model) => {
clonedModel.push(model.clone());
clonedModel.push({ ...model });
});
// Finally, remove the nodes ...

View File

@ -53,14 +53,14 @@ class DeleteCommand extends Command {
// Delete relationships
const relationships = this._collectInDepthRelationships(topic);
this._deletedRelModel.append(relationships.map((rel) => rel.getModel().clone()));
this._deletedRelModel.append(relationships.map((rel) => ({ ...rel.getModel() })));
relationships.forEach((relationship) => {
commandContext.deleteRelationship(relationship);
});
// Store information for undo ...
const clonedModel = model.clone();
const clonedModel = { ...model };
this._deletedTopicModels.push(clonedModel);
const outTopic = topic.getOutgoingConnectedTopic();
let outTopicId = null;
@ -77,9 +77,9 @@ class DeleteCommand extends Command {
const rels = commandContext.findRelationships(this._relIds);
if (rels.length > 0) {
rels.forEach(((rel) => {
this._deletedRelModel.push(rel.getModel().clone());
this._deletedRelModel.push({ ...rel.getModel() });
commandContext.deleteRelationship(rel);
}).bind(this));
}));
}
}
@ -102,7 +102,7 @@ class DeleteCommand extends Command {
const parentTopics = commandContext.findTopics(parentId);
commandContext.connect(topics[0], parentTopics[0]);
}
}).bind(this));
}));
// Add rebuild relationships ...
this._deletedRelModel.forEach((model) => {
@ -135,7 +135,7 @@ class DeleteCommand extends Command {
let parent = topic.getParent();
let found = false;
while (parent != null && !found) {
found = topicIds.contains(parent.getId());
found = topicIds.includes(parent.getId());
if (found) {
break;
}
@ -152,12 +152,10 @@ class DeleteCommand extends Command {
_collectInDepthRelationships(topic) {
let result = [];
result.append(topic.getRelationships());
result = result.concat(topic.getRelationships());
const children = topic.getChildren();
const rels = children.map(function (topic) {
return this._collectInDepthRelationships(topic);
}, this);
const rels = children.map(((t) => this._collectInDepthRelationships(t)));
result.append(rels.flatten());
if (result.length > 0) {

View File

@ -37,17 +37,17 @@ class MoveControlPointCommand extends Command {
super();
this._ctrlPointControler = ctrlPointController;
this._line = ctrlPointController._line;
this._controlPoint = this._ctrlPointControler.getControlPoint(point).clone();
this._oldControlPoint = this._ctrlPointControler.getOriginalCtrlPoint(point).clone();
this._originalEndPoint = this._ctrlPointControler.getOriginalEndPoint(point).clone();
this._controlPoint = { ...this._ctrlPointControler.getControlPoint(point) };
this._oldControlPoint = { ...this._ctrlPointControler.getOriginalCtrlPoint(point) };
this._originalEndPoint = this._ctrlPointControler.getOriginalEndPoint(point);
switch (point) {
case 0:
this._wasCustom = this._line.getLine().isSrcControlPointCustom();
this._endPoint = this._line.getLine().getFrom().clone();
this._endPoint = { ...this._line.getLine().getFrom() };
break;
case 1:
this._wasCustom = this._line.getLine().isDestControlPointCustom();
this._endPoint = this._line.getLine().getTo().clone();
this._endPoint = { ...this._line.getLine().getTo() };
break;
default:
break;
@ -62,17 +62,17 @@ class MoveControlPointCommand extends Command {
const model = this._line.getModel();
switch (this._point) {
case 0:
model.setSrcCtrlPoint(this._controlPoint.clone());
model.setSrcCtrlPoint({ ...this._controlPoint });
this._line.setFrom(this._endPoint.x, this._endPoint.y);
this._line.setIsSrcControlPointCustom(true);
this._line.setSrcControlPoint(this._controlPoint.clone());
this._line.setSrcControlPoint({ ...this._controlPoint });
break;
case 1:
model.setDestCtrlPoint(this._controlPoint.clone());
model.setDestCtrlPoint({ ...this._controlPoint });
this._wasCustom = this._line.getLine().isDestControlPointCustom();
this._line.setTo(this._endPoint.x, this._endPoint.y);
this._line.setIsDestControlPointCustom(true);
this._line.setDestControlPoint(this._controlPoint.clone());
this._line.setDestControlPoint({ ...this._controlPoint });
break;
default:
break;
@ -95,16 +95,16 @@ class MoveControlPointCommand extends Command {
case 0:
if ($defined(this._oldControlPoint)) {
line.setFrom(this._originalEndPoint.x, this._originalEndPoint.y);
model.setSrcCtrlPoint(this._oldControlPoint.clone());
line.setSrcControlPoint(this._oldControlPoint.clone());
model.setSrcCtrlPoint({ ...this._oldControlPoint });
line.setSrcControlPoint({ ...this._oldControlPoint });
line.setIsSrcControlPointCustom(this._wasCustom);
}
break;
case 1:
if ($defined(this._oldControlPoint)) {
line.setTo(this._originalEndPoint.x, this._originalEndPoint.y);
model.setDestCtrlPoint(this._oldControlPoint.clone());
line.setDestControlPoint(this._oldControlPoint.clone());
model.setDestCtrlPoint({ ...this._oldControlPoint });
line.setDestControlPoint({ ...this._oldControlPoint });
line.setIsDestControlPointCustom(this._wasCustom);
}
break;

View File

@ -23,13 +23,6 @@ import ChildrenSorterStrategy from './ChildrenSorterStrategy';
* @extends mindplot.layout.ChildrenSorterStrategy
*/
class AbstractBasicSorter extends ChildrenSorterStrategy {
/** @lends AbstractBasicSorter */
/**
* @param {} treeSet
* @param {} node
* @return the height of a node and its children if existing and not shrunken
*/
computeChildrenIdByHeights(treeSet, node) {
const result = {};
this._computeChildrenHeight(treeSet, node, result);

View File

@ -20,19 +20,6 @@ import { $assert, $defined } from '@wisemapping/core-js';
import AbstractBasicSorter from './AbstractBasicSorter';
class BalancedSorter extends AbstractBasicSorter {
/** @lends BalancedSorter */
/**
* @constructs
* @extends mindplot.layout.AbstractBasicSorter
*/
/**
* @param {} graph
* @param {} parent
* @param {} node
* @param {} position
* @param {Boolean} free
* @return an array with order and position
*/
predict(graph, parent, node, position, free) {
// If its a free node...
if (free) {
@ -42,8 +29,8 @@ class BalancedSorter extends AbstractBasicSorter {
);
$assert($defined(node), 'node cannot be null for predict in free positioning');
var rootNode = graph.getRootNode(parent);
var direction = this._getRelativeDirection(
const rootNode = graph.getRootNode(parent);
const direction = this._getRelativeDirection(
rootNode.getPosition(),
node.getPosition(),
);
@ -65,7 +52,7 @@ class BalancedSorter extends AbstractBasicSorter {
return [0, { x: xPos, y: position.y }];
}
var rootNode = graph.getRootNode(parent);
const rootNode = graph.getRootNode(parent);
// If it is a dragged node...
if (node) {
@ -86,9 +73,10 @@ class BalancedSorter extends AbstractBasicSorter {
}
}
let right; let left;
if (!position) {
var right = this._getChildrenForOrder(parent, graph, 0);
var left = this._getChildrenForOrder(parent, graph, 1);
right = this._getChildrenForOrder(parent, graph, 0);
left = this._getChildrenForOrder(parent, graph, 1);
}
// Filter nodes on one side..
const order = position
@ -101,7 +89,7 @@ class BalancedSorter extends AbstractBasicSorter {
var direction = order % 2 == 0 ? 1 : -1;
// Exclude the dragged node (if set)
const children = this._getChildrenForOrder(parent, graph, order).filter((child) => child != node);
const children = this._getChildrenForOrder(parent, graph, order).filter((child) => child !== node);
// No children?
if (children.length == 0) {
@ -120,7 +108,7 @@ class BalancedSorter extends AbstractBasicSorter {
// Try to fit within ...
let result = null;
const last = children.getLast();
const last = children[children.length - 1];
position = position || { x: last.getPosition().x, y: last.getPosition().y + 1 };
children.forEach((child, index) => {
const cpos = child.getPosition();
@ -303,7 +291,7 @@ class BalancedSorter extends AbstractBasicSorter {
}
_getChildrenForOrder(parent, graph, order) {
return this._getSortedChildren(graph, parent).filter((child) => child.getOrder() % 2 == order % 2);
return this._getSortedChildren(graph, parent).filter((child) => child.getOrder() % 2 === order % 2);
}
_getVerticalPadding() {

View File

@ -16,7 +16,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class ChildrenSorterStrategy {/** @lends ChildrenSorterStrategy */
/**
* @constructs

View File

@ -17,10 +17,7 @@
*/
import EventBus from './EventBus';
class EventBusDispatcher {/** @lends EventBusDispatcher */
/**
* @constructs
*/
class EventBusDispatcher {
constructor() {
this.registerBusEvents();
}

View File

@ -22,12 +22,7 @@ import AbstractBasicSorter from './AbstractBasicSorter';
* @class
* @extends mindplot.layout.AbstractBasicSorter
*/
class GridSorter extends AbstractBasicSorter {/** @lends GridSorter */
/**
* @param {} treeSet
* @param {} node
* @return offsets
*/
class GridSorter extends AbstractBasicSorter {
computeOffsets(treeSet, node) {
$assert(treeSet, 'treeSet can no be null.');
$assert(node, 'node can no be null.');

View File

@ -18,18 +18,6 @@
import { $assert, $defined } from '@wisemapping/core-js';
class Node {
/** @lends Node */
/**
* @constructs
* @param id
* @param size
* @param position
* @param sorter
* @throws will throw an error if id is not a finite number or is null or undefined
* @throws will throw an error if size is null or undefined
* @throws will throw an error if position is null or undefined
* @throws will throw an error if sorter is null or undefined
*/
constructor(id, size, position, sorter) {
$assert(typeof id === 'number' && Number.isFinite(id), 'id can not be null');
$assert(size, 'size can not be null');
@ -141,7 +129,7 @@ class Node {
/** */
setSize(size) {
$assert($defined(size), 'Size can not be null');
this._setProperty('size', Object.clone(size));
this._setProperty('size', { ...size });
}
/** */
@ -245,5 +233,4 @@ class Node {
}
}
export default Node;

View File

@ -77,7 +77,7 @@ class OriginalLayout {
/** */
layout() {
const roots = this._treeSet.getTreeRoots();
roots.each(((node) => {
roots.forEach(((node) => {
// Calculate all node heights ...
const sorter = node.getSorter();
@ -109,7 +109,7 @@ class OriginalLayout {
const parentPosition = node.getPosition();
const me = this;
children.each((child) => {
children.forEach((child) => {
const offset = offsetById[child.getId()];
const childFreeDisplacement = child.getFreeDisplacement();
@ -143,7 +143,7 @@ class OriginalLayout {
}
// Continue reordering the children nodes ...
children.each(((child) => {
children.forEach(((child) => {
this._layoutChildren(child, heightById);
}));
}
@ -198,7 +198,7 @@ class OriginalLayout {
if (node.isFree()) {
this._shiftBranches(node, heightById);
}
children.each(((child) => {
children.forEach(((child) => {
this._fixOverlapping(child, heightById);
}));
}
@ -211,27 +211,25 @@ class OriginalLayout {
node.getFreeDisplacement().y,
);
siblingsToShift.each(((sibling) => {
const overlappingOccurs = shiftedBranches.some(((shiftedBranch) =>{
return OriginalLayout._branchesOverlap(shiftedBranch, sibling, heightById);
}).bind(this));
siblingsToShift.forEach(((sibling) => {
const overlappingOccurs = shiftedBranches.some(((shiftedBranch) => OriginalLayout._branchesOverlap(shiftedBranch, sibling, heightById)));
if (!sibling.isFree() || overlappingOccurs) {
const sAmount = node.getFreeDisplacement().y;
this._treeSet.shiftBranchPosition(sibling, 0, sAmount);
shiftedBranches.push(sibling);
}
}).bind(this));
}));
const branchesToShift = this._treeSet
.getBranchesInVerticalDirection(node, node.getFreeDisplacement().y)
.filter((branch) => !shiftedBranches.contains(branch));
.filter((branch) => !shiftedBranches.includes(branch));
branchesToShift.each(((branch) =>{
branchesToShift.forEach(((branch) => {
const bAmount = node.getFreeDisplacement().y;
this._treeSet.shiftBranchPosition(branch, 0, bAmount);
shiftedBranches.push(branch);
}).bind(this));
}));
}
static _branchesOverlap(branchA, branchB, heightById) {

View File

@ -18,8 +18,6 @@
import { $assert, $defined } from '@wisemapping/core-js';
class RootedTreeSet {
/** @lends RootedTreeSet */
/** @constructs */
constructor() {
this._rootNodes = [];
}
@ -53,20 +51,20 @@ class RootedTreeSet {
$assert(node, 'node can not be null');
$assert(
!this.find(node.getId(), false),
`node already exits with this id. Id:${node.getId()}`,
`node already exits with this id. Id:${node.getId()}: ${this.dump()}`,
);
$assert(!node._children, 'node already added');
this._rootNodes.push(this._decodate(node));
}
/**
* @param nodeId
* @throws will throw an error if nodeId is null or undefined
*/
* @param nodeId
* @throws will throw an error if nodeId is null or undefined
*/
remove(nodeId) {
$assert($defined(nodeId), 'nodeId can not be null');
const node = this.find(nodeId);
this._rootNodes.erase(node);
this._rootNodes = this._rootNodes.filter((n) => n !== node);
}
/**
@ -89,7 +87,7 @@ class RootedTreeSet {
parent._children.push(child);
child._parent = parent;
this._rootNodes.erase(child);
this._rootNodes = this._rootNodes.filter((c) => c !== child);
}
/**
@ -102,7 +100,7 @@ class RootedTreeSet {
const node = this.find(nodeId);
$assert(node._parent, 'Node is not connected');
node._parent._children.erase(node);
node._parent._children = node._parent._children.filter((n)=> node !== n);
this._rootNodes.push(node);
node._parent = null;
}
@ -301,7 +299,7 @@ class RootedTreeSet {
`${node.getId()}[${order}]`,
);
text.attr('fill', '#FFF');
const fillColor = this._rootNodes.contains(node)
const fillColor = this._rootNodes.includes(node)
? '#000'
: node.isFree()
? '#abc'
@ -321,11 +319,11 @@ class RootedTreeSet {
node.getOrder()
}, position:(${
rectPosition.x
},${
}, ${
rectPosition.y
}), size:${
rectSize.width
}x${
},${
rectSize.height
}, freeDisplacement:(${
node.getFreeDisplacement().x

View File

@ -19,8 +19,6 @@ import { $assert, $defined } from '@wisemapping/core-js';
import AbstractBasicSorter from './AbstractBasicSorter';
class SymmetricSorter extends AbstractBasicSorter {
/** @lends SymmetricSorter */
/**
* Predict the order and position of a dragged node.
*
@ -37,10 +35,8 @@ class SymmetricSorter extends AbstractBasicSorter {
// If its a free node...
if (free) {
$assert(
$defined(position),
'position cannot be null for predict in free positioning',
);
$assert($defined(position),
'position cannot be null for predict in free positioning');
$assert($defined(node), 'node cannot be null for predict in free positioning');
const direction = this._getRelativeDirection(
@ -48,10 +44,10 @@ class SymmetricSorter extends AbstractBasicSorter {
parent.getPosition(),
);
const limitXPos = parent.getPosition().x
+ direction
* (parent.getSize().width / 2
+ node.getSize().width / 2
+ SymmetricSorter.INTERNODE_HORIZONTAL_PADDING);
+ direction
* (parent.getSize().width / 2
+ node.getSize().width / 2
+ SymmetricSorter.INTERNODE_HORIZONTAL_PADDING);
const xPos = direction > 0
? position.x >= limitXPos
@ -71,14 +67,14 @@ class SymmetricSorter extends AbstractBasicSorter {
parent.getPosition(),
);
var position = {
const result = {
x:
parent.getPosition().x
+ parentDirection
* (parent.getSize().width + SymmetricSorter.INTERNODE_HORIZONTAL_PADDING),
parent.getPosition().x
+ parentDirection
* (parent.getSize().width + SymmetricSorter.INTERNODE_HORIZONTAL_PADDING),
y: parent.getPosition().y,
};
return [graph.getChildren(parent).length, position];
return [graph.getChildren(parent).length, result];
}
// If it is a dragged node...
@ -91,81 +87,81 @@ class SymmetricSorter extends AbstractBasicSorter {
const siblings = graph.getSiblings(node);
// node has no siblings and its trying to reconnect to its own parent
const sameParent = parent == graph.getParent(node);
const sameParent = parent === graph.getParent(node);
if (siblings.length == 0 && nodeDirection == positionDirection && sameParent) {
return [node.getOrder(), node.getPosition()];
}
const parentChildren = graph.getChildren(parent);
if (parentChildren.length == 0) {
if (parentChildren.length === 0) {
// Fit as a child of the parent node...
var position = {
x:
parent.getPosition().x
+ positionDirection
* (parent.getSize().width + SymmetricSorter.INTERNODE_HORIZONTAL_PADDING),
const result = {
x: parent.getPosition().x + positionDirection * (parent.getSize().width + SymmetricSorter.INTERNODE_HORIZONTAL_PADDING),
y: parent.getPosition().y,
};
return [0, position];
return [0, result];
}
// Try to fit within ...
const result = null;
const last = parentChildren.getLast();
const last = parentChildren[parentChildren.length - 1];
for (let i = 0; i < parentChildren.length; i++) {
const parentChild = parentChildren[i];
const nodeAfter = i + 1 == parentChild.length ? null : parentChildren[i + 1];
const nodeAfter = i + 1 === parentChild.length ? null : parentChildren[i + 1];
// Fit at the bottom
if (!nodeAfter && position.y > parentChild.getPosition().y) {
var order = graph.getParent(node) && graph.getParent(node).getId() == parent.getId()
const order = graph.getParent(node) && graph.getParent(node).getId() === parent.getId()
? last.getOrder()
: last.getOrder() + 1;
var position = {
const result = {
x: parentChild.getPosition().x,
y:
parentChild.getPosition().y
+ parentChild.getSize().height
+ SymmetricSorter.INTERNODE_VERTICAL_PADDING * 2,
parentChild.getPosition().y
+ parentChild.getSize().height
+ SymmetricSorter.INTERNODE_VERTICAL_PADDING * 2,
};
return [order, position];
return [order, result];
}
// Fit after this node
if (
nodeAfter
&& position.y > parentChild.getPosition().y
&& position.y < nodeAfter.getPosition().y
&& position.y > parentChild.getPosition().y
&& position.y < nodeAfter.getPosition().y
) {
if (
nodeAfter.getId() == node.getId()
|| parentChild.getId() == node.getId()
nodeAfter.getId() === node.getId()
|| parentChild.getId() === node.getId()
) {
return [node.getOrder(), node.getPosition()];
}
var order = position.y > node.getPosition().y
const orderResult = position.y > node.getPosition().y
? nodeAfter.getOrder() - 1
: parentChild.getOrder() + 1;
var position = {
const positionResult = {
x: parentChild.getPosition().x,
y:
parentChild.getPosition().y
+ (nodeAfter.getPosition().y - parentChild.getPosition().y) / 2,
parentChild.getPosition().y
+ (nodeAfter.getPosition().y - parentChild.getPosition().y) / 2,
};
return [order, position];
return [orderResult, positionResult];
}
}
// Position wasn't below any node, so it must be fitted above the first
const first = parentChildren[0];
var position = {
const resultPosition = {
x: first.getPosition().x,
y:
first.getPosition().y
- first.getSize().height
- SymmetricSorter.INTERNODE_VERTICAL_PADDING * 2,
first.getPosition().y
- first.getSize().height
- SymmetricSorter.INTERNODE_VERTICAL_PADDING * 2,
};
return [0, position];
return [0, resultPosition];
}
/**
@ -209,16 +205,16 @@ class SymmetricSorter extends AbstractBasicSorter {
}
/**
* @param treeSet
* @param node
* @throws will throw an error if treeSet is null or undefined
* @throws will throw an error if node is null or undefined
* @throws will throw an error if the calculated x offset cannot be converted to a numeric
* value, is null or undefined
* @throws will throw an error if the calculated y offset cannot be converted to a numeric
* value, is null or undefined
* @return offsets
*/
* @param treeSet
* @param node
* @throws will throw an error if treeSet is null or undefined
* @throws will throw an error if node is null or undefined
* @throws will throw an error if the calculated x offset cannot be converted to a numeric
* value, is null or undefined
* @throws will throw an error if the calculated y offset cannot be converted to a numeric
* value, is null or undefined
* @return offsets
*/
computeOffsets(treeSet, node) {
$assert(treeSet, 'treeSet can no be null.');
$assert(node, 'node can no be null.');
@ -227,16 +223,13 @@ class SymmetricSorter extends AbstractBasicSorter {
// Compute heights ...
const heights = children
.map(function (child) {
return {
id: child.getId(),
order: child.getOrder(),
position: child.getPosition(),
width: child.getSize().width,
height: this._computeChildrenHeight(treeSet, child),
};
}, this)
.reverse();
.map(((child) => ({
id: child.getId(),
order: child.getOrder(),
position: child.getPosition(),
width: child.getSize().width,
height: this._computeChildrenHeight(treeSet, child),
})).bind(this)).reverse();
// Compute the center of the branch ...
let totalHeight = 0;
@ -254,9 +247,9 @@ class SymmetricSorter extends AbstractBasicSorter {
const yOffset = ysum + heights[i].height / 2;
const xOffset = direction
* (heights[i].width / 2
+ node.getSize().width / 2
+ SymmetricSorter.INTERNODE_HORIZONTAL_PADDING);
* (heights[i].width / 2
+ node.getSize().width / 2
+ SymmetricSorter.INTERNODE_HORIZONTAL_PADDING);
$assert(!Number.isNaN(xOffset), 'xOffset can not be null');
$assert(!Number.isNaN(yOffset), 'yOffset can not be null');
@ -281,9 +274,9 @@ class SymmetricSorter extends AbstractBasicSorter {
}
/**
* @param treeSet
* @param child
* @return direction of the given child from its parent or from the root node, if isolated */
* @param treeSet
* @param child
* @return direction of the given child from its parent or from the root node, if isolated */
getChildDirection(treeSet, child) {
$assert(treeSet, 'treeSet can no be null.');
$assert(treeSet.getParent(child), 'This should not happen');

View File

@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { $assert, $defined } from "@wisemapping/core-js";
import { $assert, $defined } from '@wisemapping/core-js';
import $ from 'jquery';
class FeatureModel {
@ -33,18 +33,24 @@ class FeatureModel {
this._attributes = {};
// Create type method ...
this[`is${$.camelCase(type)}Model`] = () => true;
this[`is${FeatureModel.camelize(type)}Model`] = () => true;
}
/** */
getAttributes() {
return Object.clone(this._attributes);
return { ...this._attributes };
}
static camelize(str) {
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (index === 0 ? word.toLowerCase() : word.toUpperCase())).replace(/\s+/g, '');
}
/** */
setAttributes(attributes) {
for (const key in attributes) {
this[`set${key.capitalize()}`](attributes[key]);
for (const attr in attributes) {
const funName = `set${FeatureModel.camelize(attr)}`;
const value = attributes[attr];
this[funName](value);
}
}

View File

@ -39,14 +39,14 @@ class LinkModel extends FeatureModel {
const fixedUrl = LinkModel._fixUrl(url);
this.setAttribute('url', fixedUrl);
const type = fixedUrl.contains('mailto:') ? 'mail' : 'url';
const type = fixedUrl.includes('mailto:') ? 'mail' : 'url';
this.setAttribute('urlType', type);
}
// url format is already checked in LinkEditor.checkUrl
static _fixUrl(url) {
let result = url;
if (!result.contains('http://') && !result.contains('https://') && !result.contains('mailto://')) {
if (!result.includes('http://') && !result.includes('https://') && !result.includes('mailto://')) {
result = `http://${result}`;
}
return result;

View File

@ -86,7 +86,7 @@ class Mindmap extends IMindmap {
*/
removeBranch(nodeModel) {
$assert(nodeModel && nodeModel.isNodeModel(), 'Remove node must be invoked with model objects');
return this._branches.erase(nodeModel);
this._branches = this._branches.filter((b) => b !== nodeModel);
}
/** */
@ -151,7 +151,7 @@ class Mindmap extends IMindmap {
* @param relationship
*/
deleteRelationship(relationship) {
this._relationships.erase(relationship);
this._relationships = this._branches.filter((r) => r !== relationship);
}
/**

View File

@ -169,7 +169,7 @@ class NodeModel extends INodeModel {
*/
removeChild(child) {
$assert(child && child.isNodeModel(), 'Only NodeModel can be appended to Mindmap object.');
this._children.erase(child);
this._children = this._children.filter((c) => c !== child);
child._parent = null;
}

View File

@ -61,11 +61,15 @@ class FloatingTip extends Events {
return this;
}
setOptions() {
const options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
setOptions(...args) {
this.options = { ...this.options, ...args };
const { options } = this;
if (this.addEvent) {
for (const option in options) {
if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
if (typeof (options[option]) != 'function' || !(/^on[A-Z]/).test(option)) {
continue;
}
this.addEvent(option, options[option]);
delete options[option];
}

View File

@ -15,12 +15,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { $assert } from "@wisemapping/core-js";
import { $assert } from '@wisemapping/core-js';
import PersistenceManager from '../PersistenceManager';
import { $notify } from './ToolbarNotifier';
import $notifyModal from './ModalDialogNotifier';
class IMenu {
constructor(designer, containerId, mapId) {
$assert(designer, 'designer can not be null');
$assert(containerId, 'containerId can not be null');
@ -97,7 +97,7 @@ class IMenu {
$notifyModal(error.message);
}
}
}
},
}, sync);
}

View File

@ -111,19 +111,19 @@ class LinkEditor extends BootstrapDialog {
}
/**
* checks whether the input is a valid url
* @return {Boolean} true if the url is valid
*/
* checks whether the input is a valid url
* @return {Boolean} true if the url is valid
*/
checkURL(url) {
const regex = /^(http|https|ftp):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/i;
return (regex.test(url));
}
/**
* overrides abstract parent method
* triggered when the user clicks the accept button - submits the url input
* @param event
*/
* overrides abstract parent method
* triggered when the user clicks the accept button - submits the url input
* @param event
*/
onAcceptClick(event) {
this.formSubmitted = false;
$('#linkFormId').trigger('submit');
@ -133,22 +133,21 @@ class LinkEditor extends BootstrapDialog {
}
/**
* overrides parent method
* sets the url input on focus
*/
* overrides parent method
* sets the url input on focus
*/
onDialogShown() {
$(this).find('#inputUrl').focus();
}
/**
* overrides abstract parent method
* triggered when the user clicks the remove button - deletes the link
*/
* overrides abstract parent method
* triggered when the user clicks the remove button - deletes the link
*/
onRemoveClick(event) {
event.data.model.setValue(null);
event.data.dialog.close();
}
}
export default LinkEditor;

View File

@ -14,9 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { $assert } from '@wisemapping/core-js';
class ModalDialogNotifier {
// FIXME: replace by alert()
show(message, title) {
$assert(message, 'message can not be null');
@ -42,11 +42,10 @@ class ModalDialogNotifier {
modalDialog.find('.alert-content').append(h4 + p);
modalDialog.modal();
},
});
}
}
const dialogNotifier = new ModalDialogNotifier();
const $notifyModal = dialogNotifier.show.bind(dialogNotifier);
export { $notifyModal };
export default ModalDialogNotifier;
export default { $notifyModal };

View File

@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { $assert } from '@wisemapping/core-js';
import BootstrapDialog from '../libraries/bootstrap/BootstrapDialog';
class NoteEditor extends BootstrapDialog {

View File

@ -1,6 +1,4 @@
/* eslint-disable no-unused-vars */
import '@libraries/mootools-core-1.4.5';
import Mindmap from './components/model/Mindmap';
import PersistenceManager from './components/PersistenceManager';
import Designer from './components/Designer';

View File

@ -20,6 +20,7 @@ import $ from 'jquery';
import { $assert } from '@wisemapping/core-js';
import TestSuite from './TestSuite';
import LayoutManager from '../../../src/components/layout/LayoutManager';
class BalancedTestSuite extends TestSuite {
constructor() {
$('#balancedTest').css('display', 'block');

View File

@ -501,13 +501,13 @@ class FreeTestSuite extends TestSuite {
_assertBranchCollision(treeSet, node, heightById) {
const children = treeSet.getChildren(node);
const childOfRootNode = treeSet._rootNodes.contains(node);
const childOfRootNode = treeSet._rootNodes.includes(node);
children.forEach((child) => {
const height = heightById[child.getId()];
let siblings = treeSet.getSiblings(child);
if (childOfRootNode) {
siblings = siblings.filter((sibling) => child.getOrder() % 2 == sibling.getOrder() % 2);
siblings = siblings.filter((sibling) => child.getOrder() % 2 === sibling.getOrder() % 2);
}
siblings.forEach((sibling) => {

View File

@ -91,7 +91,7 @@ class TestSuite extends ChildrenSorterStrategy {
manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0);
manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(1, 3, 0);
manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(3, 5, 0);
manager.addNode(6, { width: 140, height: 130 }, position).connectNode(3, 6, 1);
manager.addNode(6, { width: 140, height: 130 } , position).connectNode(3, 6, 1);
manager.addNode(7, TestSuite.NODE_SIZE, position).connectNode(6, 7, 0);
manager.addNode(8, TestSuite.NODE_SIZE, position).connectNode(7, 8, 0);
manager.addNode(9, TestSuite.NODE_SIZE, position).connectNode(7, 9, 1);
@ -105,10 +105,10 @@ class TestSuite extends ChildrenSorterStrategy {
manager.addNode(17, TestSuite.NODE_SIZE, position).connectNode(7, 17, 9);
manager.addNode(29, TestSuite.NODE_SIZE, position).connectNode(6, 29, 1);
manager.addNode(30, TestSuite.NODE_SIZE, position).connectNode(6, 30, 2);
manager.addNode(31, { width: 100, height: 50 }, position).connectNode(6, 31, 3);
manager.addNode(31, { width: 100, height: 50 } , position).connectNode(6, 31, 3);
manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(1, 4, 1);
manager.addNode(18, { width: 80, height: 70 }, position).connectNode(4, 18, 0);
manager.addNode(18, { width: 80, height: 70 } , position).connectNode(4, 18, 0);
manager.addNode(19, TestSuite.NODE_SIZE, position).connectNode(18, 19, 0);
manager.addNode(20, TestSuite.NODE_SIZE, position).connectNode(19, 20, 0);
manager.addNode(21, TestSuite.NODE_SIZE, position).connectNode(20, 21, 0);
@ -117,11 +117,11 @@ class TestSuite extends ChildrenSorterStrategy {
manager.addNode(22, TestSuite.NODE_SIZE, position).connectNode(2, 22, 0);
manager.addNode(24, TestSuite.NODE_SIZE, position).connectNode(22, 24, 0);
manager.addNode(23, { width: 80, height: 50 }, position).connectNode(2, 23, 1);
manager.addNode(25, { width: 80, height: 40 }, position).connectNode(23, 25, 0);
manager.addNode(26, { width: 80, height: 80 }, position).connectNode(25, 26, 0);
manager.addNode(23, { width: 80, height: 50 } , position).connectNode(2, 23, 1);
manager.addNode(25, { width: 80, height: 40 } , position).connectNode(23, 25, 0);
manager.addNode(26, { width: 80, height: 80 } , position).connectNode(25, 26, 0);
manager.addNode(27, TestSuite.NODE_SIZE, position).connectNode(26, 27, 0);
manager.addNode(28, { width: 80, height: 80 }, position).connectNode(27, 28, 0);
manager.addNode(28, { width: 80, height: 80 } , position).connectNode(27, 28, 0);
// manager.layout();
// manager.plot("testBaselineAligned1", {width:1600,height:800});
@ -135,7 +135,7 @@ class TestSuite extends ChildrenSorterStrategy {
const manager = new LayoutManager(0, TestSuite.ROOT_NODE_SIZE);
manager.addNode(1, TestSuite.NODE_SIZE, position).connectNode(0, 1, 0);
manager.addNode(2, { width: 130, height: 200 }, position).connectNode(1, 2, 0);
manager.addNode(2, { width: 130, height: 200 } , position).connectNode(1, 2, 0);
manager.addNode(3, TestSuite.NODE_SIZE, position).connectNode(2, 3, 0);
manager.addNode(4, TestSuite.NODE_SIZE, position).connectNode(2, 4, 1);
manager.addNode(5, TestSuite.NODE_SIZE, position).connectNode(2, 5, 2);
@ -164,9 +164,9 @@ class TestSuite extends ChildrenSorterStrategy {
manager.addEvent('change', (event) => {
console.log(
`\tUpdated nodes: {id:${event.getId()
}, order: ${event.getOrder()
},position: {${event.getPosition().x
},${event.getPosition().y
} order: ${event.getOrder()
}position: {${event.getPosition().x
}${event.getPosition().y
}}`,
);
events.push(event);
@ -206,9 +206,9 @@ class TestSuite extends ChildrenSorterStrategy {
manager.addEvent('change', (event) => {
console.log(
`\tUpdated nodes: {id:${event.getId()
}, order: ${event.getOrder()
},position: {${event.getPosition().x
},${event.getPosition().y
} order: ${event.getOrder()
}position: {${event.getPosition().x
}${event.getPosition().y
}}`,
);
events.push(event);
@ -256,12 +256,12 @@ class TestSuite extends ChildrenSorterStrategy {
const events = [];
manager.addEvent('change', (event) => {
const pos = event.getPosition();
const posStr = pos ? `,position: {${pos.x},${pos.y}` : '';
const posStr = pos ? `,position: {${pos.x}${pos.y}` : '';
const node = manager.find(event.getId());
console.log(
`\tUpdated nodes: {id:${event.getId()
}, order: ${event.getOrder()
},${posStr
} order: ${event.getOrder()
}${posStr
}}`,
);
events.push(event);
@ -385,7 +385,7 @@ class TestSuite extends ChildrenSorterStrategy {
const events = [];
manager.addEvent('change', (event) => {
const pos = event.getPosition();
const posStr = pos ? `,position: {${pos.x},${event.getPosition().y}` : '';
const posStr = pos ? `,position: {${pos.x}${event.getPosition().y}` : '';
events.push(event);
});
manager.layout(true);
@ -431,17 +431,17 @@ class TestSuite extends ChildrenSorterStrategy {
const position = { x: 0, y: 0 };
const manager = new LayoutManager(0, TestSuite.ROOT_NODE_SIZE);
manager.addNode(1, { width: 60, height: 60 }, position);
manager.addNode(1, { width: 60, height: 60 } ,position);
manager.addNode(2, TestSuite.NODE_SIZE, position);
manager.addNode(3, { width: 260, height: 30 }, position);
manager.addNode(3, { width: 260, height: 30 } ,position);
manager.addNode(4, TestSuite.NODE_SIZE, position);
manager.addNode(5, TestSuite.NODE_SIZE, position);
manager.addNode(7, { width: 80, height: 80 }, position);
manager.addNode(7, { width: 80, height: 80 } ,position);
manager.addNode(8, TestSuite.NODE_SIZE, position);
manager.addNode(9, { width: 30, height: 30 }, position);
manager.addNode(9, { width: 30, height: 30 } ,position);
manager.addNode(10, TestSuite.NODE_SIZE, position);
manager.addNode(11, TestSuite.NODE_SIZE, position);
manager.addNode(12, { width: 100, height: 70 }, position);
manager.addNode(12, { width: 100, height: 70 } ,position);
manager.addNode(13, TestSuite.NODE_SIZE, position);
manager.addNode(14, TestSuite.NODE_SIZE, position);
manager.addNode(15, TestSuite.NODE_SIZE, position);
@ -565,8 +565,8 @@ class TestSuite extends ChildrenSorterStrategy {
const { order } = prediction;
console.log(
`\t\tprediction {order:${order
}, position: (${position.x
},${position.y
} position: (${position.x
}${position.y
})}`,
);
const cx = position.x + canvas.width / 2 - TestSuite.NODE_SIZE.width / 2;

View File

@ -11,7 +11,6 @@
<![endif]-->
<link rel="stylesheet/less" type="text/css" href="css/editor.less"/>
<script type='text/javascript' src='js/mootools-core.js'></script>
<script type='text/javascript' src='js/core.js'></script>
<script type='text/javascript' src='js/less.js'></script>

View File

@ -18,6 +18,7 @@
import { $assert } from '@wisemapping/core-js';
import { PersistenceManager, Designer, LocalStorageManager, Menu } from '../../../../src/';
import * as mindplot from '../../../../src/';
import $notifyModal from '../../../../src/components/widget/ModalDialogNotifier';
import $ from 'jquery';
global.jQuery = $;

View File

@ -33,7 +33,7 @@ describe('Free Test Suite', () => {
function branchCollision(treeSet, node, heightById) {
const children = treeSet.getChildren(node);
const childOfRootNode = treeSet._rootNodes.contains(node);
const childOfRootNode = treeSet._rootNodes.includes(node);
children.forEach(((child) => {
let siblings = treeSet.getSiblings(child);

View File

@ -18,7 +18,6 @@ module.exports = {
test: /.(js$)/,
exclude: [
/node_modules/,
path.resolve(__dirname, '../../libraries/mootools-core-1.4.5'),
],
},
],

View File

@ -36,7 +36,6 @@ module.exports = {
test: /.js$/,
exclude: [
/node_modules/,
path.resolve(__dirname, '../../libraries/mootools-core-1.4.5'),
/lib\/raphael/ig,
],
},

View File

@ -13,6 +13,7 @@
"rules": {
"no-underscore-dangle": "off",
"no-restricted-syntax": "off",
"no-underscore-dangle": "off",
"no-plusplus": "off",
"max-len": [1,250],
"import/no-extraneous-dependencies": ["warn", {

View File

@ -3,7 +3,7 @@ const BASE_URL = 'http://localhost:8080';
context('Playground', () => {
it('every test page should match its snapshot', () => {
cy.visit(BASE_URL);
cy.get('a').each(($el) => {
cy.get('a').forEach(($el) => {
const url = `${BASE_URL}${$el.attr('href')}`;
cy.visit(url);
cy.matchImageSnapshot($el.text());

View File

@ -74,12 +74,14 @@ class ElementPeer {
removeChild(elementPeer) {
// Store parent and child relationship.
elementPeer.setParent(null);
const children = this.getChildren();
let children = this.getChildren();
// Remove from children array ...
const oldLength = children.length;
children.erase(elementPeer);
children = children.filter((c) => c !== elementPeer);
this.setChildren(children);
$assert(
children.length < oldLength,
`element could not be removed:${elementPeer}`,