I have a literal array that is loaded when the page loads... See below:
<script type="text/javascript">
var members = [
{
name:"Alan Lim",
id:"54700f06-a199-102c-8976-b1732b7ffc74",
positions:[
{
id:"4cdeb2a2-8897-102d-80ee-95364de284f0"
}
]
},
{
name:"Ben Sinclair",
id:"ed34b5a4-9b2f-102c-8475-9e610b13400a",
conflict:"true",
positions:[
{
id:"f00c2128-8895-102d-80ee-95364de284f0"
},
{
id:"f00c68ea-8895-102d-80ee-95364de284f0"
},
{
id:"4cde6824-8897-102d-80ee-95364de284f0"
},
{
id:"4cde9ea2-8897-102d-80ee-95364de284f0"
}
],
locations:[
{
id:"88fb5f94-aaa6-102c-a4fa-1f05bca0eec6"
},
{
id:"930555b0-a251-102c-a245-1559817ce81a"
}
]
},
{
name:"Debbie Wright",
id:"fa49307a-9cfb-102d-bd08-842c500d506d"
}
]
</script>
Is there anyway to edit the array without reloading the page? For example, I want to add conflict:"true" to Alan Lim...
E.g:
Change this:
{
name:"Alan Lim",
id:"54700f06-a199-102c-8976-b1732b7ffc74",
positions:[
{
id:"4cdeb2a2-8897-102d-80ee-95364de284f0"
}
]
},
To this:
{
name:"Alan Lim",
id:"54700f06-a199-102c-8976-b1732b7ffc74",
conflict:"true",
positions:[
{
id:"4cdeb2a2-8897-102d-80ee-95364de284f0"
}
]
},
Trust that makes sense :) The reason for this is because I use other JavaScript to pull information from this array. When I make a change with the other JavaScript I want to add and subtract to this array to reflect the changes...
You can loop through to find the member you want (by name it seems given the question) then edit it, like this:
for(var i=0; i<members.length; i++) {
if(members[i].name == "Alan Lim")
members[i].conflict = "true";
}
You can give it a try here, or make it a bit more generic like this:
function setProp(name, prop, value) {
for(var i=0; i<members.length; i++) {
if(members[i].name == name)
members[i][prop] = value;
}
}
Since your array is numerically indexed, Can you not just do:
members[0]['conflict'] = "true";
Related
I have a series of items and reports which need to pull and modify sub-arrays from a lengthy JavaScript data file (which I can't modify). The sample below contains a snippet of an entry for demonstration-purposes assigned to the variable called data. I cannot in any way change the architecture of the data structure for data itself (in practice it is retrieved via a script tag src="[URL]" property), and other data beyond what is shown here does not appear to be 100% organized like a JSON file, if it makes a difference.
In the section below, I create a variable q5_yes which ultimately will hold a single array of values for the "Yes" responses from "Question_5" of a survey. To get it to the format I need though, I need to modify it in several steps.
While what I have below works on its own, I'm wondering if there's a better practice for combining these steps into a single one (and ideally makes it easier for re-use in the future as well since I'm going to be repeating this procedure a lot).
var data = {
"reSEQ": [{
"Entry_1": "Nov-2015",
"Question_5": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
],
"Question_6": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
]
}]
};
var q5_yes = data.reSEQ.map(function(e) {
return e.Question_5.map(function(e) {
return e.Yes;
});
});
var q5_yes = q5_yes.map(function(subarray) {
return subarray.filter(function(val) {
return val !== undefined;
});
});
var q5_yes = q5_yes.splice(0, q5_yes.length - 0);
var q5_yes = [].concat.apply([], q5_yes);
document.getElementById("foo").innerHTML = q5_yes;
<div id="foo">test</div>
EDIT: I do have a solution to answer my own question, which is to simply wrap the var q5_yes calls into a single function with parameters to make it re-usable. It doesn't reduce the bloat of this section of code, but makes it easy when repeating the process for other entries.
Example:
function getQuestion(question, answer){
var arrayCon = data.reSEQ.map(function(e) {
return e[question].map(function(e) {
return e[answer];
});
});
arrayCon = arrayCon.map(function(subarray) {
return subarray.filter(function(val) {
return val !== undefined;
});
});
arrayCon = arrayCon.splice(0, arrayCon.length - 2); //removes current & lifetime entries
arrayCon = [].concat.apply([], arrayCon);
return arrayCon
}
And then I just create a var and set it to the function e.g. var q5Value = getQuestion('Question_5', 'Yes')
Given the context of the problem, you can ensure that the mapping you want is located at the 0th index of each array, thus;
var data = {
"reSEQ": [{
"Entry_1": "Nov-2015",
"Question_5": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
],
"Question_6": [{
"Yes": 30
},
{
"No": 5
},
{
"Not Sure": 13
},
{
"Total": 48
}
]
}]
};
var q5_yes = data.reSEQ[0].Question_5[0].Yes;
document.getElementById("foo").innerHTML = q5_yes;
<div id="foo">test</div>
function getQuestion(question, answer){
var arrayCon = data.reSEQ.map(function(e) {
return e[question].map(function(e) {
return e[answer];
});
});
arrayCon = arrayCon.map(function(subarray) {
return subarray.filter(function(val) {
return val !== undefined;
});
});
arrayCon = arrayCon.splice(0, arrayCon.length - 2); //removes current & lifetime entries
arrayCon = [].concat.apply([], arrayCon);
return arrayCon
}
var q5Value = getQuestion('Question_5', 'Yes') // to get the desired vals as an array
This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I have been working with complex,nested JSON file as given below:
Update:: Nested JSON file snippet (example)
{
"sample": {
"someitem": {
"thesearecool": [
{
"neat": "wow"
},
{
"neat": "tubular"
}
]
},
"coolcolors": [
{
"color":"red",
"hex": "ff0000"
},
{
"color":"blue",
"hex":"0000ff"
}
]
}
}
I want to traverse through each and every value in this JSON file.
I have tried many npm nodejs packages to make nested JSON into plain, readable JSON format.(NPM Packages-> flattenr, flat, etc.).
Kindly someone help me to resolve this issue. Please give some better solutions with examples.
Yeah, that's a nice problem of recursion.
So, the general idea is a function with a for-loop.
2 things can happen: either it's a value, then you print it. Or it's a object, then you put that object through the same function.
<div id="log"></div>
<script>
var data = {
"sample": {
"someitem": {
"thesearecool": [
{
"neat": "wow"
},
{
"neat": "tubular"
}
]
},
"coolcolors": [
{
"color":"red",
"hex": "ff0000"
},
{
"color":"blue",
"hex":"0000ff"
}
]
}
};
function readAllJson(data, level) {
var resultString = '';
for(var i in data) {
var type = typeof data[i];
switch(type) {
case 'object':
resultString += indent(level) + i +':<br/>'+ readAllJson(data[i], level + 1); // recursion
break;
default:
resultString += indent(level) + i +': '+ data[i] + '<br/>';
break;
}
}
return resultString;
}
function indent(level) {
var result = '';
for(var i=0; i<level; i++) {
result += ' '; // HTML space character
}
return result;
}
window.onload = function() {
var log = document.getElementById('log');
var result = readAllJson(data, 0);
log.innerHTML = result;
}
</script>
Got some JSON that I need to go through to fetch some IDs.
The JSON looks like this:
var carousel = [
{
"acf": {
"content": [
{
"acf_fc_layout": "custom",
"content": "Some text"
},
{
"acf_fc_layout": "exhibition",
"exhibition": 2594
},
{
"acf_fc_layout": "exhibition",
"exhibition": 1234
}
]
},
}
]
For every content where acf_fc_layout == exhibition I must fetch the value (ID) of exhibition so it can be used to fetch further data. As you can see there's multiple exhibition IDs aswell.
My confusion here is that there are both object and array, and that they're nested. I've done some similar stuff with jQuery, but that's out of the question this time. Don't think I need IE8 support, but still find this tricky..
If your JSON simply looks as you say, this is a simple solution:
var i;
for (i = 0; i < carousel[0].acf.content.length; i++) {
if (carousel[0].acf.content[i].acf_fc_layout === "exhibition") {
// do something with carousel[0].acf.content[i].exhibition
}
}
Alternatively if you have much more content in your JSON, this might be relevant:
var i, j;
for (i = 0; i < carousel.length; i++) {
if (typeof carousel[i].acf != 'undefined' && typeof carousel[i].acf.content != 'undefined') {
for (j = 0; j < carousel[i].acf.content.length; j++) {
if (carousel[i].acf.content[j].acf_fc_layout === "exhibition") {
// do something with carousel[i].acf.content[j].exhibition
}
}
}
}
carousel[0].acf.content.forEach(function (item) {
if (item["acf_fc_layout"] === "exhibition") {
// do some stuff
// id for exhibition placed in item["exhibition"]
}
});
With your current structure, you need to use a foreach and check the value.
var carousel = [
{
"acf": {
"content": [
{
"acf_fc_layout": "custom",
"content": "Some text"
},
{
"acf_fc_layout": "exhibition",
"exhibition": 2594
},
{
"acf_fc_layout": "exhibition",
"exhibition": 1234
}
]
},
}
];
$.each(carousel[0].acf.content,function (i,v){
if(v.acf_fc_layout == "exhibition")
$(".result").append(v.exhibition+"<br>");
});
JSFIddle
http://jsfiddle.net/oucp3v5x/
$(carousel).each(function(i, el){
$(el.acf.content).each(function(i, el){
if(el.acf_fc_layout === 'exhibition') {
$('<div>', {
text: el.exhibition
}).appendTo($('#results'));
}
});
});
If acf have many content, you need to run additional loop and acf have to be array of objects.
I have a JSON File with Tasks. They are structured as follows:
[
{
"id":"1",
"name":"task1",
"tags":["tag1","tag2","tag3"]
},
{
"id":"2",
"name":"task2",
"tags":["tag4","tag2","tag5"]
},
{
"id":"3",
"name":"task3",
"tags":["tag3"]
}
]
Here's a Plunkr for what I want
http://plnkr.co/edit/kMhiHDyybHYxGfV7W39z?p=preview
Basically, this is what I want : http://jsfiddle.net/TahmidTanzim/N9Vqk/
I've looked through various SO questions and they all suggest I am doing it right.
However I don't understand where I am going wrong. I want only those tasks that contain the selectedTag to be displayed in the red list.
Thanks!
Just change filters to compare inner tags using arrays.
myapp.filter('tagFilter',function()
{
return function(Data,selectedTags)
{
if(selectedTags.length===0) return Data;
var tempData=[];
for(var i in Data) {
for(var z in Data[i].tags) {
for(var k in selectedTags) {
var value = selectedTags[k];
if(value == Data[i].tags[z]) {
tempData.push(Data[i]);
break;
}
}
}
}
return tempData;
}
});
I would like to generate an HTML tree (preferably UL-LI) from the JSON example below. Does anyone have a simple, recursive JS function (not a framework) that can handle this specific structure? Thanks for your help!
{ "folder" : [ {
"title" : "1",
"folder" : [ {
"title" : "1.1",
"folder" : [ {
"title" : "1.1.1",
} , {
"title" : "1.1.2",
} ]
} ]
} , {
"title" : "2",
} ] }
function to_ul (obj) {
// --------v create an <ul> element
var f, li, ul = document.createElement ("ul");
// --v loop through its children
for (f = 0; f < obj.folder.length; f++) {
li = document.createElement ("li");
li.appendChild (document.createTextNode (obj.folder[f].title));
// if the child has a 'folder' prop on its own, call me again
if (obj.folder[f].folder) {
li.appendChild (to_ul (obj.folder[f].folder));
}
ul.appendChild (li);
}
return ul;
}
Caveat: No error checking! If a 'title' or 'folder' is missing, the whole thing could blow up.
I had a problem getting my browser to accept the data structure submitted by the OP, but here is a fully working example I've drawn up for my own, similar purposes. Beside the function I provide the data structure as well, with name/branches instead of title/folder.
function to_ul(branches) {
var ul = document.createElement("ul");
for (var i = 0, n = branches.length; i < n; i++) {
var branch = branches[i];
var li = document.createElement("li");
var text = document.createTextNode(branch.name);
li.appendChild(text);
if (branch.branches) {
li.appendChild(to_ul(branch.branches));
}
ul.appendChild(li);
}
return ul;
}
function renderTree() {
var treeEl = document.getElementById("tree");
var treeObj = {
"root": [{
"name": "George & Sarah Trede",
"branches": [{
"name": "George & Frances Trede",
"branches": [{
"name": "Mary (Trede) Jempty"
}, {
"name": "Carol (Trede) Moeller"
}]
}, {
"name": "Mary (Trede) Sheehan"
}, {
"name": "Ward Trede"
}]
}]
};
treeEl.appendChild(to_ul(treeObj.root));
}
renderTree()
<div id="tree"></div>
I've used PURE with some success in the past for this kind of thing.
function to_li(obj, name) {
var li = document.createElement("li");
if (typeof(name) != "undefined") {
var strong = document.createElement("strong");
strong.appendChild(document.createTextNode(name + ": "));
li.appendChild(strong);
}
if (typeof(obj) != "object"){
li.appendChild(document.createTextNode(obj));
} else {
var ul = document.createElement ("ul");
for (var prop in obj){
ul.appendChild(to_li(obj[prop],prop));
}
li.appendChild(ul);
}
return li;
}
Check out the jquery plugin JSON2HTML, it's a little simpler to use than PURE and I've used it on a couple of site's I've created.
http://json2html.com
#Boldewyn: I believe you can also use a For...In loop instead of a regular For loop to shorten the code a bit. Of course, I don't have much experience using this kind of loop, so please check my code snippet.
for (var i in obj.folder) {
li = document.createElement ("li");
li.appendChild (document.createTextNode (i.title));
// if the child has a 'folder' prop on its own, call me again
if (i.folder) {
li.appendChild (to_ul (i.folder));
}
}
I have made a pip package for the same do check it out JSON2tree. Install it using pip install json2tree then use cli tool to create HTML tree.
json2tree -j example.json -o output.html