KineticJS object with added property to JSON - json

I am trying to serialize KineticJS object (with one added property) to JSON, but if I call the JSON.stringify(test);, it returns only JSON representation of KineticJS object without my added property. Does anybody know, where could be a problem, please?
test = new Kinetic.Line(
{
points : [ 29, 30, 31, 32 ],
stroke : 'black',
strokeWidth : 2,
lineJoin : 'round',
id : '#line'
});
test.obj = "my own property";
JSON.stringify(test);
returns
{"attrs":{"points":[{"x":29,"y":30},{"x":31,"y":32}],"stroke":"black","strokeWidth":2,"lineJoin":"round","id":"#line"},
"nodeType":"Shape","shapeType":"Line"}"
But I need also information about test.obj..

You can do this like that :
var test = new Object();
test.kinetic = new Kinetic.Line(
{
points : [ 29, 30, 31, 32 ],
stroke : 'black',
strokeWidth : 2,
lineJoin : 'round',
id : '#line'
});
test.obj = "my own property";
console.log(JSON.stringify(test));

Related

Reference issue in AS3

Hope I can explain this reasonably well. I'm having a problem where I'm iterating through an object and calling a function based on the parameters of each of the sub-objects, then overwriting some of the values of the returned object and then stuffing it into a master array that itself will be iterated through to create on-screen objects.
It's a scenario infrastructure, where I instance a scenario switchboard class and then call its methods to figure out what ships I need for this scenario, then I pull "blank" examples of each of the ship classes required, set some of their values to be correct for this scenario, then feed them into the process that creates the real game objects.
This is the basic scenario loading process:
//instance scenario loader class
var scenarioMasterObj:LOB_Scenario_Data = new LOB_Scenario_Data();
//first grab the scenario settings object which has all of the data like short description, long description, date battle occured, balance, basically everything but the ship OOBs
//this data will be used to render the scenario selection screen and post-battle results screen. We just pass the scenario number
var scenarioSettigs:Object = scenarioMasterObj.getScenarioSettings(1);
//there are two side-specific OOBs (Orders of Battle, lists of ships for the scenario) to load
for (var OOBToggle:int = 1; OOBToggle < 3; OOBToggle++) {
var currentOOB:Object = new Object();
if (1 == OOBToggle) {
currentOOB = scenarioMasterObj.getScenarioSideOOB(1, 1);
}
else {
currentOOB = scenarioMasterObj.getScenarioSideOOB(1, 2);
}
//specific ship objects we'll need
var currentOOBShip:Object = new Object();
var finalOOBShip:Object = new Object();
//iterate through the current OOB to create the list of ships used in ship creation for side 1 or 2
for each (var currentOOBShip:Object in currentOOB) {
//pull final ship data based on shipClass and country properties of the OOB ships
finalOOBShip = scenarioMasterObj.getShip(currentOOBShip.shipClass, currentOOBShip.country);
//set scenario-specific values copying from the ship in the scenario OOB object
finalOOBShip.name = currentOOBShip.name;
finalOOBShip.sailState = currentOOBShip.sailState;
finalOOBShip.shotType = currentOOBShip.shotType;
finalOOBShip.crewQuality = currentOOBShip.crewQuality;
finalOOBShip.column = currentOOBShip.column;
finalOOBShip.row = currentOOBShip.row;
finalOOBShip.column2 = currentOOBShip.column2;
finalOOBShip.row2 = currentOOBShip.row2;
finalOOBShip.direction = currentOOBShip.direction;
//push to the array that will be iterated through to create the on-screen ship objects
if (1 == OOBToggle) {
shipDataSide1.push(finalOOBShip);
}
else {
shipDataSide2.push(finalOOBShip);
}
}
}
The currentOOB object looks like:
public function getOOB(side:int):Object {
var return_Scen_OOB:Object = new Object();
if (1 == side) {
return_Scen_OOB = {
Ship1: {shipClass: "GB_90_N", name: "London", country: "GB", column: 7, row: 7, column2: 7, row2: 8, direction: 4, sailState: "battle", shotType: "round", crewQuality: "Crack"},
Ship2: {shipClass: "GB_74A_N", name: "Impetueux", country: "GB", column: 7, row: 9, column2: 7, row2: 10, direction: 4, sailState: "battle", shotType: "round", crewQuality: "Crack"},
Ship3: {shipClass: "GB_74A_N", name: "Courageux", country: "GB", column: 7, row: 11, column2: 7, row2: 12, direction: 4, sailState: "battle", shotType: "round", crewQuality: "Average"},
Ship4: {shipClass: "GB_74B_N", name: "Captain", country: "GB", column: 1, row: 1, column2: 1, row2: 1, direction: 1, sailState: "battle", shotType: "round", crewQuality: "Elite"},
Ship5: {shipClass: "GB_38_N", name: "Indefatigable", country: "GB", column: 7, row: 15, column2: 7, row2: 16, direction: 4, sailState: "battle", shotType: "round", crewQuality: "Crack"},
Ship2: {shipClass: "GB_38_N", name: "Amelia", country: "GB", column: 1, row: 1, column2: 1, row2: 1, direction: 1, sailState: "battle", shotType: "round", crewQuality: "Average"},
Ship6: {shipClass: "GB_36A_N", name: "Amethyst", country: "GB", column: 1, row: 1, column2: 1, row2: 1, direction: 1, sailState: "battle", shotType: "round", crewQuality: "Crack"},
Ship7: {shipClass: "GB_32B_N", name: "Stag", country: "GB", column: 1, row: 1, column2: 1, row2: 1, direction: 1, sailState: "battle", shotType: "round", crewQuality: "Crack"},
Ship8: {shipClass: "GB_28_N", name: "Brilliant", country: "GB", column: 1, row: 1, column2: 1, row2: 1, direction: 1, sailState: "battle", shotType: "round", crewQuality: "Average"},
Ship9: {shipClass: "GB_18_N", name: "Cynthia", country: "GB", column: 7, row: 7, column2: 7, row2: 8, direction: 4, sailState: "battle", shotType: "round", crewQuality: "Crack"},
Ship10: {shipClass: "GB_18_N", name: "Saint Vincent", country: "GB", column: 25, row: 30, column2: 25, row2: 31, direction: 4, sailState: "battle", shotType: "round", crewQuality: "Crack"}
}
}
This is the call where it pulls the "blank" ship - an object that has the vast majority of the properties for that given ship class already set, and the OOB object includes the scenario-specific values we'll add to that blank ship. That looks like:
//After receiving the list of ships from getScenarioSideOOB(), game iterates through those lists calling this function to set up the game's master ship side arrays
public function getShip(shipClass:String, shipCountry:String) {
var returnShip:Object = new Object();
//bummer here is we have to know what classes exist, so if any are added code must change here as well
switch(shipCountry) {
case "GB":
switch(shipClass) {
case "GB_120_N":
returnShip = shipList_GB.GB_120_N;
break;
case "GB_110_N":
returnShip = shipList_GB.GB_110_N;
break;
case "GB_100_N":
returnShip = shipList_GB.GB_100_N;
break;
case "GB_98_N":
returnShip = shipList_GB.GB_98_N;
break;
case "GB_90_N":
returnShip = shipList_GB.GB_90_N;
break;
case "GB_80_N":
returnShip = shipList_GB.GB_80_N;
break;
case "GB_74A_N":
returnShip = shipList_GB.GB_74A_N;
break;
case "GB_74B_N":
returnShip = shipList_GB.GB_74B_N;
break;
So I switch first on country and then on the passed-in shipClass string to return a specific "blank" ship object.
The problem is here:
//pull final ship data based on shipClass and country properties of the OOB ships
finalOOBShip = scenarioMasterObj.getShip(currentOOBShip.shipClass, currentOOBShip.country);
If you'll notice in the OOB object, there is more than one ship of identical shipClass value. There are two with the class "GB_74A_N" and two with the class "GB_18_N". The second time the above function is called with the exact same parameters (e.g., shipCountry == "GB" and shipClass == "GB_74A_N") what is returned is not a new blank ship but a reference to the previous example.
And when I do the overrides to set this ship example to its correct values, the previous example in shipDataSide1 or shipDataSide2 are also overwritten:
//set scenario-specific values copying from the ship in the scenario OOB object
finalOOBShip.name = currentOOBShip.name;
finalOOBShip.sailState = currentOOBShip.sailState;
finalOOBShip.shotType = currentOOBShip.shotType;
finalOOBShip.crewQuality = currentOOBShip.crewQuality;
finalOOBShip.column = currentOOBShip.column;
finalOOBShip.row = currentOOBShip.row;
finalOOBShip.column2 = currentOOBShip.column2;
finalOOBShip.row2 = currentOOBShip.row2;
finalOOBShip.direction = currentOOBShip.direction;
So if the OOB object hast two ship objects with the same shipClass, in the end the the shipDataSide1 or shipDataSide2 arrays end up with one of them missing and two copies of the other, which confuses the code later in trying to draw them onscreen.
So what am I doing wrong here? How do I make sure each time I call scenarioMasterObj.getShip(currentOOBShip.shipClass, currentOOBShip.country) that the return is a "fresh" object and not a reference to an existing object? Took quite a while debugging to figure out what was going on, and I've spent a couple hours experimenting trying to get around this without ridiculous brute force methods but not having any luck. Help would be much appreciated.
=========================== UPDATE ============================
I have fixed the problem, but as noted it seems very brute force and there has to be a more elegant way to make it work. Basically I'm reinstancing the object from which we pull the "blank" ships, so each returned ship has nothing to do reference-wise to any previously returned one.
//After receiving the list of ships from getScenarioSideOOB(), game iterates through those lists calling this function to set up the game's master ship side arrays
public function getShip(shipClass:String, shipCountry:String) {
var returnShip:Object = new Object();
//bummer here is we have to know what classes exist, so if any are added code must change here as well
switch(shipCountry) {
case "GB":
switch(shipClass) {
case "GB_120_N":
var shipList_GB_Source:LOB_Ships_GB = new LOB_Ships_GB;
var shipList_GB = shipList_GB_Source.shipClasses_GB;
returnShip = shipList_GB.GB_120_N;
break;
case "GB_110_N":
var shipList_GB_Source:LOB_Ships_GB = new LOB_Ships_GB;
var shipList_GB = shipList_GB_Source.shipClasses_GB;
returnShip = shipList_GB.GB_110_N;
break;
case "GB_100_N":
var shipList_GB_Source:LOB_Ships_GB = new LOB_Ships_GB;
var shipList_GB = shipList_GB_Source.shipClasses_GB;
returnShip = shipList_GB.GB_100_N;
break;
case "GB_98_N":
var shipList_GB_Source:LOB_Ships_GB = new LOB_Ships_GB;
var shipList_GB = shipList_GB_Source.shipClasses_GB;
returnShip = shipList_GB.GB_98_N;
break;
That's easy. You add a service parameter "installed" to each ship in getScenarioSideOOB() output, and assign it to false initially. Then, when your scenarioMasterObj.getShip() is called, it should set installed to true on the ship in OOB, and skip the matching ship if it has "installed" as true already.
If no one has a better suggestion for handling this type of situation than the answer provided above in the update to my OP has to stand. It works, it just feels like using a sledgehammer when I know there's a precise tool for this out there somewhere.

Polymer, paper-datatable styling of rows

I'm trying to colour the rows of paper-datatable
using the attribute customRowStyle
This Plunk of paper-datatable is working, rows are colored, but it's not enclosed as separate Polymer element.
I need to enclose paper-datatable in separate element.
Need some help to fix this:
how to make customRowStyle(item) to get called on table render and pass the item?
<paper-datatable data="{{data}}"
custom-row-style="{{generateRowCss}}"
on-row-tap="row_tap">
<paper-datatable-column header="title" property="title"></paper-datatable-column>
<paper-datatable-column header="Calories" property="calories"></paper-datatable-column>
<paper-datatable-column header="Fat (g)" property="fat" ></paper-datatable-column>
</paper-datatable>
...
generateRowCss: function (item) {
console.log('theming_2 generateRowCss:');
var levels = ['#FFFFFF', '#FFEBEE', '#FFCDD2', '#EF9A9A'];
var min = 150;
var max = 450;
var level = Math.floor((item.calories - min) / (max - min) * levels.length);
return 'background:' + levels[level] + ';';
},
EDIT:
Plunk with #a1626 solution.
As generateRowCssthat is passed to customRowStyle is a function rather than the return value of the function(which is what your code is passing) you'll have to do something like this. Instead of creating a function generateRowCss create a property with the same name, initialize it as Object and return its value as whole function
properties: {
data: {
type: Array,
notify: true,
value: [
{id: 0, title: 'Frozen yogurt', calories: 159, fat: 6},
{id: 1, title: 'Ice cream sandwich', calories: 237, fat: 9},
{id: 2, title: 'Eclair', calories: 262, fat: 16},
{id: 3, title: 'Cupcake', calories: 305, fat: 3.7},
],
},
generateRowCss:{
type:Object, //this is optional you can skip this also
value:function(){
return function(item){
console.log('app.generateRowCss');
console.log(item);
var levels = ['#FFFFFF', '#FFEBEE', '#FFCDD2', '#EF9A9A'];
var min = 150;
var max = 450;
var level = Math.floor((item.calories - min)/(max-min)*levels.length);
console.log(level);
console.log('background:'+levels[level]+';');
return 'background:'+levels[level]+';';
}
}
}
},
Pasted above are the properties of your custom element. Here is the working plunkr

How to show floors to on a polygon using CesiumJs

I am new to CesiumJs and I want to add 12 floors to a building. I have created the building using polygon.
Here is the code I have used to create the polygon
var viewer = new Cesium.Viewer('cesiumContainer');
var wyoming = viewer.entities.add({
name : 'My location',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([cordinates of location]),
material : Cesium.Color.WHITE.withAlpha(0.5),
outline : true,
fill : true,
outlineColor : Cesium.Color.BLACK,
}
});
wyoming.polygon.extrudedHeight = 50;
viewer.camera.flyTo({
destination : Cesium.Cartesian3.fromDegrees(-79.38443,43.64843, 144.00),
orientation : {
heading : Cesium.Math.toRadians(121.00),
pitch : Cesium.Math.toRadians(60.00 - 90.0),
roll : 0.0
},
duration : 4.0, // in seconds
complete : function() {
},
point : {
pixelSize : 5,
color : Cesium.Color.RED,
outlineColor : Cesium.Color.WHITE,
outlineWidth : 2
},
label : {
text : 'My another location',
font : '14pt monospace',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth : 2,
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
pixelOffset : new Cesium.Cartesian2(0, -9)
}
});
Thanks in advance
In this case you will need something more complex than extruded polygon.
If you need a simple building with floors of alternating color you can construct it from Wall entity with stripe material and putting a polygon on top of it as a "roof" (use same coordinates, put height property to the height of the wall, and not set extrudedHeight).
This will create wall with alternating black and white floors:
function createBuildingWalls(coordinates, floors)
{
var floorHeight = 4;
var height = floors * floorHeight;
var low = Array.apply(null, Array(coordinates.length/2)).map(function() { return 0 });
var high = Array.apply(null, Array(coordinates.length/2)).map(function() { return height });
var buildingWalls = new Cesium.Entity({
name : 'Wall',
wall : {
positions : Cesium.Cartesian3.fromDegreesArray(coordinates),
maximumHeights : high,
minimumHeights : low,
material : new Cesium.StripeMaterialProperty({
evenColor : Cesium.Color.WHITE,
oddColor : Cesium.Color.BLACK,
repeat : 20
})
}});
return buildingWalls;
}
And this roof (might run into an issue with very large polygons, but should be fine for buildings):
function createBuildingRoof(coordinates, floors)
{
var floorHeight = 4;
var buildingHeight = floors * floorHeight;
var buildingRoof = new Cesium.Entity({
name : 'My location',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray(coordinates),
material : Cesium.Color.RED.withAlpha(0.9),
outline : true,
height : buildingHeight,
fill : true,
outlineColor : Cesium.Color.BLACK,
}
});
return buildingRoof;
}
You can also use a texture (image) as a material and apply it to the wall, but it is more complex. You would need to set ImageMaterial property and according propably set repeat property depending on the type of your texture (ie repeat a single floor verticaly, or single 12 floor stripe horizontaly or some other combination)
http://cesiumjs.org/Cesium/Build/Documentation/ImageMaterialProperty.html
Other solution would be to use 3D models of the buildings:
http://cesiumjs.org/2014/03/03/Cesium-3D-Models-Tutorial/

Javascript: Array overriding the same values after assinging to JSON object

I am working with jquery ajax & the ajax response is multidimensional json array, I am assinging the JSON values to coordinates array & then assinging coordinates array to new JSON coord_set, after assinging all values to coord_set, It takes last array values to all,
for e.g.
the JSON result contains following values
obj[0]={125, 343, 456, 453},
obj[1]={345, 657, 234, 787},
obj[2]={980, 677, 657, 568}
after assinging to new JSON the values are:
coord_set[0] = {
fillColor : 'rgba(255, 234, 111 ,0.5)',
data : [980, 677, 657, 568]
}
coord_set[1] = {
fillColor : 'rgba(255, 234, 111 ,0.5)',
data : [980, 677, 657, 568]
}
coord_set[2] = {
fillColor : 'rgba(255, 234, 111 ,0.5)',
data : [980, 677, 657, 568]
}
This is my code:
var obj = JSON.parse(data);
for(var j=0;j<obj.length;j++)
{
for (var i=0;i<obj[j].length;i++)
{
coordinates[i] = obj[j][i].how_many;
}
coord_set[j] = { fillColor : 'rgba(255, 234, 111 ,0.5)', data : coordinates };
}
alert(JSON.stringify(coord_set));
Please tell me, If I am doing Anything wrong in my code?
The problem is that you're using a single coordinates array. You keep setting and re-setting the values in that same array, and you keep storing that same array in new elements of coord_set. To fix this, you just need to use a new coordinates array on each pass through the outer loop:
for(var j=0;j<obj.length;j++)
{
coordinates = []; // <----- add this
for (var i=0;i<obj[j].length;i++)
I'm gonna assume that JSON.parse actually works... but since you said you are using jquery, i would use http://api.jquery.com/jQuery.parseJSON/ personally...
Few things about your code:
you never create a new object for coordinates, which is, by default, a global variable in JS. You must type:
var coordinates = []; // before the for (var i = 0; ...
where is this property "how_many" coming from? I don't see it in your first block of code... The code in your i loop should be:
coordinates[i] = obj[j][i];
finally, why do you need a copy of this transient object anyway? That should just do it:
coord_set[j] = { fillColor : 'rgba(255, 234, 111 ,0.5)', data : obj[j] };
// if you change your result set to give a code like that:
obj[0]= [ 125, 343, 456, 453 ] // and not: obj[0]={125, 343, 456, 453}

Kineticjs load json canvas

I always got the error:
"TypeError: Kinetic[type] is not a constructor"
"ReferenceError: reference to undefined property obj.nodeType"
when i try to load one json.
json = stage.toJSON();
stage = Kinetic.Node.create(json, 'myCanvas');
the method _createNode from Kineticjs 4.3.3
var no = new Kinetic[type](obj.attrs);
on my canvas I have a simple group
var circle1 = new Kinetic.Circle({
x: 40,
y: 50,
radius: 42,
fill: 'white',
stroke: 'black',
strokeWidth: 1,
draggable: false
});
var polygon1Tab1 = new Kinetic.RegularPolygon({
x: 40,
y: 50,
radius: 27,
sides: 4,
stroke: 'black',
strokeWidth: 4,
draggable: false
});
polygon1Tab1.rotateDeg(45);
var group1 = new Kinetic.Group({
draggable: true,
});
group1.add(circle1.clone());
group1.add(polygon1.clone());
What is "polygon1" here?
group1.add(polygon1.clone());
I created this example. Everything forks fine: http://jsfiddle.net/lavrton/N3UPX/
'polygon1' It's just one name ... a change!!!!
I take your code and place to run and continue with the same error!
when i print the json I noticed that it has an error!
he puts this "children": "[]" and should not have quotes in brackets
if I copy and put my string this fixed string corrected wheel normal!!
I made a method to remove the error .... Now I'm with an error
SyntaxError: JSON.parse: expected property name or '}'
var json = polygonLayer.toJSON();
json = json.replace('"children":"', '"children":');
json = json.substring(0, json.length-2) + json.substring(json.length-1, json.length);
whereas using the same fixed string works!
I'm using version 4.3.3
this work
var json = '{"attrs":{"clearBeforeDraw":true,"visible":true,"listening":true,"opacity":1,"x":0,"y":0,"scale":{"x":1,"y":1},"rotation":0,"offset":{"x":0,"y":0},"draggable":false,"dragOnTop":true},"nodeType":"Layer","children":[{\"attrs\": {\"width\": 600, \"height\": 400, \"cornerRadius\": 0, \"fillEnabled\": true, \"strokeEnabled\": true, \"shadowEnabled\": true, \"dashArrayEnabled\": true, \"fillPriority\": \"color\", \"visible\": true, \"listening\": true, \"opacity\": 1, \"x\": 0, \"y\": 0, \"scale\": {\"x\": 1, \"y\": 1}, \"rotation\": 0, \"offset\": {\"x\": 0, \"y\": 0}, \"draggable\": false, \"dragOnTop\": true, \"fill\": \"white\"}, \"nodeType\": \"Shape\", \"shapeType\": \"Rect\"}]}';
layer = Kinetic.Node.create(json, 'canvas');
but this dont work
var json = layer.toJSON();
layer = Kinetic.Node.create(json, 'canvas');