From 58eb778e9aea970281a9037dfad68ea46686341a Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Sat, 7 Apr 2012 14:39:31 -0700 Subject: [PATCH] re-integrated simple serialization and deserialization with new attrs structure --- dist/kinetic-core.js | 63 ++++++++++++++---------------------- src/Container.js | 3 -- src/GlobalObject.js | 16 ---------- src/Group.js | 2 +- src/Layer.js | 1 + src/Node.js | 9 ++++++ src/Shape.js | 2 +- src/Stage.js | 29 +++++++---------- src/shapes/Circle.js | 1 - tests/js/unitTests.js | 74 +++++++++++++++++++++---------------------- 10 files changed, 82 insertions(+), 118 deletions(-) diff --git a/dist/kinetic-core.js b/dist/kinetic-core.js index 1921e6ca..21182b88 100644 --- a/dist/kinetic-core.js +++ b/dist/kinetic-core.js @@ -56,22 +56,6 @@ Kinetic.GlobalObject = { y: 0 } }, - jsonProps: function(props) { - if(this.jsonProps === undefined) { - this.jsonProps = props; - } - else { - this.jsonProps = this.jsonProps.concat(props); - } - }, - arrayHas: function(arr, key) { - for(var n = 0; n < arr.length; n++) { - if(arr[n] === key) { - return true; - } - } - return false; - }, extend: function(obj1, obj2) { for(var key in obj2.prototype) { if(obj2.prototype.hasOwnProperty(key) && obj1.prototype[key] === undefined) { @@ -190,6 +174,10 @@ Kinetic.Node = function(config) { for(var key in config) { // handle special keys switch (key) { + /* + * config properties that require a method to + * be set + */ case 'draggable': this.draggable(config[key]); break; @@ -199,10 +187,15 @@ Kinetic.Node = function(config) { case 'rotationDeg': this.attrs.rotation = config[key] * Math.PI / 180; break; + /* + * config objects that we don't want in attrs + */ case 'drawFunc': break; case 'image': break; + case 'container': + break; default: this.attrs[key] = config[key]; break; @@ -836,9 +829,6 @@ Kinetic.Node.prototype = { Kinetic.Container = function() { this.children = []; this.childrenNames = {}; - - // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, []); }; /* * Container methods @@ -958,6 +948,7 @@ Kinetic.Stage = function(config) { } this.attrs.width = 400; this.attrs.height = 200; + this.nodeType = 'Stage'; /* * if container is a string, assume it's an id for @@ -970,8 +961,7 @@ Kinetic.Stage = function(config) { // call super constructors Kinetic.Container.apply(this, []); Kinetic.Node.apply(this, [config]); - - this.nodeType = 'Stage'; + this.container = config.container; this.content = document.createElement('div'); this.dblClickWindow = 400; @@ -1130,14 +1120,9 @@ 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.attrs[key.replace('_', '')] = node[key]; - } - } + obj.attrs = node.attrs; + obj.nodeType = node.nodeType; + obj.shapeType = node.shapeType; if(node.nodeType !== 'Shape') { obj.children = []; @@ -1160,7 +1145,7 @@ Kinetic.Stage.prototype = { function loadNode(node, obj) { // if custom shape then set draw function if(obj.nodeType === 'Shape' && obj.shapeType === undefined) { - node.drawFunc = drawFuncs[obj.attrs.drawFuncName]; + node.drawFunc = drawFuncs[obj.drawFuncName]; } var children = obj.children; @@ -1170,18 +1155,18 @@ Kinetic.Stage.prototype = { var type; // determine type - if(child.attrs.nodeType === 'Shape') { + if(child.nodeType === 'Shape') { // add custom shape - if(child.attrs.shapeType === undefined) { + if(child.shapeType === undefined) { type = 'Shape'; } // add standard shape else { - type = child.attrs.shapeType; + type = child.shapeType; } } else { - type = child.attrs.nodeType; + type = child.nodeType; } var no = new Kinetic[type](child.attrs); @@ -1193,9 +1178,7 @@ Kinetic.Stage.prototype = { var obj = JSON.parse(json); // copy over stage properties - for(var key in obj.attrs) { - this[key] = obj.attrs[key]; - } + this.attrs = obj.attrs; loadNode(this, obj); this.draw(); @@ -1796,6 +1779,7 @@ Kinetic.GlobalObject.extend(Kinetic.Stage, Kinetic.Node); */ Kinetic.Layer = function(config) { this.nodeType = 'Layer'; + this.canvas = document.createElement('canvas'); this.context = this.canvas.getContext('2d'); this.canvas.style.position = 'absolute'; @@ -1879,7 +1863,7 @@ Kinetic.GlobalObject.extend(Kinetic.Layer, Kinetic.Node); * @param {Object} config */ Kinetic.Group = function(config) { - this.nodeType = 'Group'; + this.nodeType = 'Group';; // call super constructors Kinetic.Container.apply(this, []); @@ -1949,8 +1933,8 @@ Kinetic.Shape = function(config) { // special this.drawFunc = config.drawFunc; - this.nodeType = 'Shape'; this.data = []; + this.nodeType = 'Shape'; // defaults if(config.stroke !== undefined || config.strokeWidth !== undefined) { @@ -2250,7 +2234,6 @@ Kinetic.Circle = function(config) { this.attrs = {}; } this.attrs.radius = 0; - this.shapeType = "Circle"; config.drawFunc = function() { diff --git a/src/Container.js b/src/Container.js index ecaaa201..0dd61037 100644 --- a/src/Container.js +++ b/src/Container.js @@ -9,9 +9,6 @@ Kinetic.Container = function() { this.children = []; this.childrenNames = {}; - - // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, []); }; /* * Container methods diff --git a/src/GlobalObject.js b/src/GlobalObject.js index 1a0475dc..f1eb6358 100644 --- a/src/GlobalObject.js +++ b/src/GlobalObject.js @@ -28,22 +28,6 @@ Kinetic.GlobalObject = { y: 0 } }, - jsonProps: function(props) { - if(this.jsonProps === undefined) { - this.jsonProps = props; - } - else { - this.jsonProps = this.jsonProps.concat(props); - } - }, - arrayHas: function(arr, key) { - for(var n = 0; n < arr.length; n++) { - if(arr[n] === key) { - return true; - } - } - return false; - }, extend: function(obj1, obj2) { for(var key in obj2.prototype) { if(obj2.prototype.hasOwnProperty(key) && obj1.prototype[key] === undefined) { diff --git a/src/Group.js b/src/Group.js index 906a888b..86932a31 100644 --- a/src/Group.js +++ b/src/Group.js @@ -10,7 +10,7 @@ * @param {Object} config */ Kinetic.Group = function(config) { - this.nodeType = 'Group'; + this.nodeType = 'Group';; // call super constructors Kinetic.Container.apply(this, []); diff --git a/src/Layer.js b/src/Layer.js index ab53c523..5b82b200 100644 --- a/src/Layer.js +++ b/src/Layer.js @@ -11,6 +11,7 @@ */ Kinetic.Layer = function(config) { this.nodeType = 'Layer'; + this.canvas = document.createElement('canvas'); this.context = this.canvas.getContext('2d'); this.canvas.style.position = 'absolute'; diff --git a/src/Node.js b/src/Node.js index 84f54cc1..9fb50016 100644 --- a/src/Node.js +++ b/src/Node.js @@ -39,6 +39,10 @@ Kinetic.Node = function(config) { for(var key in config) { // handle special keys switch (key) { + /* + * config properties that require a method to + * be set + */ case 'draggable': this.draggable(config[key]); break; @@ -48,10 +52,15 @@ Kinetic.Node = function(config) { case 'rotationDeg': this.attrs.rotation = config[key] * Math.PI / 180; break; + /* + * config objects that we don't want in attrs + */ case 'drawFunc': break; case 'image': break; + case 'container': + break; default: this.attrs[key] = config[key]; break; diff --git a/src/Shape.js b/src/Shape.js index 4e1e63c4..fb909a38 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -30,8 +30,8 @@ Kinetic.Shape = function(config) { // special this.drawFunc = config.drawFunc; - this.nodeType = 'Shape'; this.data = []; + this.nodeType = 'Shape'; // defaults if(config.stroke !== undefined || config.strokeWidth !== undefined) { diff --git a/src/Stage.js b/src/Stage.js index 43273170..49a30893 100644 --- a/src/Stage.js +++ b/src/Stage.js @@ -18,6 +18,7 @@ Kinetic.Stage = function(config) { } this.attrs.width = 400; this.attrs.height = 200; + this.nodeType = 'Stage'; /* * if container is a string, assume it's an id for @@ -30,8 +31,7 @@ Kinetic.Stage = function(config) { // call super constructors Kinetic.Container.apply(this, []); Kinetic.Node.apply(this, [config]); - - this.nodeType = 'Stage'; + this.container = config.container; this.content = document.createElement('div'); this.dblClickWindow = 400; @@ -190,14 +190,9 @@ 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.attrs[key.replace('_', '')] = node[key]; - } - } + obj.attrs = node.attrs; + obj.nodeType = node.nodeType; + obj.shapeType = node.shapeType; if(node.nodeType !== 'Shape') { obj.children = []; @@ -220,7 +215,7 @@ Kinetic.Stage.prototype = { function loadNode(node, obj) { // if custom shape then set draw function if(obj.nodeType === 'Shape' && obj.shapeType === undefined) { - node.drawFunc = drawFuncs[obj.attrs.drawFuncName]; + node.drawFunc = drawFuncs[obj.drawFuncName]; } var children = obj.children; @@ -230,18 +225,18 @@ Kinetic.Stage.prototype = { var type; // determine type - if(child.attrs.nodeType === 'Shape') { + if(child.nodeType === 'Shape') { // add custom shape - if(child.attrs.shapeType === undefined) { + if(child.shapeType === undefined) { type = 'Shape'; } // add standard shape else { - type = child.attrs.shapeType; + type = child.shapeType; } } else { - type = child.attrs.nodeType; + type = child.nodeType; } var no = new Kinetic[type](child.attrs); @@ -253,9 +248,7 @@ Kinetic.Stage.prototype = { var obj = JSON.parse(json); // copy over stage properties - for(var key in obj.attrs) { - this[key] = obj.attrs[key]; - } + this.attrs = obj.attrs; loadNode(this, obj); this.draw(); diff --git a/src/shapes/Circle.js b/src/shapes/Circle.js index ee38f85a..07b40ac1 100644 --- a/src/shapes/Circle.js +++ b/src/shapes/Circle.js @@ -13,7 +13,6 @@ Kinetic.Circle = function(config) { this.attrs = {}; } this.attrs.radius = 0; - this.shapeType = "Circle"; config.drawFunc = function() { diff --git a/tests/js/unitTests.js b/tests/js/unitTests.js index 98000464..89c87260 100644 --- a/tests/js/unitTests.js +++ b/tests/js/unitTests.js @@ -65,49 +65,47 @@ Test.prototype.tests = { group.add(circle); layer.draw(); }, - /* - 'STAGE - serialize stage': function(containerId) { - var stage = new Kinetic.Stage({ - container: containerId, - width: 578, - height: 200 - }); - var layer = new Kinetic.Layer(); - var group = new Kinetic.Group(); - var circle = new Kinetic.Circle({ - x: stage.getWidth() / 2, - y: stage.getHeight() / 2, - radius: 70, - fill: 'green', - stroke: 'black', - strokeWidth: 4, - name: 'myCircle', - draggable: true - }); + 'STAGE - serialize stage': function(containerId) { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + var group = new Kinetic.Group(); + var circle = new Kinetic.Circle({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + radius: 70, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + name: 'myCircle', + draggable: true + }); - stage.add(layer); - layer.add(group); - group.add(circle); - layer.draw(); + 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({ - container: containerId, - width: 578, - height: 200 - }); + var expectedJson = '{"attrs":{"width":578,"height":200,"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},"nodeType":"Stage","children":[{"attrs":{"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},"nodeType":"Layer","children":[{"attrs":{"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},"nodeType":"Group","children":[{"attrs":{"radius":70,"fill":"green","stroke":"black","strokeWidth":4,"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},"nodeType":"Shape","shapeType":"Circle"}]}]}]}'; + test(stage.toJSON() === expectedJson, 'problem with serialization'); + }, + 'STAGE - load stage with json': function(containerId) { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); - 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); + var json = '{"attrs":{"width":578,"height":200,"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},"nodeType":"Stage","children":[{"attrs":{"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},"nodeType":"Layer","children":[{"attrs":{"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},"nodeType":"Group","children":[{"attrs":{"radius":70,"fill":"green","stroke":"black","strokeWidth":4,"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},"nodeType":"Shape","shapeType":"Circle"}]}]}]}'; + stage.load(json); - test(stage.toJSON() === json, "serialized stage is incorrect"); - }, - */ + test(stage.toJSON() === json, "serialized stage is incorrect"); + }, /* 'STAGE - serialize stage with custom shape': function(containerId) { var stage = new Kinetic.Stage({