Opened 14 years ago

Closed 14 years ago

Last modified 12 years ago

#608 closed defect (fixed)

IE 100% CPU due to BackgroundIframe (was: HtmlTooltip causes IE to run amok with onResized events)

Reported by: Hannes Wyss <hannes.wyss@…> Owned by: bill
Priority: high Milestone:
Component: General Version: 0.2
Keywords: Cc:
Blocked By: Blocking:

Description

Steps to reproduce:

  1. Visit archive.dojotoolkit.org/nightly/tests/widget/test_Tooltip.html using IE 6.0
  2. Open the Task-Manager. On my AMD 1GHz, the CPU is running at 100%.
  3. Activate all tooltips on the page. As I get to the last 4, CPU usage goes down towards 0%

HtmlToolTip? works around a positioning-bug in IE using a BackgroundIframe?:

src/widget/html/ToolTip.js:

     42     // IE bug workaround
     43     this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);

src/html.js:

    898   // TODO: this function shouldn't be necessary but setting width=height=100% doesn't work!
    899   onResized: function(){
    900     if(this.iframe && this.domNode){
    901       var w = dojo.style.getOuterWidth(this.domNode);
    902       var h = dojo.style.getOuterHeight(this.domNode);
    903       if (w  == 0 || h == 0 ){
    904         dojo.lang.setTimeout(this, this.onResized, 50);
    905         return;
    906       }
    907       var s = this.iframe.style;
    908       s.width = w + "px";
    909       s.height = h + "px";
    910     }
    911   },

AFAICS what happens is this: As the page loads, onResized events are triggered for each ToolTip? on the page.

Apparently width and height are not defined for nodes that have never been displayed. Thus bgIframe.onResized keeps retriggering itself every 50ms.

Suggested Fix: none found yet, but I'll keep looking.

Change History (6)

comment:1 Changed 14 years ago by Hannes Wyss <hannes.wyss@…>

It turns out that with the current nightly build the mentioned workaround is unnecessary (as I had hoped).

This patch shows all that's needed to get Tooltips working on IE and Firefox

diff -Nur dojo.old/src/html.js dojo/src/html.js
--- dojo.old/src/html.js  2006-04-07 10:30:05.000000000 +0200
+++ dojo/src/html.js  2006-04-07 15:50:16.938735428 +0200
@@ -817,7 +817,7 @@
  var h = dojo.style.getInnerHeight(node);
  node.style.display=oldDisplay;

- if(hasScroll) {
+ if(hasScroll && !dojo.render.html.ie) {
    desiredX -= scroll.x;
    desiredY -= scroll.y;
  }
diff -Nur dojo.old/src/widget/html/Tooltip.js dojo/src/widget/html/Tooltip.js
--- dojo.old/src/widget/html/Tooltip.js 2006-04-07 10:30:03.000000000 +0200
+++ dojo/src/widget/html/Tooltip.js 2006-04-07 15:56:00.270735428 +0200
@@ -39,9 +39,6 @@
    }^M
    this.connectNode = dojo.byId(this.connectId);^M
    ^M
-   // IE bug workaround^M
-   this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);^M
-   ^M
    dojo.widget.html.Tooltip.superclass.fillInTemplate.call(this, args, frag);^M
  },^M
  ^M

Thanks Hannes

comment:2 Changed 14 years ago by Hannes Wyss <hannes.wyss@…>

... and here is another cumulative patch that even keeps the Tooltips open when the mouse is hovering there:

diff -Nur dojo.old/src/html.js dojo/src/html.js
--- dojo.old/src/html.js  2006-04-07 10:30:05.000000000 +0200
+++ dojo/src/html.js  2006-04-07 17:23:12.058735428 +0200
@@ -523,7 +523,7 @@
    var left = getAbsoluteX(element, true);
    var right = left + getInnerWidth(element);
  }
-
+
  return (mouse.x >= left && mouse.x <= right &&
    mouse.y >= top && mouse.y <= bottom);
 }
@@ -817,7 +817,7 @@
  var h = dojo.style.getInnerHeight(node);
  node.style.display=oldDisplay;

- if(hasScroll) {
+ if(hasScroll && !dojo.render.html.ie) {
    desiredX -= scroll.x;
    desiredY -= scroll.y;
  }
diff -Nur dojo.old/src/style.js dojo/src/style.js
--- dojo.old/src/style.js 2006-04-07 10:30:05.000000000 +0200
+++ dojo/src/style.js 2006-04-07 17:24:42.154735428 +0200
@@ -292,7 +292,7 @@
      endNode = document.body.parentNode;
    }

-   if(includeScroll && node.parentNode != document.body) {
+   if(includeScroll) {
      offset -= dojo.style.sumAncestorProperties(node, typeScroll);
    }
    // FIXME: this is known not to work sometimes on IE 5.x since nodes
diff -Nur dojo.old/src/widget/html/Tooltip.js dojo/src/widget/html/Tooltip.js
--- dojo.old/src/widget/html/Tooltip.js 2006-04-07 10:30:03.000000000 +0200
+++ dojo/src/widget/html/Tooltip.js 2006-04-07 17:23:08.642735428 +0200
@@ -39,9 +39,6 @@
    }^M
    this.connectNode = dojo.byId(this.connectId);^M
    ^M
-   // IE bug workaround^M
-   this.bgIframe = new dojo.html.BackgroundIframe(this.domNode);^M
-   ^M
    dojo.widget.html.Tooltip.superclass.fillInTemplate.call(this, args, frag);^M
  },^M
  ^M

The patch reverses part of changeset 2317 and I have to admit that I do not have a complete overview of the consequences - but it does fix my problem ;)

hth.

Hannes

comment:3 Changed 14 years ago by Morris Johns

Summary: HtmlTooltip causes IE to run amok with onResized eventsIE 100% CPU due to BackgroundIframe (was: HtmlTooltip causes IE to run amok with onResized events)

I had this issue with the FloatingPane? too, it is a general problem with the dojo.html.BackgroundIframe?.onResized method.

I think it is occuring when the domNode for the BackgroundIframe? is removed from the document (e.g. after closing the FloatingPane?). A timer event occurs and offsetWidth and offsetHeight are forever zero, because the frame is not on the document.

Modifying the following line fixed the problem:

if(this.iframe && this.domNode){

to:

if(this.iframe && this.domNode && this.domNode.parentElement){

Note that parentElement needs to be used, not parentNode.

It isn't a proper fix because there is no prevention for multiple timer events running in parallel (e.g. resize event occurs twice within 50ms will cause two lots of retriggering timers to occur). Also this might only be a symptom: the frame isn't being garbage collected (but maybe only because of the reference of the timer event itself!).

Sorry, I haven't checked this in because I haven't yet got svn set up correctly so I can.

comment:4 Changed 14 years ago by bill

Owner: changed from anonymous to bill

I'll try to fix this over the next few days.

When the screen is drawn or resized, onResized() is called on every widget, and then HtmlWidget::onResized() calls this.bgIframe.onResized().

In the case of Tooltip, I think the problem is not that the tooltip is detached from the document (Tooltip.js attaches the tooltip's domNode to document.body), but rather that the domNode is display:none.

The larger issue is that onResized() for any widget shouldn't do anything if the widget is hidden. Rather, the widget should size itself when show() is called.

That's my current thinking anyway.

comment:5 Changed 14 years ago by bill

Milestone: 0.3release
Resolution: fixed
Status: newclosed

OK, I deferred the tooltip iframe creation until the tooltip is shown (for performance reasons), which also works around the stated problem.

There's a similar problem if some tooltips are displayed and then the screen is resized. For that, I modified the resize propogation code to only notify visible widgets.

There's probably still some work to be done but anyway I think this problem is fixed.

comment:6 Changed 12 years ago by (none)

Milestone: 0.3release

Milestone 0.3release deleted

Note: See TracTickets for help on using tickets.