Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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();
}
like image 614
Ethan Aaron Vandal Avatar asked Aug 04 '16 05:08

Ethan Aaron Vandal


1 Answers

You can detect focus and blur for a textarea using addEventListener (events: focus and blur).

You can end a setInterval() using clearInterval() passing anintervalID.

Below a simple working example showing the principal (in vanilla JavaScript).

Basically:

  • When page load timer starts.
  • When user focus textarea timer stops.
  • When user blur textarea timer starts again.

Documentation:

WindowTimers.clearInterval()

WindowTimers.setInterval()

You may also find of interest Document.activeElement.

window.app = {
  timerRef: null,
  timerStart: function() {
    this.timerRef = setInterval(function() {
      //alert("Hello");
      console.log('refresh stream');
    }, 2000);
  },
  timerStop:function(){
      clearInterval(this.timerRef);
  },
  txtAreaListenFocus: function() {
    var txtArea = document.getElementById('txtArea');
    txtArea.addEventListener('focus', function(event) {
       this.timerStop();
      console.log('focus');
    }.bind(this));
  },
  txtAreaListenBlur: function() {
    var txtArea = document.getElementById('txtArea');
    txtArea.addEventListener('blur', function(event) {
      this.timerStart();
      console.log('blur');
    }.bind(this));
  },
  start: function() {
    this.timerStart();
    this.txtAreaListenFocus();
    this.txtAreaListenBlur();
  }

};

window.app.start();
<textarea id="txtArea" rows="4" cols="50">
  Some content here
</textarea>

Jquery version below. You can use .focusout() and .focusin():

$(document).ready(function(){
window.app = {
  timerRef: null,
  timerStart: function() {
    this.timerRef = setInterval(function() {
      //alert("Hello");
      console.log('refresh stream');
    }, 2000);
  },
  timerStop:function(){
      clearInterval(this.timerRef);
  },
  txtAreaListenFocus: function() {
    $('#txtArea').focusin(function(event) {
       this.timerStop();
      console.log('focus');
    }.bind(this));
  },
  txtAreaListenBlur: function() {
    $('#txtArea').focusout(function(event) {
      this.timerStart();
      console.log('blur');
    }.bind(this));
  },
  start: function() {
    this.timerStart();
    this.txtAreaListenFocus();
    this.txtAreaListenBlur();
  }

};

window.app.start();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="txtArea" rows="4" cols="50">
  Some content here
</textarea>

Regarding specifically your code in question, I have fix it in the working example below.

   $(document).ready(function() {
  var myInterval;
  var interval_delay = 1000;
  var is_interval_running = false; //Optional
  var interval_function = function() {
is_interval_running = true; //Optional
console.log('refresh stream');
// Code running while comment textarea is not in focus
//auto_load();
  };

  //auto_load(); //Call auto_load() function when DOM is Ready

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

  $('#textarea').focus(function() {
clearInterval(myInterval); // Clearing interval on window blur
is_interval_running = false; //Optional
  }).focusout(function() {
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);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="textarea" rows="4" cols="50">
  Some content here
</textarea>
like image 103
GibboK Avatar answered Sep 28 '22 05:09

GibboK