I want to set timeouts dynamically in jQuery. The dynamically set timeout functions need to use $("this"), but I can't seem to get it working.
An exmple:
$("div").each(function(){
var content = $(this).attr('data-content')
setTimeout("$(this).html('"+content+"')",$(this).attr('data-delay'));
});
What is the best way to do this?
$("div").each(function(){
var content = $(this).attr('data-content'),
$this = $(this); // here $this keeps the reference of $(this)
setTimeout(function() {
// within this funciton you can't get the $(this) because
// $(this) resides within in the scope of .each() function i.e $(this)
// is an asset of .each() not setTimeout()
// so to get $(this) here, we store it within a variable (here: $this)
// and then using it
$this.html(content);
}, $this.attr('data-delay'));
});
Your code should look like this:
pass a function instead of a string. Explanation: When passing a string to setTimeout you get problems, because it runs in a different scope than you original one, and thus you get errors.
use the jQuery data()
method
$("div").each(function(){ var content = $(this).attr('data-content'), $el = $(this), setContent = function(){ $el.html(content); } setTimeout(setContent,$el.data('delay')); });
You can assign a function to a variable and pass that variable as parameter to setTimeout, this is the cleanest way.
Use closures ( some tutorials ).
Using strings with setTimeout
is not a good idea. Also beware this
, since it can change its context ( ie. call-site ) if used inside a closure.
If using data attributes you can use the jQuery data function.
$("div").each(function() { var instance = $(this); var content = instance.data('content'); var method = function() { instance.html(content); }; setTimeout(method, instance.data('delay')); });
div { border: 1px solid black; margin: 5px; height: 1.5em; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div data-content="fus" data-delay="1000"></div> <div data-content="ro" data-delay="2000"></div> <div data-content="dah" data-delay="5000"></div>
I am just expanding answer one above,
So your updated HTML is,
<div data-content="fus" data-delay="1000" class="dv"></div>
<div data-content="ro" data-delay="2000" class="dv"></div>
<div data-content="dah" data-delay="5000" class="dv"></div>
Now your updated JavaScript code is,
$(".dv").each(function(){
var content = $(this).attr('data-content'),
$this = $(this);
setTimeout(function() {
$this.html(content);
}, $this.attr('data-delay'));
});
Where main line is
$this = $(this);
Where we are assigning the current element to our variable used in the setTimeout function.
Please refer this link
Take $(this) out of settimeout and save that in local variable say 'self' just after $("div").each(function(){ this line
var self=$(this);
and use that self further.
The following seems like a good compromise of whitespace, readability and revealing intention.
$('div').each(function(){
var element = $(this)
var content = element.attr('data-content')
var delayms = element.attr('data-delay')
var action = function() { element.html(content) }
setTimeout(action, delayms)
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.