-
17 Sep 2012 12:01 PM #1
[4.1.2] Menu size too large on first show
[4.1.2] Menu size too large on first show
REQUIRED INFORMATION
Ext version tested:
- Ext 4.1.2
- Ext 4.1.1
- Ext 4.1.0
- FF 15.0.1
- In Firefox on occasion, the first time a menu is shown on the page the menu container is laid out too large for its child menu items. This seems to be cache-related, as it only consistently happens after the page is loaded via Ctrl-F5 or the browser cache has been cleared/disabled. In addition, it appears to be a problem introduced in 4.1.x, as it is not reproducible on 4.0.7 and earlier.
- Create a button menu with a few simple menu items.
- Open in Firefox, and reload the page using Ctrl-F5.
- Click the button to open the menu.
- The menu should be sized appropriately for the child menu items.
- The menu is larger than expected for the child items. However, clicking the button to show the menu subsequent times shows the menu layout as expected.
HELPFUL INFORMATIONCode:Ext.onReady(function() { Ext.create('Ext.button.Button', { text: 'Test', margin: 10, renderTo: Ext.getBody(), menu: { listeners: { beforeshow: function() { var el = this.child().arrowEl; console.log('Arrow width: ' + el.getWidth()); console.log('Arrow height: ' + el.getHeight()); } }, items: [{ text: 'Menu Item 1' }, { text: 'Menu Item 2' }, { text: 'Menu Item 3' }] } }); });
Screenshot or Video:- First click:
menu-first-click.png - Subsequent clicks:
menu-next-click.png
- This appears to be an issue with the "arrowEl" element in the menu items. The information logged to the console in the test case looks like this:
Arrow width: 24
Arrow height: 24
Arrow width: 1
Arrow height: 1
Arrow width: 1
Arrow height: 1 - The issue appears to be that the blank arrow image is not yet loaded by the time the first layout is run, causing the arrowEl to report a larger size than it actually occupies once the 1px by 1px blank image is loaded.
- Hide or remove the arrowEl element from the DOM when it is not needed (i.e. when the menu item has no submenu). This override is one such solution, applying the "x-hidden" class to the arrow element when no submenu is specified:
Code:Ext.define('Ext.ux.overrides.MenuArrow', { override: 'Ext.menu.Item', beforeRender: function() { if (!this.menu) { Ext.applyIf(this.renderData, { arrowCls: 'x-hidden' }); } this.callParent(); } });
- only default ext-all.css
- Win7 x64
-
17 Sep 2012 12:18 PM #2
Thanks for the report! I have opened a bug in our bug tracker.
-
17 Sep 2012 1:48 PM #3
I can't reproduce this at all. Tried 20 times in a row, clearing the cache each time.
I would usually see:
I would occasionally see:Code:Arrow width: 0 Arrow height: 14
Either way, the menu never looked like it did in your screenshot.Code:Arrow width: 1 Arrow height: 1
Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
17 Sep 2012 1:59 PM #4
Well, that's certainly interesting...

Any idea what would be different? I'm just using the standard ext-all-debug.js and ext-all.css, so there's no custom code that would mess things up. I've tried running off the local filesystem and via webserver, with Firefox plugins disabled, and I still get this behavior.
-
17 Sep 2012 2:03 PM #5
Nothing really springs to mind. Does it happen with FF14, or one of the FF nightlies?
Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
18 Sep 2012 6:47 AM #6
Just tried against Firefox 14 and the latest Nightly, both with clean new profiles, and I'm seeing this happen in those versions as well. I only have access to Windows machines though, so I can't try to reproduce in Firefox for other platforms (Mac or Linux).
-
18 Sep 2012 9:08 PM #7
I was testing it on windows also. I tried with both the built version and loading all source files.
Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
19 Sep 2012 7:06 AM #8
I'm still mystified as to why I can reproduce this consistently but you can't. (I'm not crazy, I swear!)
In playing around with it more, I've found I can simulate the same situation by setting Ext.BLANK_IMAGE_URL manually and introducing an artificial server-side delay so that the image takes a little while to load. That is, I added this to the top of the test case:
And set up a simple Java servlet to delay all requests to "delay/*" by 2 seconds:Code:Ext.BLANK_IMAGE_URL = 'delay/blank.gif';
Of course, doing a similar thing with any backend should work. Under this setup, I see this while the image is loading:Code:import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DelayServlet extends HttpServlet { private static final int BUFFER_SIZE = 10240; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { ServletContext context = getServletContext(); // Delay the response by 2 seconds try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // Proceed to serve up the requested file File file = new File(context.getRealPath(request.getPathInfo())); response.setBufferSize(BUFFER_SIZE); response.setContentType(context.getMimeType(file.getName())); response.setHeader("Content-Length", String.valueOf(file.length())); BufferedInputStream input = null; BufferedOutputStream output = null; try { input = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE); output = new BufferedOutputStream(response.getOutputStream(), BUFFER_SIZE); byte[] buffer = new byte[BUFFER_SIZE]; int length; while ((length = input.read(buffer)) > 0) { output.write(buffer, 0, length); } } finally { close(input); close(output); } } private static void close(Closeable resource) { if (resource != null) { try { resource.close(); } catch (IOException e) { e.printStackTrace(); } } } }
menu-loading.png
Making it pretty clear that the arrowEl images on the right are causing the menu to inflate. After the images load (if the menu is still open), the text shifts and it looks exactly like the "first click" in the original test case. And again, the menu looks fine with subsequent clicks on the button after the images load.
Does that help at all? I'm not sure what other information I can provide. It seems to me that ExtJS should take care to layout the menu properly whether or not the arrow images are loading.
-
20 Sep 2012 1:35 AM #9
I can reproduce consistently in Firefox 15.0.1 on Windows 7 x64 Pro, so you're not going mad.
Fine in Chrome...Product Architect
Altus Ltd.
-
20 Sep 2012 3:46 AM #10
Is there any reason you're setting the blank image? It only needs to happen in IE 6/7, in other browsers it's set as a data image so it's inline.
Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
You found a bug! We've classified it as
EXTJSIV-7264
.
We encourage you to continue the discussion and to find an acceptable workaround while we work on a permanent fix.


Reply With Quote