Store ajax response object in global variable --- Fields get missing - javascript

I'm implementing an asynchronous webpage in Grails where I make a call to a controller and render the response as a D3.js network. I stored the object into a global variable for further use. The function worked fine when data is returned. However when I tried to use the object later I found some fields became undefined.
var similar;
function asynchroNetwork() {
var jsonData = $.ajax({
url: "${createLink(controller:'environment', action:'asynchro')}",
dataType: "json",
async: true
}).done(function(jsonData) {
console.log(jsonData);
//console.log(jsonText);
document.getElementById("result").innerHTML="Done";
console.log(jsonData.all);
//set global variable
similar=jsonData;
console.log("The object got");
console.log(similar);
draw();
});;
}
function draw(){
console.log(similar);
//draw the network based on object
}
The controller returns the following JSON:
{
"\u521B\u4E1A" : {
"nodes" : [{
"group" : 1,
"name" : "\u6c88\u9633\u8f9b\u98962\u4e16"
}
],
"links" : []
},
"all" : {
"nodes" : [{
"group" : 1,
"name" : "qwe25322570"
}, {
"group" : 1,
"name" : "\u660e\u5fb7\u7b03\u884c"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u53ef\u4e50"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u5f6d\u79c0\u8363"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u738b\u632f\u534e"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u8f9b\u98962\u4e16"
}
],
"links" : [{
"value" : 1.0,
"target" : "\u6c88\u9633\u8f9b\u98962\u4e16",
"source" : "\u660e\u5fb7\u7b03\u884c"
}, {
"value" : 1.0,
"target" : "\u6c88\u9633\u8f9b\u98962\u4e16",
"source" : "qwe25322570"
}
]
}
}
In the draw() function it uses similar[all] to draw a graph. But in the links field I see the fields source and target are all undefined, while all fields in the nodes are all fine.
I don't think the encoding is the cause because nodes also contains UTF8 characters in the fields but none got missing. After the object is passed back from asychronous function the object similar is okay, but the next time draw() is called, I can see the field links go undefined.
Does anyone know what could be the cause of this problem? I guess it maybe related to nested fields.

Did you try passing your data as an argument to the draw function? If not, then:
In your ajax callback:
similar = jsonData;
draw(similar) //pass the json
draw function:
function draw(json) {
console.log(json);
}

Related

How to access a part of a JSON file

Im trying to access some data and keep getting errors no matter what I try. Please help.
"rain":{"3h":13.625} is the part of the JSON file I am trying to access.
Here is what I have tried:
var currentRain = data.rain.3h; Which is most logical as it worked before but the number is what is giving the error.
var currentRain = data.rain["3h"];
var currentRain = data.rain[0]["3h"];
var currentRain = data.rain["3h"][0];
UPDATE:
This is the JSON payload:
{ "base" : "stations",
"clouds" : { "all" : 92 },
"cod" : 200,
"coord" : { "lat" : -33.850000000000001,
"lon" : 151.22
},
"dt" : 1429558616,
"id" : 6619279,
"main" : { "grnd_level" : 1024.97,
"humidity" : 100,
"pressure" : 1024.97,
"sea_level" : 1031.0999999999999,
"temp" : 288.77699999999999,
"temp_max" : 288.77699999999999,
"temp_min" : 288.77699999999999
},
"name" : "City of Sydney",
"rain" : { "3h" : 13.625 },
"sys" : { "country" : "AU",
"message" : 0.0101,
"sunrise" : 1429474880,
"sunset" : 1429514809
},
"weather" : [ { "description" : "heavy intensity rain",
"icon" : "10n",
"id" : 502,
"main" : "Rain"
} ],
"wind" : { "deg" : 157.5,
"speed" : 8.3200000000000003
}
}
You'll need to use ["bracket notation"] to access this, since "3h" begins with a number. As MDN explains:
An object property name can be any valid JavaScript string, or anything that can be converted to a string, including the empty string. However, any property name that is not a valid JavaScript identifier (for example, a property name that has a space or a hyphen, or that starts with a number) can only be accessed using the square bracket notation.
This is the correct JSON:
{
"rain": {
"3h": 13.625
}
}
First you need to parse it and transform into an object:
var jsonToObject = JSON.parse('{"rain":{"3h":13.625}}');
You can now access it like this:
jsonToObject.rain["3h"]
Just use data["rain"]. If you need to parse it first do JSON.parse(data) and then data["rain"].
OUTPUT
console.log(data["rain"]);
> { '3h': 13.625 }
...keep in mind that will return an Object.

Ext JS - How to get success property in custom json result object when i load store

When I store load, how can I get the success property??
load store:
store.load({
scope: this,
callback: function(records, operation, success) {
if (success) {
console.log('success');
} else {
console.log('error');
}
});
return json data:
{
"header" : {
"success" : "true",
"message" : "complete!"
},
"data" : [{
"id" : 1,
"userId" : 1,
"subject" : "Document 1"
},{
"id" : 2,
"userId" : 1,
"subject" : "Document 2"
}]}
I want get "success" property in "header" and use this in a condition of the if statement.
http://docs-origin.sencha.com/extjs/5.0/apidocs/#!/api/Ext.data.reader.Reader-cfg-successProperty
So where you define the store, you have to add a successProperty to the store's reader, which should be "header.success".
You can't use different successProperties for one store, depending on which operation you perform.

The shortest path between two addresses

Using google map, you can actually get the different possible routes between two addresses, also you get the length of every possible route.
I'm now working on a website with google map, i want to calculate the shortest path between two different addresses same as google map does. then get the path length back as javascript variable.
You can use these function:
google.maps.geometry.spherical.computeDistanceBetween (latLng1, latLng1);
The arguments are two LatLng objects.
Make sure you include:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&v=3&libraries=geometry"></script>
I found it, it can be calculated using google map api called Distance Matrix it returns a json response containing The recommended path's length and Duration.
{
"destination_addresses" : [ "Témara, Maroc" ],
"origin_addresses" : [ "Rabat, Maroc" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "13,6 km",
"value" : 13620
},
"duration" : {
"text" : "23 minutes",
"value" : 1358
},
"status" : "OK"
}
]
}
],
"status" : "OK"
}
This should work fine:
function getDistance()
{
var url="http://maps.googleapis.com/maps/api/distancematrix/json?origins=rabat&destinations=temara&mode=driving&language=fr-FR&sensor=false";
var def = new jQuery.Deferred();
$.getJSON(url,function(json)
{
if (json.status=="OK")
{
var distance=json.rows[0].elements[0].distance.text;
}
def.resolve(distance);
});
return def.promise();
}
$.when(getDistance()).then(function(distance){
alert(distance);});
Demo

Knockout mapping does represent wished for html

I have a problem with knockout mapping. I'm using knockout mapping plugin to represent a form that is serialized in JSON. It was working before using the knockout mapping but I need to use knockout mapping since I want my properties to be observable.
You can see the working html here : http://jsfiddle.net/etiennenoel/wG9SZ
Here's my not working javascript code:
var formData =
{"data":
[
{
"groupName" : "Properties",
"content" :
[
{
"title" : "Calculation Method",
"formType" : "select",
"value" :
[
{
"title" : "Voltage Drop - Unbalanced",
"selected" : true
},
{
"title" : "Voltage Drop - Balanced"
}
]
},
{
"title" : "Tolerance (% V)",
"formType" : "textBox",
"value" : 0.01
},
{
"title" : "Calculation Options",
"formType" : "radio",
"value" :
[
{
"title" : "Flat Start (at Nominal Conditions",
"checked" : false
} ,
{
"title" : "Assume Line Transposition",
"checked" : true
}
]
},
{
"title" : "Adjust Conductor Resistance at",
"formType" : "textBox",
"disabled" : true,
"value" : 77,
"appendLabel" : true,
"appendLabelText" : "°F"
}
]
},
{
"groupName" : "Properties",
"content" :
[
{
"title" : "Calculation Method",
"formType" : "select",
"value" :
[
{
"title" : "Voltage Drop - Unbalanced",
"selected" : true
},
{
"title" : "Voltage Drop - Balanced"
}
]
},
{
"title" : "Tolerance (% V)",
"formType" : "textBox",
"value" : 0.01
},
{
"title" : "Calculation Options",
"formType" : "radio",
"value" :
[
{
"title" : "Flat Start (at Nominal Conditions",
"checked" : false
} ,
{
"title" : "Assume Line Transposition",
"checked" : true
}
]
},
{
"title" : "Adjust Conductor Resistance at",
"formType" : "textBox",
"disabled" : true,
"value" : 77,
"appendLabel" : true,
"appendLabelText" : "°F"
}
]
}
]
};
ko.mapping.fromJS(formData);
Here's the jsfiddle of the same code: http://jsfiddle.net/etiennenoel/wG9SZ/3/
What is the problem between when I use mapping and when I don't use it ?
In your second case you forgot to ApplyBindings.
ko.applyBindings(formData);
I don't know if this is the case with your scenario, but it's worth a post.
I had issues with the mapping plugin, when I had a more complex viewmodel with nested properties or lists. It turned out that after mapping to an already constructed viewmodel, the sub-objects were no more observables. With this issue, for me this code worked, what I've found somewhere (unfortunately I already really don't know where). I called this function for my viewmodel after mapping to that.
function makeAllObservables(observable) {
// Loop through its children
for (var child in observable()) {
// If this child is not an observable and is an object
if ((!ko.isObservable(observable()[child])) && (typeof observable()[child] === "object")) {
// Make it an observable
observable()[child] = ko.observable(observable()[child]);
// Make all of its children observables
makeAllObservables(observable()[child]);
}
}
};
Usage (when updating the model from server response, the first line should not be there):
var model = ko.observable({});
ko.mapping.fromJS(myJSObject, {}, model);
makeAllObservables(model);
ko.applyBindings(model);
I ment mapping to an already constructed viewmodel for example, when you want to update your viewmodel with new JSON data from server. In that case I lost nested bindings without the code above.
UPDATE: I've found the source where I borrowed the technique from, here. Note that I slightly modified that code in that post, because somehow that was not working for me.
You need to bind the mapped viewmodel to the view:
ko.applyBindings(ko.mapping.fromJS(formData));
and since everything is now an observable the logic in the view needs to be changed to use the method syntax:
<!-- ko if: $data.formType() === "select" -->
To get the options to display, you need to tell knockout what the property name is on the object:
<select data-bind="options: $data.value, optionsText: 'title'"></select>

Dynamically creating nodes in a jstree tree structure

I have to retrieve a list of menu item from a database and display it in a tree structure I want to use the menu name as the node name and menu id as the id of the node.
The method I used was to retrieve the data using an ajax call and put them into a list and then display it as a tree.But I think dynamically creating nodes depending on the data is more efficient.
function createNodeList(){
$('#menuCPanel #contentData #tree').jstree({
"json_data" : {
/*"data" : [{
"data" : {title : "menuName"},
"attr" : {id : "menuId"},
"state" : "closed"
}
],*/
"ajax" :{
"type" : "POST",
"url" : "?m=admin?action=getNodeList",
"dataType" : "json",
"data" : function(result){
return {
id : result.attr ? result.attr("id") : result['menuId'],
title : result.attr ? result.attr("title") : result['menuName']
};
},
},
},
"callback" : {
},
"themes" : {
"theme" : "classic",
"dots" : true,
"icons" : true
},
"plugins" : ["json_data", "themes"]
}).bind("select_node.jstree", function (e, data) { alert(jQuery.data(data.rslt.obj[0], "jstree").id) });
}
}
this is the stucture of my json data
"data":[{"menuId":"1","menuName":"Top Menu"},{"menuId":"2","menuName":"Main Menu"},{"menuId":"3","menuName":"Bottom Menu"},{"menuId":"4","menuName":"Main Menu"}]}
I would like to know what is wrong with the above result and how to dynamically create a node within in the ajax.success();
I went through some examples but all of them use the jstree.cretate() which i can't invoke inside jstree.json_data.ajax.success()
thanks in advance :)
This is a standard jstree with json data, which also binds select_node to do actions when a node is selected. Nodes must not have an ID which are plain numbers or contain jquery special selector characters. Number IDs must have a standard character first. so 1 should be N1, 2 should be N2 for example.
$('#MyTreeDiv').jstree({
"json_data": {
"ajax": {
"type": "POST",
"url": "/MyServerPage.aspx?Action=GetNodes",
"data": function (n) { return { id: n.attr ? n.attr("id") : 0} },
}
},
"themes": {
"theme": "default",
"url": "/Content/Styles/JSTree.css",
"dots": false
},
"plugins": ["themes", "json_data", "ui", "crrm"]
}).bind("select_node.jstree", function (e, data) {
var selectedObj = data.rslt.obj;
alert(selectedObj.attr("id"));
});
The json returned from your server must be in the correct format as defined in the jstree documentation, and must no include several special characters, unless those characters are escaped or the json created using serialization.

Categories

Resources