added new destroy Node method which removes and destroys a node. remove() now simply removes a node from the stage. You can re add the node at a later time with add(). getDOM() changed to getContent(). stage.remove() now correctly removes content node

This commit is contained in:
Eric Rowell
2013-01-12 22:01:12 -08:00
parent 4136ddb398
commit ed579e4843
8 changed files with 231 additions and 115 deletions

View File

@@ -40,8 +40,6 @@
*/
add: function(child) {
var go = Kinetic.Global, children = this.children;
child._id = Kinetic.Global.idCounter++;
child.index = children.length;
child.parent = this;
children.push(child);

View File

@@ -7,7 +7,7 @@
* @param {Object} config
* @param {Boolean} [config.clearBeforeDraw] set this property to false if you don't want
* to clear the canvas before each layer draw. The default value is true.
*
*
* @param {Number} [config.x]
* @param {Number} [config.y]
* @param {Number} [config.width]
@@ -101,7 +101,7 @@
}
// otherwise get data url of the currently drawn layer
else {
return this.getCanvas().toDataURL(mimeType, quality);
return this.getCanvas().toDataURL(mimeType, quality);
}
},
/**
@@ -222,17 +222,11 @@
* remove layer from stage
*/
remove: function() {
var stage = this.getStage();
var stage = this.getStage(), canvas = this.canvas, element = canvas.element;
Kinetic.Node.prototype.remove.call(this);
/*
* remove canvas DOM from the document if
* it exists
*/
try {
stage.content.removeChild(this.canvas.element);
}
catch(e) {
Kinetic.Global.warn('unable to remove layer scene canvas element from the document');
if(stage && canvas && Kinetic.Type._isInDocument(element)) {
stage.content.removeChild(element);
}
}
};

View File

@@ -30,6 +30,8 @@
Kinetic.Node.prototype = {
_nodeInit: function(config) {
this._id = Kinetic.Global.idCounter++;
this.defaultNodeAttrs = {
visible: true,
listening: true,
@@ -147,38 +149,44 @@
}
},
/**
* remove child from container
* remove child from container, but don't destroy it
* @name remove
* @methodOf Kinetic.Node.prototype
*/
remove: function() {
var parent = this.getParent();
if(parent && this.index !== undefined && parent.children[this.index]._id == this._id) {
var stage = parent.getStage();
/*
* remove event listeners and references to the node
* from the ids and names hashes
*/
if(stage) {
stage._removeId(this.getId());
stage._removeName(this.getName(), this._id);
}
Kinetic.Global._removeTempNode(this);
if(parent && parent.children) {
parent.children.splice(this.index, 1);
parent._setChildrenIndices();
}
delete this.parent;
},
/**
* remove and destroy node
* @name destroy
* @methodOf Kinetic.Node.prototype
*/
destroy: function() {
// destroy children
while(this.children && this.children.length > 0) {
this.children[0].destroy();
}
// remove from DD
var dd = Kinetic.DD;
if(dd && dd.node && dd.node._id === this._id) {
delete Kinetic.DD.node;
}
var parent = this.getParent(), stage = this.getStage(), dd = Kinetic.DD;
this.remove();
// remove children
while(this.children && this.children.length > 0) {
this.children[0].remove();
}
delete this.parent;
// remove ids and names hashes
if(stage) {
stage._removeId(this.getId());
stage._removeName(this.getName(), this._id);
}
// remove from temp nodes
Kinetic.Global._removeTempNode(this);
// remove from DD
if(dd && dd.node && dd.node._id === this._id) {
delete Kinetic.DD.node;
}
},
/**

View File

@@ -108,6 +108,17 @@
layers[n].clear();
}
},
/**
* remove stage
*/
remove: function() {
var content = this.content;
Kinetic.Node.prototype.remove.call(this);
if(content && Kinetic.Type._isInDocument(content)) {
this.attrs.container.removeChild(content);
}
},
/**
* reset stage to default state
* @name reset
@@ -154,12 +165,12 @@
return this;
},
/**
* get stage DOM node which is a div element
* with the class name "kineticjs-content"
* @name getDOM
* get stage content div element which has the
* the class name "kineticjs-content"
* @name getContent
* @methodOf Kinetic.Stage.prototype
*/
getDOM: function() {
getContent: function() {
return this.content;
},
/**

View File

@@ -35,6 +35,14 @@
}
return names.length > 0;
},
_isInDocument: function(el) {
while( el = el.parentNode) {
if(el == document) {
return true;
}
}
return false;
},
/*
* The argument can be:
* - an integer (will be applied to both x and y)

View File

@@ -90,60 +90,6 @@ Test.Modules.CONTAINER = {
test(node.nodeType === 'Layer', 'node type should be Layer');
},
'remove shape by id or name': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
id: 'myCircle'
});
var rect = new Kinetic.Rect({
x: 300,
y: 100,
width: 100,
height: 50,
fill: 'purple',
stroke: 'black',
strokeWidth: 4,
name: 'myRect'
});
var circleColorKey = circle.colorKey;
var rectColorKey = rect.colorKey;
layer.add(circle);
layer.add(rect);
stage.add(layer);
test(stage.ids.myCircle._id === circle._id, 'circle not in ids hash');
test(stage.names.myRect[0]._id === rect._id, 'rect not in names hash');
test(Kinetic.Global.shapes[circleColorKey]._id === circle._id, 'circle color key should be in shapes hash');
test(Kinetic.Global.shapes[rectColorKey]._id === rect._id, 'rect color key should be in shapes hash');
circle.remove();
test(stage.ids.myCircle === undefined, 'circle still in hash');
test(stage.names.myRect[0]._id === rect._id, 'rect not in names hash');
test(Kinetic.Global.shapes[circleColorKey] === undefined, 'circle color key should not be in shapes hash');
test(Kinetic.Global.shapes[rectColorKey]._id === rect._id, 'rect color key should be in shapes hash');
rect.remove();
test(stage.ids.myCircle === undefined, 'circle still in hash');
test(stage.names.myRect === undefined, 'rect still in hash');
test(Kinetic.Global.shapes[circleColorKey] === undefined, 'circle color key should not be in shapes hash');
test(Kinetic.Global.shapes[rectColorKey] === undefined, 'rect color key should not be in shapes hash');
},
'set x on an array of nodes': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,

View File

@@ -421,8 +421,8 @@ Test.Modules.NODE = {
rect.setSize(210);
rect.setShadowOffset({
x: 20
});
x: 20
});
test(widthChanged === 1, 'width change event was not fired correctly');
test(shadowChanged === 1, 'shadow change event not fired correctly');
@@ -1098,23 +1098,23 @@ Test.Modules.NODE = {
test(rect.getShadowBlur() === 12, 'shadow blur should still be 12');
rect.setShadowOffset({
x: 3,
y: 4
x: 3,
y: 4
});
test(rect.getShadowOffset().x === 3, 'shadow offset x should be 3');
test(rect.getShadowOffset().y === 4, 'shadow offset y should be 4');
// test partial setting
rect.setShadowOffset({
x: 5
x: 5
});
test(rect.getShadowOffset().x === 5, 'shadow offset x should be 5');
test(rect.getShadowOffset().y === 4, 'shadow offset y should be 4');
// test partial setting
rect.setShadowOffset({
y: 6
});
y: 6
});
test(rect.getShadowOffset().x === 5, 'shadow offset x should be 5');
test(rect.getShadowOffset().y === 6, 'shadow offset y should be 6');
@@ -2197,13 +2197,42 @@ Test.Modules.NODE = {
circle.remove();
test(layer.children.length === 0, 'layer should have 0 children');
//test(layer.getChild('myCircle') === undefined, 'shape should be null');
layer.draw();
test(circle.getParent() === undefined, 'circle parent should be undefined');
},
'remove shape without adding its parent to stage': function(containerId) {
'destroy shape': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
name: 'myCircle'
});
layer.add(circle);
stage.add(layer);
test(layer.children.length === 1, 'layer should have 1 children');
circle.destroy();
test(layer.children.length === 0, 'layer should have 0 children');
layer.draw();
test(circle.getParent() === undefined, 'circle parent should be undefined');
},
'destroy shape without adding its parent to stage': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
@@ -2232,12 +2261,12 @@ Test.Modules.NODE = {
test(go.tempNodes[circle._id].attrs.id === 'myCircle', 'circle should be in temp nodes');
circle.remove();
circle.destroy();
test(go.tempNodes[circle._id] === undefined, 'circle shouldn\'t be in the temp nodes hash');
},
'remove layer with shape': function(containerId) {
'destroy layer with shape': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
@@ -2263,7 +2292,7 @@ Test.Modules.NODE = {
test(stage.get('.myLayer')[0] !== undefined, 'layer should exist');
test(stage.get('.myCircle')[0] !== undefined, 'circle should exist');
layer.remove();
layer.destroy();
test(stage.children.length === 0, 'stage should have 0 children');
test(stage.get('.myLayer')[0] === undefined, 'layer should not exist');
@@ -2271,7 +2300,75 @@ Test.Modules.NODE = {
stage.draw();
},
'remove layer with no shapes': function(containerId) {
'destroy stage with layer and shape': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer({
name: 'myLayer'
});
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
name: 'myCircle'
});
layer.add(circle);
stage.add(layer);
stage.destroy();
test(layer.getParent() === undefined, 'layer parent should be undefined');
test(circle.getParent() === undefined, 'circle parent should be undefined');
test(stage.children.length === 0, 'stage children length should be 0');
test(layer.children.length === 0, 'layer children length should be 0');
},
'destroy group with shape': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer({
name: 'myLayer'
});
var group = new Kinetic.Group({
name: 'myGroup'
});
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
name: 'myCircle'
});
group.add(circle);
layer.add(group);
stage.add(layer);
test(layer.getChildren().length === 1, 'layer should have 1 children');
test(stage.get('.myGroup')[0] !== undefined, 'group should exist');
test(stage.get('.myCircle')[0] !== undefined, 'circle should exist');
group.destroy();
test(layer.children.length === 0, 'layer should have 0 children');
test(stage.get('.myGroup')[0] === undefined, 'group should not exist');
test(stage.get('.myCircle')[0] === undefined, 'circle should not exist');
stage.draw();
},
'destroy layer with no shapes': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
@@ -2279,11 +2376,11 @@ Test.Modules.NODE = {
});
var layer = new Kinetic.Layer();
stage.add(layer);
layer.remove();
layer.destroy();
test(stage.children.length === 0, 'stage should have 0 children');
},
'remove shape multiple times': function(containerId) {
'destroy shape multiple times': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
@@ -2312,8 +2409,8 @@ Test.Modules.NODE = {
test(layer.getChildren().length === 2, 'layer should have two children');
shape1.remove();
shape1.remove();
shape1.destroy();
shape1.destroy();
test(layer.getChildren().length === 1, 'layer should have two children');
@@ -2359,5 +2456,59 @@ Test.Modules.NODE = {
stage.draw();
},
'destroy shape by id or name': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
id: 'myCircle'
});
var rect = new Kinetic.Rect({
x: 300,
y: 100,
width: 100,
height: 50,
fill: 'purple',
stroke: 'black',
strokeWidth: 4,
name: 'myRect'
});
var circleColorKey = circle.colorKey;
var rectColorKey = rect.colorKey;
layer.add(circle);
layer.add(rect);
stage.add(layer);
test(stage.ids.myCircle._id === circle._id, 'circle not in ids hash');
test(stage.names.myRect[0]._id === rect._id, 'rect not in names hash');
test(Kinetic.Global.shapes[circleColorKey]._id === circle._id, 'circle color key should be in shapes hash');
test(Kinetic.Global.shapes[rectColorKey]._id === rect._id, 'rect color key should be in shapes hash');
circle.destroy();
test(stage.ids.myCircle === undefined, 'circle still in hash');
test(stage.names.myRect[0]._id === rect._id, 'rect not in names hash');
test(Kinetic.Global.shapes[circleColorKey] === undefined, 'circle color key should not be in shapes hash');
test(Kinetic.Global.shapes[rectColorKey]._id === rect._id, 'rect color key should be in shapes hash');
rect.destroy();
test(stage.ids.myCircle === undefined, 'circle still in hash');
test(stage.names.myRect === undefined, 'rect still in hash');
test(Kinetic.Global.shapes[circleColorKey] === undefined, 'circle color key should not be in shapes hash');
test(Kinetic.Global.shapes[rectColorKey] === undefined, 'rect color key should not be in shapes hash');
}
};

View File

@@ -62,8 +62,8 @@ Test.Modules.STAGE = {
test(stage.getSize().width === 333, 'stage width should be 333');
test(stage.getSize().height === 155, 'stage height should be 155');
test(stage.getDOM().style.width === '333px', 'content width should be 333');
test(stage.getDOM().style.height === '155px', 'content height should be 155px');
test(stage.getContent().style.width === '333px', 'content width should be 333');
test(stage.getContent().style.height === '155px', 'content height should be 155px');
test(layer.getCanvas().element.width === 333, 'layer canvas element width should be 333');
test(layer.getCanvas().element.height === 155, 'layer canvas element width should be 155');
},
@@ -105,7 +105,7 @@ Test.Modules.STAGE = {
height: 200
});
test(stage.getDOM().className === 'kineticjs-content', 'stage DOM class name is wrong');
test(stage.getContent().className === 'kineticjs-content', 'stage DOM class name is wrong');
},
'test getIntersections': function(containerId) {
var stage = new Kinetic.Stage({