diff --git a/dist/kinetic-core.js b/dist/kinetic-core.js index ca812133..4d64b585 100644 --- a/dist/kinetic-core.js +++ b/dist/kinetic-core.js @@ -161,7 +161,7 @@ window.requestAnimFrame = (function(callback) { */ Kinetic.Node = function(config) { this.visible = true; - this.listening = true; + this._listening = true; this.name = undefined; this.alpha = 1; this.x = 0; @@ -188,7 +188,7 @@ Kinetic.Node = function(config) { case 'draggable': this.draggable(config[key]); break; - case 'listen': + case 'listening': this.listen(config[key]); break; case 'rotationDeg': @@ -210,7 +210,7 @@ Kinetic.Node = function(config) { } // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, ['alpha', 'centerOffset', 'dragBounds', 'dragConstraint', '_draggable', 'listening', 'name', 'nodeType', 'rotation', 'scale', 'visible', 'x', 'y']); + Kinetic.GlobalObject.jsonProps.call(this, ['alpha', 'centerOffset', 'dragBounds', 'dragConstraint', '_draggable', '_listening', 'name', 'nodeType', 'rotation', 'scale', 'visible', 'x', 'y']); }; /* * Node methods @@ -449,7 +449,7 @@ Kinetic.Node.prototype = { * @param {Boolean} listening */ listen: function(listening) { - this.listening = listening; + this._listening = listening; }, /** * move node to top @@ -1125,20 +1125,22 @@ Kinetic.Stage.prototype = { function addNode(node) { var obj = {}; + obj.attrs = {}; // copy attrs for(var key in node) { if(node.hasOwnProperty(key) && go.arrayHas(node.jsonProps, key)) { - obj[key] = node[key]; + obj.attrs[key.replace('_', '')] = node[key]; } } if(node.nodeType !== 'Shape') { - obj._children = []; + obj.children = []; + var children = node.getChildren(); for(var n = 0; n < children.length; n++) { var child = children[n]; - obj._children.push(addNode(child)); + obj.children.push(addNode(child)); } } @@ -1149,41 +1151,48 @@ Kinetic.Stage.prototype = { /** * load stage with JSON string */ - load: function(json) { + load: function(json, drawFuncs) { function loadNode(node, obj) { - // copy properties over - for(var key in obj) { - node[key] = obj[key]; + // if custom shape then set draw function + if(obj.nodeType === 'Shape' && obj.shapeType === undefined) { + node.drawFunc = drawFuncs[obj.attrs.drawFuncName]; } - var children = obj._children; + var children = obj.children; if(children !== undefined) { for(var n = 0; n < children.length; n++) { var child = children[n]; var type; // determine type - if(child.nodeType === 'Shape') { + if(child.attrs.nodeType === 'Shape') { // add custom shape - if(child.shapeType === undefined) { + if(child.attrs.shapeType === undefined) { type = 'Shape'; } // add standard shape else { - type = child.shapeType; + type = child.attrs.shapeType; } } else { - type = child.nodeType; + type = child.attrs.nodeType; } - var no = new Kinetic[type]({}); + var no = new Kinetic[type](child.attrs); node.add(no); loadNode(no, child); } } } - loadNode(this, JSON.parse(json)); + var obj = JSON.parse(json); + + // copy over stage properties + for(var key in obj.attrs) { + this[key] = obj.attrs[key]; + } + + loadNode(this, obj); this.draw(); }, /** @@ -1419,7 +1428,7 @@ Kinetic.Stage.prototype = { // propapgate backwards through children for(var i = children.length - 1; i >= 0; i--) { var child = children[i]; - if(child.listening) { + if(child._listening) { if(child.nodeType === 'Shape') { var exit = this._detectEvent(child, evt); if(exit) { @@ -1460,7 +1469,7 @@ Kinetic.Stage.prototype = { var shapeDetected = false; for(var n = this.children.length - 1; n >= 0; n--) { var layer = this.children[n]; - if(layer.visible && n >= 0 && layer.listening) { + if(layer.visible && n >= 0 && layer._listening) { if(this._traverseChildren(layer, evt)) { n = -1; shapeDetected = true; @@ -1934,7 +1943,7 @@ Kinetic.Shape = function(config) { this.drawFunc = config.drawFunc; // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, ['fill', 'stroke', 'strokeWidth', 'detectionType', 'shapeType']); + Kinetic.GlobalObject.jsonProps.call(this, ['fill', 'stroke', 'strokeWidth', 'detectionType', 'shapeType', 'drawFuncName']); // call super constructor Kinetic.Node.apply(this, [config]); diff --git a/src/Node.js b/src/Node.js index 182d1540..3f7a0b86 100644 --- a/src/Node.js +++ b/src/Node.js @@ -10,7 +10,7 @@ */ Kinetic.Node = function(config) { this.visible = true; - this.listening = true; + this._listening = true; this.name = undefined; this.alpha = 1; this.x = 0; @@ -37,7 +37,7 @@ Kinetic.Node = function(config) { case 'draggable': this.draggable(config[key]); break; - case 'listen': + case 'listening': this.listen(config[key]); break; case 'rotationDeg': @@ -59,7 +59,7 @@ Kinetic.Node = function(config) { } // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, ['alpha', 'centerOffset', 'dragBounds', 'dragConstraint', '_draggable', 'listening', 'name', 'nodeType', 'rotation', 'scale', 'visible', 'x', 'y']); + Kinetic.GlobalObject.jsonProps.call(this, ['alpha', 'centerOffset', 'dragBounds', 'dragConstraint', '_draggable', '_listening', 'name', 'nodeType', 'rotation', 'scale', 'visible', 'x', 'y']); }; /* * Node methods @@ -298,7 +298,7 @@ Kinetic.Node.prototype = { * @param {Boolean} listening */ listen: function(listening) { - this.listening = listening; + this._listening = listening; }, /** * move node to top diff --git a/src/Shape.js b/src/Shape.js index 4362d240..dac65dfa 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -35,7 +35,7 @@ Kinetic.Shape = function(config) { this.drawFunc = config.drawFunc; // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, ['fill', 'stroke', 'strokeWidth', 'detectionType', 'shapeType']); + Kinetic.GlobalObject.jsonProps.call(this, ['fill', 'stroke', 'strokeWidth', 'detectionType', 'shapeType', 'drawFuncName']); // call super constructor Kinetic.Node.apply(this, [config]); diff --git a/src/Stage.js b/src/Stage.js index 4c41349e..363f2aa4 100644 --- a/src/Stage.js +++ b/src/Stage.js @@ -191,20 +191,22 @@ Kinetic.Stage.prototype = { function addNode(node) { var obj = {}; + obj.attrs = {}; // copy attrs for(var key in node) { if(node.hasOwnProperty(key) && go.arrayHas(node.jsonProps, key)) { - obj[key] = node[key]; + obj.attrs[key.replace('_', '')] = node[key]; } } if(node.nodeType !== 'Shape') { - obj._children = []; + obj.children = []; + var children = node.getChildren(); for(var n = 0; n < children.length; n++) { var child = children[n]; - obj._children.push(addNode(child)); + obj.children.push(addNode(child)); } } @@ -215,41 +217,48 @@ Kinetic.Stage.prototype = { /** * load stage with JSON string */ - load: function(json) { + load: function(json, drawFuncs) { function loadNode(node, obj) { - // copy properties over - for(var key in obj) { - node[key] = obj[key]; + // if custom shape then set draw function + if(obj.nodeType === 'Shape' && obj.shapeType === undefined) { + node.drawFunc = drawFuncs[obj.attrs.drawFuncName]; } - var children = obj._children; + var children = obj.children; if(children !== undefined) { for(var n = 0; n < children.length; n++) { var child = children[n]; var type; // determine type - if(child.nodeType === 'Shape') { + if(child.attrs.nodeType === 'Shape') { // add custom shape - if(child.shapeType === undefined) { + if(child.attrs.shapeType === undefined) { type = 'Shape'; } // add standard shape else { - type = child.shapeType; + type = child.attrs.shapeType; } } else { - type = child.nodeType; + type = child.attrs.nodeType; } - var no = new Kinetic[type]({}); + var no = new Kinetic[type](child.attrs); node.add(no); loadNode(no, child); } } } - loadNode(this, JSON.parse(json)); + var obj = JSON.parse(json); + + // copy over stage properties + for(var key in obj.attrs) { + this[key] = obj.attrs[key]; + } + + loadNode(this, obj); this.draw(); }, /** @@ -485,7 +494,7 @@ Kinetic.Stage.prototype = { // propapgate backwards through children for(var i = children.length - 1; i >= 0; i--) { var child = children[i]; - if(child.listening) { + if(child._listening) { if(child.nodeType === 'Shape') { var exit = this._detectEvent(child, evt); if(exit) { @@ -526,7 +535,7 @@ Kinetic.Stage.prototype = { var shapeDetected = false; for(var n = this.children.length - 1; n >= 0; n--) { var layer = this.children[n]; - if(layer.visible && n >= 0 && layer.listening) { + if(layer.visible && n >= 0 && layer._listening) { if(this._traverseChildren(layer, evt)) { n = -1; shapeDetected = true; diff --git a/tests/js/unitTests.js b/tests/js/unitTests.js index c3b0eea1..991e7138 100644 --- a/tests/js/unitTests.js +++ b/tests/js/unitTests.js @@ -79,15 +79,19 @@ Test.prototype.tests = { fill: 'green', stroke: 'black', strokeWidth: 4, - name: 'myCircle' + name: 'myCircle', + draggable: true }); stage.add(layer); layer.add(group); group.add(circle); layer.draw(); - - console.log(stage.toJSON()); + + console.log(stage.toJSON()) + + var expectedJson = '{"attrs":{"nodeType":"Stage","width":578,"height":200,"scale":{"x":1,"y":1},"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"children":[{"attrs":{"nodeType":"Layer","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"children":[{"attrs":{"nodeType":"Group","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"children":[{"attrs":{"shapeType":"Circle","nodeType":"Shape","detectionType":"path","visible":true,"listening":true,"name":"myCircle","alpha":1,"x":289,"y":100,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":true,"radius":70,"fill":"green","stroke":"black","strokeWidth":4}}]}]}]}'; + test(stage.toJSON() === expectedJson, 'problem with serialization'); }, 'STAGE - load stage with json': function(containerId) { var stage = new Kinetic.Stage({ @@ -95,11 +99,73 @@ Test.prototype.tests = { width: 578, height: 200 }); - - stage.load('{"nodeType":"Stage","width":578,"height":200,"scale":{"x":1,"y":1},"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Layer","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Group","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"shapeType":"Circle","nodeType":"Shape","detectionType":"path","visible":true,"listening":true,"name":"myCircle","alpha":1,"x":289,"y":100,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"radius":70,"fill":"green","stroke":"black","strokeWidth":4}]}]}]}'); - console.log(stage.toJSON()); + var json = '{"attrs":{"nodeType":"Stage","width":578,"height":200,"scale":{"x":1,"y":1},"visible":true,"listening":true,"alpha":1,"x":0,"y":0,"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"children":[{"attrs":{"nodeType":"Layer","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"children":[{"attrs":{"nodeType":"Group","visible":true,"listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":false},"children":[{"attrs":{"shapeType":"Circle","nodeType":"Shape","detectionType":"path","visible":true,"listening":true,"name":"myCircle","alpha":1,"x":289,"y":100,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"draggable":true,"radius":70,"fill":"green","stroke":"black","strokeWidth":4}}]}]}]}'; + stage.load(json); + + test(stage.toJSON() === json, "serialized stage is incorrect"); }, + /* + 'STAGE - serialize stage with custom shape': function(containerId) { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + var group = new Kinetic.Group(); + + var drawTriangle = function() { + var context = this.getContext(); + context.beginPath(); + context.moveTo(200, 50); + context.lineTo(420, 80); + context.quadraticCurveTo(300, 100, 260, 170); + context.closePath(); + this.fillStroke(); + }; + var triangle = new Kinetic.Shape({ + drawFunc: drawTriangle, + drawFuncName: 'drawTriangle', + fill: "#00D2FF", + stroke: "black", + strokeWidth: 4 + }); + + stage.add(layer); + layer.add(group); + group.add(triangle); + layer.draw(); + + var expectedJson = '{"nodeType":"Stage","width":578,"height":200,"scale":{"x":1,"y":1},"visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Layer","visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Group","visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Shape","detectionType":"path","visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"drawFuncName":"drawTriangle","fill":"#00D2FF","stroke":"black","strokeWidth":4}]}]}]}'; + test(stage.toJSON() === expectedJson, "problem with serialization"); + + console.log(stage.toJSON()); + }, + 'STAGE - load stage with custom shape': function(containerId) { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + + var drawTriangle = function() { + var context = this.getContext(); + context.beginPath(); + context.moveTo(200, 50); + context.lineTo(420, 80); + context.quadraticCurveTo(300, 100, 260, 170); + context.closePath(); + this.fillStroke(); + }; + var json = '{"nodeType":"Stage","width":578,"height":200,"scale":{"x":1,"y":1},"visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Layer","visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Group","visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"_children":[{"nodeType":"Shape","detectionType":"path","visible":true,"_listening":true,"alpha":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"centerOffset":{"x":0,"y":0},"dragConstraint":"none","dragBounds":{},"_draggable":false,"drawFuncName":"drawTriangle","fill":"#00D2FF","stroke":"black","strokeWidth":4}]}]}]}'; + stage.load(json, { + drawTriangle: drawTriangle + }); + + test(stage.toJSON() === json, "serialized stage is incorrect"); + }, + */ 'STAGE - set stage size': function(containerId) { var stage = new Kinetic.Stage({ container: containerId, @@ -1108,7 +1174,7 @@ Test.prototype.tests = { layer.add(text); stage.add(layer); - console.log(text.getTextSize()); + console.log(text.getTextSize()); test(text.getTextSize().width > 0, 'text width should have a value'); test(text.getTextSize().height > 0, 'text height should have a value');