Trying to run your fiddle, Chrome complains about jquery.offput.ca, which it calls a site "known to distribute malware". I get the same warning if I go to the demos for that jQuery plug-in. So I haven't been able to use that actual code. As of your update, I can use your actual code, so see the very end of this answer for an answer using your original code. I'll leave the non-timer-plugin answer in place, though.
The element may or may not remain in memory, it depends entirely on how the timers plug-in works. The important thing, though, is that regardless of whether the element is in memory, nothing is stopping the timer. You need code to do that.
I've never used that timers plug-in, but presumably it has some means of telling the timer to stop, probably via a call you make on the jQuery wrapper of the element you've attached the timer to. So in your Remove
function, you'll need a way to identify elements with timers on them so you can stop them.
Here's an example of doing that without the timers plug-in, to demonstrate the concepts. Here's how I've done this:
When I create the setInterval
timer, I remember the timer handle on an attribute called data-timer-handle
. You may or may not need that, but you'll want to put some kind of marker on the element so you can tell the timer plug-in to stop.
In Remove
, before clearing out #main
, I find any children it has with the data-timer-handle
attribute and clear the interval timer.
Live copy | source:
HTML:
<div id="main">
<div id="timerpanel">I'm the timer panel</div>
</div>
<input type="button" id="removeButton" value="Remove It">
<div id="debug"></div>
JavaScript:
function TimerTest(panelId)
{
this.PanelID = panelId;
}
TimerTest.prototype.Start = function()
{
var self = this;
// Start the timer
var handle = setInterval(function() {
self.Print();
}, 1000);
// Remember the handle on a data-timer-handle property
// on the element.
$(document.getElementById(this.PanelID)).attr("data-timer-handle", handle);
}
TimerTest.prototype.Print = function()
{
$("#debug").append("<div>triggered...</div>");
}
function Remove()
{
var main = $("#main");
// Find any elements with timers on them, stop them
main.find("[data-timer-handle]").each(function() {
clearInterval($(this).attr("data-timer-handle"));
});
main.html("I'm done!");
}
$(document).ready(function(){
var timer = new TimerTest("timerpanel");
timer.Start();
$("#removeButton").click(function() {
Remove();
});
});
If I were writing a timers plug-in that attached timers to elements, I'd definitely add something to the elements (a data-*
attribute, a class, whatever) to allow you to find them again. But then, I'd also provide an option for automatically cancelling the timer if the element is removed from the DOM (so you wouldn't need to find and stop them), by having each timer tick check to see if the element was still attached. (I probably wouldn't enable that by default, but it'd be an option.)
Re your comment below:
I have a question about your code though: It does indeed stop the timer, but how do I know it actually destroyed the TimerTest
-object? The timer was just a way for me to tell. AFAIK the timer itself didn't hold a reference to the TimerTest
-object so why is that object still alive? You can tell by modifing Print() to print "this.PanelID"`
Ah, but the timer did keep a reference to the TimerTest
instance: The function you pass into the timer is a closure. It has a reference to everything that was in scope where it was created, including the self
variable that referred to the TimerTest
object (of course, otherwise self.Print()
wouldn't work). So as long as that function exists, it will keep the TimerTest
instance in memory.
So what keeps that function in memory? The reference to it from the timer. As long as the timer is alive, it has a reference to the function, and that keeps the function in memory. In my example above, clearInterval
removes the reference to the function, making it eligible for garbage collection; which means that the function no longer keeps the things it closes over in memory. If the function was the only thing with an outstanding reference to the TimerTest
instance, that means the TimerTest
instance becomes eligible for garbage collection.
In my code, nothing kept the element in memory (that may not be true of the timers plug-in you're using), but the TimerTest
instance was kept alive by the function as long as that function was being used by the browser's setInterval
stuff.
More to explore:
And now that your fiddle doesn't link to that (perhaps) dodgy site:
I'm surprised to find that the timer plug-in doesn't seem to add anything to the element to make it easy to find again. No matter, it's trivial for us to.
Change Start
to mark the element — here I used a class:
TimerTest.prototype.Start = function()
{
var self = this;
$("#" + this.PanelID)
.addClass("hastimer")
.everyTime("1s", "Test", function(){
self.Print();
});
};
(I also used jQuery to look up the element, rather than document.getElementById
. And you want the semicolon at the end of the function expression.)
And change Remove
to stop the timer on all elements with that class:
function Remove()
{
var main = $("#main");
main.find(".hastimer").stopTime();
main.html("I'm done!");
}
(There's no need to call empty
before calling html
; html
calls empty
.)
Updated fiddle