This question already has answers here:
Use jQuery to convert JSON array to HTML bulleted list
(6 answers)
Closed 4 years ago.
I have a JSON like below
{
"gists": [
{
"name": "Get the title",
"id": "beaf8a106e76f4bb82a85ca3a7707a78",
"category": "Function"
},
{
"name": "Get the content",
"id": "c6ae7c55aa27f8b6dbeb15f5d72762ec",
"category": "Uncategorized"
}
]
}
I want to foreach & get as HTML via JavaScript. Like below:
<ul>
<li>Name: Get The title, ID: beaf8a106e76f4bb82a85ca3a7707a78, Function: Function</li>
<li>Name: Get The content, ID: c6ae7c55aa27f8b6dbeb15f5d72762ec, Function: Uncategorized</li>
</ul>
I have tried this way: http://jsfiddle.net/ehsansajjad465/SLHTA/10/
But, I am not sure how to get values in one line & I want to do it using plain JS. Also my JSON will be form external link. http://rasel.tech/gist.json
This might be a very dumb question. I am sorry :(
With vanilla JS, you can loop through the array with the forEach method and construct the li elements accordingly.
var data = {
"gists": [
{
"name": "Get the title",
"id": "beaf8a106e76f4bb82a85ca3a7707a78",
"category": "Function"
},
{
"name": "Get the content",
"id": "c6ae7c55aa27f8b6dbeb15f5d72762ec",
"category": "Uncategorized"
}
]
};
var container = document.querySelector('#container');
var ul = document.createElement('ul');
data.gists.forEach(function (item) {
var li = document.createElement('li');
li.textContent = 'Name: ' + item.name + ', ID: ' + item.id + ', Function: ' + item.category;
ul.appendChild(li);
});
container.appendChild(ul);
<div id="container"></div>
You can use JSON.stringify to stringify object and i used regex to remove {} from string.
let obj = {"gists": [{"name": "Get the title","id": "beaf8a106e76f4bb82a85ca3a7707a78","category": "Function"},{ "name": "Get the content","id": "c6ae7c55aa27f8b6dbeb15f5d72762ec","category": "Uncategorized"}]}
let li = document.getElementById('list');
obj.gists.forEach( e => {
let ele = document.createElement('li')
ele.innerHTML = `${JSON.stringify(e).replace(/[{}]/g,'')}`
li.appendChild(ele);
})
<ul id='list'>
</ul>
If you want to get the items in one line you can do it with css.
You can add white-space:nowrap; in your ul and display: inline in li. I am just editing your added fiddle.
var data = {
"qA": [{
"question": "How deep is the ocean",
"answer": [
"quite deep",
"very deep",
"no deep at all"]
}, {
"question": "How high is the sky",
"answer": [
"real high",
"high enough",
"not that high"]
}]
};
var html = "";
$.each(data.qA, function (index, item) {
//console.log(item);
html += "<ul>" + item.question;
$.each(item.answer, function (index1, item1) {
html += " <li> ("+index1+ ") " + item1 + "</li>";
});
html += "</ul>";
});
$("#container").append(html);
ul{
white-space:nowrap;
}
ul li{
display: inline
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="container"></div>
Related
So I'm trying to create an online shop using HTML and Javascript as an exercise. I'm currently working on a dropdown menu which allows me to select the category of the item I wish to shop for (etc. electronics, clothes) but I'm having trouble getting all these values related to the category to show up.
So for example, I have a part of a javascript file below. The line div.innerHTML = (electronics.store) lets me print out the electronics store name "Mike's Computers" to the HTML file on my browser but I'm not quite sure how to access all the objects under its inventory. Is there a way to possibly iterate through the whole electronics inventory and print out each of the items and its cost/information below it and such?
If not, how would I go about printing things like the laptop brand name? Would it just be div.innerHTML = (electronics.inventory[0].brand) to print out the word "iMac"? I'm very confused and would appreciate any help possible.
Ultimately, I'd want my information to show up on the HTML page like:
Mike's Computers
Laptops
iMac $2000
Dell $600
Computers
Windows PC $1300
and so on.
function showOptions(){
let userPicked = document.getElementById("list").value;
var div = document.getElementById("div");
if(userPicked == 'one'){
div.innerHTML = (electronics.store);
}else{
alert("You must select a store.");
}
}
let electronics = {
store: "Mike's Computers",
inventory: {
"Laptops": {
0: {
brand: "iMac",
cost: 2000
},
1: {
brand: "Dell",
cost: 600
}
},
"Computers": {
2: {
brand: "Windows PC",
cost: 1300
}
}
}
};
Step one, take as much presentation out of your JavaScript as possible. Create the structure using HTML. Then populate that structure using JavaScript. That way if you want to change the layout, you're changing HTML and CSS and NOT Javascript. Use the <template> tag to create the structure of the repeating items.
Step Two, iterate the properties, cloning our template, then add to the DOM.
//Get the template
var template = document.getElementById("inventoryItem");
function showOptions() {
/*let userPicked = document.getElementById("list").value;
var div = document.getElementById("div");
if(userPicked == 'one'){
div.innerHTML = (electronics.store);
}else{
alert("You must select a store.");
}*/
document.querySelector("#store .storeName").innerHTML = electronics.store;
generateInventory(document.querySelector("#store .laptops > ul"), electronics.inventory.Laptops);
generateInventory(document.querySelector("#store .computers >ul"), electronics.inventory.Computers);
}
function generateInventory(node, object) {
//Iterate the properties
for (var itemName in object) {
if (Object.prototype.hasOwnProperty.call(object, itemName)) {
let item = object[itemName];
//Clone the template
let clone = template.content.cloneNode(true);
//Populate the content
clone.querySelector(".brand").textContent = item.brand;
clone.querySelector(".cost").textContent = clone.querySelector(".cost").textContent + item.cost;
//Append to the DOM
node.appendChild(clone);
}
}
}
let electronics = {
store: "Mike's Computers",
inventory: {
"Laptops": {
0: {
brand: "iMac",
cost: 2000
},
1: {
brand: "Dell",
cost: 600
}
},
"Computers": {
2: {
brand: "Windows PC",
cost: 1300
}
}
}
};
showOptions();
#store ul {
list-style: none;
padding-left: 0;
}
#store ul ul {
padding-left: 1em;
}
<div id="store">
<h1 class="storeName"></h1>
<ul class="inventory">
<li class="laptops">
<h2>Laptops</h2>
<ul></ul>
</li>
<li class="computers">
<h2>Computers</h2>
<ul></ul>
</li>
</ul>
</div>
<template id="inventoryItem">
<li>
<div class="brand"></div>
<div class="cost">$</div>
</li>
</template>
The code for duplicating the template is modified from: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template
Here is sample code to add the data.
let electronics = {
store: "Mike's Computers",
inventory: {
"Laptops": {
0: {
brand: "iMac",
cost: 2000
},
1: {
brand: "Dell",
cost: 600
}
},
"Computers": {
2: {
brand: "Windows PC",
cost: 1300
}
}
}
};
function showOptions(){
let userPicked = document.getElementById("list").value;
var div = document.getElementById("div");
if(userPicked == 'one'){
var newContent = (electronics.store);
newContent += '<br>';
Object.keys(electronics.inventory).forEach(key => {
newContent += '<br>';
newContent += key;
newContent += '<br>';
var items = Object.values(electronics.inventory[key]);
items.forEach(item => {
newContent += ` ${item.brand} $${item.cost}`;
newContent += '<br>';
});
});
div.innerHTML = newContent;
}else{
alert("You must select a store.");
}
}
showOptions();
<input type="text" id="list" value="one">
<div id="div"> </div>
You can iterate through the electronics store inventory with a for loop like so
for (let [key, value] of Object.entries(electronics))
Then in the body of the for loop, you can call the key and value and append it to the innerHTML like you are already doing above.
I want to display only parts of a .json that I scraped with scrapy.
the scrapy output looks something like this and has about 500 entries:
data.json
[
{
"Content":["<h2>Heading of Paragraph1</h2><p>the actual pargraph1</p>"],
"Titel": ["Heading of Paragraph1"]
}
,
{
"Content": ["<h2>Heading of Paragraph2</h2><p>the actual pargraph2</p>"],
"Titel": ["Heading of Paragraph2"]
}
,
{
"Content": ["<h2>Heading of Paragraph3</h2><p>the actual pargraph3</p>"],
"Titel": ["Heading of Paragraph3"]
}
]
What I want to do is to generate a list of All the "Titel" elements for the user to choose from. Then the website should display the chosen paragraphs.
I figured out that some javascript are probably the way to go. I plan to use chosen later to make the UI usable.
So far I came up with this html
index.html
<body>
<form action="/returnselected_paragraphs.js">
<select name="pargraphs" multiple>
<option value="Heading of Pargraph1">Heading of Paragraph1</option>
<option value="Heading of Pargraph2">Heading of Paragraph2</option>
<option value="Heading of Pargraph3">Heading of Paragraph3</option>
<!-- this should be genereated by javascript with data from the json --!>
<input type="submit">
</form>
<h1>output</h1>
<h2>Heading of Paragraph1</h2><p>the actual pargraph1</p>
<h2>Heading of Paragraph2</h2><p>the actual pargraph2</p>
<!-- this should be genereated by javascript with data from json--!>
My problem is the javascript.
I found this code on jsfiddle which seems similar to what I want, but the data is formated differently. I don't know how to adapt it to my data.
I put my idea here: https://jsfiddle.net/jtxzerpu/
Thank you all for your time, I hope I did stick to all the rules.
Try this
Iterate the array and create select
Bind change event on select on which content should be rendered.
Demo
var arr = [{
"Content": ["<h2>Heading of Paragraph1</h2><p>the actual pargraph1</p>"],
"Titel": ["Heading of Paragraph1"]
},
{
"Content": ["<h2>Heading of Paragraph2</h2><p>the actual pargraph2</p>"],
"Titel": ["Heading of Paragraph2"]
}, {
"Content": ["<h2>Heading of Paragraph3</h2><p>the actual pargraph3</p>"],
"Titel": ["Heading of Paragraph3"]
}
];
//prepare the options first
var options = arr.map( function( item ){
return "<option value='" + item.Titel[0] + "'>"+ item.Titel[0] + "</option>"
} ).join( "" );
//set all the options to select and then bind change event
$( "select" ).html( options ).change( function(){
$( "#paraContent" ).html( "" );
var val = $(this).val();
$( "#paraContent" ).html( val.map( function( title ){
return arr.find( (s) => s.Titel[0] == title ).Content[0];
}).join( "</br>" ) )
//console.log(val);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="/returnselected_paragraphs.js">
<select name="pargraphs" multiple>
</select>
<p id="paraContent">
</p>
<input type="submit">
</form>
You can build the options list easily:
const options = json_data.reduce(
function (fragment, item)
{
const option = document.createElement("option");
option.value = item.Titel[0];
option.textContent = option.value;
fragment.appendChild(option);
return fragment;
},
document.createDocumentFragment()
);
Then append the options to your select (the document fragment will "merge" with the select and disappear, don't worry).
From your reference on jsfiddle, you can modify that to the code below:
var data = [
{
"Content":["<h2>Heading of Paragraph1</h2><p>the actual pargraph1</p>"],
"Titel": ["Heading of Paragraph1"]
}
,
{
"Content": ["<h2>Heading of Paragraph2</h2><p>the actual pargraph2</p>"],
"Titel": ["Heading of Paragraph2"]
}
,
{
"Content": ["<h2>Heading of Paragraph3</h2><p>the actual
pargraph3</p>"],
"Titel": ["Heading of Paragraph3"]
}
]
$.each(data, function () {
var $option = $('<option/>').text(this.Titel[0]).val(this.Titel[0]);
$option.data("content",this.Content[0])
$('#selectCompany').append($option);
});
Here is the link to your modified code in action:
https://jsfiddle.net/azqxhjgx/
You can use click event on option to display the content of the object where you want, something like this:
$("#selected > option").click(function(){
// do whatever with $this.data("content")
})
I am attempting to append some li elements inside a ul. In this scenario, I am looping through the array called blogData and accessing each tags method. The issue I am having- I can't seem to loop through each array inside tags and appending data to the ul inside each article appends all tags data from each object to each ul.
const blogData = [
{
title : "blog first",
date : "01",
tags : ["first", "second"],
body : "Some text",
id : 1
},
{
title : "blog second",
date : "02",
tags : ["third", "fourth"],
body : "Some more text",
id : 2
}
];
function tagUl (object) {
setTimeout(() => {
const ul = $('.tags-ul');
for (let i = 0; i < ul.length; i++) {
const $li = $('<li>');
$li.text(object[i].tags);
ul.append($li); }
}, 10);
}
tagUl(blogData);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<article>
<ul class="tags-ul">
</ul>
</article>
<article>
<ul class="tags-ul">
</ul>
</article>
As you can see here by running the code all ul tags get the same li's appended to them. As the title says it returns [object Object]. This was the case a few minutes ago when I was first writing this. The case now is that it simply returns the wrong data
Your problem is that your ul variables represents all the <ul class="tags-ul"> elements, and so doing an "append" on that variable appends the same content to all the elements it represents.
You can access each element separately, either by looping, or more crudely (since you already have a for loop to go through your blogData object), by getting the raw element from the jQuery object by its index, and then appending specifically to that. It also creates a separate <li> for each tag by looping through the tags array itself.
const blogData = [{
title: "blog first",
date: "01",
tags: ["first", "second"],
body: "Some text",
id: 1
},
{
title: "blog second",
date: "02",
tags: ["third", "fourth"],
body: "Some more text",
id: 2
}
];
function tagUl(object) {
const ul = $('.tags-ul');
for (let i = 0; i < ul.length; i++) {
const $li = $('<li>');
for (var j = 0; j < object[i].tags.length; j++) {
$(ul[i]).append($("<li/>", { text: object[i].tags[j] }));
}
}
}
$(function() {
tagUl(blogData);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<article>
<ul class="tags-ul">
</ul>
</article>
<article>
<ul class="tags-ul">
</ul>
</article>
P.S. I assumed your setTimeout was a kludge to allow the HTML content to load before you run the code, so I replaced it with a more reliable jQuery wrapper which waits for the document to be ready before executing any code within it ($(function() { ... }); is a shorthand for the slightly more comprehensible statement $(document).ready(function() ... });)
you need to iterate tags array inside each object in blogData and then add li for each value inside the array. something like this will work:
const blogData = [
{
title : "blog first",
date : "01",
tags : ["first", "second"],
body : "Some text",
id : 1
},
{
title : "blog second",
date : "02",
tags : ["third", "fourth"],
body : "Some more text",
id : 2
}
];
function tagUl (object) {
setTimeout(() => {
const ul = $('.tags-ul');
for (let i = 0; i < ul.length; i++) {
var tags = object[i].tags;
for (var j=0; j<tags.length; j++){
$(ul[i]).append("<li>" + tags[j] + "</li>");
}
}
}, 10);
}
tagUl(blogData);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<article>
<ul class="tags-ul">
</ul>
</article>
<article>
<ul class="tags-ul">
</ul>
</article>
I have a javascript object that I would like to traverse and print data based off 1 common category.
Javascript object:
var $states = {
"AL" : {
"longname": "Alabama",
"lawOne": "Alabama Law 1",
"lawTwo": "Alabama Law 2",
"lawThree": "Alabama Law 3",
"region" : "Southeast"
},
"AK" : {
"longname": "Alaska",
"lawOne": "Alaska Law 1",
"lawTwo": "Alaska Law 2",
"lawThree": "Alaska Law 3",
"region" : "Northwest"
},
"AZ" : {
"longname": "Arizona",
"lawOne": "Arizona Law 1",
"lawTwo": "Arizona Law 2",
"lawThree": "Arizona Law 3",
"region" : "Southwest"
},
etc...
}
I am able too loop the array and get as granular as getting the console to log all of the states that are in the same region:
for (var key in $states) {
if ($states.hasOwnProperty(key)) {
var $getStateRegion = $states[key].region
if ($getStateRegion === "Northeast") {
console.log ($states[key].longname);
}
}
}
Once I try to loop through those and print a table with that data is where I am running into an issue. I want to be able to have a withthe 's longname, lawOne, lawTwo, and lawThree values input in there. What gives? Once I try running a for loops through this is where I'm hitting a roadblock. Thanks in advance!
Try the working code below.
var $states = {
"AL" : {
"longname": "Alabama",
"lawOne": "Alabama Law 1",
"lawTwo": "Alabama Law 2",
"lawThree": "Alabama Law 3",
"region" : "Southeast"
},
"AK" : {
"longname": "Alaska",
"lawOne": "Alaska Law 1",
"lawTwo": "Alaska Law 2",
"lawThree": "Alaska Law 3",
"region" : "Northwest"
},
"AZ" : {
"longname": "Arizona",
"lawOne": "Arizona Law 1",
"lawTwo": "Arizona Law 2",
"lawThree": "Arizona Law 3",
"region" : "Southwest"
}
};
var result = {};
Object.keys($states).forEach(function(key) {
if ($states[key]["region"] === "Southwest") {
result[key] = $states[key];
}
});
console.log(result);
You are on the right track. Before I continue, I would like to point out that you are using a for..in loop, but newer versions of Javascript support the for..of loop also, so this is something you may want to consider. The difference is that the for..in loop gives you the keys of the object, and the for..of loop gives you the values, so it shortens the code by skipping the step where you write something to the effect of:
for( var index in array ){
var currentObject = array[ index ];
}
The secret to your solution is in how you handle the DOM, and there are many ways to do this. I will show you one, but it is not necessarily the fastest or the best. I recommend playing around with different DOM manipulations to find the one that works best for you.
First, we know how to get a record, so the javascript aspect of looping, you have that handled...
Next, we need to create the table.... I will assume that you want four columns based on your description, but you could easily adjust this to put the state name and one law on each line, which would probably be a better design allowing a variable number of laws.
The html would look something like this:
<table>
<tr><th>State</th><th>Law 1</th><th>Law 2</th><th>Law 3</th></tr>
<!-- Here is where we would create new html for each state -->
</table>
Your loop then would need to add to this html by creating several lines that appear as:
<tr><td>[State]</td><td>[Law1]</td><td>[Law2]</td><td>[Law3]</td><tr>
We will use string manipulation of the DOM, because it is a good place to start, because it is most similar to what you would write by hand.
We will break the table into three parts: the header, the body and the footer.
var header = "<table><tr><th>State</th><th>Law 1</th><th>Law 2</th><th>Law 3</th></tr>";
var body = ""; //this is where we add the data
var footer = "</table>";
Now, on the loop, we will create each line as needed and add it to the body:
for( var index in stateObj ){
...error checking occurs here...
var state = stateObj[ index ];
var stateColumn = "<td>" + state.longname + "</td>";
var law1Col = "<td>" + state.lawOne + "</td>";
var law2Col = "<td>" + state.lawTwo + "</td>";
var law3Col = "<td>" + state.lawThree + "</td>";
var row = "<tr>" + stateColumn + law1Col + law2Col + law3Col + "</tr>";
//now that we have a row, we add it to the body
body += row; //same as body = body + row;
}
After we have the body, we can make our table by combining the header, body and footer:
var tableHTML = header + body + footer;
And then we find a place to inject it into our document:
var outputDiv = document.getElementById( "stateTableData" );
outputDiv.innerHTML = tableHTML;
Here is a live example:
var states = {
PA: {
longname:"Pennsylvania",
lawOne:"It is illegal to sing in the shower in apartment buildings within the city limits of Philadelphia",
lawTwo:"All motorists are required to stop the vehicle for passing horsemen. The vehicle shall be covered with camoflage so as not to scare the horses.",
lawThree:"Any house having more than four women occupants shall be considered a brothel and shall be in violation of the law."
},
NJ: {
longname:"New Jersey",
lawOne:"There is no such thing as the Mafia",
lawTwo:"Any reference to the denizens of New Jersey shall be derogatory and degrading, think Jersey Shore",
lawThree:"There is no escape from New Jersey and we are not a suburb of NYC"
},
VA: {
longname:"Virginia",
lawOne: "Civil War re-enactments must have the North as the victor.",
lawTwo: "All roads shall end in Richmond, VA",
lawThree: "I have run out of silly ideas for this example."
}
};
function buildTableForState( stateNames ){
var stateList = stateNames.split(",");
//remove spaces
for( var i in stateList ){ stateList[i] = stateList[i].trim(); }
//initialize table parts
var header = "<table><tr><th>State</th><th>Law 1</th><th>Law 2</th><th>Law 3</th></tr>";
var footer = "</table>";
var body = "";
//build body
for( var index in states ){
if( stateList.indexOf( index ) !== -1 ){
var currentState = states[index];
body += buildRowForState( currentState );
}
}
//compose and inject table
var tableHTML = header + body + footer;
var documentOut = document.getElementById( "outputDiv" );
documentOut.innerHTML = tableHTML;
}
function submitTable(value){
buildTableForState( value );
}
function buildRowForState( currentState ){
var state = makeTableCol( currentState.longname );
var law1 = makeTableCol( currentState.lawOne );
var law2 = makeTableCol( currentState.lawTwo );
var law3 = makeTableCol( currentState.lawThree );
var row = makeTableRow( [state, law1, law2, law3] );
return row;
}
function makeTableCol( stringText ){
return "<td>" + stringText + "</td>";
}
function makeTableRow( arrayColumns ){
return "<tr>" + arrayColumns.join("") + "</tr>";
}
<h1>Table Loader</h1>
<form>
<p>Use the values "PA", "NJ", and "VA" to generate a table. You can use more than one value by separating them with a comma.</p>
<input type="text" id="stateNames" name="stateNames" /><br/>
<button onclick="submitTable(stateNames.value);">Build Table</button>
<p>Try:
</p>
<ul>
<li>PA</li>
<li>NJ,VA</li>
<li>VA,PA,NJ</li>
</ul>
</form>
<h1>Table Output appears here</h1>
<div id="outputDiv"></div>
NOTE: Regarding the live code, the HTML is bigger than the display box. In my browser I have to scroll down on the snippit HTML to view the generated table. Either that or expand the snippit window to a full tab to view it in a larger screen.
The above code is simplified, and most coders would tell you not to use HTMLElement.innerHTML, because it is slow, but it is a good place to start. Once you have this down, start practicing with document.create( tagName ), and then use more direct DOM manipulations.
I have the following JSON:
var questions = {
section: {
"1": question: {
"1": {
"id" : "1a",
"title": "This is question1a"
},
"2": {
"id" : "1b",
"title": "This is question2a"
}
},
"2": question: {
"1": {
"id" : "2a",
"title": "This is question1a"
},
"2": {
"id" : "2b",
"title": "This is question2a"
}
}
}
};
NOTE: JSON changed based on the answers below to support the question better as the original JSON was badly formatted and how it works with the for loop below.
The full JSON will have 8 sections and each section will contain 15 questions.
The idea is that the JS code will read what section to pull out and then one by one pull out the questions from the list. On first load it will pull out the first question and then when the user clicks on of the buttons either option A or B it will then load in the next question until all questions have been pulled and then do a callback.
When the button in the appended list item is clicked it will then add it to the list below called responses with the answer the user gave as a span tag.
This is what I have so far:
function loadQuestion( $section ) {
$.getJSON('questions.json', function (data) {
for (var i = 0; i < data.length; i++) {
var item = data[i];
if (item === $section) {
$('#questions').append('<li id="' + item.section.questions.question.id + '">' + item.section.questions.question.title + ' <button class="btn" data-response="a">A</button><button class="btn" data-response="b">B</button></li>');
}
}
});
}
function addResponse( $id, $title, $response ) {
$('#responses').append('<li id="'+$id+'">'+$title+' <span>'+$response+'</span></li>');
}
$(document).ready(function() {
// should load the first question from the passed section
loadQuestion( $('.section').data('section') );
// add the response to the list and then load in the next question
$('button.btn').live('click', function() {
$id = $(this).parents('li').attr('id');
$title = $(this).parents('li').html();
$response = $(this).data('response');
addResponse( $id, $title, $response );
loadQuestion ( $('.section').data('section') );
});
});
and the HTML for the page (each page is separate HTML page):
<div class="section" data-section="1">
<ul id="questions"></ul>
<ul id="responses"></ul>
</div>
I've become stuck and confused by how to get only the first question from a section and then load in each question consecutively for that section until all have been called and then do a callback to show the section has been completed.
Thanks
Do not have multiple id's in html called "section."
Do not have multiple keys in your JSON on the same level called "section". Keys in JSON on the same level should be unique just as if you are thinking about a key-value hash system. Then you'll actually be able to find the keys. Duplicate JSON keys on the same level is not valid.
One solution can be section1, section2, etc. instead of just section. Don't rely on data-section attribute in your HTML - it's still not good if you have "section" as the duplicate html id's and as duplicate JSON keys.
If you have only one section id in HTML DOM, then in your JSON you must also have just one thing called "section" e.g.:
var whatever = {
"section" : {
"1": {
"question" : {
"1" : {
"id" : "1a",
"title" : "question1a"
},
"2" : {
"id" : "2a",
"title" : "question2a"
}
}
},
"2": {
"question" : {
"1" : {
"id" : "1a",
"title" : "aquestion1a"
},
"2" : {
"id" : "2a",
"title" : "aquestion2a"
}
}
}
}
}
console.log(whatever.section[1].question[1].title); //"question1a"
To get question, do something like this:
function loadQuestions(mySectionNum) {
$.getJSON('whatever.json', function(data){
var layeriwant = data.section[mySectionNum].question;
$.each(layeriwant, function(question, qMeta) {
var desired = '<div id="question-' +
qMeta.id +
'"' +
'>' +
'</div>';
$("#section").append(desired);
var quest = $("#question-" + qMeta.id);
quest.append('<div class="title">' + qMeta.title + '</div>');
//and so on for question content, answer choices, etc.
});
});
}
then something like this to actually get the questions:
function newQuestion(){
var myHTMLSecNum = $("#section").attr('data-section');
loadQuestions(myHTMLSecNum);
}
newQuestion();
//below is an example, to remove and then append new question:
$('#whatevernextbutton').on('click',function(){
var tmp = parseInt($("#section").attr('data-section'));
tmp++;
$("#section").attr('data-section', tmp);
$("#section").find('*').remove();
newQuestion();
});
Technically your getJSON function always retrieves the same data. Your code never compares the id given to the id you're extracting.
Your getJSON should look something like:
function loadQuestion( $section ) {
for (var i = 0; i < questions.section.length; i++) {
var item = questions.section[i];
if (item.id === $section) {
for (var j = 0; j < item.questions.length; j++) {
$('#questions').append('<li id="' +
item.questions[i].id + '">' +
item.questions[i].title +
' <button class="btn" data-response="a">A</button><button class="btn" data-response="b">B</button></li>'
);
}
}
}
}
Modify your JSON to:
var questions = {
section: [{
id: 1,
questions: [{
id: "1a",
title: "This is question1a"
},{
id: "2a",
title: "This is question2a"
}]},{
id: 2,
questions: [{
id: "1a",
title: "This is question1a"
},{
id: "2a"
title: "This is question2a"
}]
}]
};
Edit: your first parameter of getJSON is the URL of the JSON returning service.
You don't need getJSON at all if your JSON is already defined on the client. I have modified the code above.