Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / src / widgets / layout / MenuLayout.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 /**
8  * @class Ext.layout.MenuLayout
9  * @extends Ext.layout.ContainerLayout
10  * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
11  */
12  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
13     monitorResize : true,
14
15     type: 'menu',
16
17     setContainer : function(ct){
18         this.monitorResize = !ct.floating;
19         // This event is only fired by the menu in IE, used so we don't couple
20         // the menu with the layout.
21         ct.on('autosize', this.doAutoSize, this);
22         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
23     },
24
25     renderItem : function(c, position, target){
26         if (!this.itemTpl) {
27             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
28                 '<li id="{itemId}" class="{itemCls}">',
29                     '<tpl if="needsIcon">',
30                         '<img alt="{altText}" src="{icon}" class="{iconCls}"/>',
31                     '</tpl>',
32                 '</li>'
33             );
34         }
35
36         if(c && !c.rendered){
37             if(Ext.isNumber(position)){
38                 position = target.dom.childNodes[position];
39             }
40             var a = this.getItemArgs(c);
41
42 //          The Component's positionEl is the <li> it is rendered into
43             c.render(c.positionEl = position ?
44                 this.itemTpl.insertBefore(position, a, true) :
45                 this.itemTpl.append(target, a, true));
46
47 //          Link the containing <li> to the item.
48             c.positionEl.menuItemId = c.getItemId();
49
50 //          If rendering a regular Component, and it needs an icon,
51 //          move the Component rightwards.
52             if (!a.isMenuItem && a.needsIcon) {
53                 c.positionEl.addClass('x-menu-list-item-indent');
54             }
55             this.configureItem(c);
56         }else if(c && !this.isValidParent(c, target)){
57             if(Ext.isNumber(position)){
58                 position = target.dom.childNodes[position];
59             }
60             target.dom.insertBefore(c.getActionEl().dom, position || null);
61         }
62     },
63
64     getItemArgs : function(c) {
65         var isMenuItem = c instanceof Ext.menu.Item,
66             canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
67
68         return {
69             isMenuItem: isMenuItem,
70             needsIcon: canHaveIcon && (c.icon || c.iconCls),
71             icon: c.icon || Ext.BLANK_IMAGE_URL,
72             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
73             itemId: 'x-menu-el-' + c.id,
74             itemCls: 'x-menu-list-item ',
75             altText: c.altText || ''
76         };
77     },
78
79     //  Valid if the Component is in a <li> which is part of our target <ul>
80     isValidParent : function(c, target) {
81         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
82     },
83
84     onLayout : function(ct, target){
85         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
86         this.doAutoSize();
87     },
88
89     doAutoSize : function(){
90         var ct = this.container, w = ct.width;
91         if(ct.floating){
92             if(w){
93                 ct.setWidth(w);
94             }else if(Ext.isIE){
95                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
96                 var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
97                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
98             }
99         }
100     }
101 });
102 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;