Why is my loop of JSON setting values? - javascript

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/

Related

JQuery / JS - change: function issues with single characters

My Autocomplete with Ajax works extremely well providing everything I need for the most part, however a small issue arises when intended input is just a single character.
I have implemented this for several other text fields the same way without issues, however this is the only section that has potential one character input.
In case anyone wonders the Stored procedure from the url is rock solid, just having issues with my Javascript and how to handle/compare the data.
This is being used in a .net 5 web application but should not matter in this context.
The hardcoded if statement is my current work around, when I remove it I get the standard
TypeError: Cannot read properties of undefined (reading 'toLowerCase')
Looking at the console it seems to print only the last window.item (cList) from the list rather than a full list, perhaps I need to store the whole list and loop it? I tried to raise min value from 1 to 2 for the Autocomplete to avoid double character items but it doesn't help.
It only sees the input "1" on one of the four console logs below when it should realistically show for all four.
undefined Hardcoded match
1 Hardcoded match
Code1 match
Code1 match
$("#hahSearch").autocomplete({
source: function (request, response) {
$.ajax({
url: '/stationData/searchHACode',
headers: {
"RequestVerificationToken":
$('input[name="__RequestVerificationToken"]').val()
},
data: { "term2": request.term },
dataType: "json",
success: function (data) {
response($.map(data, function (item) {
window.list = item;
return item;
}))
},
error: function (xhr, textStatus, error) {
alert(xhr.statusText);
},
failure: function (response) {
alert("failure " + response.responseText);
}
});
},
change: function (event, ui) {
var cList = window.list;
//var cListLength = cList.length;
var input = $("#hahSearch").val()
if (input == 1 || input == 2 || input == 3 || input == 5 || input == 9 ) {
console.log(cList + " Hardcoded match");
console.log(input + " Hardcoded match");
$(this).css('background-color', '#b8f4b8');
cList = "";
input = "";
}
if (input.toLowerCase() == cList.toLowerCase() || ui.item) {
console.log(cList + " Code1 match");
console.log(input + " Code1 match");
$(this).css('background-color', '#b8f4b8');
cList = "";
input = "";
}
else if (input.toLowerCase() != cList.toLowerCase() && !ui.item) {
console.log(cList + " Code1 no match");
console.log(input + " Code1 no match");
$(this).css('background-color', '#ff6347');
$(this).val('');
cList = "";
input = "";
}
},
minLength: 2
});

jQuery sends NaN instead of integer in Ajax request

I develop small backend service/application with Spring Boot and some jQuery/AJAX.
Recently while testing admin functionality I faced strange issue related with the code provided below:
function updateUserRow(id) {
$.get(ajaxUrl + id, function (data) {
$('.userPlaceBtns').empty();
$('.userArticleBtns').empty();
$.each(data, function (key, value) {
form.find("textarea[name='" + key + "']").val(value);
form.find("input[name='" + key + "']").val(value);
form.find('input:checkbox').prop(value ? 'checked' : '');
if(key == 'placeIds' && value.length != 0){
for(i = 0; i < value.length; i++) {
$('<button/>', {
text: value[i],
id: 'btn_place_'+i,
click: function () {
inspectOwnedPlace(value[i]);
}
}).appendTo('.userPlaceBtns');
}
}
if(key == 'articleIds' && value.length != 0){
for(i = 0; i < value.length; i++) {
$('<button/>', {
text: value[i],
id: 'btn_article_'+i,
click: function () {
inspectOwnedArticle(value[i]);
}
}).appendTo('.userArticleBtns');
}
}
});
$('.load-bar').hide();
$('#userEditRow').modal();
});
}
So, besides modal forms data filling, this function helps me to iterate through user-related data and place a button on prepared divs for each of this data.
Strange things happen when I try to inspect user-related places or articles with $.get from server:
function inspectOwnedPlace(id){
console.log(id);
var intId = parseInt(id);
console.log(placesAjaxUrl + intId);
$.get(placesAjaxUrl + intId, function (data) {
var placeForm = $(".ownedPlaceForm");
$.each(data, function (key, value) {
placeForm.find("textarea[name='" + key + "']").val(value);
placeForm.find("input[name='" + key + "']").val(value);
});
$('#inspectOwnedPlaceModal').modal();
});
}
The Issue
For some reason, in 50-70% of cases I get NumberFormatException on server side because of NaN incoming with server request. But in SOME cases it definitely works as expected!
Important thing is: the text on generated buttons ALWAYS appears as expected, so I can make conclusion that server always gives relevant,
non-spoiled data to the front and something in JS code leads to frequent NaN exceptions when I try to request user-relevant data by id as the next step.
Here is a screenshot of the case when I face this issue (browser tab with dev console) for better understanding:
So, here I get server's NumberFormatException because of NaN instead of integer.
What I tried:
treat ids as they are by default not usig parseInt() function;
treat ids as strings and parse them as text.
I just wonder what can lead to non-predictable, non-systemic NaNs, which are more likely "spoiled integers", in the context of my current code. Thanks in advance!

Trouble getting getJSON to display values from array

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;

Parse query (callback) in for loop

New to javascript here, so callbacks are still a little iffy in my brain.
What I'm trying to do is: given a "menu" which is an array of objectId's, query for each foodItem that corresponds to that objectId, get its votes, put it in a min-heap (to determine which are the top 5 items), and return those top 5 items.
My heap at the end is empty because I realize that JavaScript is asynchronous and that when I try to get the heap data, the callback might not have necessarily completed.
If it were just one call, I would just nest the callbacks, but since this is a loop I'm not really sure what to do.
function getTopFoods(menu, heap, callback) {
//go through each objectId, get its foodItem and then its votes, then heap it
console.log("got to TopFoods");
for (var i = 0; i < menu.length; i++) {
var foodID = menu[i];
var FoodItem = Parse.Object.extend("FoodItem");
var foodQuery = new Parse.Query(FoodItem);
foodQuery.equalTo("objectId", foodID);
//get corresponding foodItem
foodQuery.find({
success: function(foodResult) {
//got specific food Item
var votes = foodResult.get("votes");
console.log("votes: " + votes);
if (heap.length < 5) {
heap.queue(foodResult);
} else {
if (votes > heap.peek().get("votes")) {
heap.dequeue();
heap.queue(foodResult);
}
}
},
error: function(error) {
console.log("Food error: " + error.code + " " + error.message);
}
});
}
var topFoods = [];
for (var i = 0; i < 5; i++) {
topFoods[i] = heap.dequeue();
}
callback(topFoods);
}
The easiest way is to use promises; at this stage, this involves using a library (coming to JavaScript proper in ES6). If you want a low-tech solution, just count stuff:
var waitingCount = menu.length;
for (....) {
...
success: function(foodResult) {
...
if (!--waitingCount) {
callback(topFive(heap));
}
},
error: function(error) {
--waitingCount;
...
}
...
}
This is just the basic idea. It would be good if you also decremented the counter on failed responses, since this way a single fail will leave you hanging.
EDIT: Err, obviously, the check needs to go to the bottom of success, not to the top as my snippet indicated before, or you'll miss the last element. I also put in the error case.
EDIT2: As eth3lbert notes, parse.com API also supports promises (I don't work with parse.com, so... thanks for the tip). In that case, here's what you do:
var promises = [];
for (....) {
var promise = foodQuery.find({
...
});
promises.push(promise);
});
Parse.Promise.when(promises).then(function()) {
callback(topFive(heap));
}

Handling no results in jquery autocomplete

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
}
},

Categories

Resources