While the other proposed solutions (on blur or on keydown if it's the enter key), would work, I think they're not what you're looking for.
What if the user neither clicks outside the textarea, nor uses enter? I would use a technique called debounce instead. You can read about it for example here: https://davidwalsh.name/javascript-debounce-function or see an example here: https://www.geeksforgeeks.org/debouncing-in-javascript/
The short version is, it only calls a function after an event has stopped firing for a given length of time.
Add the debounce function to your code by either using an NPM package (ex. https://www.npmjs.com/package/debounce) or directly adding the necessary code:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
Source: https://davidwalsh.name/javascript-debounce-function which has taken it from Underscore.js
Then have a function doing your ajax calls like:
var makeAjaxCall = function(e) {
$.ajax({ ... });
};
Now you can simply add a listener like:
var minTimeoutBetweenCallsInMilliSeconds = 500;
notesTextarea.on('change', debounce(makeAjaxCall, minTimeoutBetweenCallsInMilliSeconds));
Now the makeAjaxCall function would be called only 500ms after the last change event occurred, a.k.a. the user stopped typing.