This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am working on some project module where i am using jstree.js plugin.
I am getting following JSON via web service call:
[
{
"name":"Folder1",
"attributes": {
"SubFolder1-1":"value1-1",
"SubFolder1-2":"value1-2",
...
"SubFolder1.7":"value1-7",
"SubFolder1.8":"value1-8"
}
}, {
"name":"Folder2",
"attributes": {
"SubFolder2-1":"value2-1"
}
}, {
"name":"Folder3",
"attributes": {
"SubFolder3-1":"value2-1"
}
}
]
But jsTree.js is not accepting the JSON format, It accept following format:
{
"data" : "node_title",
"attr" : {
"id" : "node_identificator",
"some-other-attribute" : "attribute_value"
},
"children" : [ /* an array of child nodes objects */ ]
}
Our approach:
var new_avatar = new Array();
new_avatar = data.attributeSets;
// Hardcoded data for JSTree
var dirn = {};
var final_child = {};
dirn = "[";
final_child = "[";
for (var info in new_avatar) {
for (var detailInfo in new_avatar[info].attributes) {
ckey = detailInfo; // Key
cval = new_avatar[info].attributes[detailInfo]; // Key => Value
final_child += '{ "data": "' + ckey + '",';
final_child += ' "attr": { "rel":"directory" },';
final_child += ' "children": [ "' + cval + '" ] },';
}
}
final_child = final_child.substring(0, final_child.length - 1); //removing last comma so it would be a valid JSON
final_child += " ] "; //final close to this JSON
for (var info in new_avatar) {
dirn += '{ "data": "' + new_avatar[info].name + '" ,';
dirn += ' "attr": { "rel":"directory" }, ';
dirn += ' "children": ' + final_child + " }, ";
// Putting final_child in so it will build level 2 + level 3 (level 3 child is just value declared in final_child children above)
}
dirn = dirn.substring(0, dirn.length - 2); // removing whitespace + comma
dirn += " ] "; // this is main tree data var end box
dirn = $.parseJSON(dirn); // parse the whole dirn variable so it would be an array and ready to feed to jstree.
$("#tree2").jstree({
plugins: ['themes', 'json_data', "ui"],
json_data: {
"data": dirn,
},
themes: {
theme: 'default'
},
checkbox: {
real_checkboxes: true,
two_state: true
},
"types": {
"types": {
"disabled": {
"check_node": false,
"uncheck_node": false
},
"directory": {
"check_node": false,
"uncheck_node": false
}
}
}
});
Current Output:
Showing error that json is not valid string.
Expected Output:
I got the solution and is working fine now. Thanks you all for showing interest.
var new_avatar = new Array();
new_avatar = data.attributeSets;
var dirn = {};
var final_child = {};
var nodeChildren = {};
//Collect children for each node
for (var info in new_avatar) {
final_child = "[";
for (var detailInfo in new_avatar[info].attributes) {
ckey = detailInfo; // Key
cval = new_avatar[info].attributes[detailInfo]; // Key => Value
final_child += '{ "data": "' + ckey + '",';
final_child += ' "attr": { "rel":"directory" },';
final_child += ' "children": [ "' + cval + '" ] },';
}
final_child = final_child.substring(0, final_child.length - 1); //removing last comma so it would be a valid JSON
final_child += " ] "; //final close to this JSON
nodeChildren[info] = final_child;
}
// Attached collected nodes to respective parents
dirn = "[";
for (var info in new_avatar) {
dirn += '{ "data": "' + new_avatar[info].name + '" ,';
dirn += ' "attr": { "rel":"directory" }, ';
dirn += ' "children": ' + nodeChildren[info] + " }, "; //putting final_child in so it will buld level 2 + level 3 (level 3 child is just value declared in final_child children above)
}
dirn = dirn.substring(0, dirn.length - 2);
dirn += " ] ";
dirn = $.parseJSON(dirn);
$("#tree2").jstree({
plugins: ['themes', 'json_data', "ui", "dnd"],
json_data: {
"data": dirn,
},
themes: {
theme: 'default'
},
checkbox: {
real_checkboxes: true,
two_state: true
},
"types": {
"types": {
"disabled": {
"check_node": false,
"uncheck_node": false
},
"directory": {
"check_node": false,
"uncheck_node": false
}
}
}
});
Related
I am trying to create a select dropdown filter which dynamically gets its values and data from rest api.
Here is my code
HTML
<div class="container">
<select data-filter="season" class="filter_category_name filter form-control"></select>
<div class="listContent" id="listitem"></div>
</div>
JS
var data = [{
"category_name": "1",
"title": "One One",
"more": [{
"details": "some details"
}]
},
{
"category_name": "1",
"title": "One Two",
"more": [{
"details": "some details"
}]
},
{
"category_name": "2",
"title": "Two One",
"more": [{
"details": "some details"
}]
},
{
"category_name": "3",
"title": "Three One",
"more": [{
"details": "some details"
}]
}];
let listItems = "",
categoryAll = "";
for(var i = 0;i < data.length; i++) {
var title = data[i].title,
category_name = data[i].category_name;
listItems += "<a onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>" + title + "</p></div></div></a>";
if (categoryAll.indexOf("<option value='" + category_name + "'>" + category_name + "</option>") == -1) {
categoryAll += "<option value='" + category_name + "'>" + category_name + "</option>";
}
}
$("#listitem").html(listItems);
$(".filter_category_name").append(categoryAll);
var filtersObject = {};
$(".filter").on("change",function() {
var filterName = $(this).data("filter"),
filterVal = $(this).val();
if (filterVal == "") {
delete filtersObject[filterName];
} else {
filtersObject[filterName] = filterVal;
}
var filters = "";
for (var key in filtersObject) {
if (filtersObject.hasOwnProperty(key)) {
filters += "[data-"+key+"='"+filtersObject[key]+"']";
}
}
if (filters == "") {
$(".listItem").show();
} else {
$(".listItem").hide();
$(".listItem").hide().filter(filters).show();
}
});
But for some reason it hides all the items and nothing change after changing the options
I want to initially load all the items and then filter based on the option
I want the select element to dynamically create the options with the values of the category names like the first option should have the value of cars1 and display all the other objects with the same category_name.
Note: The entire code is wrapped inside an async function which renders on page load.
Here is a proper working js fiddle with the above problem
Based on your fiddle code, it would be better to filter the <a> items within the listItem area based on season, as that is the filter that is built, instead of trying to show/hide the entire listItem area.
The two minor code changes to achieve the desired result, is at these two code points:
Add a data-season reference here, to the <a> tags, with the category_name value:
listItems += '<a data-season="' + category_name + '" '
+ "onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>"
+ title + "</p></div></a>";
Change the filtering to filter on the <a> tags for the data-season that you build:
if (filters == "") {
$("a").show();
} else {
$("a").hide();
$("a").filter(filters).show();
}
Integrating those two changes into your fiddle example code, try the runnable example below:
var data = [
{
"category_name": "1",
"title": "One One",
"more": [
{
"details": "some details"
}
]
},
{
"category_name": "1",
"title": "One Two",
"more": [
{
"details": "some details"
}
]
},
{
"category_name": "2",
"title": "Two One",
"more": [
{
"details": "some details"
}
]
},
{
"category_name": "3",
"title": "Three One",
"more": [
{
"details": "some details"
}
]
},
];
let listItems = "",
categoryAll = "";
for(var i = 0; i < data.length; i++) {
var title = data[i].title,
category_name = data[i].category_name;
listItems += '<a data-season="' + category_name + '"'
+ "onclick='createAVideoContainer(" + i + ")'><div class='listItem'><p>"
+ title + "</p></div></a>";
if (categoryAll.indexOf("<option value='" + category_name + "'>" + category_name + "</option>") == -1) {
categoryAll += "<option value='" + category_name + "'>" + category_name + "</option>";
}
}
$("#listitem").html(listItems);
$(".filter_category_name").append(categoryAll);
var filtersObject = {};
//on filter change
$(".filter").on("change",function() {
var filterName = $(this).data("filter"),
filterVal = $(this).val();
if (filterVal == "") {
delete filtersObject[filterName];
} else {
filtersObject[filterName] = filterVal;
}
var filters = "";
for (var key in filtersObject) {
if (filtersObject.hasOwnProperty(key)) {
filters += "[data-"+key+"='"+filtersObject[key]+"']";
}
}
if (filters == "") {
$("a").show();
} else {
$("a").hide();
$("a").filter(filters).show();
}
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="container">
<select data-filter="season" class="filter_category_name filter form-control"></select>
<div class="listContent" id="listitem">
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.9.3/dist/umd/popper.min.js" integrity="sha384-eMNCOe7tC1doHpGoWe/6oMVemdAVTMs2xqW4mwXrXsW0L84Iytr2wi5v2QjrP/xp" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.0/dist/js/bootstrap.min.js" integrity="sha384-cn7l7gDp0eyniUwwAZgrzD06kc/tftFf19TOAs2zVinnD/C7E91j9yyk5//jjpt/" crossorigin="anonymous"></script>
Here's the updated fiddle with the same change applied.
Let's say I got an array of JSON objects like this:
const cars = [
{
"color": "purple",
"type": "minivan",
"registration": "2020-02-03",
"capacity": 7
},
{
"color": "orange",
"type": "SUV",
"registration": "2021-05-17",
"capacity": 4
},
{
"color": "green",
"type": "coupe",
"registration": "2019-11-13",
"capacity": 2
}
];
I want to convert this object to a valid XML. But the helper packages I use start tags as array indexes when converting it, and therefore the resulting XML is not valid.
For example: (function json2xml from goessner)
function json2xml(o, tab) {
var toXml = function(v, name, ind) {
var xml = "";
if (v instanceof Array) {
for (var i=0, n=v.length; i<n; i++)
xml += ind + toXml(v[i], name, ind+"\t") + "\n";
}
else if (typeof(v) == "object") {
var hasChild = false;
xml += ind + "<" + name;
for (var m in v) {
if (m.charAt(0) == "#")
xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
else
hasChild = true;
}
xml += hasChild ? ">" : "/>";
if (hasChild) {
for (var m in v) {
if (m == "#text")
xml += v[m];
else if (m == "#cdata")
xml += "<![CDATA[" + v[m] + "]]>";
else if (m.charAt(0) != "#")
xml += toXml(v[m], m, ind+"\t");
}
xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "</" + name + ">";
}
}
else {
xml += ind + "<" + name + ">" + v.toString() + "</" + name + ">";
}
return xml;
}, xml="";
for (var m in o)
xml += toXml(o[m], m, "");
return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
}
const cars = [
{
"color": "purple",
"type": "minivan",
"registration": "2020-02-03",
"capacity": 7
},
{
"color": "orange",
"type": "SUV",
"registration": "2021-05-17",
"capacity": 4
},
{
"color": "green",
"type": "coupe",
"registration": "2019-11-13",
"capacity": 2
}
];
console.log(json2xml(cars, ' '));
I tried xml2js, fast-xml-parser and jstoxml packages. Result is the same.
Edit:
Expected XML:
<element>
<color>purple</color>
<type>minivan</type>
<registration>2020-02-03</registration>
<capacity>7</capacity>
</element>
<element>
<color>orange</color>
<type>SUV</type>
<registration>2021-05-17</registration>
<capacity>4</capacity>
</element>
<element>
<color>green</color>
<type>coupe</type>
<registration>2019-11-13</registration>
<capacity>2</capacity>
</element>
How about this?
This assumes that the array of JSON objects all have the same keys.
let xml = "";
const prefixXML = `<?xml version="1.0" encoding="UTF-8"?>\n<cars>\n`;
const suffixXML = "\n</cars>";
const keys = Object.keys(cars[0]);
cars.forEach((car) => {
let valueXML = keys
.map((key) => {
return `<${key}>${car[key]}</${key}>`;
})
.join("\n\t");
xml += `
<car>
${valueXML}
</car>
`;
});
const final = prefixXML + xml + suffixXML;
console.log(final);
The XML output is:
<?xml version="1.0" encoding="UTF-8"?>
<cars>
<car>
<color>purple</color>
<type>minivan</type>
<registration>2020-02-03</registration>
<capacity>7</capacity>
</car>
<car>
<color>orange</color>
<type>SUV</type>
<registration>2021-05-17</registration>
<capacity>4</capacity>
</car>
<car>
<color>green</color>
<type>coupe</type>
<registration>2019-11-13</registration>
<capacity>2</capacity>
</car>
</cars>
If you're using FXP (fast-xml-parser), you can use folloing configuration to avoid array index as tag name
const parser = new j2xParser({
rootNodeName: "car"
});
const result = parser.parse(cars);
FXP version must be > 3.21.0
I'm the creator of jstoxml. Just for reference, this is how you'd structure your object to pass into jstoxml:
const { toXML } = window.jstoxml;
const cars = [
{
_name: 'element',
_content: {
color: 'purple',
type: 'minivan',
registration: '2020-02-03',
capacity: 7
}
},
{
_name: 'element',
_content: {
color: 'orange',
type: 'SUV',
registration: '2021-05-17',
capacity: 4
}
},
{
_name: 'element',
_content: {
color: 'green',
type: 'coupe',
registration: '2019-11-13',
capacity: 2
}
}
];
console.log(toXML(cars, { indent: ' ' }));
/**
Output:
<element>
<color>purple</color>
<type>minivan</type>
<registration>2020-02-03</registration>
<capacity>7</capacity>
</element>
<element>
<color>orange</color>
<type>SUV</type>
<registration>2021-05-17</registration>
<capacity>4</capacity>
</element>
<element>
<color>green</color>
<type>coupe</type>
<registration>2019-11-13</registration>
<capacity>2</capacity>
</element>
*/
<script src="https://cdn.jsdelivr.net/npm/jstoxml#2.2.4/dist/jstoxml.min.js"></script>
How can I create a minimum-sized Javascript serialization of a Javascript object? Essentially a JSON.stringify with all unnecessary quotes removed. (Only basic JSON data types need to be supported, not Dates etc.)
For example, the JSON:
{
"pi": 3.14,
"e!": 4.26
}
would become:
{pi:3.14,"e!":4.26}
Edit: The result is not valid JSON, but is valid Javascript.
Copied from https://stackoverflow.com/a/11233515/916000 and modified:
function stringify(obj_from_json) {
if (typeof obj_from_json !== "object") {
return JSON.stringify(obj_from_json);
} else {
if (Array.isArray(obj_from_json)) {
// if the array contains an object
var arr = [];
for (var i = 0, len = obj_from_json.length; i < len; i++) {
arr.push(stringify(obj_from_json[i]));
}
return "[" + arr.join(",") + "]";
} else {
var props = Object
.keys(obj_from_json)
.map(function(key) {
return (new RegExp(/^[1-9a-zA-Z_$][a-zA-Z0-9_$.]*$/).test(key) ? key : "\"" + key + "\"") + ":" + stringify(obj_from_json[key]);
}).join(",");
return "{" + props + "}";
}
}
}
console.log(stringify({
"pi": 3.14,
"e!": 4.26
}));
console.log(stringify([{
"adjacencies": [{
"nodeTo": "graphnode2",
"nodeFrom": "graphnode1",
"data": {
"$color": "#557EAA"
}
}],
"data": {
"$color": "#EBB056",
"$type": "triangle",
"$dim": 9
},
"id": "graphnode1",
"name": "graphnode1"
}, {
"adjacencies": [],
"data": {
"$color": "#EBB056",
"$type": "triangle",
"$dim": 9
},
"id": "graphnode2",
"name": "graphnode2"
}]));
console.log(stringify({1: 2}));
console.log(stringify({"000": 42}));
console.log(stringify({1.26: 42}));
Edit: Added object array support.
Edit: Fixed array conversion.
I have this below type of array. I want to iterate this array in JavaScript. How is this possible?
{
"result": true,
"data": [
{
"ID": 1,
"stage_ID": 1,
"badge_type_ID": 1,
"name": "Despertar da Força",
"description": "Fazer a primeira SuperAtividade",
"type": "",
"image_static": "url123.jpg",
"image_animated": "",
"SQL": "",
"published": 1
},
{
"ID": 2,
"stage_ID": 1,
"badge_type_ID": 1,
"name": "Super 3",
"description": "Fazer 3 SuperAtividades",
"type": "",
"image_static": "urlimage123.png",
"image_animated": "",
"SQL": "",
"published": 1
}
etc
I tried the following script and it is returning "undefined", "undefined".
$.getJSON('https://www.legiaodossuperpoderes.com.br/chronus/api/adm/badges', function(data) {
var output= "<ol>";
for (var i in data) {
output += "<li>" + data[i].ID + "</li>"
}
output+="</ol>";
document.getElementById("placeholder").innerHTML=output;
});
Any solutions ? Thanks!
You can try converting to Json Object
$.getJSON('https://www.legiaodossuperpoderes.com.br/chronus/api/adm/badges', function(data) {
var output= "<ol>";
var jsondata = $.JSON.parse(data); // Json object Convertion
for (var i in data) {
output += "<li>" + data[i].ID + "</li>"
}
output+="</ol>";
document.getElementById("placeholder").innerHTML=output;
});
You are trying to access an undefined property using data[i].ID .
When you are getting response from your getJSON() function then you need to call the response with a name and then you can access any inner property using this name .
Now if you want to iterate using data key/value on myResponse variable then you need to do this.
$.getJSON('https://www.legiaodossuperpoderes.com.br/chronus/api/adm/badges', function(myResponse) {
var output= "<ol>";
var dataCount = myResponse.data.length;
for (var i = 0; i < dataCount; i++) {
output += "<li>" + myResponse.data[i].ID + "</li>";
}
output+="</ol>";
document.getElementById("placeholder").innerHTML=output;
});
I have an ajax function which sends a get request to an api and returns data in the following format-
{
"firstname": "John",
"lastname": "Doe",
"email": "doej#gmail.com",
"subjects": [
{
"id": 1,
"name": "maths"
},
{
"id": 2,
"name": "chemistry"
}
]
},
I need to display this data in a table but am having trouble getting the subjects array to display correctly, ie as a list in one table cell. I have tried to put the array data into another table inside the main one but it's not working out. I presume I'm going very wrong somewhere in my iteration loops.
function getPeople() {
$.ajax({
type: "GET",
url: "http://example.com",
contentType: "application/json; charset=utf-8",
crossDomain: true,
dataType: "json",
success: function (data, status, jqXHR) {
// fill a table with the JSON
$("table.mytable").html("<tr><th></th><th>First Name</th><th>Last Name</th><th>Subjects</th></tr>" );
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].subjects.length; j++) {
var subjects = data[i].subjects[j];
$("table.insidetable").append('<tr><td>' + subjects + 'tr><td>')
}
$("table.mytable").append('<tr><td><input type = "checkbox" id = '+data[i].id+'>' + "</td><td>" + data[i].firstname + "</td><td>" + data[i].lastname + "</td><td>" + "table.insidetable" + "</td></tr>");
}
},
error: function (jqXHR, status) {
// error handler
console.log(jqXHR);
alert('fail' + status.code);
}
});
}
Below is the working (tested) code.
var data = [{
"firstname": "John",
"lastname": "Doe",
"email": "doej#gmail.com",
"subjects": [
{
"id": 1,
"name": "maths"
},
{
"id": 2,
"name": "chemistry"
}
]
},
{
"firstname": "Steve",
"lastname": "Gentile",
"email": "steve#gmail.com",
"subjects": [
{
"id": 1,
"name": "history"
},
{
"id": 2,
"name": "geography"
}
]
}];
$("table.mytable").html("<tr><th></th><th>First Name</th><th>Last Name</th><th>Subjects</th></tr>");
for (var i = 0; i < data.length; i++) {
var subjectList = '';
for (var j = 0; j < data[i].subjects.length; j++) {
subjectList += '<li>' + data[i].subjects[j].name + '</li>';
}
$("table.mytable").append('<tr><td><input type="checkbox" id=' + i +'/></td><td>' + data[i].firstname + '</td><td>' + data[i].lastname + '</td><td><ul>' + subjectList + '</ul></td></tr>');
}
It seems there are many problems in below statement like,
Tags are not closed properly
Properties that do not exist are being used (data[i].id)
Single and Double quotes don't match
...
$("table.mytable").append('<tr><td><input type = "checkbox" id = '+data[i].id+'>' + "</td><td>" +data[i].firstname + "</td><td>" + data[i].lastname + "</td><td>" + "table.insidetable"+ "</td></tr>");
As a guess are you missing a '<'?
In the line:
$("table.insidetable").append('<tr><td>' + subjects + 'tr><td>')
Also
$("table.mytable").append('<tr><td><input type = "checkbox" id = '+data[i].id+'>' + "</td><td>" + data[i].firstname + "</td><td>" + data[i].lastname + "</td><td>" + "table.insidetable" + "</td></tr>");
I don't think you should be appending "table.insidetable"? This will be seen rendered as the value "table.insidetable" and not the contents of the table. I think this should rather be something like $("table.insidetable").val()