From 826bb9845ffdbd11be427aad3ffa1f7d4a650eab Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Tue, 27 Feb 2018 12:12:19 +0100 Subject: fixed error that listener was strangely defined even if function was called without --- spec/spec/event.js | 111 +++++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 55 deletions(-) (limited to 'spec') diff --git a/spec/spec/event.js b/spec/spec/event.js index 0228fae..5f12172 100644 --- a/spec/spec/event.js +++ b/spec/spec/event.js @@ -10,7 +10,8 @@ describe('Event', function() { beforeEach(function() { rect = draw.rect(100, 100) - spyOn(SVG,'on').and.callThrough() + spyOn(SVG, 'on').and.callThrough() + spyOn(rect, 'dispatch').and.callThrough() }) afterEach(function() { @@ -25,8 +26,8 @@ describe('Event', function() { , 'mouseover' , 'mouseout' , 'mousemove' - // , 'mouseenter' -> not supported by IE - // , 'mouseleave' -> not supported by IE + , 'mouseenter' + , 'mouseleave' ].forEach(function(event) { describe(event+'()', function() { it('calls `on()` with '+event+' as event', function() { @@ -71,39 +72,32 @@ describe('Event', function() { SVG.off(el, 'event', action) }) it('attaches multiple handlers on different element', function() { - var listenerCnt = SVG.listeners.length - - var rect2 = draw.rect(100,100); - var rect3 = draw.rect(100,100); + var rect2 = draw.rect(100, 100) + var rect3 = draw.rect(100, 100) rect.on('event', action) rect2.on('event', action) rect3.on('event', function(){ butter = 'melting' }) rect3.on('event', action) - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*']).length).toBe(1) // 1 listener on rect - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect2.node)]['event']['*']).length).toBe(1) // 1 listener on rect2 - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect3.node)]['event']['*']).length).toBe(2) // 2 listener on rect3 - - expect(SVG.listeners.length).toBe(listenerCnt + 3) // added listeners on 3 different elements + expect(Object.keys(rect.events['event']['*']).length).toBe(1) // 1 listener on rect + expect(Object.keys(rect2.events['event']['*']).length).toBe(1) // 1 listener on rect2 + expect(Object.keys(rect3.events['event']['*']).length).toBe(2) // 2 listener on rect3 }) if('attaches a handler to a namespaced event', function(){ - var listenerCnt = SVG.listeners.length - - var rect2 = draw.rect(100,100); - var rect3 = draw.rect(100,100); + var rect2 = draw.rect(100, 100) + var rect3 = draw.rect(100, 100) rect.on('event.namespace1', action) rect2.on('event.namespace2', action) rect3.on('event.namespace3', function(){ butter = 'melting' }) rect3.on('event', action) - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*'])).toBeUndefined() // no global listener on rect - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['namespace1']).length).toBe( 1) // 1 namespaced listener on rect - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect2.node)]['event']['namespace2']).length).toBe(1) // 1 namespaced listener on rect - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect3.node)]['event']['*']).length).toBe(1) // 1 gobal listener on rect3 - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect3.node)]['event']['namespace3']).length).toBe(1) // 1 namespaced listener on rect3 - expect(SVG.listeners.length).toBe(listenerCnt + 3) // added listeners on 3 different elements + expect(Object.keys(rect.events['event']['*'])).toBeUndefined() // no global listener on rect + expect(Object.keys(rect.events['event']['namespace1']).length).toBe( 1) // 1 namespaced listener on rect + expect(Object.keys(rect2.events['namespace2']).length).toBe(1) // 1 namespaced listener on rect2 + expect(Object.keys(rect3.events['event']['*']).length).toBe(1) // 1 gobal listener on rect3 + expect(Object.keys(rect3.events['event']['namespace3']).length).toBe(1) // 1 namespaced listener on rect3 }) it('applies the element as context', function() { rect.on('event', action).fire('event') @@ -115,7 +109,7 @@ describe('Event', function() { }) it('stores the listener for future reference', function() { rect.on('event', action) - expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*'][action._svgjsListenerId]).not.toBeUndefined() + expect(rect.events['event']['*'][action._svgjsListenerId]).not.toBeUndefined() }) it('returns the called element', function() { expect(rect.on('event', action)).toBe(rect) @@ -130,8 +124,8 @@ describe('Event', function() { }) it('detaches a specific event listener, all other still working', function() { - rect2 = draw.rect(100,100); - rect3 = draw.rect(100,100); + rect2 = draw.rect(100,100) + rect3 = draw.rect(100,100) rect.on('event', action) rect2.on('event', action) @@ -139,7 +133,7 @@ describe('Event', function() { rect.off('event', action) - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*']).length).toBe(0) + expect(Object.keys(rect.events['event']['*']).length).toBe(0) rect.fire('event') expect(toast).toBeNull() @@ -150,11 +144,11 @@ describe('Event', function() { rect3.fire('event') expect(butter).toBe('melting') - expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['*'][action]).toBeUndefined() + expect(rect.events['event']['*'][action]).toBeUndefined() }) it('detaches a specific namespaced event listener, all other still working', function() { - rect2 = draw.rect(100,100); - rect3 = draw.rect(100,100); + rect2 = draw.rect(100,100) + rect3 = draw.rect(100,100) rect.on('event.namespace', action) rect2.on('event.namespace', action) @@ -162,7 +156,8 @@ describe('Event', function() { rect.off('event.namespace', action) - expect(Object.keys(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['namespace']).length).toBe(0) + expect(Object.keys(rect.events['event']['namespace']).length).toBe(0) + expect(Object.keys(rect2.events['event']['namespace']).length).toBe(1) rect.fire('event') expect(toast).toBeNull() @@ -173,7 +168,7 @@ describe('Event', function() { rect3.fire('event') expect(butter).toBe('melting') - expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']['namespace'][action]).toBeUndefined() + expect(rect.events['event']['namespace'][action]).toBeUndefined() }) it('detaches all listeners for a specific namespace', function() { rect.on('event', action) @@ -192,7 +187,7 @@ describe('Event', function() { rect.fire('event') expect(toast).toBeNull() expect(butter).toBeNull() - expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]['event']).toBeUndefined() + expect(rect.events['event']).toBeUndefined() }) it('detaches all listeners without an argument', function() { rect.on('event', action) @@ -202,7 +197,20 @@ describe('Event', function() { rect.fire('click') expect(toast).toBeNull() expect(butter).toBeNull() - expect(SVG.listeners[SVG.handlerMap.indexOf(rect.node)]).toBeUndefined() + expect(Object.keys(rect.events).length).toBe(0) + }) + it('detaches multiple listeners at once', function() { + rect2 = draw.rect(100,100) + rect3 = draw.rect(100,100) + + rect.on('event.namespace bla foo.bar otherfoo.bar keepthis', action) + rect.off('event.namespace bla .bar') + + expect(Object.keys(rect.events['event']).length).toBe(0) + expect(rect.events['bla']).toBeUndefined() + expect(Object.keys(rect.events['foo']).length).toBe(0) + expect(Object.keys(rect.events['otherfoo']).length).toBe(0) + expect(Object.keys(rect.events['keepthis']['*']).length).toBe(1) }) it('returns the called element', function() { expect(rect.off('event', action)).toBe(rect) @@ -218,12 +226,23 @@ describe('Event', function() { expect('Should not error out').toBe(true) } - expect(SVG.handlerMap[SVG.handlerMap.indexOf(rect.node)]).toBe(undefined) + expect(Object.keys(rect.events).length).toBe(0) }) }) describe('fire()', function() { + it('calls dispatch with its parameters', function() { + var data = {} + rect.dispatch('event', data) + expect(rect.dispatch).toHaveBeenCalledWith('event', data) + }) + + it('returns the called element', function() { + expect(rect.fire('event')).toBe(rect) + }) + }) + describe('dispatch()', function() { beforeEach(function() { rect.on('event', action) }) @@ -234,9 +253,7 @@ describe('Event', function() { expect(toast).toBe('ready') expect(fruitsInDetail).toBe(null) }) - it('returns the called element', function() { - expect(rect.fire('event')).toBe(rect) - }) + it('fires event with additional data', function() { expect(fruitsInDetail).toBeNull() rect.fire('event', {apple:1}) @@ -248,27 +265,11 @@ describe('Event', function() { rect.fire(new window.CustomEvent('event')) expect(toast).toBe('ready') }) - it('makes the event cancelable', function() { + it('returns the dispatched event and makes it cancelable', function() { rect.on('event', function(e) { e.preventDefault() }) - rect.fire('event') - expect(rect._event.defaultPrevented).toBe(true) - }) - }) - - describe('event()', function() { - it('returns null when no event was fired', function() { - expect(rect.event()).toBe(null) - }) - it('returns the last fired event', function() { - var event = new window.CustomEvent('foo') - rect.fire(event) - expect(rect.event()).toBe(event) - - event = new window.CustomEvent('bar') - rect.fire(event) - expect(rect.event()).toBe(event) + expect(rect.dispatch('event').defaultPrevented).toBe(true) }) }) }) -- cgit v1.2.3 From 75c3893a7c7af76f9bb1fe9be72e03b99d17a1e0 Mon Sep 17 00:00:00 2001 From: Ulrich-Matthias Schäfer Date: Thu, 1 Mar 2018 12:42:16 +0100 Subject: fixed all that errors which come along when removing an object. Fixed tests, too and added isRoot test --- spec/SpecRunner.html | 1 - spec/spec/doc.js | 21 +++++++++++++++++++-- spec/spec/element.js | 3 ++- spec/spec/nested.js | 13 ------------- spec/spec/svg.js | 4 ++-- src/HtmlNode.js | 10 ++-------- src/boxes.js | 2 +- src/doc.js | 45 +++++++++++++++++++++++---------------------- src/element.js | 3 ++- src/flatten.js | 2 +- src/matrix.js | 2 +- src/parent.js | 6 ++---- src/parser.js | 2 +- src/svg.js | 8 +++++--- 14 files changed, 61 insertions(+), 61 deletions(-) delete mode 100644 spec/spec/nested.js (limited to 'spec') diff --git a/spec/SpecRunner.html b/spec/SpecRunner.html index 7461bdd..bd47626 100644 --- a/spec/SpecRunner.html +++ b/spec/SpecRunner.html @@ -78,7 +78,6 @@ - diff --git a/spec/spec/doc.js b/spec/spec/doc.js index 1e1c54c..5accd5b 100644 --- a/spec/spec/doc.js +++ b/spec/spec/doc.js @@ -16,11 +16,11 @@ describe('Doc', function() { expect(draw instanceof SVG.Doc).toBe(true) }) - it('returns itself as Doc', function() { + it('returns itself as Doc when root', function() { expect(draw.doc()).toBe(draw) }) - it('has a defs element', function() { + it('has a defs element when root', function() { expect(draw.defs() instanceof SVG.Defs).toBe(true) }) @@ -33,6 +33,23 @@ describe('Doc', function() { }) }) + describe('isRoot()', function() { + it('returns true when the doc is not attached to dom', function() { + expect(SVG().isRoot()).toBe(true) + }) + it('returns true when its outer element is not an svg element', function () { + expect(SVG().addTo(document.createElement('div')).isRoot()).toBe(true) + }) + it('returns true when its the root element of the dom', function () { + if(parserInDoc) { + expect(draw.isRoot()).toBe(true) + } + }) + it('returns false when parent is svg element', function () { + expect(SVG().addTo(SVG()).isRoot()).toBe(false) + }) + }) + describe('remove()', function() { it('removes the doc from the dom only if doc is not root element', function() { var cnt = window.document.querySelectorAll('svg').length diff --git a/spec/spec/element.js b/spec/spec/element.js index a5b26a1..53ed84f 100644 --- a/spec/spec/element.js +++ b/spec/spec/element.js @@ -476,11 +476,12 @@ describe('Element', function() { it('ungroups everything to the doc root when called on SVG.Doc / does not ungroup defs/parser', function() { draw.flatten() + expect(rect1.parent()).toBe(draw) expect(rect2.parent()).toBe(draw) expect(g1.node.parentNode).toBeFalsy() - expect(g1.node.parentNode).toBeFalsy() + expect(g2.node.parentNode).toBeFalsy() expect(nested.node.parentNode).toBeFalsy() expect(rect1.transform()).toEqual(jasmine.objectContaining({ diff --git a/spec/spec/nested.js b/spec/spec/nested.js deleted file mode 100644 index 3113880..0000000 --- a/spec/spec/nested.js +++ /dev/null @@ -1,13 +0,0 @@ -describe('Nested', function() { - - afterEach(function() { - draw.clear() - }) - - describe('()', function() { - it('creates a nested svg of type SVG.Nested', function() { - expect(draw.nested() instanceof SVG.Nested).toBeTruthy() - }) - }) - -}) diff --git a/spec/spec/svg.js b/spec/spec/svg.js index 2485a32..ea51703 100644 --- a/spec/spec/svg.js +++ b/spec/spec/svg.js @@ -52,10 +52,10 @@ describe('SVG', function() { expect(SVG(rect).node).toBe(rect) }) - it('creates an instanceof SVG.Nested when importing a whole svg', function() { + it('creates an instanceof SVG.Doc when importing a whole svg', function() { var doc = SVG('') - expect(doc instanceof SVG.Nested).toBe(true) + expect(doc instanceof SVG.Doc).toBe(true) expect(doc.node.nodeName).toBe('svg') expect(doc.width()).toBe(200) expect(doc.get(0).node.nodeName).toBe('rect') diff --git a/src/HtmlNode.js b/src/HtmlNode.js index 30cb4cf..e7dae10 100644 --- a/src/HtmlNode.js +++ b/src/HtmlNode.js @@ -8,15 +8,9 @@ SVG.HtmlNode = SVG.invent({ extend: { add: function (element, i) { element = createElement(element) - if (element instanceof SVG.Nested) { - element = new SVG.Doc(element.node) - element.setData(JSON.parse(element.node.getAttribute('svgjs:data')) || {}) - } - if (i === null) { - this.node.appendChild(element.node) - } else if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i]) + if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null) } return this diff --git a/src/boxes.js b/src/boxes.js index a5ca1e8..f0154bd 100644 --- a/src/boxes.js +++ b/src/boxes.js @@ -127,7 +127,7 @@ SVG.Box = SVG.invent({ } }) -SVG.extend([SVG.Doc, SVG.Nested, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], { +SVG.extend([SVG.Doc, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View], { viewbox: function (x, y, width, height) { // act as getter if (x == null) return new SVG.Box(this.attr('viewBox')) diff --git a/src/doc.js b/src/doc.js index d4bf7e5..72ea59c 100644 --- a/src/doc.js +++ b/src/doc.js @@ -4,7 +4,7 @@ SVG.Doc = SVG.invent({ this.constructor(node || SVG.create('svg')) // set svg element attributes and ensure defs node - this.namespace().defs() + this.namespace() }, // Inherit from @@ -12,40 +12,41 @@ SVG.Doc = SVG.invent({ // Add class methods extend: { - isRoot: function() { - return !this.node.parentNode || !this.node.parentNode instanceof window.SVGElement || this.node.parentNode.nodeName == '#document' + isRoot: function () { + return !this.node.parentNode || !(this.node.parentNode instanceof window.SVGElement) || this.node.parentNode.nodeName === '#document' }, - doc: function() { - if(this.isRoot()) return this - - var parent - while(parent = this.parent(SVG.Doc)) { - if(parent.isRoot()) return parent - } - - // this can only happen when you have something like - // ... - return null + // Check if this is a root svg. If not, call docs from this element + doc: function () { + if (this.isRoot()) return this + return SVG.Element.prototype.doc.call(this) }, // Add namespaces - namespace: function() { - if(!this.isRoot()) return this.doc().namespace() + namespace: function () { + if (!this.isRoot()) return this.doc().namespace() return this .attr({ xmlns: SVG.ns, version: '1.1' }) .attr('xmlns:xlink', SVG.xlink, SVG.xmlns) .attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns) }, // Creates and returns defs element - defs: function() { - if(!this.isRoot()) return this.doc().defs() + defs: function () { + if (!this.isRoot()) return this.doc().defs() return SVG.adopt(this.node.getElementsByTagName('defs')[0]) || this.put(new SVG.Defs()) }, // custom parent method - parent: function () { - return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode + parent: function (type) { + if (this.isRoot()) { + return this.node.parentNode.nodeName === '#document' ? null : this.node.parentNode + } + + return SVG.Element.prototype.parent.call(this, type) }, // Removes the doc from the DOM remove: function () { + if (!this.isRoot()) { + return SVG.Element.prototype.remove.call(this) + } + if (this.parent()) { this.parent().removeChild(this.node) } @@ -62,8 +63,8 @@ SVG.Doc = SVG.invent({ }, construct: { // Create nested svg document - nested: function() { - return this.put(new SVG.Doc) + nested: function () { + return this.put(new SVG.Doc()) } } }) diff --git a/src/element.js b/src/element.js index e7b5326..0d08579 100644 --- a/src/element.js +++ b/src/element.js @@ -218,7 +218,8 @@ SVG.Element = SVG.invent({ // Get parent document doc: function () { - return this.parent(SVG.Doc).doc() + var p = this.parent(SVG.Doc) + return p && p.doc() }, // Get defs diff --git a/src/flatten.js b/src/flatten.js index 1c32a76..3ba6e22 100644 --- a/src/flatten.js +++ b/src/flatten.js @@ -2,7 +2,7 @@ SVG.extend(SVG.Parent, { flatten: function (parent) { if (this instanceof SVG.Defs) return this - parent = parent || (this instanceof SVG.Doc ? this : this.parent(SVG.Parent)) + parent = parent || (this instanceof SVG.Doc && this.isRoot() ? this : this.parent(SVG.Parent)) this.each(function () { if (this instanceof SVG.Defs) return this diff --git a/src/matrix.js b/src/matrix.js index 6e918d8..e823a81 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -185,7 +185,7 @@ SVG.Matrix = SVG.invent({ This is needed because FF does not return the transformation matrix for the inner coordinate system when getScreenCTM() is called on nested svgs. However all other Browsers do that */ - if (this instanceof SVG.Nested) { + if (this instanceof SVG.Doc && !this.isRoot()) { var rect = this.rect(1, 1) var m = rect.node.getScreenCTM() rect.remove() diff --git a/src/parent.js b/src/parent.js index 0ff1765..d48e086 100644 --- a/src/parent.js +++ b/src/parent.js @@ -21,10 +21,8 @@ SVG.Parent = SVG.invent({ add: function (element, i) { element = createElement(element) - if (i == null) { - this.node.appendChild(element.node) - } else if (element.node !== this.node.children[i]) { - this.node.insertBefore(element.node, this.node.children[i]) + if (element.node !== this.node.children[i]) { + this.node.insertBefore(element.node, this.node.children[i] || null) } return this diff --git a/src/parser.js b/src/parser.js index c3ab7a4..84c8d77 100644 --- a/src/parser.js +++ b/src/parser.js @@ -11,7 +11,7 @@ SVG.parser = function () { } SVG.parser.nodes = { - svg: new SVG.Nested().size(2, 0).css({ + svg: SVG().size(2, 0).css({ opacity: 0, position: 'absolute', left: '-100%', diff --git a/src/svg.js b/src/svg.js index 4cb6f26..9b3bfd6 100644 --- a/src/svg.js +++ b/src/svg.js @@ -87,13 +87,15 @@ SVG.adopt = function (node) { var element // adopt with element-specific settings - if (node.nodeName == 'svg') + if (node.nodeName === 'svg') { element = new SVG.Doc(node) - else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') + } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { element = new SVG.Gradient(node) } else if (SVG[capitalize(node.nodeName)]) { element = new SVG[capitalize(node.nodeName)](node) - } else { element = new SVG.Parent(node) } + } else { + element = new SVG.Parent(node) + } return element } -- cgit v1.2.3