Ethan Aaron Vandal Ethan Aaron Vandal - 3 months ago 39
Javascript Question

How to setInterval on ready, stop on textarea focus, then start on textarea focusout?

I have a social stream that I want to update with setInterval. SetInterval needs to be stopped when someone is leaving a comment or a reply otherwise it clears the content of the textarea because it is nested inside the content being updated.

I'm attempting to use this code, modified, from another answer, but it is failing in that it won't stop the timer after the first cycle of the setInterval timer.

HTML...

<div id="social_stream_content">
<textarea id="comments" rows="4" cols="50" placeholder="Set focus to stop timer"></textarea>
</div>


JS...

function auto_load(){
data = '<textarea id="comments" rows="4" cols="50" placeholder="Set focus to stop timer..."></textarea>';
$("#social_stream_content").html(data);
alert("auto_load invoked");
}

var myInterval;
var interval_delay = 10000;
var is_interval_running = false; //Optional

$(document).ready(function(){
auto_load(); //Call auto_load() function when document is Ready

//Refresh auto_load() function after 10000 milliseconds
myInterval = setInterval(interval_function, interval_delay);

$('textarea').focus(function () {
console.log('focus');
clearInterval(myInterval); // Clearing interval on window blur
is_interval_running = false; //Optional
}).focusout(function () {
console.log('focusout');
clearInterval(myInterval); // Clearing interval if for some reason it has not been cleared yet
if (!is_interval_running) //Optional
myInterval = setInterval(interval_function, interval_delay);
});
});

interval_function = function () {
is_interval_running = true; //Optional
// Code running while textarea is NOT in focus
auto_load();
}


Edit: I've updated the code to include everything as tested on JSfiddle. The timer will stop if you immediately set focus to the comment textarea after closing the alert at document ready.

After removing focus, and the first cycle of the interval timer completes, the timer will not stop again. The focus event seems to stop firing.

Is this because the comment textarea is nested inside the content area that is updating? I'm pulling my hair out. If I remove the nesting, it works as expected.

My caveat is that the comment textareas are always going to be nested inside of the social stream's content div, for obvious reasons.

So, to update the question further: Is there a way to get the interval timer to stop on textarea focus using jquery, while the focused element is nested inside the updating element? Why does the focus event stop firing after the first interval completes?

Edit: The complete JS code, working coreectly, with Jeremy Klukan's solution incorporated, for anyone doing the same type of project.

WORKING JS:

function auto_load(){
data = '<textarea id="comments" rows="4" cols="50" placeholder="Set focus to stop timer..."></textarea>';
$("#social_stream_content").html(data);
alert("auto_load invoked");
}

var myInterval;
var interval_delay = 10000;
var is_interval_running = false; //Optional

$(document).ready(function(){
auto_load(); //Call auto_load() function when document is Ready

//Refresh auto_load() function after 10000 milliseconds
myInterval = setInterval(interval_function, interval_delay);

$('body').on('focus', '#social_stream_content textarea', function (event) {
console.log('focus');
clearInterval(myInterval); // Clearing interval on window blur
is_interval_running = false; //Optional
}).on('focusout', '#social_stream_content textarea', function(event) {
console.log('focusout');
clearInterval(myInterval); // Clearing interval if for some reason it has not been cleared yet
if (!is_interval_running) //Optional
myInterval = setInterval(interval_function, interval_delay);
});
});

interval_function = function () {
is_interval_running = true; //Optional
// Code running while textarea is NOT in focus
auto_load();
}

Answer

The focus event stops working, because when your interval function fires, it is replacing the contents of the DIV that contains it, so that TEXTAREA no longer exists.

Do this instead:

$('body').on('focus', '#social_stream_content textarea', function (event) {
  // Focus handler
}).on('focusout', '#social_stream_content textarea', function(event) {
  // Focusout handler
});

This will capture all focus and focusout events that match the selector "#social_stream_content textarea" without directly attaching to either object.

Comments