Search and Top Navigation
#10689 open bug ()
Opened November 06, 2014 11:14AM UTC
Last modified October 05, 2017 10:28AM UTC
Tooltip memory leak - endless DOM appending
Reported by: | DysprosiumDy | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | none |
Component: | ui.tooltip | Version: | 1.11.2 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
When a tooltip is created, a hidden <div> with the class "ui-helper-hidden-accessible" is appended to the body. This <div> holds another <div> in which the contents of the tooltip is placed. However, this inner <div> is set to "display: none;" and is not being removed when the tooltip hides. This results in the "ui-helper-hidden-accessible" <div> from expanding endlessly, causing a major memory leak on pages with big tooltips.
jsFiddle
In this reduced test case I have changed the CSS of the ui-helper-hidden-accessible and its inner divs so that it becomes visible, making the problem easier to notice.
- This bug has been reproduced using jQuery UI 1.11.2 and 1.11.0. Other versions have not been tested.
- This bug even occurs on the jQuery UI Tooltip demo page itself. A simple inspection of the page shows this.
- This bug has been reproduced in both Firefox 32 and Chrome 38.
Attachments (0)
Change History (15)
Changed November 06, 2014 01:18PM UTC by comment:1
resolution: | → notabug |
---|---|
status: | new → closed |
Changed November 06, 2014 01:57PM UTC by comment:2
_comment0: | Hey Scott, \ \ How is this not a bug? What is the purpose of having a copy of the entire contents of the tooltip in the DOM until the tooltip is destroyed? In a web app that is built to stay open for a very long time, the useless divs pile up to absurd quantities. Now, if there's a particular purpose for this behavior, then I'd love to hear what it is. \ \ We have a tooltip that's a table with some information, styled. We have tooltips like that scattered all over the page. Each time a tooltip is hovered, even if just for split second, causes a complete copy of that table to be inserted into the DOM. Over time, this can build up to silly memory usage. \ \ But yeah. Can you explain what the purpose of this behavior is? It was introduced in a recent version of jQuery UI (I suspect 1.11) and it's big enough for me to have to regress to a previous version. \ \ Kind regards, \ Dys → 1415282331433857 |
---|
Hey Scott,
How is this not a bug? What is the purpose of having a copy of the entire contents of the tooltip in the DOM until the tooltip is destroyed? In a web app that is built to stay open for a very long time, the useless divs pile up to absurd quantities. Now, if there's a particular purpose for this behavior, then I'd love to hear what it is.
We have a tooltip that's a table with some information, styled. We have tooltips like that scattered all over the page. Each time a tooltip is hovered, even if just for split second, causes a complete copy of that table to be inserted into the DOM. Over time, this can build up to silly memory usage.
But yeah. Can you explain what the purpose of this behavior is? It was introduced in a recent version of jQuery UI (I suspect 1.11) and it's big enough for me to have to regress to a previous version.
Kind regards,
Dys
P.S. I'm not aware of any other tooltip plugin that has the same behavior.
Changed November 06, 2014 02:06PM UTC by comment:3
Replying to [comment:2 DysprosiumDy]:
Hey Scott, How is this not a bug? What is the purpose of having a copy of the entire contents of the tooltip in the DOM until the tooltip is destroyed? In a web app that is built to stay open for a very long time, the useless divs pile up to absurd quantities. Now, if there's a particular purpose for this behavior, then I'd love to hear what it is.
Just look at the source, it's documented pretty clearly: https://github.com/jquery/jquery-ui/blob/20a636844961a1fb2de7a892ab28890091822e6a/ui/tooltip.js#L270
We have a tooltip that's a table with some information, styled. We have tooltips like that scattered all over the page. Each time a tooltip is hovered, even if just for split second, causes a complete copy of that table to be inserted into the DOM. Over time, this can build up to silly memory usage.
Unfortunately, there's nothing we can do about this right now. Accessibility is more important here.
But yeah. Can you explain what the purpose of this behavior is? It was introduced in a recent version of jQuery UI (I suspect 1.11) and it's big enough for me to have to regress to a previous version.
It makes the content accessible in the only way that we can find to work across multiple assistive technologies.
Kind regards, Dys P.S. I'm not aware of any other tooltip plugin that has the same behavior.
Of course, because most developers completely ignore accessibility.
Changed November 06, 2014 02:38PM UTC by comment:4
Thank you for your answers. They are much appreciated. I understand the reasoning behind this design now (and I feel your pain for having to do it this way), but the fact remains that this implementation is less than desirable. It's not the expected behavior for end users and it's not documented outside the source code.
This behavior is also applied to delegated tooltips, which makes the problem worse, because delegated tooltips are rarely destroyed. There has also never been a reason to do so. I've taken the liberty to look at some code on other websites I've worked on and see the same problem. Pages that don't reload (particularly web apps) create quite big memory leaks all around. This problem did not occur in older versions of jQuery UI. It's bad enough that we'd rather regress to an older version to prevent this issue... and we'd really like to keep all our projects up to date with the latest versions of jQuery / jQuery UI.
I do understand that accessibility is important, but in all the cases I've observed in our personal projects, it didn't matter. None of these tooltips are meant to be read aloud. They are however meant to be shown incredibly often on a page that doesn't reload. Gaining accessibility in favor of a memory leak seems like a bad tradeoff. Perhaps we could look for a way to allow for both? Maybe through an option?
I really hope this issue can be addressed in future updates. I also hope we can both agree that this behavior is less than desirable at least. Marking it as "not a bug" is one thing, but maybe it could still be marked as "bad side-effect"?
Changed November 06, 2014 02:43PM UTC by comment:5
resolution: | notabug |
---|---|
status: | closed → reopened |
Replying to [comment:4 DysprosiumDy]:
Thank you for your answers. They are much appreciated. I understand the reasoning behind this design now (and I feel your pain for having to do it this way), but the fact remains that this implementation is less than desirable. It's not the expected behavior for end users and it's not documented outside the source code.
Yeah, it's really unfortunate that accessibility usually comes at the cost of hacks and mangled code.
I do understand that accessibility is important, but in all the cases I've observed in our personal projects, it didn't matter. None of these tooltips are meant to be read aloud. They are however meant to be shown incredibly often on a page that doesn't reload. Gaining accessibility in favor of a memory leak seems like a bad tradeoff. Perhaps we could look for a way to allow for both? Maybe through an option?
We will never add an option to disable accessibility. Perhaps we can dynamically create and destroy the entire live region based on a timer after all tooltips are closed.
I really hope this issue can be addressed in future updates. I also hope we can both agree that this behavior is less than desirable at least. Marking it as "not a bug" is one thing, but maybe it could still be marked as "bad side-effect"?
I'll re-open to see if the dynamic creation will work. Hopefully completely removing the element will address the JAWS problem.
Changed November 06, 2014 02:50PM UTC by comment:6
status: | reopened → open |
---|
Changed November 06, 2014 03:12PM UTC by comment:7
Thank you very much!
Changed January 31, 2015 02:10AM UTC by comment:8
I've seen this too. It's quite painful:
I have a dense menu with a lot of controls - each with a tooltip, and if you move the mouse over
the menu, tooltips go up and down quite frequently, causing a lot of these hidden divs to be created.
I work in accessibility, so I'm not against it :-) But this behavior really isn't helpful in the
sense that one mouse movement is giving a log that has the same data repeated 10s of times.
Suggestion: Set a timer and only make a log entry when a tooltip stays up for some reasonable
minimum time - say a second or two. That would keep the log, but reduce the noise. (Note that
virtual mice can move more slowly than real ones.)
Suggestion: Number the log entries. If making an entry that is within a reasonable window of
another copy of the same text, enter something like "Dup of #10" instead.
In both cases, note that bandwidth to the user is also a precious resource - voice and Braille are both
slower than optical reading. So avoiding thrash and collapsing duplicates is a good thing.
Changed March 18, 2015 08:02PM UTC by comment:9
My team found this problem while working on production site today. Worried I might have to abandon current release version.
Changed March 18, 2015 08:06PM UTC by comment:10
I ran into this today, very unfortunate.
Changed May 07, 2015 02:34PM UTC by comment:11
I did found the resolution. We can utilize "close" option of tooltip. the trick is on close option call function and use destroy method as shown below. so above fiddler example can be resolved like below.
$(document).tooltip(close: function () {$(document).tooltip('destroy'); });
Changed August 25, 2015 11:08AM UTC by comment:12
#14385 is a duplicate of this ticket.
Changed November 20, 2015 12:02AM UTC by comment:13
Created a quick hack to preserve accessibility but keep the list of created elements under control:
It cleans up the created elements, but leaves the most recently created one for accessibility's sake.
Changed October 28, 2016 05:06PM UTC by comment:14
_comment0: | Credit goes to integritydc for his workaround. I made some adjustments to have it work with delegated tooltips: \ \ $("#filters").tooltip({ \ items: ".some-class-here", \ \ close: function () { $(".ui-helper-hidden-accessible > *:not(:last)").remove(); }, \ }); → 1477680646832811 |
---|
Credit goes to integritydc for his workaround. I made some adjustments to have it work with delegated tooltips:
$("#filters").tooltip({ items: ".some-class-here", close: function () { $(".ui-helper-hidden-accessible > *:not(:last)").remove(); }, });
Changed October 05, 2017 10:28AM UTC by comment:15
I've added the workaround to my code, works nicely. What I'd still like to know is whether this is going to be fixed in 1.12.2 (or 1.13), i.e. whether the cleanup will become a "built-in" part of the close functionality.
Should I make note of removing the workaround (that I'm spreading in my code now) when upgrading?
Technically this isn't a bug. The "leak" goes away if you destroy the tooltip. If the content is so large that it's causing major memory problems for you, perhaps you should reconsider whether the content you're displaying is actually a tooltip.