Dynamic values into objects in javascript - javascript

I have the following code with more values, showing only 3 to give you an idea
var people = {
'Jon':{
age:65,
height:185,
marriage:true
},
'Mary':{
age:18,
height:170,
marriage:false
},
'Carol':{
age:45,
height:165,
marriage:true
}
};
Because now I get all the values dynamically from the server, I would like to replicate the object to get the dynamic values from the <a> tag instead listing all of them above.
<a data-name='${person.name}' data-age="${person.age}" data-height="${person.height}" data-marriage="${person.isMarried}" href='/#'>
<script>
var personName = $('a').data('name');
var personAge = $('a').data('age');
var personHeight = $('a').data('height');
var isMarried = $('a').data('marriage');
</script>
I am trying something like this, but it doesn't seem to work, do i need to create a loop, not really sure
var people = {
personName:{
age:personAge,
height:personHeight,
marriage:isMarried
}
};
Any help will be appreciated
Thanks

Yes. You will need a loop (or equivalent). Here is a simple working approach.
var people = {};
$('a').each(function(){
var a = $(this);
people[a.data('name')] = {
age: a.data('age'),
height: a.data('height'),
marriage: a.data('marriage')
}
});
document.body.innerHTML += JSON.stringify(people, null, 2);
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<a data-name='Jon' data-age="65" data-height="185" data-marriage="true" href='/#'></a>
<a data-name='Mary' data-age="age" data-height="170" data-marriage="false" href='/#'></a>
<a data-name='Carol' data-age="45" data-height="165" data-marriage="true" href='/#'></a>

If you didn't want to use jQuery, here's a simple vanilla way of doing it, making sure that the data types are what you require in your output.
var anchors = [].slice.call(document.getElementsByTagName('a'));
var people = {};
anchors.forEach(function (el) {
people[el.getAttribute('data-name')] = {
age: +el.getAttribute('data-age'),
height: +el.getAttribute('data-height'),
marriage: el.getAttribute('data-marriage') === 'false' ? false : true
};
});
people output
{
"Jon": {
"age": 65,
"height": 185,
"marriage": false
},
"Mary": {
"age": 18,
"height": 170,
"marriage": false
},
"Carol": {
"age": 40,
"height": 165,
"marriage": true
}
}
DEMO

You need to create a loop, but it's better if the server that returns this kind of object return an array.
This code will do what you want.
var peopleArray=[];
for (var i in people) {
if(people.hasOwnProperty(i) {
var currentPeople = people[i];
currentPeople.name = i;
peopleArray.push(currentPeople);
})
}
This code create an array of people like this :
[
{
name:'Jon',
age:65,
height:185,
marriage:true
},
{
...
}
]

It seems you want to create an object by reading the data-* attributes of the a elements. If this is the case one option is:
var people = {};
$('a').each(function() {
var data = $(this).data(), name = data.name;
delete data.name;
people[name] = data;
});
If you want to create an array of objects you can use the $.prototype.map method:
var people = $('a').map(function() { return $(this).data() }).get();
// [{
// "name": "${person.name}",
// "age": "${person.age}",
// "height": "${person.height}",
// "marriage": "${person.isMarried}"
// }]

Related

JSON Parse, how to get a variable with an unknown first part?

Following is a JSON output from an API, I've had trouble trying to compare the "last_save" variables, and if a profile has a larger "last_save" value, set the "profile_id" as a variable. (Im fairly new to java script, sorry if I use incorrect terminology)
Here is the code:
function profileID(){
console.log("Running profileID.")
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rawJsonText = this.responseText;
var parsedText = JSON.parse(rawJsonText);
console.log(parsedText)
console.log(playerUUID)
lastPlayedIslandID = parsedText[0].last_save
lastPlayedProfileName = parsedText.profile_id
console.log(nameMC+"'s island ID : "+lastPlayedIslandID);
console.log(nameMC+"'s island name : "+lastPlayedProfileName);
slayerZombie();
}
};
xhttp.open("GET", slothpixelAPI+"skyblock/profiles/"+nameMC, true);
xhttp.send();
}
This is the JSON output from the API:
{
"5ab88f71d10747aabf643e666c9933b1": {
"profile_id": "5ab88f71d10747aabf643e666c9933b1",
"cute_name": "Grapes",
"first_join": 1578113432038,
"last_save": 1582337480211,
"collections_unlocked": 0,
"members": [
"4878f8a455e84956b19d4873d837ab93"
]
},
"4878f8a455e84956b19d4873d837ab93": {
"profile_id": "4878f8a455e84956b19d4873d837ab93",
"cute_name": "Coconut",
"first_join": 1560932868602,
"last_save": 1583315330184,
"collections_unlocked": 59,
"members": [
"8d32864b3a364035922dd84d5247f483",
"4878f8a455e84956b19d4873d837ab93"
]
}
}
Thanks
parsedText is an object, not array, so number indexing isn't going to work. In fact objects don't order their values as you'd expect. Use Object.keys(parsedText) to get the names of the each value in the object, and iterate through them to find out what you need. There are other ways you can iterate through an object as well.
var parsedText = JSON.parse(rawJsonText);
var parsedKeys = Object.keys(parsedText);
var mostRecentProfile = "";
for(var i = 0; i < parsedKeys.length; i++) {
if(mostRecentProfile) {
if(parsedText[mostRecentProfile].last_save < parsedText[parsedKeys[i]].last_save) {
// Current profile has more recent save
mostRecentProfile = parsedKeys[i];
}
} else { // Set first profile as default
mostRecentProfile = parsedKeys[i];
}
}
console.log(parsedText[mostRecentProfile].last_save); // 1583315330184
A shorter way to do it if you're comfortable with one-liners is by getting only the values with Object.values(parsedText), sorting the objects by a property last_save, and selecting the first one.
var parsedText = JSON.parse(rawJsonText);
var mostRecentProfile = Object.values(parsedText).sort(function(a, b) {
// Sort in descending order
return b.last_save - a.last_save;
})[0].profile_id;
console.log(parsedText[mostRecentProfile].last_save); // 1583315330184
I i have understood,i think you have only one object with 2 fields. I think your parsedText returns something like:
[{
"5ab88f71d10747aabf643e666c9933b1": {"last_save": 1582337480211},
"4878f8a455e84956b19d4873d837ab93": {"last_save": 1583315330184}
}]
And parsedText[0] is like:
{
"5ab88f71d10747aabf643e666c9933b1": {"last_save": 1582337480211},
"4878f8a455e84956b19d4873d837ab93": {"last_save": 1583315330184}
}
You could access to the childrens like:
var text = '{"5ab88f71d10747aabf643e666c9933b1": {"last_save": 1582337480211},"4878f8a455e84956b19d4873d837ab93": {"last_save": 1583315330184}}'
obj = JSON.parse(text);
console.log(obj)
console.log(obj["4878f8a455e84956b19d4873d837ab93"]["last_save"])
console.log(obj["5ab88f71d10747aabf643e666c9933b1"]["last_save"])

Populating Javascript Array of Objects with an embedded Array of Objects

I am new to Javascript (familiar with C/C++) and I am trying to parse out an XML file and store it in an Array of Objects. The structure is similar to a bullet list where there is one main List item and possibly multiple List subitems:
var MenuLine =
[{
label : "null",
icon : "null",
Subitem:
[{
label : "null",
icon : "null"
}]
}];
Which allows me to use the following syntax:
var someRandomSubitemText = MenuLine[2].Subitem[4].label;
I tried populating this array using the .push method:
var tempMenuLine = [];
var tempSubitem = [];
$(xml).find("item").each(function()
{
tempMenuLine.label = $(xml).children("label").text();
tempMenuLine.icon = $(xml).children("icon").text();
$(this).children("subitem").each(function()
{
tempSubitem.label = $(this).children("label").text();
tempSubitem.icon = $(this).children("icon").text();
tempMenuLine.Subitem.push(tempSubitem);
});
MenuLine.push(tempMenuLine);
});
However this does not work since the .push method passes a reference to tempMenuLine and I am overwriting tempMenuLine with each iteration. Is there a way that I could write directly to the MenuLine array using something similar to the following syntax?
$(xml).find("item").each(function(index1)
{
MenuLine[index1].label = $(xml).children("label").text();
MenuLine[index1].icon = $(xml).children("icon").text();
$(this).children("subitem").each(function(index2)
{
MenuLine[index1].Subitem[index2].label = $(this).children("label").text();
MenuLine[index1].Subitem[index2].icon = $(this).children("icon").text();
});
});
Move your temp var declarations inside of your loops:
$(xml).find("item").each(function() {
var tempMenuLine = [];
tempMenuLine[0].label = $(xml).children("label").text();
tempMenuLine[0].icon = $(xml).children("icon").text();
tempMenuLine[0].Subitem = []
$(this).children("subitem").each(function(){
var tempSubitem = [];
tempSubitem[0].label = $(this).children("label").text();
tempSubitem[0].icon = $(this).children("icon").text();
tempMenuLine[0].Subitem.push(tempSubitem);
});
MenuLine.push(tempMenuLine);
});
This way, you're initializing a new item for each iteration of the loops, removing the "link" it had to the previous item.
A recursive solution just for fun.
var MenuLine = Xml2Array(xmlText, 'item');
function Xml2Array(xmlDocument, itemName) {
if (!$(itemName, xmlDocument).length) {
return;
}
var tmpArray = [];
$(itemName, xmlDocument).each(function() {
tmpArray.push({
label: $('label', this).first().text(),
icon: $('icon', this).first().text(),
Subitem: Xml2Array(this, 'subitem')
});
});
return tmpArray;
}

How to Iterate over a hash in mustache.js

Given this hash
a = {
foo : { ... },
bar : { ... },
zap : { ... }
}
i want to iterate over it but since the keys are different I am not sure how to in Mustache.js
the output will look something like this foo : (contents here)
If you know the key in the nested object that you're trying to retrieve, you can use a function.
see: http://jsfiddle.net/jimschubert/zPWDJ/
js:
$(function() {
var names = {
"a": [
{"foo": { "name": "foo name"}},
{"bar": { "name": "bar name"}},
{"zap": { "name": "zap name"}}
],
"n": function() {
var self = this;
var n = "";
Object.keys(self).forEach(function(k, v) {
if (typeof self[k] == "object") {
if(!n) n = self[k]["name"];
}
});
return n;
}
};
var template = $('#template').html();
var out = $('#output');
var html = Mustache.to_html(template, names);
console.log(html);
out.html(html);
});​
html:
<script id="template" class="template" type="text/x-mustache">
{{#a}}
<p>{{n}}</p>
{{/a}}
</script>
<h1>Output</h1>
<div id="output">
</div>
​
This of course assumes your data is an array of objects (the a in your post would be one key of a greater array, maybe?) If you don't have an array, I don't see why you wouldn't be able to adjust this for an object and make a getter function for whatever properties of each key you're looking for.

Use a JSON array with objects with javascript

I have a function that will get a JSON array with objects. In the function I will be able to loop through the array, access a property and use that property. Like this:
Variable that I will pass to the function will look like this:
[{
"id": 28,
"Title": "Sweden"
}, {
"id": 56,
"Title": "USA"
}, {
"id": 89,
"Title": "England"
}]
function test(myJSON) {
// maybe parse my the JSON variable?
// and then I want to loop through it and access my IDs and my titles
}
Any suggestions how I can solve it?
This isn't a single JSON object. You have an array of JSON objects. You need to loop over array first and then access each object. Maybe the following kickoff example is helpful:
var arrayOfObjects = [{
"id": 28,
"Title": "Sweden"
}, {
"id": 56,
"Title": "USA"
}, {
"id": 89,
"Title": "England"
}];
for (var i = 0; i < arrayOfObjects.length; i++) {
var object = arrayOfObjects[i];
for (var property in object) {
alert('item ' + i + ': ' + property + '=' + object[property]);
}
// If property names are known beforehand, you can also just do e.g.
// alert(object.id + ',' + object.Title);
}
If the array of JSON objects is actually passed in as a plain vanilla string, then you would indeed need eval() here.
var string = '[{"id":28,"Title":"Sweden"}, {"id":56,"Title":"USA"}, {"id":89,"Title":"England"}]';
var arrayOfObjects = eval(string);
// ...
To learn more about JSON, check MDN web docs: Working with JSON
.
This is your dataArray:
[
{
"id":28,
"Title":"Sweden"
},
{
"id":56,
"Title":"USA"
},
{
"id":89,
"Title":"England"
}
]
Then parseJson can be used:
$(jQuery.parseJSON(JSON.stringify(dataArray))).each(function() {
var ID = this.id;
var TITLE = this.Title;
});
By 'JSON array containing objects' I guess you mean a string containing JSON?
If so you can use the safe var myArray = JSON.parse(myJSON) method (either native or included using JSON2), or the usafe var myArray = eval("(" + myJSON + ")"). eval should normally be avoided, but if you are certain that the content is safe, then there is no problem.
After that you just iterate over the array as normal.
for (var i = 0; i < myArray.length; i++) {
alert(myArray[i].Title);
}
Your question feels a little incomplete, but I think what you're looking for is a way of making your JSON accessible to your code:
if you have the JSON string as above then you'd just need to do this
var jsonObj = eval('[{"id":28,"Title":"Sweden"}, {"id":56,"Title":"USA"}, {"id":89,"Title":"England"}]');
then you can access these vars with something like jsonObj[0].id etc
Let me know if that's not what you were getting at and I'll try to help.
M
#Swapnil Godambe
It works for me if JSON.stringfy is removed.
That is:
$(jQuery.parseJSON(dataArray)).each(function() {
var ID = this.id;
var TITLE = this.Title;
});
var datas = [{"id":28,"Title":"Sweden"}, {"id":56,"Title":"USA"}, {"id":89,"Title":"England"}];
document.writeln("<table border = '1' width = 100 >");
document.writeln("<tr><td>No Id</td><td>Title</td></tr>");
for(var i=0;i<datas.length;i++){
document.writeln("<tr><td>"+datas[i].id+"</td><td>"+datas[i].Title+"</td></tr>");
}
document.writeln("</table>");

how to get distinct values from json in jquery

I've got a jquery json request and in that json data I want to be able to sort by unique values. so I have
{
"people": [{
"pbid": "626",
"birthDate": "1976-02-06",
"name": 'name'
}, {
"pbid": "648",
"birthDate": "1987-05-22",
"name": 'name'
}, .....
So, far, i have this
function(data) {
$.each(data.people, function(i, person) {
alert(person.birthDate);
})
}
but, I am at a total loss as to how efficiently get only the unique birthDates, and sort them by year (or any sort by any other personal data).
I'm trying to do this, and be efficient about it (i'm hoping that is possible).
Thanks
I'm not sure how performant this will be, but basically I'm using an object as a key/value dictionary. I haven't tested this, but this should be sorted in the loop.
function(data) {
var birthDates = {};
var param = "birthDate"
$.each(data.people, function() {
if (!birthDates[this[param]])
birthDates[this[param]] = [];
birthDates[this[param]].push(this);
});
for(var d in birthDates) {
// add d to array here
// or do something with d
// birthDates[d] is the array of people
}
}
function(data){
var arr = new Array();
$.each(data.people, function(i, person){
if (jQuery.inArray(person.birthDate, arr) === -1) {
alert(person.birthDate);
arr.push(person.birthDate);
}
});
}
Here's my take:
function getUniqueBirthdays(data){
var birthdays = [];
$.each(data.people, function(){
if ($.inArray(this.birthDate,birthdays) === -1) {
birthdays.push(this.birthDate);
}
});
return birthdays.sort();
}

Categories