Loop through JSON array in jquery - javascript

I have an external JSON file that has this in it:
{
"Home": [
{ "link":"index.php" , "text":"Home" },
{ "link":"index.php?page=aboutus" , "text":"About Us" }
]
"Games": [
{ "link":"games.php" , "text":"All Games" },
{ "link":"games.php?name=game" , "text":"Game" }
]
}
That is the basic setup of my JSON file. I plan on adding more as my site expands. I am using that as part of my menu bar setup. It has 3 buttons, Home, Games, and Forum. When you mouse over the Home button I want to turn the stuff in "Home" into links and show it up on my site, same with the Games button, nothing is going to show up when you mouse over the Forum button. I have tried this:
Edit: changed the function slightly again, trying to keep it from calling the server on each mouse over, as well as loop through them all and show them in the .navDD div tag.
$(document).ready(function(){
var menu
$.getJSON('menu.json', function(data) {
menu = data;
});
$(".navlink").mouseenter(function(){
var find=$(this).text();
$.each(data,function(index){
$(".navDD").html(menu[find][index]['text']);
});
});
});
I am sure I mess something up still. Now I getUncaught TypeError: Cannot read property 'length' of undefined. I am not sure at all what I am doing wrong. Though I have never worked with JSON before this.
Could someone please help me?
Thanks,
Legobear154

You could try doing it this way:
$(".navlink").mouseenter(function(){
var find=$(this).text;
$.getJSON('menu.json', function(data) {
$(".navDD").html(data[find][0].text);
});
});
Access a property via it's name. This is assuming that the text value you are using matches the JSON property of your object.
I would also suggest not doing the $.getJSON() on every mouse enter. That is a lot of server traffic. Users could be "mouse entering" hundreds of times.

Are you sure that this is correct?
var find=$(this).text;
I'd do:
var find=$(this).text();
And then
$.getJSON('menu.json', function(data) {
$(".navDD").html(data.[find][0].text);
});

There is no find property in your object, so that's giving you undefined. You're then trying to read the 0th index of this undefined property, which is giving you the error.
If you want to access the the text property of the 0th element in the home object, you would say data.home[0].text

for (var key in data) {
if (key == 'Home'){
$(".navDD").html(data[key]['text']);
}
}
you should also make sure that you are working with an object when using for loops. That might be where your 'undefined' error is coming from.
if (typeof data === 'object'){
for (var key in data) {
if (key == 'Home'){
$(".navDD").html(data[key]['text']);
}
}
}

You are using var find=$(this).text to get the content of the element, you need to use var find=$(this).text() to call the text method.
You are using data.find[0].text to get a value from the object, you need to use menuData[find][0].text.
You should not request the JSON file every time the mouseenter event happens, you should only request it the first time, then hold on to it.
$(document).ready(function(){
var menuData = null;
$(".navlink").mouseenter(function(){
var find = $(this).text();
if (menuData != null) {
$(".navDD").text(menuData[find][0].text);
} else {
$.getJSON('menu.json', function(data) {
menuData = data;
$(".navDD").text(menuData[find][0].text);
});
}
});
});

Related

Random User Generator API - get user by ID Angular JS

I am new to Angular, but managed to make an Ajax-call and print out users from Random User Generator API in a list view.
Now I want to make a detailed view while clicked on a user.
In my HTML I make a function call: fetchInfoById(user.id.value)
In my script the function:
$scope.fetchInfoById = function(info_id) {
$http.get("https://randomuser.me/api/?id.value="+info_id)
//also tried: $http.get("https://randomuser.me/api/?id/value="+info_id)
.success(function(data) {
$scope.oneUserResult = data.results;
});
}
It does give me a user to a detail view, but not the chosen one. What am I doing wrong?
Thanks for your good suggestions.
I know it is a random generator, but setting parameters for the request to: "seed=...", the same persons is displayed on each listview request:
$http.get('https://randomuser.me/api/?results=15&seed=abc&inc=gender,name,location,email,dob,phone,cell,id,picture,info,nat&nat=gb')
.success(function(response){
$scope.userResult = response.results;
});
Then I fetched the id for each person and passed in as a parameter to the function call for the request for the detail view.
I tried with console.log() to make sure I passed in the right value for the detail view request and then even hardcoded the
parameter for the request ie:
$scope.getInfoById = function(info_id) {
console.log("from HTML: "+info_id.value ); // = JK 00 46 67
$http.get("https://randomuser.me/api/?id="+'JK 00 46 67 H') ...
The jason data behind the API is formatted like this for the id-property:
{
"results": [
{
"id": {
"name": "BSN",
"value": "04242023"
},...
I still haven't figured out how to get the one user by id. Getting different users all the time, even with hard coded id...
Instead of making the second request my solution was to a pass the "clicked user" as a parameter for the detailed view.
Change your code to this:
$scope.fetchInfoById = function(info_id) {
$http.get("https://randomuser.me/api/?id="+info_id)
//also tried: $http.get("https://randomuser.me/api/?id/value="+info_id)
.success(function(data) {
$scope.oneUserResult = data.results;
});
}
Also, make sure you are passing in the correct value to this function.
Fetch a list of users from API call "https://randomuser.me/api/?results=5".
$scope.getAllUsers= function(resultCount) {
$http.get("https://randomuser.me/api/?results="+resultCount)
.success(function(data) {
$scope.users= data.results;
});
Display them on the screen.
On click of one record fetch details for that particular record from users list fetched earlier.
$scope.getUserById= function(userId) {
return $scope.users.filter(function(user) {
return user.id.value=== userId;
})[0]; // apply necessary null / undefined checks wherever required.
}
another way using ng-model:
$scope.user = {};
$scope.fetchInfoById = function() {
$http.get("https://randomuser.me/api/?id="$scope.user.id)
.success(function(data) {
$scope.oneUserResult = data.results;
});
}

Check for duplicate record in Chrome Storage extension before saving

I'm developing a small Chrome extension that would allow me to save some records to chrome.storage and then display them.
I've managed to make the set and get process work as I wanted (kinda), but now I'd like to add a duplicate check before saving any record, and I'm quite stuck trying to find a nice and clean solution.
That's what I came up for now:
var storage = chrome.storage.sync;
function saveRecord(record) {
var duplicate = false;
var recordName = record.name;
storage.get('records', function(data) {
var records = data.records;
console.log('im here');
for (var i = 0; i < records.length; i++) {
var Record = records[i];
if (Record.name === recordName) {
duplicate = true;
break;
} else {
console.log(record);
}
}
if (duplicate) {
console.log('this record is already there!');
} else {
arrayWithRecords.push(record);
storage.set({ bands: arrayWithRecords }, function() {
console.log('saved ' + record.name);
});
}
});
}
I'm basically iterating on the array containing the records and checking if the name property already exists. The problem is it breaks basic set and get functionality -- in fact, when saving it correctly logs 'im here' and the relative record object, but it doesn't set the value. Plus, after a while (generally after trying to list the bands with a basic storage.get function) it returns this error:
Error in response to storage.get: TypeError: Cannot read property
'name' of null
I'm guessing this is due to the async nature of the set and get and my incompetence working with it, but I can't get my head around it in order to find a better alternative. Ideas?
Thanks in advance.

Circular Structure error .postJSON data

var selectFormula = $(htmlContainer).find("ins").map(function (i, el) {
return {
fName: $(el).attr("data-record-name"),
fID: $(el).attr("data-record-id"),
fContent: $(el).text()
}
//fContent: $(htmlContainer).each(function () { if (!$(this).text().trim().length) { $(this).remove(); } }),
});
//keep
//var selFormInner = $(htmlContainer).find("ins").map(function (i, el) { return {
// fName: $(htmlContainer).find("ins[data-record-name]"),
// fID: $(htmlContainer).find("ins[data-record-id]"),
// fContent: $(htmlContainer).find("ins").each(function () { if (!$(this).text().trim().length) { $(this).remove(); } })
//}
//}); //inner content (array)
if (selectFormula /*&& selFormInner.length*/) {
// Get formula HTML from server
$.postJSON(formulaUrl, {
//name: selFormName.map(function () {
// return $(this).data('record-name');
//}).toArray(),
////return information on the corresponding record id
//recordID: selFormID.map(function () {
// return $(this).data('record-id');
//}).toArray(),
//return infmoration on the corresponding content of ins.
//formula: selFormInner.map(function () {
// return $(this);
//}).toArray()
formula: selectFormula };
This is a part of my script file(all javascript) that is requesting to execute a server-side method with the shorthand $.postJSON. I keep running into this "Converting circular structure to JSON" It happens on this line: 'data': JSON.stringify(data) in the included postJSON script file.
My question is specifically focused on the on the circular structure. This could be wrong, but I think it highly likely that it is referring to my variable selectFormula declared at the top. What is circular about this structure? I have done some reading with people getting the same error but their examples seemed more obvious than mine, an object referring to itself etc.
This JSON data that i am passing to the server has a struct created in a similar manner in c# but that doesn't really matter since it doesn't hit my server side method, this error is all client side. As you can see with lots of my commented out code, I have tried quite a few things. All of them wrong of course!
Thanks in advance for any insights.
In my case, converting the structure to an array here stopped the Circular Structure error. Jquery's: .toArray() method. Then All I had to do was edit my server side method argument to match. Thanks anyway if anyone tried to work on this!

Passing result from .getJSON() to another function results in undefined

Good day everyone,
I am pulling back some data from a database (via a PHP script) using jQuery's .getJSON() method. This is all well and good, the data comes back just fine and as expected. The problem occurs when I try to pass the data to a secondary function, no matter how I try to access the values of that data they come back as undefined. I have a feeling I am overlooking something very simple but after a lot of trial and error I come to SO asking for an extra set of eyes.
Here is a simple example of the JavaScript code.
function fnCheck_Vis(Row, sField, sMode)
{
sField = sField+"_vis";
sTest = Row.sField.val();
alert(sTest); // Comes back as undefined.
}
$(document).ready(function()
{
$("#btnSearch").click(function()
{
$("#divResults").empty();
var ssearch = $("#ssearch").val();
var i = 0;
$.getJSON("get_results.php?keywords=" + ssearch,
function(Data)
{
var iRec = 0;
$.each(Data, function(i, Row)
{
fnCheck_Vis(Row, "slinkpic1", "Int");
var content = Row.slast;
$("#divResults").append(content);
iRec++;
});
alert(iRec + " records retrieved using AJAX.");
});
});
});
The first piece of the fnCheck_Vis() function works fine and "_vis" is appended to the field name, this is proper behavior. No matter how I try to access that member in the dataset (Row) I can not get a value back.
I really appreciate any insight that can be given on this issue.
Thanks,
Nicholas
It looks like you want to access the property of Row whose name is stored in sField, not its actual sField property. Try:
function fnCheck_Vis(Row, sField, sMode)
{
sField = sField + "_vis";
var sTest = Row[sField];
alert(sTest);
}

javascript undefined error, but alert toSource shows the object exists

I grabbed a bit of code to do some paging with jQuery, via Luca Matteis here
Paging Through Records Using jQuery
I've made some edits to the paging script so that I can use the same code to provide paging of different content in different locations on the same site.
For the most part, I think it works, except that I get a jsonObj is undefined error in firebug.
When I use alert(jsonObj.toSource()), I am shown the variables that I am trying to populate, but at the same time, the script dies because of the error.
I can't figure out why I am getting this conflict of 'undefined' and yet I can easily out put the 'undefined' values in an alert. I can even say alert(jsonObj.name), and it will give me that value, but still launch an jsonObj is undefined error.
Here's the code I'm using
var pagedContent = {
data: null
,holder: null
,currentIndex : 0
,init: function(data, holder) {
this.data = data;
this.holder=holder;
this.show(0); // show last
}
,show: function(index) {
var jsonObj = this.data[index];
if(!jsonObj) {
return;
}
var holdSubset='';
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
this.currentIndex = index;
if(this.holder=='div#firstList'){
var returnedId = jsonObj.id;
var returnedName = jsonObj.name;
var calcScore=this.data[index+i].score/this.data[0].score*100;
var resultInput="<div ' id='"+returnedId+"'><div class='name'>"+returnedName+"</div><div class='score'><div style='width:"+calcScore+"%;'></div></div>";
}
if(this.holder=='div#secondList'){
var name=jsonObj.name;
var city=jsonObj.city;
var region=jsonObj.state;
var resultInput='<li><div>'+name+'</div<div>'+city+'</div><div>'+region+'</div></li>';
}
holdSubset= holdSubset+resultInput;
}
jQuery(this.holder).html('<br/>'+holdSubset);
if(index!=0){
var previous = jQuery("<a>").attr("href","#").click(this.previousHandler).text("< previous");
jQuery(this.holder).append(previous);
}
if(index+i<this.data.length){
var next = jQuery("<a style='float:right;'>").attr("href","#").click(this.nextHandler).text("next >");
jQuery(this.holder).append(next);
}
}
,nextHandler: function() {
pagedContent.show(pagedContent.currentIndex + 5);
return false;
}
,previousHandler: function() {
pagedContent.show(pagedContent.currentIndex - 5);
return false
}
};
I call the function like this
pagedContent.init(json.users.locations, 'div#secondList');
The json looks like this
{"locations" : [ {"id":"21319","name":"Naugatuck American Legion","city":"Ansonia","region":"Connecticut"},{"id":"26614","name":"Studio B789","city":"Acton","region":"Maine"},{"id":"26674","name":"Deering Grange Hall","city":"Bailey Island","region":"Maine"},{"id":"27554","name":"Accu Billiards","city":"Acushnet","region":"Massachusetts"}]}
I may have found the problem with your code:
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
(...)
When you call show(0) you set index to 0. You expect a fixed number of items in the array (5 in the range [0..4]) but there are only 4 locations in your data.
If you are using console.log to trace the problems in firebug you might find that it is a problem with firebug. Try just running console.log on it's own.
If it is a problem with firebug try updating it. There are some development versions around which might fix the problem.
I had a similar problem and fixed it by doing the above.

Categories