I have a search input that listens to keyup
and change
to trigger an update of a listview via Ajax.
Looks like this:
input.on
I would try to set up a value-checking function like this:
var $inputIntance = $("#path-to-your-input");
var lastInputValue;
function checkInputValue () {
var newValue = $inputIntance.val();
if (newValue != lastInputValue) {
// make your AJAX call here
lastInputValue = newValue;
el = $inputIntance.closest('ul');
widget[func](dyn, el, lib_template, locale, lastInputValue, "update");
}
}
and then then fire this checks by any user-action event you like:
$inputIntance.on('keyup change', function(e) {
checkInputValue();
}
or like this
$inputIntance.on('keyup change', checkInputValue );
UPDATE: there might be the case when you have to limit the number of AJAX requests per time. I added time control functionality to my previous code. You can find the code below and try it live here in JSFiddle.
$(document).ready(function () {
var $inputIntance = $("#test-input");
var lastInputValue;
var valueCheckTimer;
var MIN_TIME_BETWEEN_REQUESTS = 100; //100ms
var lastCheckWasAt = 0;
function checkInputValue () {
lastCheckWasAt = getTimeStamp();
var newValue = $inputIntance.val();
if (newValue != lastInputValue) {
// make your AJAX call here
lastInputValue = newValue;
$("#output").append("<p>AJAX request on " + getTimeStamp() + "</p>");
//el = $inputIntance.closest('ul');
//widget[func](dyn, el, lib_template, locale, lastInputValue, "update");
}
}
function getTimeStamp () {
return (new Date()).getTime();
}
function checkInputValueScheduled() {
if (valueCheckTimer) { // check is already planned: it will be performed in MIN_TIME_BETWEEN_REQUESTS
return;
} else { // no checks planned
if ((getTimeStamp() - lastCheckWasAt) > MIN_TIME_BETWEEN_REQUESTS) { // check was more than MIN_TIME_BETWEEN_REQUESTS ago
checkInputValue();
} else { // check was not so much time ago - schedule new check in MIN_TIME_BETWEEN_REQUESTS
valueCheckTimer = window.setTimeout(
function () {
valueCheckTimer = null;
checkInputValue();
},
MIN_TIME_BETWEEN_REQUESTS
);
}
}
}
$inputIntance.bind('keyup change', function(e) {
$("#output").append("<p>input event captured</p>");
checkInputValueScheduled();
});
});
Any reason for listening to keyUp
in addition to change
? Maybe what really matters is just one of these events.
If not, I guess you will have to use a closure as you suggested.
If one is triggered first, then delete the other.
const handler = e => {
const eventType = e.type === 'mousedown' ? 'click' : 'mousedown';
window.removeEventListener(eventType, handler);
};
window.addEventListener('click', handler);
window.addEventListener('mousedown', handler);
I came across this problem before and what I ended up doing is saving the request on an object upon creation and test for a previously set one to abort it if necessary. You'd have to edit the function that triggers the ajax call. For example:
if ( ajaxRequest ) {
ajaxRequest.abort();
}
ajaxRequest = $.ajax({ ... }); // triggers ajax request and saves it
If the widget
function returns an ajax object then you can probably assign that to the variable instead of modifying the original ajax request.
Ok. I got it (after a felt 1000 tries...).
Here is what works = triggers whichever event fires first, blocks the trailer:
var isEven;
input.on('keyup change', function(e) {
isEven = true;
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout( function() {
timer = null;
val = input.val();
el = input.closest('ul');
// prevent double firing after interval passed
if (isEven === true ){
isEven = false;
} else {
isEven = true;
return;
}
widget[func](dyn, el, lib_template, locale, val, "update");
}, interval );
});
Seems to do what it should. Feel free to correct me, if it's wrong.