I'm making a list filter and want a delay in case the user is a fast typer. Looking at different solutions for similar questions hasn't helped me and I don't understand the logic they implement.
This is my current code:
$.fn.filterList = function(){
var inputFilter = $(this);
var list = $('#' + inputFilter.data('list'));
var listItems = list.children('li');
inputFilter.keyup(function(){
setTimeout(function () {
var term = inputFilter.val().toLowerCase();
listItems.each(function(i, e){
var city = ($(e).text()).toLowerCase();
if(city.startsWith(term)){
console.log(city);
}
});
}, 800);
});
};
$('.my-input').filterList();
The problem with this is that it will trigger on each keyup, no matter how fast the user types.
How can I implement a delay so that it does not trigger for each keyup?
On each successive keypress you need to clear the previous timer so that the function only fires X milliseconds after typing ends. Try this:
var timer;
inputFilter.keyup(function() {
clearTimeout(timer);
timer = setTimeout(function() {
var term = inputFilter.val().toLowerCase();
listItems.each(function(i, e) {
var city = $(e).text().toLowerCase();
if (city.startsWith(term)) {
console.log(city);
}
});
}, 800);
});
Here's a simplified working example:
var timer;
$('#foo').keypress(function() {
clearTimeout(timer);
timer = setTimeout(function() {
$('div').fadeIn('fast').delay(1000).fadeOut('fast');
}, 800);
});
div { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="foo" />
<div>You stopped typing 1 second ago</div>
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
inputFilter.keyup(function() {
delay(function(){
var term = inputFilter.val().toLowerCase();
listItems.each(function(i, e){
var city = ($(e).text()).toLowerCase();
if(city.startsWith(term)){
console.log(city);
}
});
}, 800 );
});
try the following code:
Html:
<input type="text" id="inputtext" />
Jquery code:
<script type="text/javascript">
$(document).ready(function () {
$('#inputtext').keyup(function () {
setTimeout(function () {
alert("Hi");
}, 5000);
});
});
</script>
On each keyup count clicks and after some of them trigger function.
Pro-tip: And use
.on('keyup', function(){}).
Related
I have a search field to allow users to filter the results that are returned from the database. I have it set so that the search field has a .on('input', function() { which will trigger another function.
This poses a problem in which if a user was to search for "crumble" the ajax request will be triggered for each character the user types in.
Is there a way to delay the JavaScript so that if the user is searching for a product, the function isn't fired for each character inputted, but will trigger when detected that the user hasn't typed something further in. I.E. when the user is done typing in what that are searching.
Code:
$(document).ready(function () {
$('#cards-search').on('input', function() {
cards_page = ''
cards_search = this.value;
get_card_data()
});
});
try this, this is called debouncing in case u need to search more about it
$(document).ready(function () {
let oldTimeout = null;
let timeToWaitBeforeSending = 1000 //ms
$('#cards-search').on('input', function () {
if (oldTimeout !== null) {
clearTimeout(oldTimeout);
}
timout = setTimeout(() => {
cards_page = '';
cards_search = this.value;
get_card_data();
}, timeToWaitBeforeSending );
});
});
// Run javascript function when user finishes typing instead of on key up?
var typingTimer;
var doneTypingInterval = 5000;
//on keyup, start the countdown
$('#cards-search').on('keyup', function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('#cards-search').on('keydown', function () {
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
//do something
console.log("DOne");
}
Following VLAZ advice I looked into debouncing and it is exactly what I needed.
I followed the steps here
HTML:
<input type="search" id="cards-search" onkeyup="cardSearchChange()"...
Javascript:
function debounce(func, timeout = 250){
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => { func.apply(this, args); }, timeout);
};
}
function card_search() {
cards_page = '';
cards_search = document.getElementById('cards-search').value;
get_card_data();
}
cardSearchChange = debounce(() => card_search());
I have a map with multiple cities on it. I also have a loop showing the details of each city. I would like to completely stop the loop once I click on one of the cities.
I tried with: clearTimeout(loopIdx) but it didn't work. Could you please help me?! Cheers.
LOOP:
$(function() {
var $mapCol = $('.map-col');
var $mapBtn = $('.map-btn');
var $mapLoops = $('.map-loop');
var $btnLoops = $('.btn-loop');
loopIdx = (function _loop(idx) {
$mapCol.removeClass('active-map');
$mapBtn.removeClass('active-btn');
$mapLoops.removeClass('active-map').eq(idx).addClass('active-map');
$btnLoops.removeClass('active-btn').eq(idx).addClass('active-btn');
setTimeout(function() {
_loop((idx + 1) % $mapLoops.length);
}, 6000);
}(0));
});
BTN:
<div class="btn-loop">City</div>
Assign the result of setInterval() to a variable, and use that in the clearTimeout() call.
$(function() {
var $mapCol = $('.map-col');
var $mapBtn = $('.map-btn');
var $mapLoops = $('.map-loop');
var $btnLoops = $('.btn-loop');
var timer;
loopIdx = (function _loop(idx) {
$mapCol.removeClass('active-map');
$mapBtn.removeClass('active-btn');
$mapLoops.removeClass('active-map').eq(idx).addClass('active-map');
$btnLoops.removeClass('active-btn').eq(idx).addClass('active-btn');
timer = setTimeout(function() {
_loop((idx + 1) % $mapLoops.length);
}, 2000);
}(0));
$btnLoops.click(function() {
clearTimeout(timer);
});
});
.map-loop.active-map {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="btn-loop">City</div>
<div class="map-loop">1</div>
<div class="map-loop">2</div>
<div class="map-loop">3</div>
<div class="map-loop">4</div>
<div class="map-loop">5</div>
<div class="map-loop">6</div>
<div class="map-loop">7</div>
You need to access the timeoutID by name or identifier to clear it. (See https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout.)
If you want loopIdx to be the identifier, you can use something like:
let needToClear = false;
let loopIdx = setTimeout(function(){}, 6000);
// ...state changes here...
if(needToClear){ clearTimeout(loopIdx); }
I wrote the function for check if button was clicked twice and if it was to measure the time between two clicks. It has to prevent multiple clicks in short time.
Button click:
$("#Save").click(function () {
dateTime1 = new Date().getTime();
BtnId = this.id;
showSaveDialog();
});
And measuring function:
ButtonWasTriggeredTwice: function () {
var result = false;
var currentTime = new Date().getTime();
var time = currentTime - dateTime1;
if (PreviousBtn === null) {
result= false;
} else {
if (PreviousBtn === BtnId) {
if ( time < 1500) {
result = true;
}
else result = false;
}
else {
result= false;
}
}
PreviousBtn = BtnId;
BtnId = null;
return result;
}
BtnId and PreviosusBtn are global scope variables.
The strange thing is this function works great when I set breakpoints in debugger. If I switch off debugger function blocks every next click on button, no matter what time interval is between clicks
You can use this solution with unbind and timeout, like this:
HTML
<input type="button" id="Save" value="save me" />
JS:
function saveEventButton(){
$("#Save").click(function () {
alert('saved!');
$("#Save").unbind('click');
setTimeout(function(){
saveEventButton();
}, 5000); // 5sec
});
}
saveEventButton();
This is the JSFiddle
UPDATE This solution is a mix from mine and Revish Patel solution
function disableTimeout(_this){
$(_this).prop('disabled','disabled');
setTimeout(function(){
$(_this).prop('disabled','');
}, 5000); // 5sec
}
$("#Save").click(function () {
alert('saved!');
disableTimeout(this);
});
This is the JSfiddle
You can also disable button when you first click is performed.
$(document).ready(function () {
$("#Save").click(function(){
$('#Save').prop('disabled','disabled');
// Perform your button click operation
});
});
This is a followup to this question, where I found out how to make code be repeated every x seconds. Is it possible to make an event that can change this? I.e. I have a checkbox which is meant to control whether this is repeated or not, so I figured I'd need something like this:
$(checkbox).bind("change", function() {
switch(whether if it is ticked or not) {
case [ticked]:
// Make the code repeat, while preserving the ability to stop it repeating
case [unticked]:
// Make the code stop repeating, while preserving the ability to start again
}
});
I have no idea what I could put in the cases.
You can do it by assigning your setInterval function to a variable.
var interval = setInterval(function() { }, 1000);
and then you can stop setInterval by
clearInterval(interval);
p.s.
to start your interval you need to call var interval = setInterval(function() { }, 1000); again
You can either stop and start the interval:
var timer;
function start() {
timer = window.setInterval(function(){
// do something
}, 1000);
}
function stop() {
window.clearInterval(timer);
}
start();
$(checkbox).bind("change", function() {
if ($(this).is(':checked')) {
start();
} else {
stop();
}
});
Or you can have a flag causing the interval to skip the code:
var enabled = true;
var timer = window.setInterval(function(){
if (!enabled) {
// do something
}
}, 1000);
$(checkbox).bind("change", function() {
enabled = $(this).is(':checked');
});
function fooFunc() {
$('#foo').text(+new Date());
}
var id;
var shouldBeStopped = false;
$('input').change(function() {
if (shouldBeStopped)
clearInterval(id);
else
id = setInterval(fooFunc, 200);
shouldBeStopped = !shouldBeStopped;
});
Live DEMO
I'm not a JS coder my any means. I know enough to make things do what I want, but couldn't code from scratch. My issue is:
We have a shopping cart that when you add a product the cart shows itself for 4 secs unless the customer hovers over the cart. I can't seem to get it to stop the timeout when the cursor is hovered over it.
$(document).ready(function () {
setTimeout(function () { $('#ctl00_ctl00_ctlHeader_divOrderProducts').hide(); }, 4000);
});
Store the return of setTimeout() in a variable, and use that to clearTimeout():
// t is a global scope variable.
// Probably a good idea to use something better than 't'
var t;
$(document).ready(function () {
// Store the return of setTimeout()
t = setTimeout(function () { $('#ctl00_ctl00_ctlHeader_divOrderProducts').hide(); }, 4000);
});
$('cart-selector').hover(function() {
if (t) {
// Call clearTimeout() on hover()
clearTimeout(t);
}
});
You need to set your timer to a variable:
var timer1 = setTimeout(function () { ... })
then use:
clearTimeout(timer1)
You need to save the return value of setTimeout() so you can later use it with clearTimeout(). One way to that is like this:
$(document).ready(function () {
var hideTimer = setTimeout(function () {
$('#ctl00_ctl00_ctlHeader_divOrderProducts').hide();
}, 4000);
$('#ctl00_ctl00_ctlHeader_divOrderProducts').hover(function() {
if (hideTimer) {
clearTimeout(hideTimer);
hideTimer = null;
}
});
});
If you want to re-enable the timer when the mouse leaves the cart again (assuming #ctl00_ctl00_ctlHeader_divOrderProducts is the cart), you can do so like this:
$(document).ready(function () {
var hideTimer;
function delayHideCart() {
if (!hideTimer) {
hideTimer = setTimeout(function () {
$('#ctl00_ctl00_ctlHeader_divOrderProducts').hide();
}, 4000);
}
}
delayHideCart();
$('#ctl00_ctl00_ctlHeader_divOrderProducts').hover(function() {
if (hideTimer) {
clearTimeout(hideTimer);
hideTimer = null;
}
}, function() {
delayHideCart();
});
});
This should do it:
$(document).ready(function () {
var timeout = setTimeout(function () { $('#ctl00_ctl00_ctlHeader_divOrderProducts').hide(); }, 4000);
$('#ctl00_ctl00_ctlHeader_divOrderProducts').mouseover(function() {
clearTimeout(timeout);
});
});
You save the timeout as a variable and then call clearTimeout when you mouseover the cart and pass in that timeout.
var timer = window.setTimeout(function () {
$('#ctl00_ctl00_ctlHeader_divOrderProducts').hide();
if(someCondition)clearTimeout(timer);
}