From 6a57b8cd9da1d0abc77b6ba4a2ce3d15fe675048 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ulrich-Matthias=20Sch=C3=A4fer?= Date: Thu, 9 Apr 2020 11:01:56 +1000 Subject: [PATCH] fixes and tests - fixed flatten and ungroup - added position argument to ungroup, toParent and toRoot - added tests for Container --- CHANGELOG.md | 4 + spec/SpecRunnerEs6.html | 21 +++-- spec/spec/element.js | 2 +- spec/spec/elements/Container.js | 131 ++++++++++++++++++++++++++++++ spec/spec/elements/Dom.js | 33 ++++++-- src/elements/Container.js | 24 +++--- src/elements/Svg.js | 2 - src/modules/optional/transform.js | 8 +- 8 files changed, 187 insertions(+), 38 deletions(-) create mode 100644 spec/spec/elements/Container.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 64c67e2..7ba04d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http: - fixed `replace()` which works without a parent now, too - fixed `defs()` which correctly returns `null` when called on a detached node that is not a root node - fixed `reference()` which correctly returns `null` instead of throwing when specifying an attribute which holds a number + - fixed `flatten()` which correctly flattens now but doesnt accept parameters anymore (makes no sense) + - fixed `ungroup()` which now inserts the elements at the correct position in the correct order and has position as second argument now ### Added - added second Parameter to `SVG(el, isHTML)` which allows to explicitely create elements in the HTML namespace (#1058) @@ -34,6 +36,8 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http: - added `options` parameter to `dispatch()` and `fire()` to allow for more special needs - added `newLine()` constructor to `Text` to create a tspan marked as new line (#1088) - added `Fragment` as a wrapper for document-fragment + - added position argument for `toParent()` + - added position argument for `toRoot()` - added lots of tests in es6 format ## [3.0.16] - 2019-11-12 diff --git a/spec/SpecRunnerEs6.html b/spec/SpecRunnerEs6.html index e5629e9..0f5ff75 100644 --- a/spec/SpecRunnerEs6.html +++ b/spec/SpecRunnerEs6.html @@ -19,23 +19,26 @@ - - - - - - + + + + - + - + - + + + + + + diff --git a/spec/spec/element.js b/spec/spec/element.js index b1686c0..87f4481 100644 --- a/spec/spec/element.js +++ b/spec/spec/element.js @@ -457,7 +457,7 @@ describe('Element', function () { it('redirects to toParent(root)', function () { rect.toRoot() - expect(rect.toParent).toHaveBeenCalledWith(rect.root()) + expect(rect.toParent).toHaveBeenCalledWith(rect.root(), undefined) }) }) diff --git a/spec/spec/elements/Container.js b/spec/spec/elements/Container.js new file mode 100644 index 0000000..5d53eb1 --- /dev/null +++ b/spec/spec/elements/Container.js @@ -0,0 +1,131 @@ +/* globals describe, expect, it, beforeEach, jasmine, container */ + +import { Container, create, SVG } from '../../../src/main.js' + +const { any } = jasmine + +describe('Container.js', () => { + describe('()', () => { + it('creates a new object of type Container', () => { + expect(new Container(create('g'))).toEqual(any(Container)) + }) + }) + + let canvas + let rect1 + let group1 + let rect2 + let circle1 + let group2 + let circle2 + let group3 + let line1 + let line2 + let circle3 + let group4 + let rect3 + + beforeEach(() => { + canvas = SVG().addTo(container) + rect1 = canvas.rect(100, 100).id('rect1') + group1 = canvas.group().id('group1') + rect2 = group1.rect(100, 100).id('rect2') + circle1 = group1.circle(50).id('circle1') + group2 = group1.group().id('group2') + circle2 = group2.circle(50).id('circle2') + group3 = group2.group().id('group3') + line1 = group3.line(1, 1, 2, 2).id('line1') + line2 = group3.line(1, 1, 2, 2).id('line2') + circle3 = group2.circle(50).id('circle3') + group4 = canvas.group().id('group4') + rect3 = group4.rect(100, 100).id('rect3') + + /* should be: + canvas + rect1 + group1 + rect2 + circle1 + group2 + circle2 + group3 + line1 + line2 + circle3 + group4 + rect3 + */ + }) + + describe('flatten()', () => { + it('flattens the whole document when called on the root', () => { + canvas.flatten() + + expect(canvas.children()).toEqual([ rect1, rect2, circle1, circle2, line1, line2, circle3, rect3 ]) + }) + + it('flattens a group and places all children into its parent when called on a group - 1', () => { + group1.flatten() + + /* now should be: + canvas + rect1 + group1 + rect2 + circle1 + circle2 + line1 + line2 + circle3 + group4 + rect3 + */ + + expect(canvas.children()).toEqual([ rect1, group1, group4 ]) + expect(group1.children()).toEqual([ rect2, circle1, circle2, line1, line2, circle3 ]) + }) + + it('flattens a group and places all children into its parent when called on a group - 2', () => { + group2.flatten() + + /* now should be: + canvas + rect1 + group1 + rect2 + circle1 + group2 + circle2 + line1 + line2 + circle3 + group4 + rect3 + */ + + expect(group2.children()).toEqual([ circle2, line1, line2, circle3 ]) + }) + }) + + describe('ungroup()', () => { + it('ungroups a group and inserts all children in the correct order in the parent parent of the group', () => { + group1.ungroup() + + expect(canvas.children()).toEqual([ rect1, rect2, circle1, group2, group4 ]) + + group4.ungroup() + + expect(canvas.children()).toEqual([ rect1, rect2, circle1, group2, rect3 ]) + }) + + it('ungroups a group into another group and appends the elements to the other group', () => { + group1.ungroup(group4) + expect(group4.children()).toEqual([ rect3, rect2, circle1, group2 ]) + }) + + it('ungroups a group into another group at the specified position', () => { + group2.ungroup(group1, 1) + expect(group1.children()).toEqual([ rect2, circle2, group3, circle3, circle1 ]) + }) + }) +}) diff --git a/spec/spec/elements/Dom.js b/spec/spec/elements/Dom.js index 6689822..3227ba1 100644 --- a/spec/spec/elements/Dom.js +++ b/spec/spec/elements/Dom.js @@ -1,6 +1,6 @@ /* globals describe, expect, it, beforeEach, spyOn, jasmine, container */ -import { SVG, G, Rect, Svg, Dom, List, Fragment, Circle, Tspan } from '../../../src/main.js' +import { SVG, G, Rect, Svg, Dom, List, Fragment, Circle, Tspan, create } from '../../../src/main.js' import { getWindow } from '../../../src/utils/window.js' const { any, createSpy, objectContaining } = jasmine @@ -66,9 +66,7 @@ describe('Dom.js', function () { it('handles a node', () => { const g = new G() - const rect = new Rect() - const node = rect.node - delete rect.instance + const node = create('rect') g.add(node) expect(g.children().length).toBe(1) expect(g.get(0)).toEqual(any(Rect)) @@ -219,6 +217,10 @@ describe('Dom.js', function () { g.circle(100, 100) expect(g.first()).toBe(rect) }) + + it('returns null if no first child exists', () => { + expect(new G().first()).toBe(null) + }) }) describe('get()', () => { @@ -289,6 +291,12 @@ describe('Dom.js', function () { const rect = g.rect(100, 100) expect(g.index(rect)).toBe(1) }) + + it('returns -1 if element is no child', () => { + const g = new G() + const rect = new Rect() + expect(g.index(rect)).toBe(-1) + }) }) describe('last()', () => { @@ -298,6 +306,10 @@ describe('Dom.js', function () { const rect = g.rect(100, 100) expect(g.last()).toBe(rect) }) + + it('returns null if no last child exists', () => { + expect(new G().last()).toBe(null) + }) }) describe('parent()', () => { @@ -528,7 +540,13 @@ describe('Dom.js', function () { it('returns the parent when outerHtml = true', () => { const canvas = new Svg() const g = canvas.group() - expect(g.svg('', true)).toBe(canvas) + expect(g.svg('', true)).toBe(canvas) + expect(canvas.children()).toEqual([ any(Rect), any(Circle) ]) + }) + + it('works without a parent', () => { + const canvas = new Svg() + expect(canvas.svg('')).toBe(canvas) }) }) @@ -655,13 +673,10 @@ describe('Dom.js', function () { }) it('allows to pass an svg node as element', () => { - var g = new G() - const node = g.node - delete node.instance + const node = create('g') rect.wrap(node) expect(rect.parent()).toEqual(any(G)) expect(rect.parent().node).toBe(node) - expect(rect.parent()).not.toBe(g) expect(rect.parent().parent()).toBe(canvas) }) }) diff --git a/src/elements/Container.js b/src/elements/Container.js index ebaba50..9278435 100644 --- a/src/elements/Container.js +++ b/src/elements/Container.js @@ -2,28 +2,26 @@ import { register } from '../utils/adopter.js' import Element from './Element.js' export default class Container extends Element { - flatten (parent) { + flatten (parent = this, index) { this.each(function () { - if (this instanceof Container) return this.flatten(parent).ungroup(parent) - return this.toParent(parent) + if (this instanceof Container) { + return this.flatten().ungroup() + } }) - // we need this so that the root does not get removed - this.node.firstElementChild || this.remove() - return this } - ungroup (parent) { - parent = parent || this.parent() + ungroup (parent = this.parent(), index = parent.index(this)) { + // when parent != this, we want append all elements to the end + index = index === -1 ? parent.children().length : index - this.each(function () { - return this.toParent(parent) + this.each(function (i, children) { + // reverse each + return children[children.length - i - 1].toParent(parent, index) }) - this.remove() - - return this + return this.remove() } } diff --git a/src/elements/Svg.js b/src/elements/Svg.js index 8699327..51f4202 100644 --- a/src/elements/Svg.js +++ b/src/elements/Svg.js @@ -25,10 +25,8 @@ export default class Svg extends Container { } isRoot () { - return !this.node.parentNode || (!(this.node.parentNode instanceof globals.window.SVGElement) && this.node.parentNode.nodeName !== '#document-fragment') - // || this.node.parentNode.nodeName === '#document' } // Add namespaces diff --git a/src/modules/optional/transform.js b/src/modules/optional/transform.js index d57c428..68455ed 100644 --- a/src/modules/optional/transform.js +++ b/src/modules/optional/transform.js @@ -35,19 +35,19 @@ export function matrixify () { } // add an element to another parent without changing the visual representation on the screen -export function toParent (parent) { +export function toParent (parent, i) { if (this === parent) return this var ctm = this.screenCTM() var pCtm = parent.screenCTM().inverse() - this.addTo(parent).untransform().transform(pCtm.multiply(ctm)) + this.addTo(parent, i).untransform().transform(pCtm.multiply(ctm)) return this } // same as above with parent equals root-svg -export function toRoot () { - return this.toParent(this.root()) +export function toRoot (i) { + return this.toParent(this.root(), i) } // Add transformations -- 2.39.5