In the book, author uses "setTimeout" to reset the form in HTML page.But I didn't find this usage in the JS document.So, why function"setTimeout()" can reset the form?
//reset
$("#reset").click(function(){
setTimeout(function() {
countChecked();//initial
$("select").change();//initial
},0);
});
function countChecked() {
var n = $("input:checked").length;
$("div").eq(0).html("<strong>"+n+" elements are selected!</strong>");
}
$("select").change(function () {
var str = "";
$("select :selected").each(function () {
str += $(this).text() + ",";
});
$("div").eq(1).html("<strong>you have selected:"+str+"</strong>");
}).trigger('change');
So, why function"setTimeout()" can reset the form?
It doesn't, it just waits to run the code within it until after the event trigged by the button click has been processed.
You haven't shown the HTML, but I'm guessing that the id="reset" button is also type="reset", which does reset the form (standard HTML functionality, no scripting required). So by waiting to call countChecked until after the reset, the code shows the state once the reset is complete.
The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds.
I see the time is set to 0 so it does not count.
Window setTimeout() Method: https://www.w3schools.com/jsref/met_win_settimeout.asp
setTimeout(function,0) or setTimeout(function), the zero is optional, both place the code to be executed at the end of the current code being executed, and after any updates the browser may have pending.
This was useful before ES6 to deblock the browser for scripts that took a long time to finish. Just use setTimeout for each iteration of the loop without a delay.
For example
setTimeout(function() { console.log(2) }); // will log 2 after this script finishs
console.log(1)
Will place into the console log 1 then 2, not 2 then 1.
I don't see the point of doing
countChecked();//initial
$("select").change();//initial
after the code which is shown, has finished?
Related
I am creating tests for a page and HAVE to use jQuery to change elements on the control version of the page for each different experience.
I'm using jquery to load an element from an external page and replace a div. However, on the external page, it uses an ajax call to an api to populate the div, so I copied over the function with the ajax call.
I think it is attempting to make the ajax call before the new div is actually loaded on the page.
I've tried moving the function, wrapping the load function within the ajax call, but it still doesnt work.
I could be missing something obvious, but here's that part of my code:
$('.replace-div').load('external.html #replace-div');
function waitForLoad() {
if ($('#replace-div')) {
var object;
$.ajax({
url: "https://api.com",
async: false,
success: function(result) {
object = result;
var variable1 = object["blah"][0].value,
var variable2 = object["blah"][0].value,
var variable3 = object["blah"][0].value,
var variable4 = object["blah"][0].value,
$('newElement').attr('href', variable1);
$('newElement2').attr('src', variable2);
$('newElement3').attr('href', variable3);
$('newElement4').text("text" + variable4 + "more text");
}
});
} else {
setTimeout(waitForLoad, 15);
}
}
waitForLoad();
I don't get any errors in the console, and when I paste the above waitForLoad function into the console, it populates totally fine. obviously this is after the page loads the new div, so i just need to know how to make the ajax call wait for the load.
I've tried .ajaxComplete(), but it doesnt help.
$(function() {}); also does not work
.load() has a callback argument where you supply a function to run after the data is loaded.
$('replace-div').load('external.html #replace-div', function() {
$.ajax(...);
});
So, what happens is that, once waitForLoad is called for the first time, it doesn't see the div loaded, the code goes to the else block and executes again with a 15ms timeout. 15ms is not enough for the div to load, most likely.
You can try three things (ordered from worse to better):
Try increasing the timeout to a bigger number. Start with 1000 (1000ms - 1 second) and see if it works or you need to increase it. It's more likely you'll have to decrease it
Try using setInterval instead of setTimeout, which will repeat itself. Of course, once it loads, you'll need to clear the interval so it stops. Also, better use bigger timeouts/intervals, like 50 or 100ms b/c the fast firing timers can slow down a page a lot
E.g.
$('.replace-div').load('external.html #replace-div');
function waitForLoad() {
if ($('#replace-div')) {
clearInterval(window.waiter);
...
} else {
window.timer = setInterval(waitForLoad, 50);
}
}
waitForLoad();
Same as 2, but using more idiomatic callback function after load call.
// the window.waiter is the interval handle, and it will run every 100ms. It calls .load every time, and if the #replace-div is found, unsets the interval handle.
window.waiter = setInterval(function() {
$(".replace-div").load("external.html #replace-div", function() {
if ($(".replace-div #replace-div").length) {
// found the DIV
// code...
clearInterval(window.waiter); // bye interval handle, thanks
}
});
}, 100);
I have this code:
window.setTimeout(function() {
let sudokuBodyWidth = $sudokuBody.outerWidth(true);
let sudokuBodyHeight = $sudokuBody.outerHeight(true);
console.log(sudokuBodyWidth + ',' + sudokuBodyHeight);
$sudoku.hide();
$welcomeOverlay.css({
width: sudokuBodyWidth,
height: sudokuBodyHeight
}).show();
}, 800);
window.clearTimeout();
I've put this code in a setTimeout because it takes a lot of time the DOM to load, so the JS code is to early with executing and returns 0 for the values (it's a huge codebase and I'm not 'allowed' to change the site structure to make the JS load later).
The problem is that this code runs twice. First, it returns the correct result, but then it returns 0 for both variables immediately after the correct values. As you can see, I've added a clearTimeout to prevent the execution to happen twice. But it keeps executing twice.
I've also tried:
let welcomeTimeout = setTimeout(function() {
// the code
});
clearTimeout(welcomeTimeout);
When doing this, the code doesn't execute at all.
window.clearTimeout() will do nothing because you are not passing the timerId witch get returned by window.setTimeout() and this should not run twice there is something else witch is causing this function to run twice
and in second one clearTimeout(welcomeTimeout); clears the timer that's why your code doesn't run
if you want to run your code after the document get loaded fully then you can use window.onload = function(){...}
or if you are using jQuery then you can also try $(document).ready(function(){...})
It should execute only once check Ur code base if u r loading script two times mean while put clearTimeout code at the end in the ananymous function given to setTimeout function
Putting the code at the end of HTML executes it when the DOM is loaded.
Use this:
<html>
<head>
<script async src="..."></script>
...
</head>
<body>
...
...
<script>(function() { init(); })();</script>
</body>
</html>
Function init() will fire when the DOM is ready.
Also you're using setTimeout() wrong, take a look at this example.
var what_to_do = function(){ do_stuff(); };
var when_to_do = 3000; // 3000ms is 3 seconds
var timer = setTimeout(what_to_do, when_to_do);
I have a question regarding the order of execution of JavaScript (listener) methods. While I appreciate the below code is probably not best practise, is there any way to guarantee the order the below functions will fire when btn1 is changed?
$(function() {
$('#btn1').change(function(){
doStuff();
});
});
$(function() {
$(#btn1, btn2).change(function(){
doMoreStuff();
});
});
E.g. is it possible to assert that based on the order the JS code "appears in" (i.e listed in the actual js / html file), that (when #btn1 changes):
1. that doStuff() will execute first
2. that doStuff() will complete fully before doMoreStuff() is invoked – assuming all doStuff is doing is updating the DOM
I have a real example, where doStuff updates the DOM and doMoreStuff invokes an Ajax endpoint, using the updated DOM values - and want to be sure doStuff will always be invoked first (again based on the flaky design that it is "listed" first).
Thanks,
Damien
As far as I'm aware, jQuery ensures event handlers fire in the order in which they were created (first in, first out). Currently I can't find any documentation on this, but I'm sure I have read that somewhere in the past.
As long as your first change function isn't asynchronous, it should be the case that the first function will finish execution before the second starts. We can test this by adding a loop within our first change function:
$(function() {
$('#btn1').change(function(){
console.log("First change event triggered at " + +(new Date()));
for (var i = 0; i < 100000000; i++)
continue;
console.log("First change event finished at " + +(new Date()));
});
});
$(function() {
$('#btn1, #btn2').change(function(){
console.log("Second change event triggered at " + +(new Date()));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="btn1"><option>1</option><option>2</option></select>
<select id="btn2"><option>1</option><option>2</option></select>
As you can see, the first finishes before the second starts.
I use Ajax load icons all the time for when I do ajax requests.
I want to know if it's possible to accomplish the same thing with just regular javascript code. For example:
$('button').on('click', function(){
showLoadingBar();
longProcess();
hideLoadingBar();
});
longProcess() is just a function that can take 1-3 seconds to process (it does a lot of calculations and manipulates the DOM but doesn't do any ajax requests).
Right now, the browser halts/freezes during these 1-3 seconds, so what I would rather do is show a loading icon during this time. Is this possible? The code I have above pretty much ignores showLoadingBar().
The DOM won't be updated until the current Javascript process ends, so you can't do it just like that. You can however use setTimeout to get around that:
showLoadingBar();
setTimeout(function() {longProcess(); hideLoadingBar(); }, 1);
What happens above, in case it isn't clear, is that showLoadingBar is executed, then a timeout is set up. The current process will then end and allow the DOM to update with the loading bar, before the timeout is invoked, very shortly after. The handler executes your heavy function and when it's done, hides the loading bar again.
The following will give you control over the action on click. What this means is you can disable the clicking ability till it has finished running. But also i've including setTimeout which returns control to the browser (thus removing that annoying "lockup" feeling) and in the timeout function we preform our long process then re-enable the button! VIOLA!
function startProc() {
var $this = $(this);
$this.off("click", startProc);
showLoadingBar();
setTimeout(function() {
longProcess();
hideLoadingBar();
$('button').on('click', startProc);
});
}
$('button').on('click', startProc);
Dude,
Use the .bind method, which in this case is performed so:
$('button').bind('click', function(){
showLoadingBar();
longProcess();
hideLoadingBar();
});
I am trying to run small snippet code in JavaScript, where I want to write on the web page simple hello world each 5 seconds. I think it must be ok, but no, still I got only first hello world and no more. Could you give me a hand in this? Thanks
<script type="text/javascript">
var i=0;
function startTimer() {
window.setTimeout('refresh()',5000);
}
function refresh() {
document.write("Hello world "+i+"<br/>");
i++;
window.setTimeout('startTimer()',1);
}
startTimer();
</script>
NOTE: As Amar Palsapure has noted in this answer, the root cause of the problem was the use of document.write. In my demonstration, I use a p element to document.body.appendChild() to add the text to the screen.
You can use setTimeout(), but you have to make it contingent on the last setTimeout() that ran; so that each time the caller runs, it creates the next timeout.
setInterval() is designed to run at a "regular" interval (neither setTimeout() nor setInterval() are truly reliable in when they run); however, if the calls to setInterval() get backed up due to some other process blocking it's execution (Javascript is single-threaded), you could have issues with those queued callbacks. That's why I prefer the approach I have below.
Note, refrain from the setTimeout('funcCalled()', 100) usage; this is running an eval() on that string you're passing in, which can change the scope in which you're running the callback, as well as being considered "evil" due to security issues related to eval(). You're best to avoid it altogether.
EDIT - Modified slightly.
I have made some changes to the approach. See my comments.
// The first and last lines comprise a self-executing,
// anonymous function, eg, (function(){})();.
// This allows me to use a local function scope and not the
// global window scope, while still maintaining my variables
// due to it being a "closure" (function(){}).
(function(){
var i = 0,
timer = 5000,
// I'm just going to add this to the DOM.
text = document.createElement('p');
// This is a variable function, meaning it stores a
// reference to a function.
var helloWorld = function() {
// Here is where I add the Hello World statement
text.innerHTML += 'Hello World! Loop: ' + i++ + '<br/>';
// Them add it to the DOM.
document.body.appendChild(text);
// I added this so it wouldn't run forever.
if (i < 100) {
// A setTimeout() will be added each time the last
// was run, as long as i < 100.
// Note how I handle the callback, which is the
// first argument in the function call.
setTimeout(helloWorld, timer);
}
// I added the change so it wouldn't take so long
// to see if was working.
timer = 500;
}
// Here I use a variable function and attach it to the
// onload page event, so it will run when the page is
// done loading.
window.onload = helloWorld;
})();
http://jsfiddle.net/tXFrf/2/
The main issue is document.write. There is nothing wrong with setTimeout or rest of the code.
The reason it does not work is that once document.write is called the first time, it overwrites your existing code of setTimeout() and since there is no code so it will not work.
What you need to do is use some other means to write the value in the page, certainly no document.write...
Instead of using setInterval use setTimeout.
You can try this
<html>
<body>
<div id="clock" ></div>
<script type="text/javascript">
var i = 0,
timerHandle,
clock;
function startTimer() {
clock = document.getElementById('clock');
//You can use timerHandle, to stop timer by doing clearInterval(timerHandle)
timerHandle = self.setInterval(funRefresh, 2000);
}
var funRefresh = function refresh() {
clock.innerHTML += "Hello world " + i++ + "<br/>";
}
startTimer();
</script>
</body>
</html>
Hope this helps you.
Here is the working Code
var i = 0;
function startTimer() {
window.setInterval(refresh, 5000);
}
function refresh() {
document.write("Hello world " + i + "<br/>");
i++;
// window.setTimeout(startTimer,1);
}
startTimer();