I have multiple textareas on a web page like below. What happens is when you type into one of the textareas, there is a delay which triggers on keyup and then takes the text in the textarea and sends it to an AJAX call to save it. The ajax call and saving is working fine.
The issue is if I type in more than one textarea before the delay trigger runs, only the last textarea I type in is sent to an ajax call.
Currently what is happening:
What should happen:
Typing into textarea 2 should not affect the saving of textarea 1.
HTML
<div data-mid="123">
<div class="box" data-id="1">
<textarea class="note" placeholder="...write something">123</textarea>
</div>
<div class="box" data-id="2">
<textarea class="note" placeholder="...write something">1234</textarea>
</div>
<div class="box" data-id="3">
<textarea class="note" placeholder="...write something">12345</textarea>
</div>
<div class="box" data-id="4">
<textarea class="note" placeholder="...write something">123456</textarea>
</div>
</div>
Javascript
function delay(callback, ms) {
var timer = 0;
return function() {
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
callback.apply(context, args);
}, ms || 0);
};
}
function save(rootNode)
{
var note = rootNode.val();
ajaxCall(null, 2, note, false);
}
$('.box').on('keyup', 'textarea', delay(function(event) {
save($(this));
}, 2000));
The problem is that, while the function delay
would work as expected,
with a different timer
for each returned closure, the jQuery
$(box).on('keyup', 'textarea', delay(....));
will call delay
only once, and the result of that call will be
assigned to each of the textareas.
A solution would be to call the on
for each of the .box
es:
$('.box').each((_, box) => $(box).on('keyup', 'textarea', delay(function(event) {
save($(this));
}, 2000)));
or in vanilla javascriptL
document.querySelectorAll('.box textarea').forEach(
textArea => textArea.addEventListener('keyup', delay(function(event) {
save($(textArea));
}, 2000))
);
Full example in stack snippet:
function delay(callback, ms) {
var timer = 0;
return function() {
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
callback.apply(context, args);
}, ms || 0);
};
}
function save(rootNode){
var note = rootNode.val();
document.querySelector('#out').innerHTML += `Saving ${note}<br>`;
}
$('.box').each((_, box) => $(box).on('keyup', 'textarea', delay(function(event) {
save($(this));
}, 2000)));
<div data-mid="123">
<div class="box" data-id="1">
<textarea class="note" placeholder="...write something">123</textarea>
</div>
<div class="box" data-id="2">
<textarea class="note" placeholder="...write something">1234</textarea>
</div>
<div class="box" data-id="3">
<textarea class="note" placeholder="...write something">12345</textarea>
</div>
<div class="box" data-id="4">
<textarea class="note" placeholder="...write something">123456</textarea>
</div>
</div>
<div id="out"></div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>