How to parse json into nested html list strucuture - javascript

I tried this with xml, but the behavior was odd from firefox to IE.
I haven't worked with json before, so any help would be appreciated.
here's my json:
{
"storeList":{
"state":[
{
"stateName":"Maine",
"store":[
{
"storeName":"Store 1",
"storeID":"store1",
"storeURL":"http:\/\/www.sitename.com"
},
{
"storeName":"Store 2",
"storeID":"store2",
"storeURL":"http:\/\/www.sitename.com"
},
{
"storeName":"Store 3",
"storeID":"store3",
"storeURL":"http:\/\/www.sitename.com"
}
]
},
{
"stateName":"Connecticut",
"store":[
{
"storeName":"Store 1",
"storeID":"store1",
"storeURL":"http:\/\/www.sitename.com"
}
]
}
]
}
}
and the structure I'm going for -
<div id="storeList">
<ul>
<li>
<h3>State Name 1</h3>
storename
storename
</li>
<li>
<h3>State Name 2</h3>
storename
</li>
</ul>
</div>
update
tried a solution below, loading the json from an external file, but I get an error that object is not defined:
$(document).ready(function() {
var object;
$.getJSON('xml/storeList.json', function(json) {
object = json;
});
$('#storeList').append('<ul/>')
$.each(object.storeList.state, function() {
var list = $('#storeList ul'),
listItem = $('<li/>'),
html = listItem.append($('<h3/>').text(this.stateName));
$.each(this.store, function() {
listItem.append($('<a />').attr('href', this.storeURL).text(this.storeName));
});
list.append(html)
});
});

I would use a template engine. With a template engine you can define your template (which is easy to read and maintain) like that:
<script id="template" type="text/x-jquery-tmpl">
<ul>
{{#each state}}
<li>
<h3>{{=stateName}}</h3>
{{#each store}}
{{=storeName}}
{{/each}}
</li>
{{/each}}
</ul>
</script>
and then simply call
$("#storeList").html(
$("#template").render(json.storeList)
);
to fill your div
<div id="storeList"></div>
I have a demo ready. The template engine I use here is JsRender.

Here's a simple example:
$('#storeList').append('<ul/>')
$.each(object.storeList.state, function() {
var list = $('#storeList ul'),
listItem = $('<li/>'),
html = listItem.append($('<h3/>').text(this.stateName));
$.each(this.store, function() {
listItem.append($('<a />').attr('href', this.storeURL).text(this.storeName));
});
list.append(html)
});
Example
EDIT
var object;
$.getJSON('xml/storeList.json', function(json) {
object = json;
$('#storeList').append('<ul/>')
$.each(object.storeList.state, function() {
var list = $('#storeList ul'),
listItem = $('<li/>'),
html = listItem.append($('<h3/>').text(this.stateName));
$.each(this.store, function() {
listItem.append($('<a />').attr('href', this.storeURL).text(this.storeName));
});
list.append(html)
});
});

JSON is nothing but a subset of Javascript object literal notation that allows nested objects and/or arrays, so you will want to study up on the Javascript object and array data structures.
That being said, once your "bare" json is assigned to a variable, let's assume "json" (test by prepending with "json=") you can probably begin to work with your JSON in the following manner, just as you would with an array:
for (var i=0, n=json.storeList.state.length; i<n; i++) {
var state = json.storeList.state[i];
console.log(state.stateName); //Maine, then Connecticut
for (var j=0, k=state.store.length; j<k; j++) {
var store = state.store[j]; //the object containing store name, id & URL
console.log(store.storeID);
}
}
PS....my answer is "pure" Javascript as opposed to using jQuery, so if you're committed to doing things the jQuery way, definitely consider the other answers. But it's good to get familiar with the Javascript foundation behind the various frameworks such as jQuery, ExtJS, etcetera, in case you ever have to switch.

Use jQuery's $.each() function to iterate over object properties, and just a standard for loop for iterating over the arrays.
Here's a working example: http://jsfiddle.net/qZ6U4/
And the code:
var htmlStr = '';
$.each(myObj, function(i,v){
htmlStr += '<div id="' + i + '">';
$.each(v, function(i, v){
htmlStr += '<ul>';
for(var i = 0; i < v.length; i++){
htmlStr += '<li><h3>' + v[i].stateName + '</h3>';
for(var n = 0; n < v[i].store.length; n++){
var store = v[i].store[n];
htmlStr += '' + store.storeName + '';
}
htmlStr += '</li>';
}
htmlStr += '</ul>';
});
htmlStr += '</div>';
});

Related

How to parse XML in JavaScript

https://jsfiddle.net/recklesswish/6yw1tdwh/5/ The following link has the JSON and i have converted this particular JSON in XML. Now the issue is I am not getting that how to parse it using javascript.
Here is the code of xml, JSON resp.
XML
var carsData = "<cars>
"<Honda>"
"<model>Figo</model>"
"</Honda>"
"<Honda>"
"<model>City</model>"
"</Honda>"
"<Audi>"
"<model>A6</model>"
"</Audi>"
"<Audi>"
"<model>A8</model>"
"</Audi>"
"</cars>"
JSON
var carsData = '{"cars":{"Honda":[{"model":"Figo"},{"model":"City"}],"Audi":[{"model":"A6"},{"model":"A8"}]}}';
$('#newCollection').on('click', function() {
$(this).empty();
var data = JSON.parse(carsData);
$(this).append('New Collection<ul></ul>');
for (var make in data.cars) {
for (var i = 0; i < data.cars[make].length; i++) {
var model = data.cars[make][i].model;
$(this).find('ul').append('<li>' + make + ' - ' + model + '</li>')
}
}
});
With HTML
<ul>
<li id="newCollection">New Collection</li>
</ul>
First of all make your xml look like this in javascript -
var carsData = "<cars><Honda><model>Figo</model></Honda><Honda><model>City</model>
</Honda><Audi><model>A6</model></Audi><Audi><model>A8</model></Audi></cars>"
And your JS code would look like this -
$('#newCollection').on('click', function() {
$(carsData).find("Honda").each(function() {
var model = $(this).find("model").text();
console.log("model: " + model );
});
});
newCollection is the id of your button. This will print model as below-
model: Figo
model: City
I would suggest you to go through basics first rather than trying to jump into coding directly. Clear basics will make you a good coder in long run :)
I see. Use below code to achieve what you want -
<body>
<h1>Hello</h1>
<button type="button" id="newCollection">Click Me!</button>
<ul id="myul"></ul>
</body>
And your JS code should be -
$('#newCollection').on('click', function() {
var data = $($.parseXML(carsData));
data.find('cars').children().each(function() {
var make = $(this).find("model").text();
$('#myul').append('<li>'+make+'</li>');
});
});

Access Dynamically Created Data Tag in Single Page Application

I have a single page application that is dynamically populating a div with list items that will call a function on click. I am trying to populate the data-tag dynamically and then access that within the appended list item.
The backslash in the $(\#documents) is there because this is a kendoUI-template that is being called by my route function.
The build tree function is being called within an Ajax success function once the data has been retrieved from the server. Any insight or help is appreciated!!!
function buildTreeView(tree, jobCode){
var treeHtml = "<div class='row'><div class='col-xs-12 col-sm-8 col-sm-offset-2'><div class='panel-group'><div class='panel panel-default'><div class='panel-heading'><h3 class='text-center'>View or Download Documents</h3></div><div class='panel-body'><ul class='list-group'>";
for(var i =0;i < tree.length;i++){
if(typeof tree[i] === 'object'){
for(var ind = 0;ind < tree[i].length; ind++){
//another element will be populated here
}
}else{
treeHtml += "<li class='list-group-item viewDoc' data-docName='"+tree[i]+"' data-jobCode='"+jobCode+"'>"+tree[i]+"</li>";
}
}
treeHtml += "</ul></div></div></div></div></div>";
$('\#documents').append(treeHtml);
}
$(document).on("click", ".viewDoc", function(){
var docName = $(this).data('docName');
var jobCode = $(this).data('jobCode');
console.log(docName);
console.log(jobCode);
});
You are not able to access these data because the data attribute "docName" and "jobName" was normalized to lowercase.
eg the html then looks like this:
<li class="list-group-item viewDoc" data-docname="something" data-jobcode="something">something</li>
Look here for better answer:
In any case this will work:
$(document).on("click", ".viewDoc", function(){
var docName = $(this).data('docname');
var jobCode = $(this).data('jobcode');
console.log(docName);
console.log(jobCode);
});
UPDATE: added jsfiddle
Change your function so it sets data using .data(key,value). See https://api.jquery.com/data/
function buildTreeView(tree, jobCode){
$('\#documents').append("<div class='row'><div class='col-xs-12 col-sm-8 col-sm-offset-2'><div class='panel-group'><div class='panel panel-default'><div class='panel-heading'><h3 class='text-center'>View or Download Documents</h3></div><div class='panel-body'><ul class='list-group'></ul></div></div></div></div></div>");
for(var i =0;i < tree.length;i++){
if(typeof tree[i] === 'object'){
for(var ind = 0;ind < tree[i].length; ind++){
//another element will be populated here
}
}else{
var li = $('\#documents').find('ul:last()').append("<li class='list-group-item viewDoc'>"+tree[i]+"</li>");
$(li).data("docName",tree[i]);
$(li).data("jobCode",jobCode);
}
}
// ---- EDITED ----//
var li = $('\#documents').find('ul:last()').append("<li class='list-group-item viewDoc' id='docIndex"+i+"'>"+tree[i]+"</li>");
$('\#docIndex'+i).data({"docName":tree[i], "jobCode":jobCode});

Local JSON file Update

Hi trying to update the local JSON file with new input values.
Creating a posts app which is now working on local Json file.
I have a button and a text area, and a dynamic list.
once I add some input values in textarea and submit it should get appends to li and if I add another value then it should get append to another li.
What ever new values had added it should get append to the local json file.
Here is the code what I have tried.
HTML:
<ul class='Jsonlist'></ul>
<a id='postData' href='#'>Post</a>
<textarea id="tArea"></textarea>
JS:
var Json = {"three":["red","yellow","orange"]}
var items = [];
$.each( Json, function( key, val ) {
debugger;
items.push( "<li id='" + key + "'>" + Json.three + "</li>" );
});
$('.Jsonlist').append(items);
$('#postData').click(function(){
a=$('#tArea').val();
$(".Jsonlist li").append(a);
});
Working Demo
JS fiddle:
http://jsfiddle.net/JwCm9/
What's inside?
variable to hold the items
var items;
creates <ul> for items and for each item a <li>
function make_list() {
var list = $(".Jsonlist");
list.empty();
for (var i in items) {
var value = items[i];
var li = $('<li>');
li.html(value);
list.append(li);
}
};
saving and reading from local json from/into items
function save_to_local_json() {
var items_json = JSON.stringify(items);
localStorage.setItem('items', items_json);
};
function read_from_local_json() {
var items_json = localStorage.getItem('items');
items = JSON.parse(items_json);
// If the file is empty
if (!items) {
items = [];
}
};
first time calling to these functions:
read_from_local_json();
make_list();
on click event
$('#postData').click(function () {
var text = $('#tArea').val();
items.push(text);
make_list();
save_to_local_json();
});
updated my answer:
function update_json(json_data){
localStorage.setItem('json',JSON.stringify(json_data));
}
function fetch_json(){
var json_data_local = JSON.parse(localStorage.getItem('json'));
return json_data_local;
}
function display_list(json_data){
json_data.three.forEach(function(val,key) {
$('.Jsonlist').append("<li id='" + key + "'>" + val + "</li>");
});
}
console.log(localStorage.getItem('json'));
if(localStorage.getItem('json') == ""){
var Json = {"three":["red","yellow","orange"]}
update_json(Json);
}
var Json = fetch_json();
display_list(Json);
console.log(Json);
$('#postData').click(function(){
a=$('#tArea').val();
Json.three.push(a);
update_json(Json);
$('.Jsonlist li').remove();
display_list(fetch_json());
});

Convert JSON to a Multilevel Bulleted List Using JS

Can some one help me make the following JSON data:
{
"main": {
"label":"Main",
"url":"#main"
},
"project": {
"label":"Project",
"url":"#project"
},
"settings": {
"label":"Settings",
"url":"#settings",
"subnav":[
{
"label":"Privacy",
"url":"#privacy"
},
{
"label":"Security",
"url":"#security"
},
{
"label":"Advanced",
"url":"#advanced"
}
]
}
}
into the following bullets list using JS? Assuming you don't know what the first nodes are call labeled (e.g. "main", "project" <- these will be dynamically generated):
Main (#main)
Project (#project)
Settings (#settings)
Privacy (#privacy)
Security (#security)
Advanced (#advanced)
Thanks
Let's not use HTML string-hacking, shall we? That would break as soon as any of the data had characters like < or & in (or " in attribute values). Use DOM methods and you don't have to worry about character escaping:
function createNav(navs) {
var ul= document.createElement('ul');
for (name in navs) {
var nav= navs[name];
var a= document.createElement('a');
a.href= nav.url;
a.appendChild(document.createTextNode(nav.label));
var li= document.createElement('li');
li.id= 'nav-'+name;
li.appendChild(a)
if ('subnav' in nav)
li.appendChild(createNav(nav.subnav));
ul.appendChild(li);
}
return ul;
}
document.getElementById('navcontainer').appendChild(createNav(jsondata));
Most JS frameworks offer shortcuts to make this a bit less wordy. For example with jQuery:
function createNav(navs) {
var ul= $('<ul>');
for (name in navs) {
var nav= navs[name];
var li= $('<li>', {id: name});
li.append($('<a>', {href: nav.url, text: nav.label}));
if ('subnav' in nav)
li.append(createNav(nav.subnav));
ul.append(li);
}
}
$('#navcontainer').append(createNav(jsondata));
Note that either way, you're using an Object literal which means you get no control over the order the list of navs comes out. You have no guarantee that main will be above project. If you want a defined order, you will have to have the returned JSON data be an array.
My code is on JSfiddle.
As JSON parser I used this one.
The main code is a recursive renderer of the parsed JSON:
function recursive_parse(result) {
var html = '<ul>';
for (var k in result) {
html = html + '<li>' + result[k].label + ' (' + result[k].url + ')';
html = html + recursive_parse(result[k].subnav);
html = html + '</li>';
}
html = html + '</ul>';
return html;
}
var result = json_parse($("div#test1111").html());
var html = recursive_parse(result);
$("div#test2222").html(html);

cannot set selectedIndex off select with javascript

I have this code and I keep getting undefined if I test the selectedIndex.
alert(x.selectedIndex);
So, setting it is also a problem.
Does anyone possibly see what the problem is?
//makes list off tags
function ttyps_select(data,naamsel,selectid, containerid){
if(!ttyps.length){
jQuery.each(data, function(index, itemData) {
ttyps.push( new Tagtype(itemData.tag_id, itemData.tag ));
});
}
opties = "<option value=\"-1\"></option>\n";
for(var i=0; i<ttyps.length; i++) {
var dfnkey = ttyps[i].tag_id;
var dfnsel = ttyps[i].tag;
if (dfnkey==selectid) {
opties +="<option value="+ttyps[i].tag_id+" SELECTED>"+dfnsel+"</option>\n";
} else {
opties +="<option value="+dfnkey+">"+dfnsel+"</option>\n";
}
}
$("<select name=\"" + naamsel + "\" size=\"1\" ></select>")
.html(opties)
.change(function(e){
select_tag(containerid);
})
.appendTo("#"+naamsel);
}
function select_tag(id) {
var x = $('#frmttypid'+id+' select');
var ttidx = x.val();
var tag = getTagtype(ttidx).tag;
x.selectedIndex=0;
x.blur();
if( tag ){
document.forms['frmtags']['frmtag'+id].value=tag;
}
}
thanks, Richard
$('selector') (jQuery) returns an object with array-like collection of matched DOM nodes. Your x variable is an jQuery object, not a reference to any particular <select/> element. use
x[0].selectedIndex
x[0] is a reference to the first DOM node in the jQuery object.

Categories