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);
Related
in my React-native app I am trying to call another function within my listenForItems function, but keep getting the error this.populateArray is not a function. In 'this.populateArray(solutions)', this.populateArray is undefined. I do this in other classes and it's working, but for some reason it's not working here. Is there anything I'm missing?
populateArray: function(solutions) {
var completed = [];
var inProgress;
for (var i = 0; i < solutions.length; i++ ) {
if (solutions[i].completed == 0) {
inProgress = solutions[i].id;
}
else {
completed.push(solutions[i].id);
}
}
},
listenForItems: function(cluesRef) {
var solutions = [];
userSolutionsRef.orderByChild('user_id').startAt(0).endAt(0).once('value', function(snap){
var solution = snap.val();
for (var i = 0; i < solution.length; i++) {
if (solution[0].hunt_id == 0) {
solutions.push(solution[0]);
}
}
this.populateArray(solutions);
});
},
The classic this scope issue of javascript. Google will help with better understanding. In short, the word "this" inside a function refers to that function. In this example it refers the anonymous function (callback) that you use in userSolutionsRef.orderByChild. There are many ways to solve this. You can use ES6(ES2015) arrow functions in which case it becomes something like
userSolutionsRef.orderByChild('user_id').startAt(0).endAt(0).once('value', (snap) => {
var solution = snap.val();
for (var i = 0; i < solution.length; i++) {
if (solution[0].hunt_id == 0) {
solutions.push(solution[0]);
}
}
this.populateArray(solutions);
});
or es5 solution
var that = this;
userSolutionsRef.orderByChild('user_id').startAt(0).endAt(0).once('value', function(snap){
var solution = snap.val();
for (var i = 0; i < solution.length; i++) {
if (solution[0].hunt_id == 0) {
solutions.push(solution[0]);
}
}
that.populateArray(solutions);
});
I have a for-loop that is terminating without finishing the loop. It seems to be related to whether or not a call to another function is made within the loop.
this.cycle = function() {
var list = this.getBreaches("Uncontained");
if (list.length > 0) {
for (i=0; i < list.length; i++) {
this.saveVsRupture(DC=11, i); //calls this.rupture() if save failed
}}
return 1;
};
this.saveVsRupture() calls a function that rolls a d20 and checks the result. If the save fails, it calls a method called this.rupture() that does some adjusting to this.
Problem
If the saving throw is successful, the loop continues, but if the saving throw fails, it runs the this.rupture() function and then breaks the for-loop. It should keep running the for-loop.
Why is this happening?
Additional Details
Here are the other functions...
savingThrow = function(DC=11) {
// DC = Difficulty Check on a d20
try {
if (0 <= DC) {
var roll = Math.floor((Math.random() * 20))+1; //roll d20
var msg = "(Rolled "+roll+" vs DC "+DC+")";
console.log(msg);
if (roll >= DC) { //Saved
return true;
}
else { //Failed save
return false;
}
}
}
catch(e) {
console.log("Exception in savingThrow: "+e);
};
};
this.saveVsRupture = function(DC=1, i=null) {
try {
if (!savingThrow(DC)) {
this.rupture(i);
return false;
}
return true;
}
catch(e) {
console.log(e);
}
};
this.rupture = function(i=null) {
if (i == null) {
i = range(1,this.damageList.length).sample();
}
var hole = this.damageList[i];
var dmg = range(1,this.harmonics()).sample();
hole.rupture(dmg);
msg = "*ALERT* " + hole + " expanded by " + dmg + "% Hull Integrity #"+this.hullIntegrity();
this.log(msg);
if (hole.size % 10 == 0) {
this.health -= 25;
msg = "The ship creaks ominously.";
this.log(msg);
}
return 1;
};
The correct syntax for the for-loop declares the counter variable.
for (var i=0; i < list.length; i++) {etc..
/// Causes the For-Loop to exit prematurely...
for (i=0; i < list.length; i++) {etc..
Once the "var i=0" is used, the for-loop operates as expected.
consider implementing a try-catch in your for loop, with your saveVsRupture function within the try. This implementation will catch errors in your function but allow the program to keep running.
Change the saveVsRupture function like this:
function saveVsRupture(a,b) {
try{
//your saveVsRupture code here...
}
catch(e){}
}
Your should catch problems that occurred in your code with try,catch block to prevent throw them to top level of your code (the browser in this example) .
Don't use return in for loop!
Change your code as following:
this.cycle = function() {
var list = this.getBreaches("Uncontained");
if (list.length > 0) {
for (i=0; i < list.length; i++) {
var temp = this.saveVsRupture(DC=11, i); //calls this.rupture() if save failed
console.log(temp);
}}
return 1;
};
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>
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");
}
});
})();
}
I have an append button which appends endlessly if you click it endlessly.
Lets say i want this button to do this 10 times.
Let me tell you in fantasy code :p what i was thinking so that i can learn from my mistakes; ( i know its wrong but hey im learning)
thismany = 1;
appendbutton.onClick = "thismany = +1";
if{ thismany = <9}
appendbutton.onClick = disabled
thanks in advance
(function(){
var count = 1;
document.getElementById("the_node_id").onclick = function(){
if(count > 10){
return;
}
do_stuff();
count ++;
};
})()
UPDATE:
var count = 1;
addEvent(append, "click", function(/* someargument */){
if(count > 10){
return;
}
// if you need arguments that are passed to the function,
// you can add them to the anonymous one and pass them
// to appendFunction
appendFunction(/* someargument */);
count++;
});
This is straight javascript. You might also consider looking into a framework such as jQuery to make it easier for you.
This assumes your HTML for the button has id="appendButton" as an attribute.
var count = 0;
document.getElementById("appendButton").onClick = function(e) {
if( count >= 10 ) {
return false;
}
else {
count ++;
document.getElementById("id_of_thing_you_append_to").innerHTML += "Whatever you're appending";
}
}
Using your variable names:
var thismany = 0;
appendbutton.onclick = function() {
if (thismany++ < 10) {
// append things
}
};
Variable encapsulated:
appendbutton.onclick = function() {
if (this.count == undefined) {
this.count = 0;
}
if (this.count++ < 10) {
// append things
}
};