suggestion list catching user input delay - javascript

I wrote below code to retrieve suggestion using ajax when the user is typing. The problem is the call may be too many so I used setTimeout. Is my flow done correctly?
$('.text').on('keydown', function(e) {
if ($(this).val().length >= 3) {
var suggestionURL = "example.com?q"
+ $(this).val();
setTimeout(function(){
show_suggestion();
}, 1000);
function show_suggestion(){
// $.ajax..
}
}
});

You can use setTimeout() and clearTimeout() for this. This will ensure that the function is only called it the user has typed more than 3 characters and has stopped typing for at least half a second. Adjust the time as needed:
$(function() {
var timeOut = 0;
$(".text")
.keyup(function() {
// check input has at least 4 chars
if ($(this).val().length >= 3) {
// cancel looking, the user typed another character
clearTimeout(timeOut);
// set a timeout
// if user doesn't type another key
// within half a second the function is called
timeOut = setTimeout(function() {
show_suggestion();
}, 500); // change time as needed
}
});
});
function show_suggestion(){
alert('user stopped typing, call the ajax');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="text"/><br><br>
<input type="text" class="text"/><br><br>
<input type="text" class="text"/><br><br>
<input type="text" class="text"/><br><br>

Related

Throttling a jQuery .load() function for autocomplete

I use the following function to get autocomplete suggestions as a user types from a PHP file using jQuery .load().
How should I throttle the number of autocomplete requests being made with this function if a user is typing really fast? I'm new to this sort of thing.
<script>
function getSuggestions(){
var query = document.getElementsByName("q")[0].value;
$(document).ready(function(){
$("#suggestions").load("https://example.com/autosuggest.php", {
q: query
});
});
}
$(document).ready(function(){
let debounce;
$('.searchBox').on('keydown', function(e){
// get keycode of current keypress event
var code = (e.keyCode || e.which);
// do nothing if it's an arrow key
if(code == 37 || code == 38 || code == 39 || code == 40 || code == 13) {
return;
}
// do normal behaviour for any other key
debounce = setTimeout(() => {
getSuggestions();
}, 350);
});
$(".searchBox").click(function(){
getSuggestions();
});
});
</script>
<input class="searchBox" type="text" name="q" placeholder="" value="" onkeydown="getSuggestions()">
<div id="suggestions">
</div>
The general concept is called "debounce" - and basically you just have to set a timeout and wait to make the request for say, 500 milliseconds. Every time you receive input, you clear the timeout. Then, once they've finally stopped typing for a bit, the timeout will get triggered. Something like this (where I'm just logging the input, but you can see that it only triggers when you stop typing):
$(function() {
let debounce;
$('.searchBox').on('input', function() {
clearTimeout(debounce);
debounce = setTimeout(() => {
const value = $(this).val();
console.log({value});
/* $("#suggestions").load("https://example.com/autocomplete.php", {
q: value
}); */
}, 500);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="searchBox" type="text" name="q" placeholder="" value="">
<div id="suggestions">
</div>

How to detect `input` value changes as user typing in?

What I want to do is that, there is an input box, when user types in any thing, the code should fire a request to the server and get back some data to users.
This is just a typeahead suggestion functionality, but still not exactly the same.
What I currently have is following code
$("input").on("input", function(ev) {
alert(`${ev.type} event detected`)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" placeholder="text">
And the code works as expected, that is saying whenever the input box value changes, the event is captured.
My question is, how to make the code wait a few seconds or milli-seconds before handling the input change events? Say fire the code 1000ms later when the input stops changing.
Since now, the code will fire per every single letter I typed in, that would results into a lots of events, which I don't want.
You can set a timer when a key is pressed and if another key is pressed and the timer is still running (timer var is not null) cancel it before setting the timer again.
var timer;
$("input").on("input", function(ev) {
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function(){
console.log(`${ev.type} event detected`);
timer = null;
}, 1000);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" placeholder="text">
Here is a sample code to execute 1 seconds after done typing.
Basically what it does. it's simply setting a setTimeout if a key is pressed then clearingTimeout if another key is pressed before 1000ms. If not, setTimeout will execute.
var typingTimer;
var doneTypingInterval = 1000;
$("input[type='text']").on('input', function(e) {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
function doneTyping() {
alert("Hey!");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" placeholder="text">
All you need to do, is to set a timeout and a flag.
with each event, you set the flag to true, but when the timeout occurs, you only run your code once and then reset the flag for later events.
$("input").on("input", function(ev) {
$(this).data({
changed: true
});
window.setTimeout(() => {
if ($(this).data("changed") == true) {
alert(`${ev.type} event detected`);
$(this).data({
changed: false
});
}
}, 1000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" placeholder="text" />
To detect input value changes as user typing in , You just have to check onInput event -
$('#testId').on("input", function (e) {
var valInput = $('#testId').val();
$('#inputVal').html(valInput);
$('#inputChar').html(valInput.length);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="testId" />
<br />
<br />
<div>You typed : <strong><span id="inputVal"></span></strong> </div>
<br />
<div>No. of character : <strong><span id="inputChar">0</span></strong> </div>

OnChange event not working in Input Type = Number when click on spinner in JQuery

I have an
<input type="number" class="post-purchase-amount"/>.
I am calling an
ajax call when the value get changed. It is working (with the following code) when the cursor is in the
text box itself and doing any changes. But it not working when i click the spinner (up/down button) of the input type.
parentPanel.on("change", ".post-purchase-amount", null, function (event) {
updateAmount($(this));
});
My problem is that i could use the "input" event here but that can call the ajax
every time when in change the value like if i want to send value 65
then it calls twice when typing each number. I need to call ajax only when the value has been changed not every key
stroke.
Sorry for my English. Thanks in advance
How about you create a function to throttle the input and trigger it on keypress instead. Something like this:
function throttle(func, interval) {
var last = 0;
return function() {
var now = Date.now();
if (last + interval < now) {
last = now;
return func.apply(this, arguments);
}
};
}
parentPanel.on("keypress", ".post-purchase-amount", null, throttle(function(event) {
updateAmount($(this));
}, 800));
Your problem is that you are watching for a change and anytime you make a change this is going to fire. What you could do instead is use focusout to watch when you "exit" the number input. What the below function does is it checks to see if the previous value is equal to the new value when you exit focus on the input. If the current value is not the same then it has been updated.
var prevVal = $('.numOfPeople').val();
$('.numOfPeople').on('focusout', null, function(e) {
var curVal = $('.numOfPeople').val();
if(prevVal !== curVal) {
//Value is different so do your updates here.
preVal = curVal;
$('#changed').show();
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="numOfPeople" type="number" name="quantity" min="1" max="5">
<p id="changed" style="display: none;">Value has changed</p>

Function to disable a button if a given input text doesn't contain at least n characters

I need help with this function
function block_button(min){
current=$(this).val().length;
if(current>=min){
$(this).next().css('opacity','1');
}else{
$(this).next().css('opacity','0.5');
}
}
$('input').keyup(function(){
block_button.apply(4,this);
});
The purpose of the function is to count the length of the string while user writes and then disable or enable the button below (I changed only the opacity so this is a "visual" disable but it's intended).
The function has a number for parameter and this is the minimum string length to enable the button. The problem is that nothing happens when I reach 4 characters.
How would I be able to fix this?
You cannot use $(this) directly inside a function. Instead you should put it inside a variable before you call the function, and then use that variable inside the function:
function block_button(min){
current=$this.val().length;
if(current>=min){
$this.next().css('opacity','1');
}else{
$this.next().css('opacity','0.5');
}
}
$('input').keyup(function(){
$this = $(this);
block_button(4);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="text">
<button>Button</button>
You should instead have the button disabled by default, and then if the user enters more than X characters in the input-field, have the disabled attribut removed. If the user then deletes characters, add the attribute back again:
function disableButton(min) {
current = $this.val().length;
if (current >= min) {
$this.next().removeAttr("disabled");
} else {
$this.next().attr("disabled", "");
}
}
$('input').keyup(function() {
$this = $(this);
disableButton(4);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="text">
<button disabled>Button</button>
https://jsfiddle.net/ugeshgupta000/5grrzdnn/1/
function block_button(elem, min){
current=elem.val().length;
if(current>=min){
elem.next().css('opacity','1');
}else{
elem.next().css('opacity','0.5');
}
}
$('input').keyup(function(){
block_button($(this), 4);
});

Is there a way of binding all double click events to their single click equivalent in jQuery / JavaScript?

I have some jQuery with a lot of different click events. Some of my users are habitual double clickers, which because I have no double click events bound, fires the single click event twice; this can be a pain - for example if one click opens something, and another closes it, double clicking is a zero-sum game.
Is there any way to bind all double click events to their single click equivalent without have the code them individually?
I don't think mapping dblclick to click would help; I'd think it would make things worse, if anything.
You've said you hook up your events using delegation. You could give yourself a function that debounces calls to your event handler:
// Very simple debounce, accepts first event and disregards
// subsequent ones for a period of time
function debouncedHandler(handler, delay) {
delay = delay || 300; // milliseconds, I'm told Windows uses 500 but that seems awfully long
var last;
return function() {
var now = Date.now();
if (last && last + delay > now) {
return false;
}
last = now;
return handler.apply(this, arguments);
};
}
$(document).on("click", "input[type=button]", debouncedHandler(function() {
$(".container").toggleClass("toggle-open toggle-closed");
}));
.toggle-open .closed {
display: none;
}
.toggle-closed .open {
display: none;
}
<input type="button" value="Open/Close">
<div class="container toggle-open">
<span class="open">OPEN</span>
<span class="closed">closed</span>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
HTML
<button class="btn">
click me
</button>
JQUERY
$(document).ready(function(){
var clickDisabled = false;
$('.btn').click(function(){
if (clickDisabled)
return;
// do your real click processing here
console.log('hi');
clickDisabled = true;
setTimeout(function(){clickDisabled = false;}, 5000);
});
});
kindly check https://jsfiddle.net/05tvvaeq/
preventing click handler for 5secs (you can set the time as per your need)
check console to see the result
This is what I would do it:
<input type="hidden" id='counter' value='0'>
<input type="button" value="Save" onclick="save()">
function save(){
var counter = parseInt(document.getElementById("counter").value);
counter = counter+1;
if(counter == 1){
console.log('Saving...')
}
document.getElementById("counter").value = counter;
//after 3 seconds set counter back to 0
setTimeout(function(){
document.getElementById("counter").value = 0;
}, 3000)
}

Categories