In the following function, how can I include an else statement once the for statement is no longer true?
<script>
$(function () {
$(".current").text("1");
$("#NextPage").click(function () {
var a = parseInt($(".current").text());
var b = parseInt($(".total").text());
if (a <= b){
for (var i = 0; i <= b; i++) {
$(".current").text(i);
}
}
});
});
</script>
The else keyword isn't paired with for, only with if. If you want to execute code once the loop is done, simply put code below the for loop's body, and that code will execute when the loop finished. Loops finish when their conditions are false.
for (var i = 0; i <= b; i++) {
// for loop body code
}
// put code here to execute immediately after the loop finishes
Maybe like this?
<script>
$(function () {
$(".current").text("1");
$("#NextPage").click(function () {
var a = parseInt($(".current").text());
var b = parseInt($(".total").text());
if (a <= b){
for (var i = 0; i <= b; i++) {
$(".current").text(i);
if (a >= b){
break;
}
}
}
});
});
</script>
Related
I have the following script that opens urls in a list:
function openWindow(){
var x = document.getElementById('a').value.split('\n');
for (var i = 0; i < x.length; i++)
if (x[i].indexOf('.') > 0)
if (x[i].indexOf('://') < 0)
window.open('http://'+x[i]);
else
window.open(x[i]);
}
However, I would like to add a delay (let's say about 5 seconds) between opening each url. How can I do this?
I'm not familiar with functions. Usually much better with Linux and such. Your insight is highly appreciated.
A better approach is to use setTimeout() along with a self-executing anonymous function:
function openWindow() {
var i = 0;
var x = document.getElementById('a').value.split('\n');
(function() {
if(typeof x[i] !== 'undefined') {
if(x[i].indexOf('.') > 0) {
if(x[i].indexOf('://') < 0) {
window.open('http://' + x[i++]);
} else {
window.open(x[i++]);
}
}
setTimeout(arguments.callee, 1000);
}
return false;
})();
}
This will guarantee that the next call is not made before your code was executed. I used arguments.callee in this example as a function reference. Once the index no longer exists in the array, by checking if it's undefined, it simply returns false instead of setting another timout.
You can do it like this, to avoid issues caused by setTimeout being non-blocking.
What you need is to wait for the setTimeout to be executed before starting the next iteration.
var i = 0;
function openWindow(){
var x = document.getElementById('a').value.split('\n');
doLoop(x);
}
function doLoop(x)
setTimeout(function () {
if (x[i].indexOf('.') > 0){
if (x[i].indexOf('://') < 0){
window.open('http://'+x[i]);
}else{
window.open(x[i]);
}
}
i+=1;
if(i<x.length){
doLoop(x);
}
}, 5000)
}
Using a self executing function, it'd go like this :
function openWindow() {
var i = 0;
var x = document.getElementById('a').value.split('\n');
(function fn() {
if(x[i].indexOf('.') > 0) {
if(x[i].indexOf('://') < 0) {
window.open('http://' + x[i++]);
} else {
window.open(x[i++]);
}
}
i++;
if( i < x.length ){
setTimeout( fn, 3000 );
}
})();
}
create array x with all url's
var x = [url1, url2, url3, ...];
create a for loop
for(var i = 0; i<x.length; i++) {
setTimeout(function() {
window.open('http://'+x[i])}, 1000); // 1000 for 1 second
}
}
setInterval(function(){window.open('http://'+x[i]);},5000);
I have to sort an array of objects and I've written the code but it just doesn't execute. The array is the same and when I look in my debugger console it jumps right to the next function and doesn't execute my sort. I've tried many things but nothing seems to work. Maybe I'm overlooking something but I hope someone knows why it doesn't execute.
My code:
function orderData(toSort) {
console.dir(toSort);
toSort.sort(compareCountries);
console.dir(toSort);
return toSort;
}
function compareCountries(a, b) {
var avgx = 0;
var avgy = 0;
avgx = calcAvgForAllProperties(a, avgx);
avgy = calcAvgForAllProperties(b, avgy);
a["overalAvg"] = avgx;
b["overalAvg"] = avgy;
if (a.overalAvg > b.overalAvg)
return -1;
else if (b.overalAvg < a.overalAvg)
return 1;
else
return 0;
}
or:
function orderData(toSort) {
console.dir(toSort);
toSort.sort(function (a, b) {
var avgx = 0;
var avgy = 0;
avgx = calcAvgForAllProperties(a, avgx);
avgy = calcAvgForAllProperties(b, avgy);
a["overalAvg"] = avgx;
b["overalAvg"] = avgy;
if (a.overalAvg > b.overalAvg)
return -1;
else if (b.overalAvg < a.overalAvg)
return 1;
else
return 0;
});
console.dir(toSort);
return toSort;
}
//EDIT
Here's an example of my data:
There are several issues with your code:
The sorting function has side effects
You should not calculate overallAvg in compareCountries. Instead, you should do this before sorting.
var countries = [ /* your countries */ ];
countries.forEach(calculateCountryOverallFooAverage); // Standard forEach is not chainable.
countries.sort(compareCountriesByOverallFooAverage);
function calculateCountryOverallFooAverage(country) {
country.calculateOverallFooAverage();
}
function compareCountriesByOverallFooAverage(lhs, rhs) {
var lhsAvg = lhs.overallFooAverage();
var rhsAvg = rhs.overallFooAverage();
if (lhsAvg < rhsAvg) { return -1; }
else if(lhsAvg > rhsAvg) { return 1; }
return 0;
}
The comparison is incorrect, because the second test is equivalent with the first one (you do if (a < b) {} else if (b > a) {} else {}). It should be:
if (a.overalAvg > b.overalAvg) return -1;
else if (a.overalAvg < b.overalAvg) return 1;
else return 0;
for (var e = 0; e < markers.length; e += 1) {
(function (e, markers, latLngBounds) {
if (latLngBounds.contains(markers[e])) {
updatePrompt("Marker is contained");
// Break for loop
}
})();
}
In the example above, after the updatePrompt method is invoked how can I break out of the loop containing the closure?
var broken = false;
for (var e = 0; e < markers.length; e += 1) {
if (broken) {
break;
} else {
(function (e, markers, latLngBounds) {
if (latLngBounds.contains(markers[e])) {
updatePrompt("Marker is contained");
broken = true;
}
})();
}
}
A little verbose, but you get the point.
This could also be done with Array.some in modern browsers
markers.some(function(marker) {
if (latLngBounds.contains(marker)) {
updatePrompt("Marker is contained");
return true;
}
return false;
});
not sure if i get you correct, but if you want to break the loop set
e= markers.length;
The loop will not continue after this statement
Another way:
for (var e = 0; e < markers.length; e += 1) {
if ((function (e, markers, latLngBounds) {
if (latLngBounds.contains(markers[e])) {
updatePrompt("Marker is contained");
return 1;
}
return 0;
})())
break;
}
So, I have been trying for the past few hours to get an result out of a function after performing some for loops :
Cluster.prototype.initiate_api_data_fetching = function(username) {
var self = this,
object = [];
return self.initiate_available_market_search(username, function(data_object){
var json_obj = JSON.parse(data_object);
for(var obj_key in json_obj) {
for (var i = json_obj[obj_key].length - 1; i >= 0; i--) {
self.initiate_market_items_data_fetching(username, json_obj[obj_key][i].site, function(data_obj){
var json_object = JSON.parse(data_obj);
for(var data_key in json_object) {
for (var j = json_object[data_key].length - 1; j >= 0; j--) {
object.push(json_object[data_key][j]);
/*log(object);*/
};
};
log(object);
});
};
};
});
};
Making abstraction of all the variables and other things that make no sense to you readers, I would just like to know how can I return the object array with the data that I\m pushing in it. Everything is fine if I\m logging where the /*log(object);*/ is, but if I want to see what the object contains at the end of the function, I get an empty array.
I suggest you add a callback to your main function and call it when done..
Cluster.prototype.initiate_api_data_fetching = function (username, callback) {
var self = this,
object = [];
return self.initiate_available_market_search(username, function (data_object) {
var json_obj = JSON.parse(data_object)
, counter = 0;
function done() {
counter -= 1;
if (counter === 0) {
callback(object);
}
}
for (var obj_key in json_obj) {
if (!json_obj.hasOwnProperty(obj_key)) { continue; }
for (var i = json_obj[obj_key].length - 1; i >= 0; i--) {
counter += 1;
self.initiate_market_items_data_fetching(username, json_obj[obj_key][i].site, function (data_obj) {
var json_object = JSON.parse(data_obj);
for (var data_key in json_object) {
if (!json_object.hasOwnProperty(data_key)) { continue; }
for (var j = json_object[data_key].length - 1; j >= 0; j--) {
object.push(json_object[data_key][j]);
/*log(object);*/
}
}
done();
});
}
}
});
};
PS. 1 assumption is that initiate_api_data_fetching is async.
PS. 2 Follow the advice from the commenters above to improve your code. I answered your immediate question by showing you how to synchronise async calls, but don't stop there.
for (var i = 0; i < 32; i++) {
var thisId = dropId+i;
$("#p"+thisId).animate({ left:"+=32px" }, function(){
if ($("#p"+thisId).position().left == 1024) {
$("#p"+thisId).remove();
window.console.log("removed");
}
});
}
In the above code example, by the time I get around to executing animate's complete function, thisId represents the last assigned value from the for loop NOT the value that I wanted to pass in for each iteration of the loop. Is there a way to get it to access the correct thisId?
JavaScript does not have block scope. You can create a new scope by calling a function. E.g.
for (var i = 0; i < 32; i++) {
(function(thisId) {
$("#p"+thisId).animate({ left:"+=32px" }, function(){
if ($("#p"+thisId).position().left == 1024) {
$("#p"+thisId).remove();
window.console.log("removed");
}
});
}(dropId+i)); // <-- calling the function expression and passing `dropId+i`
}
Variables declarations area always hoisted to the top of the function. So even if you have the declaration inside the loop, it is actually the same as:
var i, thisId;
for(...) {
thisId = dropId + i;
//...
}
Every closure you create inside the loop references the same thisId. It's like in Highlander: "There can be only one."
You need to use a closure around the current thisId.
for (var i = 0; i < 32; i++) {
var thisId = dropId+i,
complete = (function(id) {
return function() {
if ($("#p"+id).position().left == 1024) {
$("#p"+id).remove();
window.console.log("removed");
}
}
}(thisId));
$("#p"+thisId).animate({ left:"+=32px" }, complete);
}
Just wrapping what you had in an anonymous function should work:
for (var i = 0; i < 32; i++) {
(function() {
var thisId = dropId+i;
$("#p"+thisId).animate({ left:"+=32px" }, function(){
if ($("#p"+thisId).position().left == 1024) {
$("#p"+thisId).remove();
window.console.log("removed");
}
});
})();
}