JQuery treating my non-empty array as empty? - javascript

Very simply I have built a multi-dimensional array across a long section of script and at the end I want to loop through each level and do something. I have logged the array out in the console and can see everything as it should be, but the console then tells me the array length is 0 and sure enough if I .length it is also tells me the length is 0, so my JQuery each isn't firing. I can't understand what one can do to make it behave like this. I am absolutely stumped!
This is the console:
Here is the JQuery, although the array/object is built over so much script and ajax calls that I've tried to only put in the bits that count...
var field_layers = [];
function blah_blah() {
do_api_call("api_call_url_here")
.done(function(response, textStatus, xhr) {
var map_layers = response;
$(map_layers).each(function(map_layers_key, map_layers_detail) {
var datalayer_id = map_layers_detail.Layer.DataLayerId;
// add field ids to array:
field_layers["field_id_"+map_layers_detail.Layer.FieldId] = [];
do_api_call("api_call_url_here/"+datalayer_id)
.done(function(response, textStatus, xhr) {
// create an empty array for field layers:
field_layers["field_id_"+map_layers_detail.Layer.FieldId]["layer_id_"+datalayer_id] = [];
var map_layer_zones = response;
$(map_layer_zones).each(function(map_layer_zone_key, map_layer_zone_detail) {
// Add the zones to the layer
field_layers["field_id_"+map_layers_detail.Layer.FieldId]["layer_id_"+datalayer_id].push({
"zone_id":zone.DataLayerZoneId,
"title":zone.DataLayerZoneId+" title here"
});
});
});
});
});
}
function go_to_field(field_id) { // this is what gives me the console screenshot
console.log("field_id: "+field_id);
console.log(field_layers["field_id_"+field_id]);
console.log(field_layers["field_id_"+field_id].length);
}

Try changing your field_layers = [] to be an object instead of an array: field_layers = {}. I think if you change each place you are initializing an empty array to initializing an empty object, then your code should work as-is.
Notice the difference between square brackets and curly braces.
With you coming from a PHP background, you can think of Javascript objects (the {}) as associative (or named) arrays in PHP.
So the final code would look like:
var field_layers = {};
function blah_blah() {
do_api_call("api_call_url_here")
.done(function(response, textStatus, xhr) {
var map_layers = response;
$(map_layers).each(function(map_layers_key, map_layers_detail) {
var datalayer_id = map_layers_detail.Layer.DataLayerId;
// add field ids to object:
field_layers["field_id_"+map_layers_detail.Layer.FieldId] = {};
do_api_call("api_call_url_here/"+datalayer_id)
.done(function(response, textStatus, xhr) {
var map_layer_zones = response;
$(map_layer_zones).each(function(map_layer_zone_key, map_layer_zone_detail) {
// Add the zones to the layer
field_layers["field_id_"+map_layers_detail.Layer.FieldId]["layer_id_"+datalayer_id] = {
"zone_id":zone.DataLayerZoneId,
"title":zone.DataLayerZoneId+" title here"
}; // notice the assignment of object literal here
});
});
});
});
}
function go_to_field(field_id) { // this is what gives me the console screenshot
console.log("field_id: "+field_id);
console.log(field_layers["field_id_"+field_id]);
console.log(field_layers["field_id_"+field_id].length);
}
I haven't tested this, but I think it should work.

Related

Object created from a loop in JavaScript, how to analyse them in a json

I'm a begginer in Javascript and I need to analyse a JavaScript Object generated in a loop to keep one parameter and to save this parameter for all object generated in the loop.
This is my program
var onvif = require('onvif');
var fs = require('fs');
var nombrecamera=0;
var taille=0;
var test ='';
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
var STREAM = fs.createWriteStream('STREAM.txt',{flags:'r+'});
onvif.Discovery.on('device', function(cam,rinfo,xml){
// function will be called as soon as NVT responses
nombrecamera+=1;
console.log(cam);
test += cam;
cam2= JSON.stringify({cam}, null , ' ');
//console.log(cam2);
STREAM.write(cam2);
console.log(test);
});
onvif.Discovery.probe({timeout:1000,resolve:false});
And in output in my example i've got 4 of these:
{ probeMatches:
{ probeMatch:
{ endpointReference: [Object],
types: 'tdn:NetworkVideoTransmitter',
scopes: ' onvif://www.onvif.org/type/video_encoder onvif://www.onvif.org/location/country/china onvif://www.onvif.org/type/network_video_transmitter onvif://www.onvif.org/hardware/IPC-122 onvif://www.onvif.org/Profile/Streaming onvif://www.onvif.org/name/IPC-BO',
XAddrs: 'http://192.168.1.81:10004/onvif/device_service',
metadataVersion: 1
}
}
}
And I want to keep only the XAddrs for all object generated and then put these in a json.
My first idea was to stringify this object then create a writable stream and put all json together but in this case there are no coma between the json so it doesn't create a big json with the whole data.
Thank you for your help
Jules
The easiest way to know how many addresses you have is the .length function of an array.
As I don't know whether you need a list with unique addresses or the same address can show up multiple times, I'm gonna show you both solutions.
Unique Addresses Only
function extract() {
test.forEach(cam => {
const deviceAddress = cam.probeMatches.probeMatch.XAddrs;
// only if the xaddrs is not in list yet, add it
if(test.filter(xad => xad === deviceAddress).length <= 0) {
xaddrs.push(cam.probeMatches.probeMatch.XAddrs);
}
});
// show the number of addresses
const listCount = xaddrs.length;
console.log('listCount: ', listCount);
}
No Unique Address
function extract() {
test.forEach(cam => {
xaddrs.push(cam.probeMatches.probeMatch.XAddrs);
});
// show the number of addresses
const listCount = xaddrs.length;
console.log('listCount: ', listCount);
}
Make testan array and push()the camobjects into it. Also define an array for your XAddrs-values.
var test = [];
var xaddrs = [];
// your other code
...
onvif.Discovery.on('device', function(cam,rinfo,xml){
// function will be called as soon as NVT responses
nombrecamera+=1;
console.log(cam);
// push cam object into array
test.push(cam);
cam2= JSON.stringify({cam}, null , ' ');
//console.log(cam2);
STREAM.write(cam2);
console.log(test);
});
Then extract XAddrs and push it into xaddrs array.
function extract() {
test.forEach(cam => {
xaddrs.push(cam.probeMatches.probeMatch.XAddrs);
});
// now you have an array containing only the XAddrs elements
console.log(xaddrs);
}

Parse not retrieving array of objects

I am storing an array of Javascript objects in Parse under the name 'AcceptedInvitees'. The objects each have two values; an example entry is:
[{"id":"QpAETvSYaB","type":"Requested"},{"id":"Ojjp3TdmTM","type":"unknown"},{"id":"STAUUgVxJp","type":"unknown"},{"id":"AXBC5iZvKQ","type":"unknown"},{"id":"YixKjqrjTM","type":"unknown"},{"id":"b2YwmMcO6n","type":"unknown"},{"id":"DjZePR0Wif","type":"unknown"},{"id":"94Harl1hxm","type":"unknown"},{"id":"1bOE07B0C8","type":"unknown"}]
I am trying to retrieve this value using .get("AcceptedInvitees"), but I am being returned an array of empty objects. For example, retrieving the above entry gives me
[{},{},{},{},{},{},{},{},{}]
This is the specific code I am using to query the data. All the other fields are being retrieved without a problem, but printing node.children gives me the above.
var query = new Parse.Query("UserInvite");
query.include("AcceptedInvitees");
query.get(id, {
success: function (user) {
node.name = user.get("name");
node.TotalInvitees = user.get("TotalInvitees");
node.type = type;
node.children = user.get("AcceptedInvitees");
}
Any help with this would be greatly appreciated!
Parse.Query expects Parse.Object. Therefore, do as following:
var UserInvite = Parse.Object.extend("UserInvite");
var id = 'someUserInviteId';
var query = new Parse.Query(UserInvite);
query.include("AcceptedInvitees");
query.get(id, {
success: function(obj) {
console.log(obj.toJSON());
},
error: function(err) {
console.log(err);
}
});

How to extract data from array in javascript

I have an object (array type) ,its console representation looks like following image . please see the image
This array is created by restangulr using following code ,
restangularProvider.addResponseInterceptor(function (data, operation, what, url, response, deferred) {
if (operation == "getList") {
var extractedData;
extractedData = data.result;
extractedData.paginginfo = data.paginginfo;
return extractedData;
}
if (operation != "get") {
var item = { status: response.status };
feedBackFactory.showFeedBack(item);
}
return response.data;
});
How can I read the elements from this array, I want to extract properties like paginginfo ,also object collection
// The EDIT :1 js libraries I used here angularjsu 1.3.4, and restangular 1.4
My app.js : here I configured rest angular provider
restangularProvider.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
if (operation == "getList") {
var extractedData;
extractedData = data.result;
extractedData.paginginfo = data.paginginfo;
return extractedData;
}
if (operation != "get") {
var item = {
status: response.status
};
feedBackFactory.showFeedBack(item);
}
return response.data;
});
// according to my knowledge this function will intercept every ajax call (api calls) and modify the response , unfortunately I need to apply custom modification because the getlist method must return collection but my api returning object, so according to restangular ,the above code is the possible solution, and here its fine its fetching the data.
userservice.js : this is angular service which using restangular
function(restangular) {
var resourceBase = restangular.all("account");
this.getUsers = function(pagenumber, recordsize) {
var resultArray = resourceBase.getList({
page: pagenumber,
size: recordsize
}).$object;
};
};
according to my knowledge .$object in restangulr resolve the promise and bring back the data, also I am getting the resultArray its looks like in the image in the console, here I can log this array so I think I got all the data from server and filled in this object. I applied some array accessing techniques available jquery and JavaScript like index base accessing , associate accessing but I am getting undefined ie.
resultArray[1] //undifiend;
In angular you can use angular.forEach(items, function(item){ //your code here});
Where items is the array you want to traverse.
If you want to access to one specific position use [], for example var item= items[5].
Then you can do item.property.
UPDATE
Your problem is that you are setting properties in an Array JS Object:
extractedData.paginginfo = data.paginginfo;
You should return the object data like it is and in your controller do something like:
var results= data.result;
var pagInfo= data.paginationInfo;
angular.forEach(results,function(result){});
It looks like the array is numerically indexed (0..1..5); you should be able to simply iterate through it using ForEach (in Angular) or .each (in Jquery).
Something like (JQuery):
$.each(array, function(key, value)
{
// key would be the numerical index; value is the key:value pair of the array index's element.
console.log(value.firstname); // should print the firstname of the first element.
});
First of all, as I said in the comments, you shouldn't be attaching named properties to arrays. Return an object thact contains what you need:
if (operation == "getList") {
return { values: data.result, paging: data.pagingInfo };
}
The getList() method returns a promise, so you need to use that:
this.getUsers = function(pagenumber, recordsize) {
resourceBase.getList({
page: pagenumber,
size: recordsize
}).then(function (data) {
console.log(data.values[0]);
console.log(data.paging.totalRecords);
});
};

Concat objects is not working or I need to convert values to the right format?

I need to get data.entities.paises from the first $.post and concat() with data.entities from the second $.post and this is how I'm doing:
var paisesFromEntity;
$.post(Routing.generate('productoGuardarPasoCinco'), $form.serialize(), 'json').done(function (data, textStatus, jqXHR) {
if (data.entities !== "undefined" || data.entities != "") {
paisesFromEntity = data.entities.paises;
}
}).fail(function () {
return false;
});
var returnList = function (entities) {
if (entities.length > 0) {
var items = [];
entities.forEach(function (value, index, array) {
items.push(value.pais);
});
return items.join(', ');
}
};
var fullList = [];
$.post(Routing.generate('agregarPaisesDistribuidor'), $form.serialize(), 'json').done(function (data, textStatus, jqXHR) {
fullList = fullList.concat(data.entities, JSON.stringify(paisesFromEntity));
var displayText = returnList(fullList);
$('#td-' + data.idToUpdate).html(displayText);
}).fail(function () {
return false;
});
Taking this output for first $.post():
{
"success":true,
"entities":{
"id":13,
"nombre":"dsdsfsdfsd",
"direccion":"fsdfsdfsdf",
"telefono":"4234234",
"paises":[
"Bolivia",
"Costa Rica",
"Ecuador"
]
}
}
And the this for the second $.post():
{
"success":true,
"entities":[
{
"pais":"Colombia"
},
{
"pais":"Panam\u00e1"
},
{
"pais":"Ciudad del Vaticano"
}
],
"idToUpdate":"14"
}
The expected output in displayText should be something like: Bolivia, Costa Rica, Ecuador, Colombia, Panam\u00e1, Ciudad del Vaticano but I get this output instead Colombia, Panamá, Ciudad del Vaticano, and some values are missing the ones from data.entities.paises. I suspect the error is that data.entities.paises is not in the same format as data.entities and for that the function on returnList doesn't do the job god, so where is the error on the concat() function or on the data.entities.paises format? If is the second one how can I convert to the same format as data.entities before concatenate both?
You have 3 issues here.
First of all, you can have a timing issue, since there is no guarantee that the first $.post will finish before the second. You need to ensure both are finished before moving in. You have a few ways to do that - chaining, caolan's async lib https://github.com/caolan/async, callbacks that check, etc. - but that is not what you are asking about here.
The second issue is that the first response is an array of strings; the second is an array of objects whose values you want, and you need to combine them.
The third issue is that you are converting the array of strings to JSON string, which will not work either.
Try this.
// assuming data.entities is an array of objects, and paisesFromEntity is an array of strings
fullList = fullList.concat(paisesFromEntity, getValues(data.entities));
The getValues() function
getValues = function(arr){
var ret = [], i;
for (i=0; i<arr.length; i++) {
ret.push(arr[i].pais);
}
return(ret);
};
If you are doing this in jQuery, you can use
getValues = function(arr){
var ret = [];
$.each(arr,function(i,entry) {
ret.push(entry.pais);
});
return(ret);
};
If you have access to lodash or underscore, it is even easier with pluck.

Format returned table data in json

I'm fairly new to javascript. I retreive data from a sql server database that looks like this :
[Object { shortcode="0013A2004031AC9A", latest_measurement=1067, keyid="6801"},
Object { shortcode="0013A2004031AC9A", latest_measurement=7, keyid="6802"},
Object { shortcode="0013A2004031AC9A", latest_measurement=8598838, keyid="6803"}]
I want to format this in a json like this :
{mac : 0013A2004031AC9A, keys : {6801:1067, 6802:7, 6803:8598838}}
but I just don't get to that.
I have
var jsonDataPerMac = {};
I loop over the json object above and for every new mac I find I do :
jsonDataPerMac[i]={"mac": device.shortcode, "keys":[]};
but how do I get to fill the keys?
Any hints would be appreciated.enter code here
var macs = [];
var jsonDataPerMac = {};
var i = 0;
$.ajax({
url: "/bmmeasurements",
type: "GET",
data: {"unitid" : unitid},
async: false,
success: function (data) {
console.log(data);
initializeTable();
$.each(data, function (index,device) {
//add all distinct macs in an array, to use them as a column header
if($.inArray(device.shortcode, macs) == -1) {
macs.push(device.shortcode);
jsonDataPerMac[i]={"mac": device.shortcode, "keys":[]};
i++;
//create a table cell for each possible key. id = 'mac-key'
createTableGrid(device.shortcode);
}
//add the measurement data to the correct cell in the grid
$('#' + device.shortcode + '-' + device.keyid).html(device.latest_measurement);
});
}});
Here is my proposition. I would rather avoid using jQuery to perform such a simple operations. In this particular example, we use forEach and for..in loop.
//new output array
var newArray = [];
//we traverse the array received from AJAX call
array.forEach(function(el) {
var added = false; // it's false by default
// we check if the mac is already in newArray, if yes - just add the key
for(var i in newArray) {
if(newArray[i].mac == el.shortcode) {
newArray[i].keys.push(el.keyid+":"+el.latest_measurement);
added = true; // tells us whether the key has been added or not
}
}
// if key hasn't been added - create a new entry
if(!added) {
newArray.push({"mac": el.shortcode, "keys":[el.keyid+":"+el.latest_measurement]});
}
});
console.log(newArray);
You can transform above code to a function and then, reuse it in your ajax onSuccess method. Remember to pass the array as an argument and to return newArray.
JSFiddle:
http://jsfiddle.net/2d5Vq/2/
You need to combine the entries first...
var reducedData = {};
$.each(macs, function(index,macitem){
if (reducedData.hasOwnProperty(macitem.shortcode)) {
reducedData[macitem.shortcode].push(macitem.key);
} else {
reducedData[macitem.shortcode] = [ macitem.key ];
}
});
And then map to your desired format inside an array...
var jsonDataPerMac = [],
i = 0;
$.map(reducedData, function(keys,mac){
jsonDataPerMac[i++] = {"mac": mac, "keys": keys};
// your other code goes here
});
Also your usage of jsonDataPerMac suggests that you want it to be an array.

Categories

Resources