I am trying to get the value of a div and then output it using jquery. However, it doesn't seems to work.
Here is my code:
<div id="container">
<p id="textbit"></p>
</div>
<script type="text/javascript">
$(document).ready(function() {
var barcode = $('#textbit');
var container = $('#container');
setTimeout(function() {barcode.text('1233')}, 5000);
barcode.each(function() {
if (barcode.html().length > 0) {
var codereader = barcode.text();
container.hide(100);
alert('The code is '+ codereader);
}
});
});
</script>
It works when I don't have the setTimeout function but this div will be populated dynamically using AJAX in future.
Any help with this would be greatly appreciated!
Javascript is single threaded and setTimeout function is an asynchronous function. It doesn't delay the code execution for 5000ms as you think. It only schedules the callback function to be executed after a 5000ms.
After scheduling the callback to be executed, javascript will keep executing the code below the setTimeout function. After 5000ms when the callback is executed, the code below the setTimeoutYou is already executed. When you try to fetch the value, the html is not set yet as it's been scheduled to set after 5000ms.
If you want to simulate AJAX time delay, you may move the code for getting value into a new function and call it in the settimeout callback like this.
$(document).ready(function() {
var barcode = $('#textbit');
var container = $('#container');
var success = function(){
barcode.each(function() {
if (barcode.html().length > 0) {
var codereader = barcode.text();
container.hide(100);
alert('The code is '+ codereader);
}
}
setTimeout(function() {
barcode.text('1233');
success();
});
}, 5000);
});
In that case you need to check in the "done" promise which will be executed after the AJAX completes.
similarly like this .
$(document).ready(function() {
var barcode = $('#textbit');
var container = $('#container');
setTimeout(function() {
barcode.text('1233');
barcode.each(function() {
if (barcode.html().length > 0) {
var codereader = barcode.text();
container.hide(100);
alert('The code is '+ codereader);
}
});
}, 5000);
});
Ajax is a asynchronous, the execution will continue to next line, and later point when it completes. The callback provided will be executed. You need to make this execution in sequence.
use ajax complete event: when ajax will finish its task then this code will run
complete: function( xhr, status ) {
alert( "The request is complete! now u can get other function form here" );
getvalues();
}
Related
I have multiple JavaScript functions and all of them run at the same time and are running in a loop because I'm reading some data from REST API.
Is there any way to stop execution of those scripts with a button or something?
function termostat1_on_off_get() {
var request = $.ajax({
type: "GET",
url: "http://192.168.1.113:8080/rest/items/termostat1_on_off/state"
});
request.done(function(data) {
console.log("On/off" + data);
if (data == 1) {
termostat1_on_off = "Vklopljen";
$("#m_t1_vklopljen").css('background-color', '#cccccc');
$("#m_t1_izklopljen").css('background-color', '#efefef');
} else {
termostat1_on_off = "Izklopljen";
$("#m_t1_vklopljen").css('background-color', '#efefef');
$("#m_t1_izklopljen").css('background-color', '#cccccc');
}
});
request.fail(function(jqXHR, textStatus) {
console.log( "Failure: " + textStatus );
});
setTimeout(termostat1_on_off_get, 5000);
}
termostat1_on_off_get();
You can use clearTimeout() to stop an in-progress timeout from running. To do this you need to save the id returned from the setTimeout call, then provide it as a parameter to clearTimeout(), like this:
var timeout;
function termostat1_on_off_get()
{
// your ajax logic here...
// inside the callbacks:
timeout = setTimeout(termostat1_on_off_get, 5000);
}
termostat1_on_off_get();
function stopTimeout() {
clearTimeout(timeout);
}
However, you should note that AJAX polling is an anti-pattern which should really be avoided. If you need to keep the UI in sync with the server then you should look in to WebSockets or Server Side Events instead. They perform much better, and save your server from having a meltdown.
Use setInterval instead of setTimeout
var i = 0;
function log() {
console.log(i++);
}
var interval = setInterval(log, 1000);
function stop() {
clearInterval(interval)
};
<button onclick="stop()">Stop</button>
My objective is to keep a user in a view as long as he/she keeps clicking a button within a certain lapse.
I'm using Rails and was exploring a solution via an embedded JS in the pertinent view.
So far I'm able to set a time after which the user will be redirected to root path with the following script:
var delayedRedirect = function (){
window.location = "/";
}
var delay = 10000;
$(document).ready(function() {
setTimeout('delayedRedirect()', delay);
});
I've been trying to write a function that resets the value of 'delay'or that calls the setTimeoutFunction again.
$('#btn-persist').click(function() {
delay = 3000;
// or calling again setTimeout('delayedRedirect()', delay);
});
But I noticed that changing the variable won't affect the setTimeout function that has already been called.
I've also tried to use the clearTimeout function as below without success
var delayedRedirect = function (){
window.location = "/persists";
}
var delay = 3000;
var triggerRedirect = function() { setTimeout('delayedRedirect()', delay);
}
var stopRedirect = function (){
clearTimeout(triggerRedirect);
}
$(document).ready(function() {
triggerRedirect();
$('#btn-persist').click(function() {
stopRedirect();
});
});
I wonder why this may not be working and if there's any other way to stop the execution of the setTimeout function that has already been called so I can call it again to effectively reset the time to the original value of 'delay'.
At the same time, I don't want to stop any other JS functions that are running in parallel.
Do you see a better solution to achieve this?
The main problem why clearTimeout is not working. because you are clearing a anonymous function instead of a setTimeout variable
change this
var triggerRedirect = function() { setTimeout('delayedRedirect()', delay);
}
to this
var triggerRedirect = setTimeout('delayedRedirect()', delay);
Edit:
also change this (if you want to restart the inactive redirect trigger)
$('#btn-persist').click(function() {
stopRedirect();
});
to this
$('#btn-persist').click(function() {
stopRedirect();
triggerRedirect();
});
I am executing setTimeout function in a page which loads via ajax call. but if i click the link to load the page again, i afraid the last setTimeout call still continues and the number of intervals of the calls set by setTimeout executes multiple times.
tried this is the remote page:
var RefreshInterval = null;
clearTimeout(RefreshInterval);
function someFunction()
{
....
setNextRefresh();
}
function setNextRefresh() {
console.log(wifiRadarRefreshInterval);
RefreshInterval = null;
clearTimeout(RefreshInterval);
RefreshInterval = setTimeout('someFunction();', 20*1000);
}
declare var RefreshInterval = null; outside of page loaded by ajax and use this code on the page:
clearTimeout(RefreshInterval);
function someFunction()
{
....
setNextRefresh();
}
function setNextRefresh() {
console.log(wifiRadarRefreshInterval);
clearTimeout(RefreshInterval);
RefreshInterval = setTimeout('someFunction();', 20*1000);
}
if i don't want to declare it in parent page, here is the solution i found:
//Clear previously loaded calls if exists
try{ clearTimeout(wifiRadarRefreshInterval); }catch(e){}
var wifiRadarRefreshInterval = null;
function somefunction(){
....
setNextRefresh();
}
function setNextRefresh() {
try{
clearTimeout(wifiRadarRefreshInterval);
wifiRadarRefreshInterval = null;
wifiRadarRefreshInterval = setTimeout('somefunction();', 20*1000);
}
catch(e){
console.log(e.message + e.stack);
}
}
Do not use this
var RefreshInterval = null;
clearTimeout(RefreshInterval);
You are actually assigning a null and then trying to clear it. Which will not work, The timeout must be cleared by using the clearTimeout and by passing the variable which was assigned to the setTimeout. Here you will end up passing a null so the timer is never cleared.
Here is a small sample which will demonstrate a fix to your problem JS Fiddle
So insted of setting the variable to null and then trying to clear it, Just check if the variable is not defined and if it is defined clear it, else move on. Use the code below, Also you must remove the top two lines as mentioned
function setNextRefresh() {
console.log(wifiRadarRefreshInterval);
if (typeof RefreshInterval !== 'undefined') {
clearTimeout(RefreshInterval);
}
RefreshInterval = setTimeout('someFunction();', 20*1000);
}
Click on the button say like 4 times, The output should be printed only once. That is if the ajax call is made 4 times the set time out must execute only once. Check below snippet for demo
var clickCount= 0; // just to maintain the ajax calls count
function NewPageSimilator(clicksTillNow) { // this acts as a new page. Let load this entire thing on ajaX call
if (typeof RefreshInterval !== 'undefined') {
clearTimeout(RefreshInterval);
}
function setNextRefresh() {
window.RefreshInterval = setTimeout(printTime, 3000); //20*1000
}
function printTime() {// dumy function to print time
document.getElementById("output").innerHTML += "I was created at click number " + clicksTillNow + '<br/>';
}
setNextRefresh();
}
document.getElementById("ajaxCall").addEventListener("click", function() { // this will act as a ajax call by loading the scripts again
clickCount++;
NewPageSimilator(clickCount);
});
document.getElementById("clear").addEventListener("click", function() { //reset demo
clickCount = 0;
document.getElementById("output").innerHTML = "";
});
<p id="output">
</p>
<button id="ajaxCall">
AJAX CALL
</button>
<button id="clear">
Clear
</button>
I am trying to create a loop that each time, retrieves another pages' content via $.post and upon completion, does the next page, until an element on that page shows 0 results.
function scrapeIt() {
$(".currentPage").html("Current Page: " + page);
$.post("scrapePosts.aspx", { page: page, search: keyword }, function (data) {
$(".status").html(data);
if ($("#count").html() == "10") {
scrapeIt();
} else {
alert("Stopping...");
}
});
page++;
}
$(document).ready(function () {
var page = 1;
var keyword;
var stillGettingResults = true;
$("#go").click(function () { //Start Button
keyword = $("#keyword").val(); // Textbox
$(".status").html("Loading...");
scrapeIt();
});
});
The idea was for the scrapeIt() function to call itself again, but only when it has completed the post request. It seems to just freeze though.
var page = 1 and var keyword should both be declared in global scope, otherwise they are undefined in function scrapeIt().
Your page could appear to be freezing because no page or keyword is being sent as part of the post request, and the server may not understand the request.
see setTimeout() $.post is not asynchronous i guess and constantly calling it will freeze the browser thread
Because of recursion page is always zero.
You need to increment the page variable in the post callback not at the end of scrapeIt.
$.post("scrapePosts.aspx", { page: page, search: keyword }, function (data) {
page++;
$(".status").html(data);
if ($("#count").html() == "10") {
scrapeIt();
} else {
alert("Stopping...");
}
I've got a search input which sends data from an input to a php file as I type. The php file does a search on my database and shows up a list of search options. You know, the ajax style live searching.
My problem is, if you type something really fast, it might just conduct a search off of the first 1 or 2 letters even though another 10 have been typed. This causes a few problems.
My jQuery looks a bit like this:
$(document).ready(function(){
$('#searchMe').keyup(function(){
lookup(this.value);
});
});
and
function lookup(searchinput) {
if(searchinput.length == 0) {
// Hide the suggestion box.
$("#suggestions").hide();
} else {
$('#loading').fadeIn();
$.post("/RPCsearch.php", {queryString: ""+searchinput+""}, function(data){
if(data.length > 0) {
$("#suggestions").html(data).show();
$('#loading').fadeOut();
}
});
}
} // lookup
So I'm just curious, how can I make it so that my script waits until I've finished typing before running the function? My logic says something like if a key hasn't been pressed for 200 micro seconds, run the function, otherwise hold up a bit.
How is this done?
Easy, using setTimeout. Of course you only want one timer going at once, so it's important to use clearTimeout at the beginning of the function...
$(function() {
var timer;
$("#searchMe").keyup(function() {
clearTimeout(timer);
var ms = 200; // milliseconds
var val = this.value;
timer = setTimeout(function() {
lookup(val);
}, ms);
});
});
You may be interested in my bindDelayed jQuery mini-plugin. It:
Allows you to specify a delay before kicking off the request
Automatically cancels any previous requests that were scheduled to go off
Automatically cancels any in-air XHR requests that were in progress when you make your request
Only invokes your callback for the latest request
If the user types "s", waits long enough for the request to go out, and then types "a", and the response for "s" comes back before the response for "sa" you won't have to deal with it.
The answer to the original question using bindDelayed would look like so:
// Wait 200ms before sending a request,
// avoiding, cancelling, or ignoring previous requests
$('#searchMe').bindDelayed('keyup',200,'/RPCsearch.php',function(){
// Construct the data to send with the search each time
return {queryString:this.value};
},function(html){
// Use the response, secure in the knowledge that this is the right response
$("#suggestions").html(html).show();
},'html','post');
In case my site is down, here's the plugin code for Stack Overflow posterity:
(function($){
// Instructions: http://phrogz.net/jquery-bind-delayed-get
// Copyright: Gavin Kistner, !#phrogz.net
// License: http://phrogz.net/js/_ReuseLicense.txt
$.fn.bindDelayed = function(event,delay,url,dataCallback,callback,dataType,action){
var xhr, timer, ct=0;
return this.on(event,function(){
clearTimeout(timer);
if (xhr) xhr.abort();
timer = setTimeout(function(){
var id = ++ct;
xhr = $.ajax({
type:action||'get',
url:url,
data:dataCallback && dataCallback(),
dataType:dataType||'json',
success:function(data){
xhr = null;
if (id==ct) callback.call(this,data);
}
});
},delay);
});
};
})(jQuery);
You really ought to look at using the jQuery autocomplete plugin. I find this plugin to be very useful and it already does what you need. Look particularly at the delay option, which you can customize to change how long the plugin waits after a keystroke to run.
1 solution in psuedocode:
OnKeyPress()
txt = getTxt
sleep(200)
newTxt = getTxt
if (txt == newTxt) // nothing has been typed so do something
run my thing
this one is happy
$(document).ready(function(){
$("#searchMe").keyup(function () {
try{window.clearTimeout(timeoutID);}catch(e){}
timeoutID = window.setTimeout(run, 2000); //delay
function run()
{ //dowhatev
var text = $("#searchMe").val();
//$("#showit").html(text);
}
});
});
I have found the best success when attaching the event to keypress, keydown, and keyup inputs. Safari/FireFox/IE all seem to handle special keypresses (delete, backspace, etc.) a bit differently but using all events together seems to cover it. The only way that running all events works though is to use setTimeout so that when they all fire it just resets the timer and ultimately the callback only gets executed once.
var delay = 200;
var search_timer = null;
$("#searchMe").keydown(function(e) {
if(search_timer) {
clearTimeout(search_timer);
}
search_timer = setTimeout(lookup, delay);
});
$("#searchMe").keypress(function(e) {
if(search_timer) {
clearTimeout(search_timer);
}
search_timer = setTimeout(lookup, delay);
});
$("#searchMe").keyup(function(e) {
if(search_timer) {
clearTimeout(search_timer);
}
search_timer = setTimeout(lookup, delay);
});