mirror of
https://github.com/konvajs/konva.git
synced 2025-06-28 15:23:44 +08:00
ids and names hashes used for node selection via get() has moved to Global in order to greatly simplify the selection logic. This means that node ids and names are shared across all stages. If two stages each have a node with the same id, only the last id set will be accessibile (similar to DOM)
This commit is contained in:
parent
f5f2fbaba9
commit
b6ba1a503c
@ -43,21 +43,6 @@
|
|||||||
child.index = children.length;
|
child.index = children.length;
|
||||||
child.parent = this;
|
child.parent = this;
|
||||||
children.push(child);
|
children.push(child);
|
||||||
var stage = child.getStage();
|
|
||||||
|
|
||||||
if(!stage) {
|
|
||||||
go._addTempNode(child);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stage._addId(child);
|
|
||||||
stage._addName(child);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pull in other nodes that are now linked
|
|
||||||
* to a stage
|
|
||||||
*/
|
|
||||||
go._pullNodes(stage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// chainable
|
// chainable
|
||||||
return this;
|
return this;
|
||||||
@ -99,14 +84,14 @@
|
|||||||
return collection;
|
return collection;
|
||||||
},
|
},
|
||||||
_getNodeById: function(key) {
|
_getNodeById: function(key) {
|
||||||
var stage = this.getStage();
|
var stage = this.getStage(), go = Kinetic.Global, node = go.ids[key];
|
||||||
if(stage.ids[key] !== undefined && this.isAncestorOf(stage.ids[key])) {
|
if(node !== undefined && this.isAncestorOf(node)) {
|
||||||
return stage.ids[key];
|
return node;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
_getNodesByName: function(key) {
|
_getNodesByName: function(key) {
|
||||||
var arr = this.getStage().names[key] || [];
|
var go = Kinetic.Global, arr = go.names[key] || [];
|
||||||
return this._getDescendants(arr);
|
return this._getDescendants(arr);
|
||||||
},
|
},
|
||||||
_get: function(selector) {
|
_get: function(selector) {
|
||||||
|
@ -28,8 +28,7 @@
|
|||||||
/**
|
/**
|
||||||
* @namespace
|
* @namespace
|
||||||
*/
|
*/
|
||||||
var Kinetic = {};
|
var Kinetic = {}; (function() {
|
||||||
(function() {
|
|
||||||
Kinetic.version = '@version';
|
Kinetic.version = '@version';
|
||||||
/**
|
/**
|
||||||
* @namespace
|
* @namespace
|
||||||
@ -39,7 +38,8 @@ var Kinetic = {};
|
|||||||
Kinetic.Global = {
|
Kinetic.Global = {
|
||||||
stages: [],
|
stages: [],
|
||||||
idCounter: 0,
|
idCounter: 0,
|
||||||
tempNodes: {},
|
ids: {},
|
||||||
|
names: {},
|
||||||
//shapes hash. rgb keys and shape values
|
//shapes hash. rgb keys and shape values
|
||||||
shapes: {},
|
shapes: {},
|
||||||
warn: function(str) {
|
warn: function(str) {
|
||||||
@ -58,22 +58,39 @@ var Kinetic = {};
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_pullNodes: function(stage) {
|
_addId: function(node, id) {
|
||||||
var tempNodes = this.tempNodes;
|
if(id !== undefined) {
|
||||||
for(var key in tempNodes) {
|
this.ids[id] = node;
|
||||||
var node = tempNodes[key];
|
|
||||||
if(node.getStage() !== undefined && node.getStage()._id === stage._id) {
|
|
||||||
stage._addId(node);
|
|
||||||
stage._addName(node);
|
|
||||||
this._removeTempNode(node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_addTempNode: function(node) {
|
_removeId: function(id) {
|
||||||
this.tempNodes[node._id] = node;
|
if(id !== undefined) {
|
||||||
|
delete this.ids[id];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_removeTempNode: function(node) {
|
_addName: function(node, name) {
|
||||||
delete this.tempNodes[node._id];
|
if(name !== undefined) {
|
||||||
|
if(this.names[name] === undefined) {
|
||||||
|
this.names[name] = [];
|
||||||
|
}
|
||||||
|
this.names[name].push(node);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_removeName: function(name, _id) {
|
||||||
|
if(name !== undefined) {
|
||||||
|
var nodes = this.names[name];
|
||||||
|
if(nodes !== undefined) {
|
||||||
|
for(var n = 0; n < nodes.length; n++) {
|
||||||
|
var no = nodes[n];
|
||||||
|
if(no._id === _id) {
|
||||||
|
nodes.splice(n, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nodes.length === 0) {
|
||||||
|
delete this.names[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
89
src/Node.js
89
src/Node.js
@ -55,23 +55,6 @@
|
|||||||
this.setDefaultAttrs(this.defaultNodeAttrs);
|
this.setDefaultAttrs(this.defaultNodeAttrs);
|
||||||
this.eventListeners = {};
|
this.eventListeners = {};
|
||||||
this.setAttrs(config);
|
this.setAttrs(config);
|
||||||
|
|
||||||
// bind events
|
|
||||||
var that = this;
|
|
||||||
this.on('idChange.kinetic', function(evt) {
|
|
||||||
var stage = that.getStage();
|
|
||||||
if(stage) {
|
|
||||||
stage._removeId(evt.oldVal);
|
|
||||||
stage._addId(that);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.on('nameChange.kinetic', function(evt) {
|
|
||||||
var stage = that.getStage();
|
|
||||||
if(stage) {
|
|
||||||
stage._removeName(evt.oldVal, that._id);
|
|
||||||
stage._addName(that);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* bind events to the node. KineticJS supports mouseover, mousemove,
|
* bind events to the node. KineticJS supports mouseover, mousemove,
|
||||||
@ -167,22 +150,18 @@
|
|||||||
* @methodOf Kinetic.Node.prototype
|
* @methodOf Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
|
var parent = this.getParent(), stage = this.getStage(), dd = Kinetic.DD, go = Kinetic.Global;
|
||||||
|
|
||||||
|
this.remove();
|
||||||
|
|
||||||
// destroy children
|
// destroy children
|
||||||
while(this.children && this.children.length > 0) {
|
while(this.children && this.children.length > 0) {
|
||||||
this.children[0].destroy();
|
this.children[0].destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = this.getParent(), stage = this.getStage(), dd = Kinetic.DD;
|
// remove from ids and names hashes
|
||||||
this.remove();
|
go._removeId(this.getId());
|
||||||
|
go._removeName(this.getName(), this._id);
|
||||||
// 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
|
// remove from DD
|
||||||
if(dd && dd.node && dd.node._id === this._id) {
|
if(dd && dd.node && dd.node._id === this._id) {
|
||||||
@ -558,16 +537,8 @@
|
|||||||
* @param {Container} newContainer
|
* @param {Container} newContainer
|
||||||
*/
|
*/
|
||||||
moveTo: function(newContainer) {
|
moveTo: function(newContainer) {
|
||||||
var parent = this.parent;
|
Kinetic.Node.prototype.remove.call(this);
|
||||||
// remove from parent's children
|
newContainer.add(this);
|
||||||
parent.children.splice(this.index, 1);
|
|
||||||
parent._setChildrenIndices();
|
|
||||||
|
|
||||||
// add to new parent
|
|
||||||
newContainer.children.push(this);
|
|
||||||
this.index = newContainer.children.length - 1;
|
|
||||||
this.parent = newContainer;
|
|
||||||
newContainer._setChildrenIndices();
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* convert Node into an object for serialization. Returns an object.
|
* convert Node into an object for serialization. Returns an object.
|
||||||
@ -892,6 +863,30 @@
|
|||||||
newVal: newVal
|
newVal: newVal
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* set id
|
||||||
|
* @name setId
|
||||||
|
* @methodOf Kinetic.Node.prototype
|
||||||
|
* @param {String} id
|
||||||
|
*/
|
||||||
|
setId: function(id) {
|
||||||
|
var oldId = this.getId(), stage = this.getStage(), go = Kinetic.Global;
|
||||||
|
go._removeId(oldId);
|
||||||
|
go._addId(this, id);
|
||||||
|
this.setAttr('id', id);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* set name
|
||||||
|
* @name setName
|
||||||
|
* @methodOf Kinetic.Node.prototype
|
||||||
|
* @param {String} name
|
||||||
|
*/
|
||||||
|
setName: function(name) {
|
||||||
|
var oldName = this.getName(), stage = this.getStage(), go = Kinetic.Global;
|
||||||
|
go._removeName(oldName, this._id);
|
||||||
|
go._addName(this, name);
|
||||||
|
this.setAttr('name', name);
|
||||||
|
},
|
||||||
setAttr: function(key, val) {
|
setAttr: function(key, val) {
|
||||||
if(val !== undefined) {
|
if(val !== undefined) {
|
||||||
var oldVal = this.attrs[key];
|
var oldVal = this.attrs[key];
|
||||||
@ -1090,7 +1085,7 @@
|
|||||||
return no;
|
return no;
|
||||||
};
|
};
|
||||||
// add getters setters
|
// add getters setters
|
||||||
Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'opacity', 'name', 'id']);
|
Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'opacity']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set x position
|
* set x position
|
||||||
@ -1115,20 +1110,6 @@
|
|||||||
* @param {Object} opacity
|
* @param {Object} opacity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* set name
|
|
||||||
* @name setName
|
|
||||||
* @methodOf Kinetic.Node.prototype
|
|
||||||
* @param {String} name
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set id
|
|
||||||
* @name setId
|
|
||||||
* @methodOf Kinetic.Node.prototype
|
|
||||||
* @param {String} id
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get x position
|
* get x position
|
||||||
* @name getX
|
* @name getX
|
||||||
@ -1147,6 +1128,8 @@
|
|||||||
* @methodOf Kinetic.Node.prototype
|
* @methodOf Kinetic.Node.prototype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Kinetic.Node.addGetters(Kinetic.Node, ['name', 'id']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get name
|
* get name
|
||||||
* @name getName
|
* @name getName
|
||||||
|
50
src/Stage.js
50
src/Stage.js
@ -46,8 +46,6 @@
|
|||||||
this._buildDOM();
|
this._buildDOM();
|
||||||
this._bindContentEvents();
|
this._bindContentEvents();
|
||||||
Kinetic.Global.stages.push(this);
|
Kinetic.Global.stages.push(this);
|
||||||
this._addId(this);
|
|
||||||
this._addName(this);
|
|
||||||
|
|
||||||
if(Kinetic.DD) {
|
if(Kinetic.DD) {
|
||||||
this._initDragLayer();
|
this._initDragLayer();
|
||||||
@ -283,12 +281,6 @@
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
_getNodeById: function(key) {
|
|
||||||
return this.ids[key] || null;
|
|
||||||
},
|
|
||||||
_getNodesByName: function(key) {
|
|
||||||
return this.names[key] || [];
|
|
||||||
},
|
|
||||||
_resizeDOM: function() {
|
_resizeDOM: function() {
|
||||||
if(this.content) {
|
if(this.content) {
|
||||||
var width = this.attrs.width;
|
var width = this.attrs.width;
|
||||||
@ -582,41 +574,6 @@
|
|||||||
|
|
||||||
this._resizeDOM();
|
this._resizeDOM();
|
||||||
},
|
},
|
||||||
_addId: function(node) {
|
|
||||||
if(node.attrs.id !== undefined) {
|
|
||||||
this.ids[node.attrs.id] = node;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_removeId: function(id) {
|
|
||||||
if(id !== undefined) {
|
|
||||||
delete this.ids[id];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_addName: function(node) {
|
|
||||||
var name = node.attrs.name;
|
|
||||||
if(name !== undefined) {
|
|
||||||
if(this.names[name] === undefined) {
|
|
||||||
this.names[name] = [];
|
|
||||||
}
|
|
||||||
this.names[name].push(node);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_removeName: function(name, _id) {
|
|
||||||
if(name !== undefined) {
|
|
||||||
var nodes = this.names[name];
|
|
||||||
if(nodes !== undefined) {
|
|
||||||
for(var n = 0; n < nodes.length; n++) {
|
|
||||||
var no = nodes[n];
|
|
||||||
if(no._id === _id) {
|
|
||||||
nodes.splice(n, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(nodes.length === 0) {
|
|
||||||
delete this.names[name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* bind event listener to container DOM element
|
* bind event listener to container DOM element
|
||||||
* @param {String} typesStr
|
* @param {String} typesStr
|
||||||
@ -640,13 +597,6 @@
|
|||||||
this.clickStart = false;
|
this.clickStart = false;
|
||||||
this.touchPos = undefined;
|
this.touchPos = undefined;
|
||||||
this.tapStart = false;
|
this.tapStart = false;
|
||||||
|
|
||||||
/*
|
|
||||||
* ids and names hash needs to be stored at the stage level to prevent
|
|
||||||
* id and name collisions between multiple stages in the document
|
|
||||||
*/
|
|
||||||
this.ids = {};
|
|
||||||
this.names = {};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Kinetic.Global.extend(Kinetic.Stage, Kinetic.Container);
|
Kinetic.Global.extend(Kinetic.Stage, Kinetic.Container);
|
||||||
|
@ -798,7 +798,8 @@ Test.Modules.MANUAL = {
|
|||||||
x: 5,
|
x: 5,
|
||||||
y: 5
|
y: 5
|
||||||
},
|
},
|
||||||
draggable: true
|
draggable: true,
|
||||||
|
name: 'star'
|
||||||
});
|
});
|
||||||
|
|
||||||
layer.add(star);
|
layer.add(star);
|
||||||
|
@ -236,7 +236,7 @@ Test.Modules.CONTAINER = {
|
|||||||
fill: 'green',
|
fill: 'green',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 4,
|
strokeWidth: 4,
|
||||||
id: 'myCircle'
|
id: 'myCircle3'
|
||||||
});
|
});
|
||||||
|
|
||||||
var rect = new Kinetic.Rect({
|
var rect = new Kinetic.Rect({
|
||||||
@ -247,23 +247,25 @@ Test.Modules.CONTAINER = {
|
|||||||
fill: 'purple',
|
fill: 'purple',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 4,
|
strokeWidth: 4,
|
||||||
name: 'myRect'
|
name: 'myRect3'
|
||||||
});
|
});
|
||||||
|
|
||||||
layer.add(circle);
|
layer.add(circle);
|
||||||
layer.add(rect);
|
layer.add(rect);
|
||||||
stage.add(layer);
|
stage.add(layer);
|
||||||
|
|
||||||
test(stage.ids['myCircle'].getId() === 'myCircle', 'circle id not in ids hash');
|
var go = Kinetic.Global;
|
||||||
test(stage.names['myRect'][0].getName() === 'myRect', 'rect name not in names hash');
|
|
||||||
|
test(go.ids['myCircle3'].getId() === 'myCircle3', 'circle id not in ids hash');
|
||||||
|
test(go.names['myRect3'][0].getName() === 'myRect3', 'rect name not in names hash');
|
||||||
|
|
||||||
circle.setId('newCircleId');
|
circle.setId('newCircleId');
|
||||||
test(stage.ids['newCircleId'] !== undefined, 'circle not in ids hash');
|
test(go.ids['newCircleId'] !== undefined, 'circle not in ids hash');
|
||||||
test(stage.ids['myCircle'] === undefined, 'old circle id key is still in ids hash');
|
test(go.ids['myCircle3'] === undefined, 'old circle id key is still in ids hash');
|
||||||
|
|
||||||
rect.setName('newRectName');
|
rect.setName('newRectName');
|
||||||
test(stage.names['newRectName'][0] !== undefined, 'new rect name not in names hash');
|
test(go.names['newRectName'][0] !== undefined, 'new rect name not in names hash');
|
||||||
test(stage.names['myRect'] === undefined, 'old rect name is still in names hash');
|
test(go.names['myRect3'] === undefined, 'old rect name is still in names hash');
|
||||||
},
|
},
|
||||||
'add layer': function(containerId) {
|
'add layer': function(containerId) {
|
||||||
var stage = new Kinetic.Stage({
|
var stage = new Kinetic.Stage({
|
||||||
|
@ -2252,20 +2252,14 @@ Test.Modules.NODE = {
|
|||||||
|
|
||||||
var go = Kinetic.Global;
|
var go = Kinetic.Global;
|
||||||
|
|
||||||
test(go.tempNodes[circle._id] === undefined, 'circle shouldn\'t be in the temp nodes hash');
|
|
||||||
|
|
||||||
layer.add(circle);
|
layer.add(circle);
|
||||||
|
|
||||||
var node = stage.get('#myCircle')[0];
|
var node = stage.get('#myCircle')[0];
|
||||||
|
|
||||||
test(node === undefined, 'node should be undefined');
|
test(node === undefined, 'node should be undefined');
|
||||||
|
|
||||||
test(go.tempNodes[circle._id].attrs.id === 'myCircle', 'circle should be in temp nodes');
|
|
||||||
|
|
||||||
circle.destroy();
|
circle.destroy();
|
||||||
|
|
||||||
test(go.tempNodes[circle._id] === undefined, 'circle shouldn\'t be in the temp nodes hash');
|
|
||||||
|
|
||||||
},
|
},
|
||||||
'destroy layer with shape': function(containerId) {
|
'destroy layer with shape': function(containerId) {
|
||||||
var stage = new Kinetic.Stage({
|
var stage = new Kinetic.Stage({
|
||||||
@ -2472,7 +2466,7 @@ Test.Modules.NODE = {
|
|||||||
fill: 'green',
|
fill: 'green',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 4,
|
strokeWidth: 4,
|
||||||
id: 'myCircle'
|
id: 'myCircle2'
|
||||||
});
|
});
|
||||||
|
|
||||||
var rect = new Kinetic.Rect({
|
var rect = new Kinetic.Rect({
|
||||||
@ -2483,32 +2477,33 @@ Test.Modules.NODE = {
|
|||||||
fill: 'purple',
|
fill: 'purple',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 4,
|
strokeWidth: 4,
|
||||||
name: 'myRect'
|
name: 'myRect2'
|
||||||
});
|
});
|
||||||
|
|
||||||
var circleColorKey = circle.colorKey;
|
var circleColorKey = circle.colorKey;
|
||||||
var rectColorKey = rect.colorKey;
|
var rectColorKey = rect.colorKey;
|
||||||
|
var go = Kinetic.Global;
|
||||||
|
|
||||||
layer.add(circle);
|
layer.add(circle);
|
||||||
layer.add(rect);
|
layer.add(rect);
|
||||||
stage.add(layer);
|
stage.add(layer);
|
||||||
|
|
||||||
test(stage.ids.myCircle._id === circle._id, 'circle not in ids hash');
|
test(go.ids.myCircle2._id === circle._id, 'circle not in ids hash');
|
||||||
test(stage.names.myRect[0]._id === rect._id, 'rect not in names hash');
|
test(go.names.myRect2[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[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');
|
test(Kinetic.Global.shapes[rectColorKey]._id === rect._id, 'rect color key should be in shapes hash');
|
||||||
|
|
||||||
circle.destroy();
|
circle.destroy();
|
||||||
|
|
||||||
test(stage.ids.myCircle === undefined, 'circle still in hash');
|
test(go.ids.myCircle2 === undefined, 'circle still in hash');
|
||||||
test(stage.names.myRect[0]._id === rect._id, 'rect not in names hash');
|
test(go.names.myRect2[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[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');
|
test(Kinetic.Global.shapes[rectColorKey]._id === rect._id, 'rect color key should be in shapes hash');
|
||||||
|
|
||||||
rect.destroy();
|
rect.destroy();
|
||||||
|
|
||||||
test(stage.ids.myCircle === undefined, 'circle still in hash');
|
test(go.ids.myCircle2 === undefined, 'circle still in hash');
|
||||||
test(stage.names.myRect === undefined, 'rect still in hash');
|
test(go.names.myRect2 === undefined, 'rect still in hash');
|
||||||
test(Kinetic.Global.shapes[circleColorKey] === undefined, 'circle color key should not be in shapes 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');
|
test(Kinetic.Global.shapes[rectColorKey] === undefined, 'rect color key should not be in shapes hash');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user