Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / docs / source / Menu.html
diff --git a/docs/source/Menu.html b/docs/source/Menu.html
new file mode 100644 (file)
index 0000000..0464169
--- /dev/null
@@ -0,0 +1,341 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>The source code</title>
+  <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
+  <script type="text/javascript" src="../prettify/prettify.js"></script>
+  <style type="text/css">
+    .highlight { display: block; background-color: #ddd; }
+  </style>
+  <script type="text/javascript">
+    function highlight() {
+      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
+    }
+  </script>
+</head>
+<body onload="prettyPrint(); highlight();">
+  <pre class="prettyprint lang-js"><span id='Ext-layout-container-boxOverflow-Menu'>/**
+</span> * @class Ext.layout.container.boxOverflow.Menu
+ * @extends Ext.layout.container.boxOverflow.None
+ * @private
+ */
+Ext.define('Ext.layout.container.boxOverflow.Menu', {
+
+    /* Begin Definitions */
+
+    extend: 'Ext.layout.container.boxOverflow.None',
+    requires: ['Ext.toolbar.Separator', 'Ext.button.Button'],
+    alternateClassName: 'Ext.layout.boxOverflow.Menu',
+    
+    /* End Definitions */
+
+<span id='Ext-layout-container-boxOverflow-Menu-cfg-afterCtCls'>    /**
+</span>     * @cfg {String} afterCtCls
+     * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
+     * which must always be present at the rightmost edge of the Container
+     */
+
+<span id='Ext-layout-container-boxOverflow-Menu-property-noItemsMenuText'>    /**
+</span>     * @property noItemsMenuText
+     * @type String
+     * HTML fragment to render into the toolbar overflow menu if there are no items to display
+     */
+    noItemsMenuText : '&lt;div class=&quot;' + Ext.baseCSSPrefix + 'toolbar-no-items&quot;&gt;(None)&lt;/div&gt;',
+
+    constructor: function(layout) {
+        var me = this;
+
+        me.callParent(arguments);
+
+        // Before layout, we need to re-show all items which we may have hidden due to a previous overflow.
+        layout.beforeLayout = Ext.Function.createInterceptor(layout.beforeLayout, this.clearOverflow, this);
+
+        me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-menu-' + layout.parallelAfter;
+<span id='Ext-layout-container-boxOverflow-Menu-property-menuItems'>        /**
+</span>         * @property menuItems
+         * @type Array
+         * Array of all items that are currently hidden and should go into the dropdown menu
+         */
+        me.menuItems = [];
+    },
+    
+    onRemove: function(comp){
+        Ext.Array.remove(this.menuItems, comp);
+    },
+
+    handleOverflow: function(calculations, targetSize) {
+        var me = this,
+            layout = me.layout,
+            methodName = 'get' + layout.parallelPrefixCap,
+            newSize = {},
+            posArgs = [null, null];
+
+        me.callParent(arguments);
+        this.createMenu(calculations, targetSize);
+        newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
+        newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - me.afterCt[methodName]();
+
+        // Center the menuTrigger button.
+        // TODO: Should we emulate align: 'middle' like this, or should we 'stretchmax' the menuTrigger?
+        posArgs[layout.perpendicularSizeIndex] = (calculations.meta.maxSize - me.menuTrigger['get' + layout.perpendicularPrefixCap]()) / 2;
+        me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs);
+
+        return { targetSize: newSize };
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-clearOverflow'>    /**
+</span>     * @private
+     * Called by the layout, when it determines that there is no overflow.
+     * Also called as an interceptor to the layout's onLayout method to reshow
+     * previously hidden overflowing items.
+     */
+    clearOverflow: function(calculations, targetSize) {
+        var me = this,
+            newWidth = targetSize ? targetSize.width + (me.afterCt ? me.afterCt.getWidth() : 0) : 0,
+            items = me.menuItems,
+            i = 0,
+            length = items.length,
+            item;
+
+        me.hideTrigger();
+        for (; i &lt; length; i++) {
+            items[i].show();
+        }
+        items.length = 0;
+
+        return targetSize ? {
+            targetSize: {
+                height: targetSize.height,
+                width : newWidth
+            }
+        } : null;
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-showTrigger'>    /**
+</span>     * @private
+     */
+    showTrigger: function() {
+        this.menuTrigger.show();
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-hideTrigger'>    /**
+</span>     * @private
+     */
+    hideTrigger: function() {
+        if (this.menuTrigger !== undefined) {
+            this.menuTrigger.hide();
+        }
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-beforeMenuShow'>    /**
+</span>     * @private
+     * Called before the overflow menu is shown. This constructs the menu's items, caching them for as long as it can.
+     */
+    beforeMenuShow: function(menu) {
+        var me = this,
+            items = me.menuItems,
+            i = 0,
+            len   = items.length,
+            item,
+            prev;
+
+        var needsSep = function(group, prev){
+            return group.isXType('buttongroup') &amp;&amp; !(prev instanceof Ext.toolbar.Separator);
+        };
+
+        me.clearMenu();
+        menu.removeAll();
+
+        for (; i &lt; len; i++) {
+            item = items[i];
+
+            // Do not show a separator as a first item
+            if (!i &amp;&amp; (item instanceof Ext.toolbar.Separator)) {
+                continue;
+            }
+            if (prev &amp;&amp; (needsSep(item, prev) || needsSep(prev, item))) {
+                menu.add('-');
+            }
+
+            me.addComponentToMenu(menu, item);
+            prev = item;
+        }
+
+        // put something so the menu isn't empty if no compatible items found
+        if (menu.items.length &lt; 1) {
+            menu.add(me.noItemsMenuText);
+        }
+    },
+    
+<span id='Ext-layout-container-boxOverflow-Menu-method-createMenuConfig'>    /**
+</span>     * @private
+     * Returns a menu config for a given component. This config is used to create a menu item
+     * to be added to the expander menu
+     * @param {Ext.Component} component The component to create the config for
+     * @param {Boolean} hideOnClick Passed through to the menu item
+     */
+    createMenuConfig : function(component, hideOnClick) {
+        var config = Ext.apply({}, component.initialConfig),
+            group  = component.toggleGroup;
+
+        Ext.copyTo(config, component, [
+            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
+        ]);
+
+        Ext.apply(config, {
+            text       : component.overflowText || component.text,
+            hideOnClick: hideOnClick,
+            destroyMenu: false
+        });
+
+        if (group || component.enableToggle) {
+            Ext.apply(config, {
+                group  : group,
+                checked: component.pressed,
+                listeners: {
+                    checkchange: function(item, checked){
+                        component.toggle(checked);
+                    }
+                }
+            });
+        }
+
+        delete config.ownerCt;
+        delete config.xtype;
+        delete config.id;
+        return config;
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-addComponentToMenu'>    /**
+</span>     * @private
+     * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
+     * @param {Ext.menu.Menu} menu The menu to add to
+     * @param {Ext.Component} component The component to add
+     */
+    addComponentToMenu : function(menu, component) {
+        var me = this;
+        if (component instanceof Ext.toolbar.Separator) {
+            menu.add('-');
+        } else if (component.isComponent) {
+            if (component.isXType('splitbutton')) {
+                menu.add(me.createMenuConfig(component, true));
+
+            } else if (component.isXType('button')) {
+                menu.add(me.createMenuConfig(component, !component.menu));
+
+            } else if (component.isXType('buttongroup')) {
+                component.items.each(function(item){
+                     me.addComponentToMenu(menu, item);
+                });
+            } else {
+                menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component)));
+            }
+        }
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-clearMenu'>    /**
+</span>     * @private
+     * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
+     * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
+     */
+    clearMenu : function() {
+        var menu = this.moreMenu;
+        if (menu &amp;&amp; menu.items) {
+            menu.items.each(function(item) {
+                if (item.menu) {
+                    delete item.menu;
+                }
+            });
+        }
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-createMenu'>    /**
+</span>     * @private
+     * Creates the overflow trigger and menu used when enableOverflow is set to true and the items
+     * in the layout are too wide to fit in the space available
+     */
+    createMenu: function(calculations, targetSize) {
+        var me = this,
+            layout = me.layout,
+            startProp = layout.parallelBefore,
+            sizeProp = layout.parallelPrefix,
+            available = targetSize[sizeProp],
+            boxes = calculations.boxes,
+            i = 0,
+            len = boxes.length,
+            box;
+
+        if (!me.menuTrigger) {
+            me.createInnerElements();
+
+<span id='Ext-layout-container-boxOverflow-Menu-property-menu'>            /**
+</span>             * @private
+             * @property menu
+             * @type Ext.menu.Menu
+             * The expand menu - holds items for every item that cannot be shown
+             * because the container is currently not large enough.
+             */
+            me.menu = Ext.create('Ext.menu.Menu', {
+                hideMode: 'offsets',
+                listeners: {
+                    scope: me,
+                    beforeshow: me.beforeMenuShow
+                }
+            });
+
+<span id='Ext-layout-container-boxOverflow-Menu-property-menuTrigger'>            /**
+</span>             * @private
+             * @property menuTrigger
+             * @type Ext.button.Button
+             * The expand button which triggers the overflow menu to be shown
+             */
+            me.menuTrigger = Ext.create('Ext.button.Button', {
+                ownerCt : me.layout.owner, // To enable the Menu to ascertain a valid zIndexManager owner in the same tree
+                iconCls : Ext.baseCSSPrefix + layout.owner.getXType() + '-more-icon',
+                ui      : layout.owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default',
+                menu    : me.menu,
+                getSplitCls: function() { return '';},
+                renderTo: me.afterCt
+            });
+        }
+        me.showTrigger();
+        available -= me.afterCt.getWidth();
+
+        // Hide all items which are off the end, and store them to allow them to be restored
+        // before each layout operation.
+        me.menuItems.length = 0;
+        for (; i &lt; len; i++) {
+            box = boxes[i];
+            if (box[startProp] + box[sizeProp] &gt; available) {
+                me.menuItems.push(box.component);
+                box.component.hide();
+            }
+        }
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-createInnerElements'>    /**
+</span>     * @private
+     * Creates the beforeCt, innerCt and afterCt elements if they have not already been created
+     * @param {Ext.container.Container} container The Container attached to this Layout instance
+     * @param {Ext.core.Element} target The target Element
+     */
+    createInnerElements: function() {
+        var me = this,
+            target = me.layout.getRenderTarget();
+
+        if (!this.afterCt) {
+            target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
+            this.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + this.afterCtCls}, 'before');
+        }
+    },
+
+<span id='Ext-layout-container-boxOverflow-Menu-method-destroy'>    /**
+</span>     * @private
+     */
+    destroy: function() {
+        Ext.destroy(this.menu, this.menuTrigger);
+    }
+});</pre>
+</body>
+</html>