loop through JSON with null objects - javascript

I have this problem with my JSON file.
{"results" :[{
"name" : "name1",
"type" :[{
"id" : '2',
},{
"id" : '1',
},{
"id" : '4',
},{
"id" : '6',
}],
}],
"images" :[{
"url" : "url0",
},{
"url" : "url1",
},{
"url" : "url2",
},{
"url" : "url3",
},{
"url" : "url4",
}],
},{
"name" : "name2",
"type" :[{
{
"id" : '25',
},{
"id" : '123',
},{
"id" : '423',
},{
"id" : '346',
}],
"images" :[{
"url" : "url0",
},{
"url" : "url1",
},
{
"url" : "url2",
},
{
"url" : "url3",
},{
"url" : "url4",
}],
},
},{
"name" : "name3",
"type" : null,
"images" :null,
},.....
]}
the JSON object looks like this
When i loop through the it kicks me out when it comes to the null
for(var i = 0; i < results.length; i++){
$('.results')append('<p class="liste">'+results[i].name+'</p><ul></ul>');
$('.liste').prepend('<img src="'+results[i].images[1].url+'"');
for(var j = 0; j < results[i].type.length; j++){
$('.results ul').append('<li>'+results[i].type[j].id+'</li>');
}
}
the result should look somewhat like this
<div class="results">
<img src="url1"><p>name1</p>
<ul>
<li>2</li>
<li>1</li>
<li>4</li>
<li>6</li>
</ul>
<img src="url1"><p>name2</p>
<ul>
</ul>
<img src="url1"><p>name3</p>
<ul>
<li>25</li>
<li>123</li>
<li>423</li>
<li>346</li>
</ul>
</div>
i tryed
if(results[i].images != null){
$('.liste').prepend('<img src="'+results[i].images[1].url+'">');
}else{
$('.liste').prepend('<img src="some default image" width="170" height="170">');
}
if(results[i].type != null){
for (var j = 0; j < results[i].type.length.length; j++) {
$('.album').append('<li>'+[i]+'-'+[j]+'-'+results[i].type.length[j].id+'</li>');
};
it gehts really messy the image comes for every [i] and the first [k] appears as it suppose to be as well as last [k] in in the pre. [i]
[i][j]
name1
[0][0]
[0][1]
[0][2]
[0][3]
[1][0]
name2
[1][0]
......
I hope some one can help me with that
EDIT
I forgot every "type" is listed under each name.

The JSON you provided is invalid, but, assuming the JSON looks like this (based on your current iteration code):
var results = [{
"name": "name1",
"type": [{ "id": '2'},
{ "id": '1'},
{ "id": '4'},
{ "id": '6'}],
"images": [{ "url": "url0" },
{ "url": "url1" },
{ "url": "url2" },
{ "url": "url3" },
{ "url": "url4" }],
}, {
"name": "name2",
"type": [{ "id": '25' },
{ "id": '123' },
{ "id": '423' },
{ "id": '346' }],
"images": [{ "url": "url0" },
{ "url": "url1" },
{ "url": "url2" },
{ "url": "url3" },
{ "url": "url4" }],
}, {
"name": "name3",
"type": null,
"images": null
}];
You have several problems with this statement:
for(var i = 0; i < results.length; i++){
$('.results')append('<p class="liste">'+results[i].name+'</p><ul></ul>');
$('.liste').prepend('<img src="'+results[i].images[1].url+'"');
for(var j = 0; j < results[i].type.length; j++){
$('.results ul').append('<li>'+results[i].type[j].id+'</li>');
}
}
$('.liste').prepend will append the provided element to ALL elements with a class of .liste. Each time you prepend a new image, all existing <p> elements will get it.
$('.results ul').append - see above comment. Each time you append, all existing elements that match will get additional, unwanted values attached
Both the type and images values can be null and you haven't provided any guards against this in your loop.
Something like this given the assumption above will work better for you:
Demo Fiddle
Code:
// Use a document fragment to avoid DOM updates in the loop
var $fragment = $(document.createDocumentFragment());
for (var i = 0; i < results.length; i++) {
// If there is an image, add it
if(results[i].images) {
$fragment.append($('<img src="' + results[i].images[1].url + '"/>'));
}
$fragment.append($('<p class="liste">' + results[i].name + '</p>'));
// Keep track of the current UL so it can be appended to directly
var $curULTag = $('<ul></ul>').appendTo($fragment);
if(results[i].images && results[i].type) {
for (var j = 0; j < results[i].type.length; j++) {
// add the li to the current UL
$curULTag.append('<li>' + results[i].type[j].id + '</li>');
}
}
}
// Append the full results
$('.results').append($fragment);
Results:
<div class="results">
<img src="url1">
<p class="liste">name1</p>
<ul>
<li>2</li>
<li>1</li>
<li>4</li>
<li>6</li>
</ul>
<img src="url1">
<p class="liste">name2</p>
<ul>
<li>25</li>
<li>123</li>
<li>423</li>
<li>346</li>
</ul>
<p class="liste">name3</p>
<ul></ul>
</div>
If my assumption about the JSON structure you provided isn't correct, you can adjust the above code to provide the results you need.

Start off with a more clear code structure so you don't get lost too fast...
if (jsonData.results)
{
$.each(jsonData.results, function(obj)
{
// process obj.name if exists
// process obj.type if exists
});
}
Do you see any error messages in the console?

Related

Mongodb mapreduce Join 2 collections

I have 2 collections and I am new to Mongo MapReduce concept.
My collection Value looks like this
{
"_id" : ObjectId("5bc4f20e1a80d2045029ccb7"),
"name" : "Title 1",
"value" : "value 1 for title 1"
}
{
"_id" : ObjectId("5bc4f20e1a80d2045029ccb8"),
"name" : "Title 1",
"value" : "Value 2 for title1. "
}
{
"_id" : ObjectId("5bc4f20e1a80d2045029ccb9"),
"name" : "Title 2",
"value" : " Definitely a motivational text!"
}
{
"_id" : ObjectId("5bc4f20e1a80d2045029ccba"),
"name" : "Title 2",
"value" : "It's tough but I'm carrying on. "
}
Other collection Details look like:
{
"_id" : ObjectId("5bc4f2361a80d2045029d05b"),
"name" : "Title 1",
"totalValues" : 6.0000000000000000,
"link": "Link1",
"description" : "Some More Text to Make title 1 look better"
}
{
"_id" : ObjectId("5bc4f2361a80d2045029d2eb"),
"name" : "Title 2",
"totalValues" : 2,
"link": "Link2",
"description" : "Some More Text to Make title 2 look better"
} ...
I want the output result as
{
“name” : “XXXXXXXX”,
“comments” : [ {“value”: “XXXXXXX”}, {“value”: “YYYYYYYY”}],
“totalValues” : 2,
“link”: “XXXXXXXXXX”,
“description”: “XXXXXXXXXXXXXXXXXX”
}
with the following output document. Please help.
I have tried following code:
var mapDetails = function(){
var output = {name: this.name,totalValues :this.totalValues, description : this.description, link :this.link}
emit(this.name, output);
};
var mapGpas = function() {
emit(this.name,{name:this.name, value:this.value, totalValues:0, description: 0, link: 0});
};
var r = function(key, values) {
var outs = { name: 1,value: 1, description: 0,totalValues:0, link: 0};
values.forEach(function(v){
outs.name = v.name;
if (v.value == 0) {
outs.description = v.description;
outs.totalValues = v.totalValues;
outs.link = v.link;
}
});
return outs;
};
res = db.Value.mapReduce(mapGpas, r, {out: {reduce: 'joined'}})
res = db.Details.mapReduce(mapDetails, r, {out: {reduce: 'joined'}})
db.joined.find().pretty()

How to get last active node status preserved or selected as it was before on page load

i have a jstree where i want to get the last active node to intact as it was before by saving last state in localStorage
below image shows on page load i want to get the result:
here is how i'm saving last state to localStorage
var lastClickedData = data.inst.get_json();
localStorage.setItem('lastnode',JSON.stringify(lastClickedData));
here is jsfiddle: http://jsfiddle.net/2Jg3B/2128/
$(function () {
$('#jstree').jstree({
"json_data" : {
"data" : [
{
"data" : "A node",
"metadata" : { id : 23 },
"children" : [ "Child 1", "A Child 2" ]
},
{
"attr" : { "id" : "li.node.id1" },
"data" : {
"title" : "Long format demo",
"attr" : { "href" : "#" }
}
}
]
},
"plugins" : [ "themes", "json_data", "ui" ]
});
var highlightAndExpandLastActiveNode = JSON.parse(localStorage.getItem('lastnode'));
// $('#jstree') //set last acive node
console.log(highlightAndExpandLastActiveNode);
});
$("#jstree").bind("select_node.jstree", function(evt, data) {
if (data.inst._get_parent().length <= 0 || data.inst._get_parent() === -1){
console.log('clicked data', data.inst.get_json());
} else {
var lastClickedData = data.inst.get_json();
localStorage.setItem('lastnode',JSON.stringify(lastClickedData));
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://old.static.jstree.com/v.1.0pre/jquery.jstree.js"></script>
<div id="jstree">
</div>
please help me thanks in advance!!!!!
Here is a solution using a newer version of jstree (v3.2.1). When you select a node in the tree and then reload the page, the node is selected again based on the node's id saved in localStorage.
http://jsfiddle.net/t4s7dz52/
javascript:
$(function() {
$('#jstree').jstree({
'core': {
'data': [{
"text": "A node",
"children": ["Child 1", "A Child 2"]
},
"Long format demo"
]
}
});
$('#jstree').bind('loaded.jstree', function() {
var selectedNodeId = localStorage.getItem('selectedNodeId');
$('#jstree').jstree(true).select_node(selectedNodeId);
});
});
$("#jstree").bind("select_node.jstree", function(e, data) {
localStorage.setItem('selectedNodeId', data.node.id);
});
html:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
<div id="jstree">
</div>

Angular ng-repeat filter on nested array in object

I'm trying to applay a filter in my ng-repeat based on a nested array. The object that is used for the ng-repeat:
Updated
master_array:
{
"0": {
"Employee_Id": "hni",
"comptencies": [
{
"Title": "Bunker Knowledge",
"Level": 1
},
{
"Title": "Bunker Knowledge",
"Level": 3
},
{
"Title": "IT Compliance",
"Level": 2
},
{
"Title": "Bunker Knowledge",
"Level": 5
}
],
}
}
JS:
$scope.myFilter = {
competencyTitle : ""
}
HTML:
<label>Competencies
<select ng-model="myFilter.competencyTitle" ng-options="item.Title for item in competencies_list"></select>
</label>
<tr ng-repeat="item in master_array | filter: { competencies: [{ Competency.Title: myFilter.competencyTitle }] }">
The above doesn't work.
Case
I have a list of employees and each employee has an id and array of competencies attached. Each item in this array has a comptency array attached, which holds the title an id of the competency. What I want is to be able to filter out employees with specific competencies.
Any suggestions?
I found a solution. You probably have to adapt it to your specific code:
The main idea is this: filter: { $: {Title: myFilter.competencyTitle.Title} }
The $ selects any element whose child is Title.
html
<label>Competencies {{myFilter.competencyTitle.Title}}
<select ng-model="myFilter.competencyTitle" ng-options="item.Title for item in competencies_list"></select>
</label>
<p ng-repeat="item in master_array | filter: { $: {Title: myFilter.competencyTitle.Title} }">{{item.employee_id}} {{item.competencies}} </p>
js - this is the model is used, I'm not sure if this reflects your actual model.
$scope.competencies_list = [{Title : "Math"},{Title : "English"},{Title : "Spanish"}];
$scope.master_array =
[
{
employee_id: "hni",
competencies:
[
{Title : "Math", "Level": 1},
{Title : "English", "Level": 2}
]
},
{
employee_id: "xyz",
competencies:
[
{Title : "Spanish", "Level": 3},
{Title : "English", "Level": 5}
]
}
];
$scope.myFilter = {
competencyTitle : ""
};

Displaying data from socket io using angularJs

I'm trying to get data from socket io and display the data on a graph using angularJs. I'm getting the correct data from the server but when I'm trying to display it I'm getting:"No Data To Display". I tried to debug my controller and i saw that I'm getting data but some how angular on my HTML doesn't show it.
i also tried using Async.js but it still doesn't work.
my controller code:
$scope.graph2,data2 = [];
socketFactory.emit('getTemplateStatistics', null);
socketFactory.on('sendTemplateStatistics', function(result) {
for (var i=0; i < result.length; i++) {
var temp = {label: result[i]._id, value: ""+result[i].total};
data2.push(temp);
}
$scope.graph2 = {
chart: {
caption: "Age profile of website visitors",
subcaption: "Last Year",
startingangle: "120",
showlabels: "0",
showlegend: "1",
enablemultislicing: "0",
slicingdistance: "15",
showpercentvalues: "1",
showpercentintooltip: "0",
plottooltext: "Age group : $label Total visit : $datavalue",
theme: "fint"
},
data2
};
});
my HTML code:
<div class="statistics view indent">
<div class="container" style="margin-top:10px">
<header>
<h3>Statistics Preview Displayer</h3>
</header>
<div>
<fusioncharts
width="600"
height="400"
type="pie3d"
datasource="{{ graph2 }}"
></fusioncharts>
</div>
Go back
</div>
</div>
I dont think this is a socket issue. Probably '$scope.graph2' is getting assigned before the for loop completes execution and so 'data2' has no value. Try changing the code like this
$scope.graph2,data2 = [];
socketFactory.emit('getTemplateStatistics', null);
socketFactory.on('sendTemplateStatistics', function(result) {
for (var i=0; i < result.length; i++) {
var temp = {label: result[i]._id, value: ""+result[i].total};
data2.push(temp);
if(i == result.length - 1) { // To ensure $scope.graph2 is assigned only after for loop completes and data has all values
$scope.graph2 = {
chart: {
caption: "Age profile of website visitors",
subcaption: "Last Year",
startingangle: "120",
showlabels: "0",
showlegend: "1",
enablemultislicing: "0",
slicingdistance: "15",
showpercentvalues: "1",
showpercentintooltip: "0",
plottooltext: "Age group : $label Total visit : $datavalue",
theme: "fint"
},
data2
};
}
}
});
This way $scope.graph2 gets assigned only after completion of for loop and so data2 wont be null

How to create jstree based on json Data?

I am creating JsTree with json Data. the tree is created upto second level but after second the tree is not populated.
I want to recursively call the function to add leaf to it until leaf doesnt exit.
Below is my Json:
[ {
"id" : 25,
"name" : "Output",
"path" : "/",
"type" : "folder",
}, {
"id" : 26,
"name" : "Templates",
"path" : "/",
"type" : "folder",
}, {
"id" : 27,
"name" : "Temp",
"path" : "/Output/",
"type" : "folder",
}, {
"id" : 28,
"name" : "December",
"path" : "/Output/",
"type" : "folder",
}, {
"id" : 29,
"name" : "ParameterDOC",
"path" : "/Templates/DecemberTemplates/",
"type" : "Doc",
}, {
"id" : 30,
"name" : "SimpleDoc",
"path" : "/Templates/DecemberTemplates/",
"type" : "Doc",
}, {
"id" : 31,
"name" : "DecemberTemplates",
"path" : "/Templates/",
"type" : "folder",
}, {
"id" : 32,
"name" : "NovemberTemplates",
"path" : "/Templates/",
"type" : "folder",
} ]
and code is:
function createTreeForDoc(jsonData,path,id){
for(var i=0; i < jsonData.length;i++){
if(jsonData[i].path == path){
$("<li id="+jsonData[i].name+" class=\"lib\" rel="+jsonData[i].path+" data-jstree='{\"icon\":\"images/"+jsonData[i].type+"_small.png\"}' >"+jsonData[i].name+"</li>").appendTo("#maptree");
createSubTree(jsonData,jsonData[i].path+jsonData[i].name+"/",jsonData[i].name,i);
}
}
$('#rptTree').jstree({
"plugins" : ["types"],
"core" : { "check_callback" : false, "themes" : { "dots" : false }, },
});
}
function createSubTree(jsonData,path,gid,counter){
$("<ul id=\"test"+counter+"\"></ul>").appendTo("#"+gid);
for(var i=0; i < jsonData.length;i++){
if(jsonData[i].path == path ){
$("<li id="+jsonData[i].name+" class=\"lib\" rel="+jsonData[i].path+" >"+jsonData[i].name+"</li>").appendTo("#test"+counter);
}
}
}
and right now i am getting out this:
so this creates till second level third level is not created how to recursively call a function to create all other level to end.
I am not able to get what you are trying to do ,but by looking your json data you can do in the following way.Here I am using a recursive function:
function filterData(globalData,parentPath){
var result=[];
for(var i =0; i<globalData.length;i++){
if(globalData[i].path == parentPath){
result.push(data[i]);
}
}
return result;
}
function renderTree(data,parentNodeId)
{
for (var i=0; i<data.length;i++)
{
if(data[i].type == 'folder')
{
$("<li id="+data[i].name+ ">"+data[i].name+"</li>").appendTo($('#'+parentNodeId));
var childNodes=filterData(globalData,data[i].path+data[i].name+"/");
if(childNodes.length > 0)
{
$("<ul id="+data[i].path+data[i].name+"></ul>").appendTo($('#'+data[i].name));
renderTree(childNodes,data[i].path+data[i].name);
}
}
else
{
$("<li id="+data[i].name+">"+data[i].name+"</li>").appendTo($('#'+parentNodeId));
}
}
hope it will work.
You have to use a recursive function to build your tree. This function should look like:
function recursive(jsonData,parent,counter=0)
{
$("<li id="+parent.path+parent.name+" class=\"lib\" rel="+parent.path+" >"+parent.name+"</li>").appendTo("#test"+counter);
counter = 0;
for(a = 0; a<jsonData.length; a++)
{
if((parent.path+ parent.name) == jsonData[a].path)
{
$("<li id="+jsonData[a].path+jsonData[a].name+" class=\"lib\" rel="+jsonData[a].path+" data-jstree='{\"icon\":\"images/"+jsonData[i].type+"_small.png\"}' >"+jsonData[a].name+"</li>").appendTo("#maptree");
if(jsonData[a].type == "folder")
{
recursive(jsonData,jsonData[a],counter);
}
}
counter++;
}
}
This is an example, i'm notsure it works but it might be close enought for you to enhance it. :)
Good luck...

Categories