I am having trouble displaying the contents of a $.getJSON call. I have this code which retrieves some JSON data from a page.
var loadItems = function() {
if (hasNextPage === false) {
return false
}
pageNum = pageNum + 1;
var url = baseUrl + "json/" + pageNum + '/';
var jqxhr = $.getJSON(url, function (data) {
var a = [];
$.each(data.itemList, function (item) {
a.push("<li>" + item.title + "</li>");
});
$("<ul/>", {html: a.join(" ")}).appendTo("#anchor");
});
jqxhr.complete(function () { alert('done!'); $(window).bind('scroll', loadOnScroll); });
};
The idea is just to load a page dynamically based on scroll position, and get the JSON contents of that page (for an infinite scroll effect). The JSON structure is something like this:
{ "key1": val1, "key2": val2, "itemList": [ {"title": "title", "author": "author", "id": 100, "slug": slug, }, ... ] }
The important values are in itemList, where I have to retrieve data that will get plugged into my django template, which in turn will get some data from the view. Everything seems to work just fine, except that I can't access the data in itemList. Nothing seems to get pushed into the array. because nothing gets displayed on the page (namely, the <li> that should be created). This seems to be a simple implementation of a basic ajax move, but its not working.
EDIT:
I've done some bug tracking and have found that the code never executes the $.each loop. Not sure how to resolve this though.
you should be using error log to check what is going wrong:and always use index,obj format in $.each to be safe.
$.getJSON(url).success( function( data ) {
console.log(data);
$.each(data.itemList, function (index, item) {
a.push("<li>" + item.title + "</li>");
});
$("<ul/>", {html: a.join(" ")}).appendTo("#anchor");
}).error(function(error){
console.log(error);// see if you are getting in error log..
});
and your json data is also wrong it should be something like this:
{ "key1": "val1",
"key2": "val2",
"itemList":
[
{
"title": "title", "author": "author", "id": 100, "slug": "slug"
},.......
]
}
try with corrected data it will work.
you can check your data here:http://json.parser.online.fr/
I saw the problems in your code when you using
$.each() //It should using for dictionary.
So I have two solutions for you
1) You can use forEach method.
ex:
`if(data != null && data.itemList.length > 0)
{
data.itemList.forEach(function (item) {
a.push("<li>" + item.title + "</li>");
});
}`
==> This way will work for IE 10+, and the other browers.
2) Using the $.each method
ex:
if(data != null && data.itemList.length > 0)
{
$.each(data.itemList, function (key, item) {
a.push("<li>" + item.title + "</li>");
});
}
==> Your Json data is dictionary type, so if you use $.each you need to define two variable with
key: is the key of data.
item: is the value of data.
Note: this way will be worked for all browers version.
Hope this can helps you.
It's because your 'item' is an index, not an 'object' as you want. you have to use the second parameter:
$.each(data.itemList, function (index, item) {
a.push("<li>" + item.title + "</li>");
});
also, where is hasNextPage defined? is it defined? you might also shorten that to:
if (!hasNextPage) return;
Related
I have a JSON document of variable depth. An example:
[
{
"type": "firsttype",
"text": {
"id": "content"
}
}
]
What I am trying to do is to retrieve the values of certain keys, say text. Since I do not know where these keys might appear in the .JSON, I need to use a recursive function. I then try to display these keys and values in a HTML file.
I have a preliminary attempt here:
$.getJSON("file.json", function getText (oValue, sKey) {
links = [];
if (typeof oValue == "object" || typeof oValue == "array") {
for (i in oValue) {
getText (oValue [i], i);
}
} else {
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
}
$( "<ul/>", {
"class": "my-new-list",
html: links.join( "" )
}).appendTo( "body" );
});
When I load the page locally or remotely or on python -m SimpleHTTPServer, I get no errors and nothing on the page. What am I doing wrong? I have included all the JS in the $.getJSON call so no async issues arise.
In the future I would also like to include a regexp check so I can extract values with a certain string, e.g. /http/. What would be the best way to do this?
As the other answers cover most of the things that you should consider, I think I'll just post a solution for your actual problem. :)
You want to traverse an arbitrary JSON and search for a specific key, and may have a condition on its value. Then you want to return all values for your specified key (that pass your condition if specified).
Consider you have the following json:
{
"hello": "some text",
"object": {
"key1": "hello!",
"key2": "Bye!"
},
"array": [{
"some_key1": "blah blah blah",
"some_key2": 24
}, {
"some_key1": "ghiojd",
"some_key2": 13
}],
"numeric_array": [2, 3, 4, 5]
}
This snippet will search the above json for some_key1 that its value starts with blah:
function regexpConditionFactory(regex) {
return function(value) { return regex.test(value); };
}
function searchObjectForKey(obj, key, condition, result) {
if ($.isPlainObject(obj)) {
if (obj.hasOwnProperty(key)) {
if (!condition || ($.isFunction(condition) && condition(obj[key])))
result.push(obj[key]);
}
}
if ($.isPlainObject(obj) || $.isArray(obj)) {
for (var k in obj) {
if (obj.hasOwnProperty(k))
searchObjectForKey(obj[k], key, condition, result);
}
}
}
$.getJSON('file.json', function(data) {
var res = [];
searchObjectForKey(data, 'some_key1', regexpConditionFactory(/^blah/), res);
$('<ul/>', {
'class': 'my-new-list',
'html': res.map(function(value) { return '<li>' + value + '</li>'; }).join('')
}).appendTo('body');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I think your error is in the declaration of variable links :
it must be outside the recursive function i think.
inside the function it will be reinitialized every time.
var links = [];
$.getJSON("file.json", function getText (oValue, sKey) {
if (typeof oValue == "object" || typeof oValue == "array") {
for (i in oValue) {
getText (oValue [i], i);
}
} else {
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
}
$( "<ul/>", {
"class": "my-new-list",
html: links.join( "" )
}).appendTo( "body" );
});
Try moving your function definition outside of the event handler:
function getText (links, oValue, sKey) {
if (typeof oValue == "object" || typeof oValue == "array") {
for (i in oValue) {
getText (links, oValue [i], i);
}
} else {
if(oValue && sKey)
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
}
$( "<ul/>", {
"class": "my-new-list",
html: links.join( "" )
}).appendTo( "body" );
};
$.getJSON("file.json", function(data, success){
var links = [];
getText (links, data, 0);
});
Feel free to edit this if there are errors.
The aim is to pass the links array in to the recursive function, and to avoid mixing the named function definition with the getJSON, for clarity at least, and to ensure you can pass an initialized sKey.
You can, but in your case you probably shouldn't
You can pass a named function as a callback function — which is useful for recursion (See: Using Named Callback Functions In Javascript Methods, Ben Nadel) — but in your case, you probably shouldn't.
Based on your example, there are some things you will want to do before and after you invoke a recursive function. These things, such as declaring variables and appending elements to the body, will need to happen [once] outside of recursion.
So, pass an anonymous function as your callback that contains your recursive function definition and invokes it as needed.
In your case, you'll want to invoke it for each object returned in the JSON response array. So, you can put it inside of an iterator as well. Here I used jQuery's $.each() for convenience.
/* FUNCTION THAT MAKES JSON REQUEST */
function doJsonThing() {
/* BEGIN REWRITE OF OP's EXAMPLE CODE */
$.getJSON('file.json', function (json) {
var links = [];
function getText (key, val) {
if (typeof val === 'object' || typeof val === 'array') {
for (i in val) {
getText(i, val[i]);
}
} else {
links.push('<li id="' + val + '">' + key + ' (' + val + ')</li>' );
}
}
$.each(json, function (key, val) {
getText(key, val);
});
$('<ul/>', {
"class": "my-new-list",
"html" : links.join('')
}).appendTo('body');
});
/* END REWRITE OF EXAMPLE CODE */
}
/* THE FOLLOWING IS NOT PART OF THE EXAMPLE,
// IT IS JUST USED TO SIMULATE A SERVER RESPONSE */
/* BEGIN UNIT TEST */
// CREATE CLOSURE TO RETURN DUMMY FUNCTION AND FAKE RESPONSE
function json_response(response) {
return function (url, success) {
success(response);
};
}
// OVERRIDE $.getJSON WITH DUMMY FUNCTION AND FAKE RESPONSE
$.getJSON = json_response(
// SIMULATED CONTENTS OF 'file.json'
$.parseJSON(
'['
+ ' {'
+ ' "type": "firsttype",'
+ ' "text": {'
+ ' "id": "content"'
+ ' }'
+ ' },'
+ ' {'
+ ' "type": "secondtype",'
+ ' "text": {'
+ ' "id": "other"'
+ ' }'
+ ' }'
+ ']'
)
);
doJsonThing();
/* END UNIT TEST */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I keep getting [object, Object] from array for $.each when i try and alert it.
Below is the code I am using, I have tried several different ways but this seems to be the way that works the best.
Could someone please help me out
var min_chats = [];
$(function () {
$(".append_chat").click(function () {
var chatid = $(this).attr('alt');
var data = $(this).attr('data');
min_chats.push({
"chatid": chatid,
"data": data
});
});
$("#max_close").live("click", function () {
var chatid = $(this).attr('alt');
var data = $(this).attr('data');
$.each(min_chats, function (key, val) {
alert(key + val);
});
});
});
The callback parameters for $.each are index and value, not key and value.
In your case key will contain the index of the array and val will contain your object containing 2 properties: chatid and data.
So your code should look like:
$.each(min_chats, function(index, val) {
alert(val.chatid + val.data);
});
$.each documentation: http://api.jquery.com/jquery.each/
I am trying to build a simple page to view messages saved in a mysql db via JSON and jQuery.
My JSON IS
{"unread_msgs":[{"id":"6","title":"33333","user1":"19","timestamp":"1383747146","client_id":"Generic"},{"id":"5","title":"42142","user1":"19","timestamp":"1383740864","client_id":"Generic"}],"read_msgs":[{"id":"4","title":"test to addnrow","user1":"19","timestamp":"1383676647","client_id":"Generic"},{"id":"2","title":"kll","user1":"19","timestamp":"1383675548","client_id":"Generic"},{"id":"1","title":"jkjljklj","user1":"19","timestamp":"1382539982","client_id":"Generic"}],"urm_t":2,"rm_t":3}
My JS
<script type="text/javascript">
function GetClientMsgs () {
$.post("assets/server/client_msgs.php",{ client_id:local_client_id } ,function(data)
{
var MsgData = $.parseJSON(data);
console.log("Msg json data parsed");
$.each(MsgData, function(key, value)
{
console.log(value);
$('#unread_row').append('<td>'+value.unread_msgs.title+'</td><td>'+value.unread_msgs.studioname+'</td><td>'+value.unread_msgs.timestamp+'</td><td>X</td>');
$('#read_row').append('<td>'+value.read_msgs.title+'</td><td>'+value.read_msgs.studioname+'</td><td>'+value.read_msgs.timestamp+'</td><td>X</td>');
});
});
}
</script>
PHP
$msgs = array('unread_msgs' => $dn1s, 'read_msgs' => $dn2s, 'urm_t' => $unread_msgs, 'rm_t' => $read_msgs);
$json = json_encode($msgs);
I am trying to post values returned such as unread_msgs.title or .id and am not able to access any of the objects. I have searched on here and could not find something specific to my structure. Thanks alot.
I would loop over the unread and read results separately, like this:
$.each(MsgData.unread_msgs, function(key, value)
{
// code append to unread row
console.log(value.id, value.title, "etc");
});
$.each(MsgData.read_msgs, function(key, value)
{
// append to append to read row
console.log(value.id, value.title, "etc");
});
Pasting your json into a formatter such as http://jsonformatter.curiousconcept.com/ can help you to see its structure.
In this row:
$('#unread_row').append('<td>'+value.unread_msgs.title+'</td><td>'+value.unread_msgs.studioname+'</td><td>'+value.unread_msgs.timestamp+'</td><td>X</td>');
You are accessing the value variable as an object, while it is in fact an array.
To access the first unread message id within your $.each loop, you would do: value[0].id.
If you are trying to get a list of unread and read messages, try to loop over them.
$.each(MsgData.unread_msgs, function(index, message) {
$('#unread_row').append('<td>' + message.id + '</td><td>.......');
});
$.each(MsgData.read_msgs, function(index, message) {
$('#read_row').append('<td>' + message.id + '</td><td>.......');
});
Or with a nested loop:
$.each(MsgData, function(key, value) {
$.each(value, function(index, message) {
$('#' + key).append('<td>' + message.id + '</td><td>....);
});
]);
I'm really sorry to be posting all day. I'm a total newbie with this coding. Basically, with the help of a lot of amazing people here, I'm setting up a JSON thingy for the first time. I'm trying to evaluate a list against an input. Here's sample data:
{
"
films": [{
"label": "34",
"value": "34",
"currently_streaming": "1",
"full_streaming_url": "http://www.url.com",
"url": "http://www.url.com"},
{
"label": "A Different Color",
"value": "A Different Color",
"currently_streaming": "1",
"full_streaming_url": "http://www.url.php",
"url": "http://www.url.com"}]
}
and here's my code. I finally got it, (thank you everyone!) to select the value portion that I wanted. I then tried to compare it in an if/else statement, and it's doing weird things. First, it seems to be pulling more values than actually exist on the file, but I'm not completely sure about that. Secondly, however, it seems to be not comparing values, but setting one the value I'm iterating through equal to another value! I don't understand!
var test = "34x25x36";
$(document).ready(function () {
$.ajax({
dataType: 'json',
beforeSend: function () {
console.log('Before Ajax Request Starts !!');
},
success: function (data) {
console.log(data);
alert("Edddddddd");
$.each(data.films, function (i, object) {
$.each(object, function (property, value) {
//alert(property + "=" + value);
for (i = 0; i < data.films.length; i++) {
var theFilm = (data.films[i].value);
if (theFilm == test) {
document.write(theFilm);
document.write(test + "<br>");
} else {}
}
});
});
},
error: function (jqXHR, textStatus, errorThrown) {
alert("Error occurred: " + errorThrown);
},
beforeSend: function () {
console.log('Ajax Request Complete !!');
},
url: 'test.php'
});
});
EDIT
When I do have something in the else{ } section, it seems to run the whole thing multiple times, judging correctly when doesn't match, but then it seems to run again, running the text for the one match and then a bunch of "not match" text. When there is nothing in the else{} section, it seems to set the value of theFilm = test . Help!
your success function is messed up.. Look's like you are getting confused by using many loops..
Also do not write it to a document.. Use console.log or alert to debug..
Try this approach
success: function(data) {
console.log(data);
alert("Edddddddd");
var keys = ["label", "value", "currently_streaming", "full_streaming_url", "url"]
for (i = 0; i < data.films.length; i++) {
for (j = 0; j < keys.length; j++) {
// alert('Key - ' + keys[j] + ' :: Value - ' + data.films[i][keys[j]]);
var theFilm = data.films[i][keys[j]];
if (theFilm == test) {
alert('TheFilm Variable is : ' + theFilm);
alert('Test Variable is : ' + test );
}
else {
alert('No Match Found !!');
}
}
}
}
You are looping through all films, and then inside that you are looping through all properties of each film. Then inside that you are looping through all films again. That's a lot of looping for no reason. If you have for example 100 films with 5 properties in each, you will be looping through all the films 500 times, thus writing out the film that you find 500 times.
You only need one loop to loop through the films and find one:
$.each(data.films, function(i, object) {
var theFilm = object.value;
if (theFilm == test) {
document.write(theFilm);
}
});
Demo: http://jsfiddle.net/baJtf/
You can also use the grep method to find items in an array:
var film = $.grep(data.films, function(f){
return f.value == test;
});
if (film.length == 1) {
document.write(film[0].value);
}
Demo: http://jsfiddle.net/baJtf/1/
Hey I'm trying to return a message when there are no results for the users current query! i know i need to tap into the keyup event, but it looks like the plugin is using it
This question is really out of date, anyways I'm working with the new jQuery UI 1.8.16, autocomplete is now pretty different:http://jqueryui.com/demos/autocomplete/#default
Anyways if you're trying to the do the same thing as the question asks, there is no more parse function, as far as I know there is no function that is called with the search results.
The way I managed to pull this off is by overriding the autocomplete's filter function - Note: this will affect all your autocompletes
$.ui.autocomplete.filter = function(array, term) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
var aryMatches = $.grep( array, function(value) {
return matcher.test(value.label || value.value || value);
});
if (aryMatches.length == 0){
aryMatches.push({
label: '<span class="info" style="font-style: italic;">no match found</span>',
value: null
});
}
return aryMatches;
};
The function is slightly modified from the source, the grep call is the same, but if there are no results I add an object with a value of null, then I override the select calls to check for a null value.
This gives you an effect where if you keep typing and no matches are found you get the 'no matches found' item in the dropdown, which is pretty cool.
To override the select calls see jQuery UI Autocomplete disable Select & Close events
$(this).data('autocomplete').menu.options.selected = function(oEvent, ui){
if ($(ui.item).data('item.autocomplete').value != null){
//your code here - remember to call close on your autocomplete after
}
};
Since I use this on all my autocompletes on a page, make sure you check if value is null first! Before you try to reference keys that aren't there.
You could try supplying a parse option (function to handle data parsing) and do what you need when no results are returned to parse.
This example assumes you're getting back an array of JSON objects that contain FullName and Address attributes.
$('#search').autocomplete( {
dataType: "json",
parse: function(data) {
var array = new Array();
if (!data || data.length == 0) {
// handle no data case specially
}
else {
for (var i = 0; i < data.length; ++i) {
var datum = data[i];
array[array.length] = {
data: datum,
value: data.FullName + ' ' + data.Address,
result: data.DisplayName
};
}
}
return array;
}
});
I'm using the following code for the same purpose (the message is shown in the autocomplete list):
success: function(data, status, xhr){
if(!data.length){
var result = [
{
label: 'There are no matches for your query: ' + response.term,
value: response.term
}
];
response(result);
}
else{
// normal response
}
}
You can also utilize the "response" event to examine this. Simple but powerful. http://api.jqueryui.com/autocomplete/#event-response
response: function (event, ui) {
if (ui.content.length == 0) {
//Display an alert or something similar since there are no results
}
},