jQuery delay on keyup - javascript

I'm trying to implement this answer in my own code:
$(document).ready(function() {
$('#qty').delayKeyup(function() {
var qty = $(this).val();
$(this).val(Math.round(qty / 10) * 10);
}, 1000);
});
(function ($) {
$.fn.delayKeyup = function(callback, ms){
var timer = 0;
$(this).keyup(function(){
clearTimeout (timer);
timer = setTimeout(callback, ms);
});
return $(this);
};
})(jQuery);
but no change in the input value is occurring. If I remove the delayKeyup function the change works OK but obviously not with the delay. What am I missing?

You need to make sure that the handler function is invoked with the proper this value:
var timer = 0, elem = this;
$(this).keyup(function(){
clearTimeout (timer);
timer = setTimeout(callback.bind(elem), ms);
});
Your callback is written to expect that this will be the DOM element involved.
Also, it's good practice to make sure that your jQuery add-on methods behave like good jQuery citizens. In a case like this, you should be using .each() in case the selector for "delayKeyup" refers to multiple elements:
(function ($) {
$.fn.delayKeyup = function(callback, ms){
return this.each(function() { // $(this) not necessary for a jQuery add-on
var timer = 0, elem = this;
$(this).keyup(function(){
clearTimeout (timer);
timer = setTimeout(callback.bind(elem), ms);
});
});
};
})(jQuery);
Not all browsers support .bind(), but luckily in this case there's a really simple alternative that works everywhere:
(function ($) {
$.fn.delayKeyup = function(callback, ms){
return this.each(function() {
var timer = 0, elem = this;
$(this).keyup(function(){
clearTimeout (timer);
timer = setTimeout( function() { callback.call(elem); }, ms);
});
});
};
})(jQuery);

Related

Jquery - hasclass after delay

I want to check if an element has a class after some time. Like delay. Basically the class is being added to the element by some other function. So If I check the hasClass on that clicked element it returns false.
var check_selected = $(this).hasClass('selected');
if ( $(this).hasClass('selected').delay(500) ) {
console.log(check_selected);
}
This is what I am trying but I want to know if we can add delay to hasClass, or any other way to achieve this. But it is not working
As per answers suggested I tried this -
var check_selected = $(this).hasClass('selected');
setTimeout(function(){
if ( $(this).hasClass('selected') ) {
console.log(check_selected);
}
}, 500);
But no outcome now in console.
Just to update -
The class is being applied on click, and the same click I basically wants to know if the class is applied, so I am using hasclass. Is there any other way out, or am I doing it wrong
EDIT -
var _this = this;
var check_selected = $(this).hasClass('selected');
setTimeout(function(){
if ( $(_this).hasClass('selected') ) {
console.log(check_selected);
}
}, 5000);
I am trying this but still getting false
UPDATE -
var checkSelected = setInterval(function(){
var check_selected = $(_this).hasClass('selected');
if(check_selected) {
clearInterval(checkSelected);
}
console.log(check_selected);
}, 500);
This worked!!
Try setTimeout for simulating the delay. And if you want to test this repeatedly until you get it selected you can try setInterval(function(){}, interval). You need to call clearInterval if you want to stop calling the function.
$("#test").on("click", function(){
const component = $(this);
setTimeout(function(){
component.addClass("selected");
}, 600);
setTimeout(function(){
var check_selected = component.hasClass('selected');
console.log(check_selected);
}, 500);
var checkSelected = setInterval(function(){
var check_selected = component.hasClass('selected');
if(check_selected) {
clearInterval(checkSelected);
}
console.log(check_selected);
}, 500);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">Check my class</div>
you can use setTimeout its javascript function that does callback execution after the miliseconds passed in as second parameter
var check_selected = $(this).hasClass('selected');
setTimeout(function(){
if ( $(this).hasClass('selected') ) {
console.log(check_selected);
}
}, 500);
You can use timer function
var currObj = this;
setTimeout(function(){
var check_selected = $(currObj ).hasClass('selected');
if ($(currObj).hasClass('selected')) {
console.log(check_selected);
}
},500);

How can I stop custom jQuery function which is running?

I have a custom jQuery function. When it runs every 5 seconds.
(function($) {
$.fn.mycustomfunction = function() {
interval = setInterval(function() {
console.log("I am running every 5 seconds");
}, 5000);
}
return this;
};
})(jQuery);
$("#container").mycustomfunction();
I have a
clearInterval(interval);
to stop, but I also want to stop the function completely. How can I do that ?
Functions you add to this object will be attached to your object and Simple and naive solution will follow:
(function($) {
$.fn.mycustomfunction = function() {
interval = setInterval(function() {
console.log("I am running every 5 seconds");
}, 1000);
this.stop= function(){
clearInterval(interval);
}
// another function
this.alert = function(msg){
alert(msg)
}
return this;
};
})(jQuery);
to stop use
var feature = $("#container").mycustomfunction();
feature.stop();

JQuery merge two functions keyup and focusout

On a form-field I work with two active functions: keyup and focusout.
The functions execute the same code, only the key-up uses a delay-function.
Function for delay:
$(function() {
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
Functions for keyup and focusout:
$("#name").on('keyup', function (){
var textn = $(this).val();
var nbrCharn = textn.length;
delay(function(){
if(nbrCharn > '2'){ $('#nameMsg').html('Nice.');
}else { $('#nameMsg').html(''); }
}, 1000 );
});
$("#name").on('focusout', function (){
var textn = $(this).val();
var nbrCharn = textn.length;
if(nbrCharn > '2'){ $('#nameMsg').html('Nice.');
}else { $('#nameMsg').html(''); }
});
The keyup needs the delay, the focusout does not.
This code works fine, but is it possible to merge those functions, so I don't have the same code twice?
you could define a handler that takes an argument which is a completion function
var handler = function (completion){
return function(){
var textn = $(this).val(),
nbrCharn = textn.length;
completion(function(){
if(nbrCharn > '2'){
$('#nameMsg').html('Nice.');
} else {
$('#nameMsg').html('');
}
});
};
};
and then define the handlers
$("#name").on('keyup',handler(function(cb){delay(cb,1000);}));
$("#name").on('focusout',handler(function(cb){cb();}));
If you use several events in one handler use the event object argument to check event.type
$("#name").on('keyup focusout', function (evt){
if(evt.type === 'keyup'){
/* keyup only code */
}
});
Or something like
var delay = evt.type === 'keyup' ? 0 :1000;
then use delay() for both
You could try passing the relevant jquery this object to a function:
var delay =
(function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
}
)()
$(document).ready(init);
function init() {
$("#name").on('keyup', function (){
var self = this;
delay(
(function(self){
return function(){
writeNameMsg(self)
};
})(self)
, 1000 );
});
$("#name").on('focusout', function (){
writeNameMsg(this);
});
}
function writeNameMsg(self){
var textn = $(self).val();
var nbrCharn = textn.length;
if(nbrCharn > '2'){
$('#nameMsg').html('Nice.');
} else {
$('#nameMsg').html(''); }
}
};
One straightforward way is to .trigger() one event from the other after a delay:
$("#name").on('keyup', function (){
var $this = $(this);
setTimeout(function() {
$this.trigger('focusout');
}, 1000); // milliseconds
});
Alternatively, use an external callback function for both, using .call() to pass along the same element as this:
$("#name").on('keyup', function() {
var el = this;
setTimeout(function() { callbackFunc.call(el) }, 1000); // milliseconds
});
$("#name").on('focusout', callbackFunc);

I try to call .hide() after 1sec (using setTimeout), but it's executed directly, why?

I try to hide a subnavigation when mouseout (second function in .hover()) after 1sec and for that I using setTimeout. I need the this variable in the inner function of setTimeout, so I try it like this:
jQuery(".topnav > ul > li").hover(function() {
jQuery("ul.topnavsub").hide();
jQuery(this).find("ul.topnavsub").show();
}, function() {
var t = setTimeout((function(that){jQuery(that).find("ul.topnavsub").hide(); console.log(that);})(this), 1000);
});
This works but with no delay. 1. Why is there not a 1000milisec deplay and 2. How would I have to do that it works correctly?
If I get this working I want to add: when entering the subnav in that 1000milisec, the setTimeout stops, so that the nav does not get hidden. That's what I have but I couldn't test it cause the hole setTimeout-thing don't work:
jQuery(".topnav > nav > ul > li").hover(function() {
jQuery("ul.topnavsub").off();
jQuery("ul.topnavsub").hide();
jQuery(this).find("ul.topnavsub").show();
}, function() {
var t = setTimeout((function(that){jQuery(that).find("ul.topnavsub").hide(); console.log(that);})(this), 1000);
jQuery(this).find("ul.topnavsub").on("mouseenter", function() {
clearTimeout(t);
jQuery(this).off();
});
});
The anonymous function is being self executed.
var t = setTimeout((function(that){
jQuery(that).find("ul.topnavsub").hide();
console.log(that);
})(this), //(this) is self executing
1000);
});
Alternative:
var that = this;
var t = setTimeout(function(){
jQuery(that).find("ul.topnavsub").hide();
console.log(that);
},1000);
The convoluted way :
var t = setTimeout((function(that){ return function(){
jQuery(that).find("ul.topnavsub").hide();
console.log(that);
}
})(this), 1000);
The less-cool-but-still-works-(-and-is-probably-more-readable-) way :
var that = this;
var t = setTimeout(function(){
jQuery(that).find("ul.topnavsub").hide();
console.log(that);
}, 1000);
It's because you executing a function and pass undefined to setTimeout
var t = setTimeout((function(that){
jQuery(that).find("ul.topnavsub").hide();
console.log(that);
})(this), 1000);
just remove (this) from the end of the function
var self = this;
var t = setTimeout(function(){
jQuery(self).find("ul.topnavsub").hide();
console.log(self);
}, 1000);

Resetting a setTimeout

I have the following:
window.setTimeout(function() {
window.location.href = 'file.php';
}, 115000);
How can I, via a .click function, reset the counter midway through the countdown?
You can store a reference to that timeout, and then call clearTimeout on that reference.
// in the example above, assign the result
var timeoutHandle = window.setTimeout(...);
// in your click function, call clearTimeout
window.clearTimeout(timeoutHandle);
// then call setTimeout again to reset the timer
timeoutHandle = window.setTimeout(...);
clearTimeout() and feed the reference of the setTimeout, which will be a number. Then re-invoke it:
var initial;
function invocation() {
alert('invoked')
initial = window.setTimeout(
function() {
document.body.style.backgroundColor = 'black'
}, 5000);
}
invocation();
document.body.onclick = function() {
alert('stopped')
clearTimeout( initial )
// re-invoke invocation()
}
In this example, if you don't click on the body element in 5 seconds the background color will be black.
Reference:
https://developer.mozilla.org/en/DOM/window.clearTimeout
https://developer.mozilla.org/En/Window.setTimeout
Note: setTimeout and clearTimeout are not ECMAScript native methods, but Javascript methods of the global window namespace.
You will have to remember the timeout "Timer", cancel it, then restart it:
g_timer = null;
$(document).ready(function() {
startTimer();
});
function startTimer() {
g_timer = window.setTimeout(function() {
window.location.href = 'file.php';
}, 115000);
}
function onClick() {
clearTimeout(g_timer);
startTimer();
}
var myTimer = setTimeout(..., 115000);
something.click(function () {
clearTimeout(myTimer);
myTimer = setTimeout(..., 115000);
});
Something along those lines!
For NodeJS it's super simple:
const timeout = setTimeout(...);
timeout.refresh();
From the docs:
timeout.refresh()
Sets the timer's start time to the current time, and reschedules the timer to call its callback at the previously specified duration adjusted to the current time. This is useful for refreshing a timer without allocating a new JavaScript object.
But it won't work in JavaScript because in browser setTimeout() returns a number, not an object.
This timer will fire a "Hello" alertbox after 30 seconds. However, everytime you click the reset timer button it clears the timerHandle then re-sets it again. Once it's fired, the game ends.
<script type="text/javascript">
var timerHandle = setTimeout("alert('Hello')",3000);
function resetTimer() {
window.clearTimeout(timerHandle);
timerHandle = setTimeout("alert('Hello')",3000);
}
</script>
<body>
<button onclick="resetTimer()">Reset Timer</button>
</body>
var redirectionDelay;
function startRedirectionDelay(){
redirectionDelay = setTimeout(redirect, 115000);
}
function resetRedirectionDelay(){
clearTimeout(redirectionDelay);
}
function redirect(){
location.href = 'file.php';
}
// in your click >> fire those
resetRedirectionDelay();
startRedirectionDelay();
here is an elaborated example for what's really going on http://jsfiddle.net/ppjrnd2L/
i know this is an old thread but i came up with this today
var timer = []; //creates a empty array called timer to store timer instances
var afterTimer = function(timerName, interval, callback){
window.clearTimeout(timer[timerName]); //clear the named timer if exists
timer[timerName] = window.setTimeout(function(){ //creates a new named timer
callback(); //executes your callback code after timer finished
},interval); //sets the timer timer
}
and you invoke using
afterTimer('<timername>string', <interval in milliseconds>int, function(){
your code here
});
$(function() {
(function(){
var pthis = this;
this.mseg = 115000;
this.href = 'file.php'
this.setTimer = function() {
return (window.setTimeout( function() {window.location.href = this.href;}, this.mseg));
};
this.timer = pthis.setTimer();
this.clear = function(ref) { clearTimeout(ref.timer); ref.setTimer(); };
$(window.document).click( function(){pthis.clear.apply(pthis, [pthis])} );
})();
});
To reset the timer, you would need to set and clear out the timer variable
$time_out_handle = 0;
window.clearTimeout($time_out_handle);
$time_out_handle = window.setTimeout( function(){---}, 60000 );

Categories

Resources