Spyros Rallis Spyros Rallis - 4 months ago 7
jQuery Question

Hiding content with jQuery, after a time period specified with an HTML class name

I am trying to hide some content after a specific time, with JavaScript / jQuery parsing the class list to figure out the time. To make it more clear, I'm giving these examples:

<div id="one" class="some-class some-other-class timeout-3500"> </div>
<div id="two" class="another-irrelevant-class timeout-2000"> </div>


The script should hide
div
"one" after 3500ms, and
div
"two" after 2000ms.

My code so far, combining the jQuery library with vanilla JavaScript, is as follows:

$('div[class*="timeout-"]').each(function()
{
var classList = $(this).attr('class').split(/\s+/);

var timeoutDelay;

for (var i = 0; i < classList.length; i++)
{
if (classList[i].includes('timeout-'))
{
timeoutDelay = parseInt(classList[i].split('-').pop(), 10);

setTimeout(function()
{
$(this).hide();
}, timeoutDelay);
}
}
});


Here's a (non-working) fiddle to demonstrate: https://jsfiddle.net/56o57t0j/.

The
setTimeout
fires, but
$(this).hide();
does nothing. It's like nothing is selected with jQuery (which of course isn't true, since all the code is inside a selector block with
each()
appended).

Any help with this? It has been troubling me since the morning. Thanks in advance.

Answer

You need to bind your timeout function with the correct scope. Scope and binding is a fairly advanced topic in JS that can be confusing at first, but since the "timeout" is being executed asynchronously, it is actually executed outside the scope of the parent "each" loop. Therefore, "this" is not known at the time of execution. If you bind the function like below, it will work:

setTimeout(function() {
    $(this).hide();
}.bind(this), timeoutDelay);

I have forked your fiddle with a working example: https://jsfiddle.net/jg7m6cyu/1/

MDN has a great article on how "bind" works. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Comments