I get stacked on a looping issue and couldn't get it.
for (var i = 0; i < count; i++) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[i]
}, function (response) {
for (var x = 0; x < count; x++) {
$("#divfather" + x).html(response[0].name);
}
});
}
The second loop is done through response[0].name which is the name of Facebook and showing me the same response for all divs.
I want only this second loop being done to the i variable.
How can I do it?
It's a little hard to understand what you want, but I assume you only want the i from the outer for loop.
You'll need to create a new variable scope in order to retain it.
for (var i = 0; i < count; i++) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[i]
}, (function( j ) { // <---- create a function...
// v---------...that returns a function...
return function (response) {
$("#divfather" + j ).html(response[0].name);
};
})( i ) // <------...and invoke it immediately, passing "i"
);
}
Here's the same thing, but using a named function, which I think is a little nicer.
function get_callback( j ) {
return function (response) {
$("#divfather" + j ).html(response[0].name);
};
}
for (var i = 0; i < count; i++) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[i]
}, get_callback( i ) );
}
Or personally, I'd place all the logic in the function instead of splitting it up.
function set_up_FB_api( j ) {
FB.api({
method: 'fql.query',
query: 'SELECT name FROM user WHERE uid=' + temparray[ j ]
}, function (response) {
$("#divfather" + j ).html(response[0].name);
});
}
for (var i = 0; i < count; i++) {
set_up_FB_api( i );
}
You have a scope issue sken boy.
You are using i in the outer loop and then redeclaring it in the inner loop.
Change the second loop to some other letter like x.
Related
I have one callback function
function QueryKeyword(keyword, site, callback) {
var querykeyword = keyword;
var website = site;
$.ajax({
url: "http://www.test.com",
jsonp: "jsonp",
dataType: "jsonp",
data: {
Query: querykeyword
},
success: callback
});
}
I am calling this function with in for loop like this :
for (i = 0; i < questionTerm.length; i++) {
for (j = 0; j < site.length; j++) {
var searchTerm = questionTerm[i] + ' ' + $('#search').val();
QueryKeyword(searchTerm, site[j], function(reslt) {
// I need to get j variable value here
console.log(j);
});
}
}
Now I need to get "j" variable value in function see I console the j variable value but it does not get the j variable value.
Would you please let me know how I can fetch the value in this.
Thanks in advance
The problem is, that at the moment of your callback, j was reassigned multiple times to something different.
There are a few options you could do.
call your callback with the params you need
function QueryKeyword(keyword, site, index, callback) {
// ...
$.ajax(
success: function(result) {
// call the callback with a second param (the index j)
callback(result, index);
}
)
}
QueryKeyword(searchTerm, site[j], j, function(reslt, param) {
// param is j
console.log(result, param);
});
save the var in a closure
(function() {
var value = j;
...
})();
use forEach
questionTerm.forEach((term, i) => {
site.forEach((s, j) => {
// we are in a closure,
// j will be correct here.
QueryKeyword(term, s, function(reslt) {
// j is still correct here
console.log(j);
});
})
});
if you use es6, you could use let keyword. Here is some good explanation, how it works when using for loops
for(let i = 0; i < 10; i++) {
console.log(i);
setTimeout(function() {
console.log('The number is ' + i);
},1000);
}
You have to pass it in separately:
definition
function QueryKeyword(keyword, site, index, callback)
{
...
}
execution
QueryKeyword(searchTerm, site[j], j, function(reslt) {
// I need to get j variable value here
console.log(j);
});
I'm using React as a front-end library for my rails project, I have been through an issue which is showing the errors for the user, I'm using Ajax to send request but I found my self duplicating error call back function if the server-side returns errors in every request inside every React.Component something like:
$.ajax({
url: URL,
type: METHOD,
data: {
//data
},
success: function () {
//calling some function
}.bind(this),
error(error) {
// begin
server_errors = JSON.parse(error.responseText);
array_of_keys_of_errors = Object.keys(server_errors);
for( i = 0 ; i < array_of_keys_of_errors.length; i++){
nested_keys = Object.keys(server_errors[array_of_keys_of_errors[i]]);
for( j = 0 ; j < nested_keys.length; j++){
array_of_errors = server_errors[array_of_keys_of_errors[i]][nested_keys[j]];
for( k = 0 ; k < array_of_errors.length; k++){
bootbox.alert({
message: nested_keys[j] + ' ' + array_of_errors[k],
closeButton: false,
});
}
}
}
// end
},
});
Is there an efficient way to keep my code away from redundancy, I was thinking about a shared file contains shared functions and include it inside each React.Component but I didn't find something similar to this.
You could create a function to handle your errors:
function handleErrors(errors) {
const server_errors = JSON.parse(error.responseText);
const array_of_keys_of_errors = Object.keys(server_errors);
for( i = 0 ; i < array_of_keys_of_errors.length; i++){
nested_keys = Object.keys(server_errors[array_of_keys_of_errors[i]]);
for( j = 0 ; j < nested_keys.length; j++){
array_of_errors = server_errors[array_of_keys_of_errors[i]][nested_keys[j]];
for( k = 0 ; k < array_of_errors.length; k++){
bootbox.alert({
message: nested_keys[j] + ' ' + array_of_errors[k],
closeButton: false,
});
}
}
}
}
And share that function across your files.
You would use it like this:
$.ajax({
url: URL,
type: METHOD,
data: {
//data
},
success: function () {
//calling some function
}.bind(this),
handleErrors
})
I'm trying to run a check against two arrays (one has 4 objects, one just have a few strings) with for loops and if statement for a problem set.
The idea is to use for loop to iterate over every element in the object array and the string array, then use if statement to figure out matches and shove the matching string into a new array. Once all the elements are iterated, it returns the string if there is a matching one.
The problem is the function calls it a day once a single match in the object array is found and returns that only that instead of iterating over the rest of the elements in the object array.
var passengers = [
{ name: ["Michael Jackson"], paid: true },
{ name: ["Osama"], paid: false },
{ name: ["Harambe"], paid: true },
{ name: ["Pepe"], paid: true },
];
var noFlyList = ["Jimmy", "John", "Pepe", "Osama"];
function checkNoFly(passengers, noFlyList) {
for (var i = 0; i < passengers.length; i++) {
for (var j = 0; j < noFlyList.length; j++) {
if (passengers[i].name[0] == noFlyList[j]) {
var passengerList = [];
passengerList.push(passengers[i].name[0]);
return passengerList;
}
}
}
return true;
}
function checkNotPaid(passengers) {
return (!passengers.paid);
}
function processPassenger(passengers, testFunction) {
for (var i = 0; i < passengers.length; i++) {
if (testFunction(passengers[i])) {
return false;
}
}
return true;
}
var allCanFly = processPassenger(passengers, checkNoFly);
if (!allCanFly) {
console.log("We cannot fly because " + checkNoFly(passengers, noFlyList) + " is on the no-fly list");
}
var allPaid = processPassenger(passengers, checkNotPaid);
if (!allPaid) {
console.log("we cannot fly because not all passengers have paid");
}
use this: having passengerList in the loop make its reinitialized to empty array on each loop, and returning passengerList in the loop makes the loop break once it finishes the first loop
function checkNoFly(passengers, noFlyList) {
var passengerList = [];
for (var i = 0; i < passengers.length; i++) {
for (var j = 0; j < noFlyList.length; j++) {
if (passengers[i].name[0] == noFlyList[j]) {
passengerList.push(passengers[i].name[0]);
}
}
}
return passengerList;
}
EDIT:
change your original processPassenger function to the one below, originally you have only 1 argument passed to your checkNoFly function, where you'd defined it to take 2 arguments, so the false is returned for wrong number of argument, which stop you from getting it the way you want.
function processPassenger(passengers, testFunction) {
if (testFunction(passengers, noFlyList).length !=0) {
return false;
}
return true;
}
EDIT 2: for your updated question, since for the first check we are returning an array for the single function processPassenger() for validation, we can take similar approach for the checkNotPaid function to return an array for those who have not paid.
function checkNotPaid(passengers) {
var passengerNotPaid = [];
for (var i = 0; i < passengers.length; i++) {
if (!passengers[i].paid) {
passengerNotPaid.push(passengers[i].name[0]);
}
}
return passengerNotPaid;
}
unless you'd want to refactor everything, i think this would be ok.
You're telling it to do so: return passengerList; in your inner loop. Also, you keep re-declaring the variable var passengerList = []; inside your inner for-loop, emptying it every time.
var passengers = [
{ name: ["Michael Jackson"], paid: true },
{ name: ["Osama"], paid: false },
{ name: ["Harambe"], paid: true },
{ name: ["Pepe"], paid: true },
];
var noFlyList = ["Jimmy", "John", "Pepe", "Osama"];
function checkNoFly(passengers, noFlyList) {
var passengerList = [];
for (var i = 0; i < passengers.length; i++) {
for (var j = 0; j < noFlyList.length; j++) {
if (passengers[i].name[0] == noFlyList[j]) {
passengerList.push(passengers[i].name[0]);
}
}
}
return passengerList;
}
function checkNoPay(passengers) {
var nonPayers = [];
for (var i = 0; i < passengers.length; i++) {
if (!passengers[i].paid) { nonPayers.push(passengers[i].name); }
}
return nonPayers;
}
var banList = checkNoFly(passengers, noFlyList);
if (banList.length) {
console.log("We cannot fly because " + banList + " is/are on the no-fly list");
}
var unpaidList = checkNoPay(passengers);
if (unpaidList.length) {
console.log("We cannot fly because " + unpaidList + " has/have not payed the flight");
}
var canWeFly = !(banList.length || unpaidList.length);
console.log(canWeFly ? "We can fly" : "We cannot fly");
I am trying to dynamically populate the jquery chosen plugin both with "optgroup" and "option". I therefore have nested ajax requests and forloops:
$.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: metada },
success: function (data) {
var categories = data.split(",");
for (i = 0; i < categories.length; i++) {
$.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: cetada },
success: function (data) {
$("#picker").append("<optgroup label='" + categories[i] + "'>");
var subcategories = data.split(",");
for (i = 0; i < subcategories.length; i++) {
$("#picker").append("<option value='"+subcategories[i]+"'>" + subcategories[i] + "</option>")
}
$("#picker").append("</optgroup>");
}
});
}
$("#picker").trigger('chosen:updated');
}
});
Currently when I run the above the chosen select is empty and no options or optgroups are visible.
I think you need to use promises for this:
var promises = [];
for (var i = 0; i < categories.length; i++) {
promises.push(
(function(innerI){
return $.ajax({
url: '#Html.Raw(Url.Action("GetCat", "MController"))',
data: { ID: cetada },
success: function (data) {
var optgroup = $('<optgroup>').attr('label', categories[innerI]);
var subcategories = data.split(",");
for (var i = 0; i < subcategories.length; i++) {
var option = $('<option>').val(subcategories[i]).text(subcategories[i]);
optgroup.append(option);
}
$("#picker").append(optgroup);
}
});
})(i)); // unbind i to make closure work.
}
$.when.apply($, promises).then(function() {
$("#picker").trigger('chosen:updated');
});
UPDATE1:
I missed closures on first look, now th code is updated.
UPDATE2:
Rewrote working with tags inside success callback of ajax request.
UPDATE3:
Here is simple demo, I've commented some non-important code to show how it works.
I want to create a loop for input so that the variable img get number 1 to 5 like this:
img1, img2 ... img5.
How to write $i after img?
for ($i=1;$i<=5;$i++) {
function(data) { $('input[name="img1"]').val(data) });
}
Note: img is between two quotation mark.
it's edite:
user = $('input[name="name"]').val();
for (var i = 1; i <= 5; i++) {
$.post("test.php", { name: user, num: i },
function(data) {
$('input[name="img'+i+'"]').val(data)
});
}
The function you have declared in your loop seems weird. That's not valid javascript. You may try the following:
for (var i = 1; i <= 5; i++) {
$('input[name="img' + i + '"]').val(data);
}
or if we suppose that you have defined some function:
var foo = function(data, index) {
$('input[name="img' + index + '"]').val(data);
}
you could invoke it like this:
for (var i = 1; i <= 5; i++) {
foo('some data ' + i, i);
}
UPDATE:
An interesting example was provided in the comments section:
for (var i = 1; i <= 5; i++) {
$.post(
"test.php",
{ name: username, num: i },
function(data) {
$('input[name="img'+i+'"]').val(data);
}
);
}
This won't work because the i variable might have changed value between the loop and the AJAX success callback. To fix this you may try the following:
for (var i = 1; i <= 5; i++) {
(function(index) {
$.post(
"test.php",
{ name: username, num: index },
function(data) {
$('input[name="img'+index+'"]').val(data);
}
);
})(i);
}
or use the $.ajax() method which allows you to pass a context to the success callback:
for (var i = 1; i <= 5; i++) {
$.ajax({
url: 'test.php',
type: 'POST',
data: { name: username, num: i },
context: i, // here we are defining the context
success: function(result) {
// since we have used the context parameter, this variable
// here will point to the value that i had when we initiated
// the AJAX request
$('input[name="img' + this + '"]').val(result);
}
});
}
Like this:
for ($i=1;$i<=5;$i++) {
function(data) { $('input[name="img' + $i + '"]').val(data) });
}
By the way, I'm guessing you'e coming from a PHP background, but in JavaScript it is not conventional to use $ for variable names (except sometimes for jQuery objects). So normally you'd write your code like this:
for (i=1;i<=5;i++) {
function(data) { $('input[name="img' + i + '"]').val(data) });
}