1. #11
    Ext JS Premium Member
    Join Date
    Nov 2009
    Location
    St Louis,MO
    Posts
    267
    Vote Rating
    18
    James Goddard will become famous soon enough James Goddard will become famous soon enough

      0  

    Default


    This needs a tweak on onLayout:

    Code:
         onLayout: function() {
             var ct = this.containe,
                 cte = ct.getLayoutTarget(),
                 s = cte.getStyleSize(),
                 padding = Ext.apply({}, this.padding);
     
             this.renderAll(ct, cte);
    Without this line you cannot add components to the container after it is initially rendered.

  2. #12
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,501
    Vote Rating
    47
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default Code updated for latest 3.2 BoxLayout class.

    Code updated for latest 3.2 BoxLayout class.


    The following example works with the latest updates to the BoxLayout class. The code is a little smaller because BoxLayout handles calculating child positions and actually positioning them seperately, and we can use this.

    Warning: You might need the latest SVN code for it to work.

    Code:
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <title>Toolbar with Menus</title>
    <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
    <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="../../ext-all-debug.js"></script>
    <script type="text/javascript" src="../form/states.js"></script>
    <style type="text/css">
    .ux-float-layout-ct {
        position: relative;
    }
    .ux-float-layout-ct .ux-float-layout-sizer {
        background: transparent none;
        border: 0 none;
        padding: 0;
        margin: 0;
        width: 0;
    }
    
    .ux-float-layout-ct .x-box-inner {
        overflow: auto;
    }
    
    .x-box-item {
        position: absolute!important;
    }
    
    .test-item {
        height: 77px;
        width: 60px;
    }
    
    .test-item-inner {
        margin-left: 5px;
        margin-top: 5px;
        background-image: url(http://demo.qooxdoo.org/current/demobrowser/resource/qx/icon/Tango/48/devices/computer.png);
        height:48px;
        width:48px;
    }
    
    .test-item-desc {
        margin-top: 5px;
        text-align: center;
    }
    
    .x-btn-text-icon em {
        display: block;
        height: 100%;
    }
    
    button.test-button {
        height: 100%!important;
        width: 100%!important;
        background-image: url(http://demo.qooxdoo.org/current/demobrowser/resource/qx/icon/Tango/48/devices/computer.png)!important;
        padding-left: 40px!important;
    }
    
    </style>
    <script type="text/javascript">
    Ext.override(Ext.Element, (function(){
        var pxMatch = /(\d+\.?\d+)px/;
    
        return {
            // private.
            // Return the addressable area of the element using explicit CSS style in preference to offsetHeight/offsetWidth.
            // Optionally subtract padding if contentBox parameter is truthy
            getStyleSize : function(contentBox){
                var doc = document,
                    me = this,
                    d = me.dom,
                    extdom = Ext.lib.Dom,
                    isDoc = (d == doc || d == doc.body),
                    isBB, w, h, tbBorder = 0, lrBorder = 0,
                    tbPadding = 0, lrPadding = 0;
                if (isDoc) {
                    return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };
                }
                isBB = me.isBorderBox();
                tbBorder = me.getBorderWidth('tb');
                lrBorder = me.getBorderWidth('lr');
                tbPadding = me.getPadding('tb');
                lrPadding = me.getPadding('lr');
    
                // Width calcs
                // Try the style first, then offsetWidth
                if (w = me.getStyle('width').match(pxMatch)){
                    if ((w = parseFloat(w[1])) && isBB){
                        // Style includes the padding and border if isBB
                        w -= (lrBorder + lrPadding);
                    }
                    w += lrPadding;
                } else if (w = d.offsetWidth){
                    w -= lrBorder;
                }
                w && contentBox && (w -= lrPadding);
    
                // Height calcs
                // Try the style first, then offsetHeight
                if (h = me.getStyle('height').match(pxMatch)){
                    if ((h = parseFloat(h[1])) && isBB){
                        // Style includes the padding and border if isBB
                        h -= (tbBorder + tbPadding);
                    }
                    h += tbPadding;
                } else if (h = d.offsetHeight){
                    h -= tbBorder;
                }
                h && contentBox && (h -= tbPadding);
    
                return {
                    width : w,
                    height : h
                };
            },
    
            /**
             * <p>Returns the dimensions of the element available to lay content out in.<p>
             * <p>If the element (or any ancestor element) has CSS style <code>display : none</code>, the dimensions will be zero.</p>
             * example:<pre><code>
            var vpSize = Ext.getBody().getViewSize();
    
            // all Windows created afterwards will have a default value of 90% height and 95% width
            Ext.Window.override({
                width: vpSize.width * 0.9,
                height: vpSize.height * 0.95
            });
            // To handle window resizing you would have to hook onto onWindowResize.
            </code></pre>
             * @param {Boolean} contentBox True to return the W3 content box <i>within</i> the padding area of the element. False
             * or omitted to return the full area of the element within the border. See <a href="http://www.w3.org/TR/CSS2/box.html">http://www.w3.org/TR/CSS2/box.html</a>
             * @return {Object} An object containing the elements's area: <code>{width: &lt;element width>, height: &lt;element height>}</code>
             */
            getViewSize : function(contentBox){
                var doc = document,
                    me = this,
                    d = me.dom,
                    extdom = Ext.lib.Dom,
                    isDoc = (d == doc || d == doc.body),
                    ss = Ext.isIE ? me.getStyleSize(contentBox) : null, w, h;
                if (isDoc) {
                    return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };
                }
    
                // Width calcs
                // Try clientWidth, then styleWidth
                if (w = d.clientWidth){
    
    //              IE sometimes overestimates client size
                    Ext.isIE && w > ss.width && (w = ss.width);
    
                    if (contentBox){
                        w -= me.getPadding('lr');
                    }
                } else {
                    if (!ss) ss = me.getStyleSize(contentBox);
                    w = ss.width;
                }
    
                // Height calcs
                // Try clientHeight, then styleHeight
                if (h = d.clientHeight){
    
    //              IE sometimes overestimates client size
                    Ext.isIE && h > ss.height && (h = ss.height);
                    if (contentBox){
                        h -= me.getPadding('tb');
                    }
                } else {
                    if (!ss) ss = me.getStyleSize(contentBox);
                    h = ss.height;
                }
    
                return {
                    width : w,
                    height : h
                };
            }
        };
    })());
    
    /**
     * @class Ext.layout.FloatLayout
     * @extends Ext.layout.BoxLayout
     * <p>A layout that arranges items in a left to right flow similar to using HTML's <code>float: left</code> style.</p>
     * <p>When a Component's width (including its padding) won't fit within the available width of the Container (within its padding)
     * then the Component is wrapped to the beginning of a new line, clearing the tallest item on the current line.</p>
     * <p>Items may be vertically aligned with the row they happen to fall within. A line's height is the height of its tallest child
     * item (including its margins), and vertical alignment take place within this space. Vertical alignment is specified for the layout using the
     * {@link #verticalAlign} config, and may be overriden for a single item by configuring an item with a verticalAlign value.</p>
     * <p>Row content may be aligned within the available width of the Container using the {@link #horizontalAlign} config.</p>
     * <p>Child items may be cleared left or right by configuring a <b>clear</b> value in the item.</p>
     * <p>Row and column spacing may be specified using the {@link #verticalSpacing} and {@link #horizontalSpacing} options.
     */
    Ext.layout.FloatLayout = Ext.extend(Ext.layout.BoxLayout, {
        /**
         * @cfg {Boolean} animate
         * <p><code>true</code> to animate child items into their calculated positions.</p>
         * <p>Defaults to <code>false</code>.</p>
         */
    
        /**
         * @cfg {String} verticalAlign
         * <p>Vertical alignment of child items within each row. Defaults to 'middle'. Values may be</p>
         * <code>'top'</code>, <code>'middle'</code> or <code>'bottom'</code>
         * <p>May be overriden by an individual child item.</p>
         */
        verticalAlign: 'middle',
    
        /**
         * @cfg {String} horizontalAlign
         * <p>Horizontal alignment of child items within each row. Defaults to 'left'. Values may be</p>
         * <code>'left'</code>, <code>'center'</code>, <code>'right'</code> or <code>'justify'</code>
         * <p>May be overriden by an individual child item.</p>
         */
        horizontalAlign: 'left',
    
        /**
         * @cfg {Number} horizontalSpacing
         * <p>Horizontal space to leave between items.</p>
         */
        horizontalSpacing: 0,
    
        /**
         * @cfg {Number} verticalSpacing
         * <p>Vertical space to leave between rows.</p>
         */
        verticalSpacing: 0,
    
        targetCls : 'ux-float-layout-ct',
    
        updateChildBoxes: function(b) {
            for (var i = 0, l = b.length; i < l; i++) {
                if (this.animate) {
                    Ext.lib.Anim.motion(b[i].component.getPositionEl().dom, {left: {to: b[i].left}, top: {to: b[i].top}}).animate();
                } else {
                    b[i].component.setPosition([b[i].left, b[i].top]);
                }
            }
        },
        
        calculateChildBoxes: function() {
            var ct = this.container,
                ce = ct.getLayoutTarget(),
                paddingLeft = this.padding.left + ce.getPadding('l'),
                paddingTop = this.padding.top + ce.getPadding('t'),
                s = ce.getStyleSize(),
                rightLimit = (s.width -= (this.padding.right + ce.getPadding('r'))),
                bottomLimit = s.height - (this.padding.bottom + ce.getPadding('b')),
                rowStart = 0,
                rowHeight = 0,
                rowWidth = 0,
                x = paddingLeft,
                y = paddingTop,
                items = this.getRenderedItems(ct),
                l = items.length, i, c, cs, m, r,
                boxes = [], a;
    
    //      We never want to see horizontal scroll bars if possible
            ce.setStyle('overflow-x', 'hidden');
    
    //      Content Width.
            s.width -= paddingLeft;
    
            for (var i = 0, l = items.length; i < l; i++) {
                c = items[i];
                cs = c.getSize();
                cs.width += c.getPositionEl().getMargins('lr');
                cs.height += c.getPositionEl().getMargins('tb');
                m = c.margins;
                r = x + m.left + cs.width + m.right;
    
    //          This item won't fit on the row.
                if ((r > rightLimit) || (c.clear == 'left') || ((i > 0) && items[i - 1].clear == 'right')) {
                    this.adjustRow(boxes, rowStart, i - 1, rowHeight, rowWidth, s.width);
                    x = paddingLeft;
                    y += rowHeight + this.verticalSpacing;
                    r = x + m.left + cs.width + m.right;
                    rowStart = i;
                    rowHeight = 0;
                    rowWidth = 0;
                }
    
                rowHeight = Math.max(rowHeight, cs.height);
                rowWidth += cs.width;
    
    //          We are laying out an autoScroll Container, and this item is going to cause a vertical scrollbar:
    //          Adjust the right padding to account for that scrollbar, and reflow.
                if (ct.autoScroll && !this.reflow && ((y + rowHeight) > bottomLimit)) {
                    r = this.padding.right;
                    this.padding.right += Ext.getScrollBarWidth();
                    this.reflow = true;
                    this.onLayout(ct, ce);
                    delete this.reflow;
                    this.padding.right = r;
                    return this.childBoxCache;
                }
    
                boxes.push({
                    component: c,
                    left     : x,
                    top      : y,
                    height   : cs.height,
                    width    : cs.width
                });
                x = r + this.horizontalSpacing;
            }
    
    //      Adjust the last row
            this.adjustRow(boxes, rowStart, i - 1, rowHeight, rowWidth, s.width);
    
    //      Stretch the container heightwise.
            if (!this.sizer) {
                this.sizer = this.innerCt.insertFirst({
                    cls: 'ux-float-layout-sizer'
                });
            }
            this.sizer.setHeight(y + rowHeight - paddingTop);
    
            return {
                boxes: boxes,
                meta: {}
            };
        },
    
    //  Adjust vertical alignment within row.
    //  Adjust horizontal alignment if required.
        adjustRow: function(boxes, rowStart, rowEnd, rowHeight, rowWidth, availWidth) {
            var i, c, h, j = 0, spareWidth = availWidth - rowWidth, gaps = rowEnd - rowStart, alignmentIncrement = 0;
    
            switch (this.horizontalAlign) {
                case 'middle':
                case 'center':
                    alignmentIncrement = Math.max(spareWidth / 2, 0);
                    break;
                case 'right':
                    alignmentIncrement = Math.max(spareWidth, 0);
                    break;
                case 'justify':
                    if (gaps) {
                        j = Math.max(spareWidth / gaps, 0);
                    }
            }
    
            for (i = rowStart; i <= rowEnd; i++) {
                c = boxes[i].component;
                h = c.getHeight() + c.getPositionEl().getMargins('tb');
                boxes[i].left += alignmentIncrement;
                alignmentIncrement += j;
                switch (c.verticalAlign || this.verticalAlign) {
                    case 'middle':
                    case 'center':
                        boxes[i].top += (rowHeight - h) / 2;
                        break;
                    case 'bottom':
                        boxes[i].top += (rowHeight - h);
                }
            }
        }
    });
    Ext.Container.LAYOUTS['float'] = Ext.layout.FloatLayout;
    
    Ext.onReady(function(){
        Ext.QuickTips.init();
    
        // Menus can be prebuilt and passed by reference
        var dateMenu = new Ext.menu.DateMenu({
            handler: function(dp, date){
                Ext.example.msg('Date Selected', 'You chose {0}.', date.format('M j, Y'));
            }
        });
    
        var colorMenu = new Ext.menu.ColorMenu({
            handler: function(cm, color){
                Ext.example.msg('Color Selected', 'You chose {0}.', color);
            }
        });
        
        var store = new Ext.data.ArrayStore({
            fields: ['abbr', 'state'],
            data : Ext.exampledata.states // from states.js
        });
    
        var combo = new Ext.form.ComboBox({
            store: store,
            displayField: 'state',
            typeAhead: true,
            mode: 'local',
            triggerAction: 'all',
            emptyText: 'Select a state...',
            selectOnFocus: true,
            width: 135,
            getListParent: function() {
                return this.el.up('.x-menu');
            },
            iconCls: 'no-icon'
        });
    
        var menu = new Ext.menu.Menu({
            id: 'mainMenu',
            style: {
                overflow: 'visible'     // For the Combo popup
            },
            items: [
                combo,                  // A Field in a Menu
                {
                    text: 'I like Ext',
                    checked: true,       // when checked has a boolean value, it is assumed to be a CheckItem
                    checkHandler: onItemCheck
                }, '-', {
                    text: 'Radio Options',
                    menu: {        // <-- submenu by nested config object
                        items: [
                            // stick any markup in a menu
                            '<b class="menu-title">Choose a Theme</b>',
                            {
                                text: 'Aero Glass',
                                checked: true,
                                group: 'theme',
                                checkHandler: onItemCheck
                            }, {
                                text: 'Vista Black',
                                checked: false,
                                group: 'theme',
                                checkHandler: onItemCheck
                            }, {
                                text: 'Gray Theme',
                                checked: false,
                                group: 'theme',
                                checkHandler: onItemCheck
                            }, {
                                text: 'Default Theme',
                                checked: false,
                                group: 'theme',
                                checkHandler: onItemCheck
                            }
                        ]
                    }
                },{
                    text: 'Choose a Date',
                    iconCls: 'calendar',
                    menu: dateMenu // <-- submenu by reference
                },{
                    text: 'Choose a Color',
                    menu: colorMenu // <-- submenu by reference
                }
            ]
        });
    
        var tb = new Ext.Toolbar({
            id: 'tb',
            layout: {
                type: 'float',
                verticalSpacing: 4,
                horizontalSpacing: 4
            }
        });
    
        tb.add({
                text:'Button w/ Menu',
                iconCls: 'bmenu',  // <-- icon
                menu: menu  // assign menu by instance
            }, {
                text: 'Users',
                iconCls: 'user',
                menu: {
                    xtype: 'menu',
                    plain: true,
                    items: {
                        xtype: 'buttongroup',
                        title: 'User options',
                        autoWidth: true,
                        columns: 2,
                        defaults: {
                            xtype: 'button',
                            scale: 'large',
                            width: '100%',
                            iconAlign: 'left'
                        },
                        items: [{
                            text: 'User<br/>manager',
                            iconCls: 'edit'
                        },{
                            iconCls: 'add',
                            width: 'auto',
                            tooltip: 'Add user'
                        },{
                            colspan: 2,
                            text: 'Import',
                            scale: 'small'
                        },{
                            colspan: 2,
                            text: 'Who is online?',
                            scale: 'small'
                        }]
                    }
                }
            },
            new Ext.Toolbar.SplitButton({
                text: 'Split Button',
                handler: onButtonClick,
                tooltip: {text:'This is a an example QuickTip for a toolbar item', title:'Tip Title'},
                iconCls: 'blist',
                // Menus can be built/referenced by using nested menu config objects
                menu : {
                    items: [{
                        text: '<b>Bold</b>', handler: onItemClick
                    }, {
                        text: '<i>Italic</i>', handler: onItemClick
                    }, {
                        text: '<u>Underline</u>', handler: onItemClick
                    }, '-', {
                        text: 'Pick a Color',
                        handler: onItemClick,
                        menu: {
                            items: [
                                new Ext.ColorPalette({
                                    listeners: {
                                        select: function(cp, color){
                                            Ext.example.msg('Color Selected', 'You chose {0}.', color);
                                        }
                                    }
                                }), '-',
                                {
                                    text: 'More Colors...',
                                    handler: onItemClick
                                }
                            ]
                        }
                    }, {
                        text: 'Extellent!',
                        handler: onItemClick
                    }]
                }
            }), '-', {
            text: 'Toggle Me',
            enableToggle: true,
            toggleHandler: onItemToggle,
            pressed: true
        });
    
        menu.addSeparator();
        // Menus have a rich api for
        // adding and removing elements dynamically
        var item = menu.add({
            text: 'Dynamically added Item'
        });
        // items support full Observable API
        item.on('click', onItemClick);
    
        // items can easily be looked up
        menu.add({
            text: 'Disabled Item',
            id: 'disableMe'  // <-- Items can also have an id for easy lookup
            // disabled: true   <-- allowed but for sake of example we use long way below
        });
        // access items by id or index
        menu.items.get('disableMe').disable();
    
        // They can also be referenced by id in or components
        tb.add('-', {
            icon: 'list-items.gif', // icons can also be specified inline
            cls: 'x-btn-icon',
            tooltip: '<b>Quick Tips</b><br/>Icon only button with tooltip'
        }, '-');
        
        var scrollMenu = new Ext.menu.Menu();
        for (var i = 0; i < 50; ++i){
            scrollMenu.add({
                text: 'Item ' + (i + 1)
            });
        }
        
        tb.add(new Ext.form.TextField());
        
        // scrollable menu
        tb.add({
            scale: 'large',
            icon: 'preview.png',
            cls: 'x-btn-text-icon',
            text: 'Scrolling Menu',
            menu: scrollMenu
        });
        
        // add a combobox to the toolbar
        var combo = new Ext.form.ComboBox({
            store: store,
            displayField: 'state',
            typeAhead: true,
            mode: 'local',
            triggerAction: 'all',
            emptyText:'Select a state...',
            selectOnFocus:true,
            width:135
        });
        tb.addField(combo);
    
        tb.add({
            text: 'Another'
        }, {
            text: 'Yet another'
        }, {
            text: 'Still another'
        }, {
            text: 'The last one!'
        });
    
        // sample static data for the store
        var myData = [
            ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
            ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],
            ['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am'],
            ['American Express Company',52.55,0.01,0.02,'9/1 12:00am'],
            ['American International Group, Inc.',64.13,0.31,0.49,'9/1 12:00am'],
            ['AT&T Inc.',31.61,-0.48,-1.54,'9/1 12:00am'],
            ['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'],
            ['Caterpillar Inc.',67.27,0.92,1.39,'9/1 12:00am'],
            ['Citigroup, Inc.',49.37,0.02,0.04,'9/1 12:00am'],
            ['E.I. du Pont de Nemours and Company',40.48,0.51,1.28,'9/1 12:00am'],
            ['Exxon Mobil Corp',68.1,-0.43,-0.64,'9/1 12:00am'],
            ['General Electric Company',34.14,-0.08,-0.23,'9/1 12:00am'],
            ['General Motors Corporation',30.27,1.09,3.74,'9/1 12:00am'],
            ['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'],
            ['Honeywell Intl Inc',38.77,0.05,0.13,'9/1 12:00am'],
            ['Intel Corporation',19.88,0.31,1.58,'9/1 12:00am'],
            ['International Business Machines',81.41,0.44,0.54,'9/1 12:00am'],
            ['Johnson & Johnson',64.72,0.06,0.09,'9/1 12:00am'],
            ['JP Morgan & Chase & Co',45.73,0.07,0.15,'9/1 12:00am'],
            ['McDonald\'s Corporation',36.76,0.86,2.40,'9/1 12:00am'],
            ['Merck & Co., Inc.',40.96,0.41,1.01,'9/1 12:00am'],
            ['Microsoft Corporation',25.84,0.14,0.54,'9/1 12:00am'],
            ['Pfizer Inc',27.96,0.4,1.45,'9/1 12:00am'],
            ['The Coca-Cola Company',45.07,0.26,0.58,'9/1 12:00am'],
            ['The Home Depot, Inc.',34.64,0.35,1.02,'9/1 12:00am'],
            ['The Procter & Gamble Company',61.91,0.01,0.02,'9/1 12:00am'],
            ['United Technologies Corporation',63.26,0.55,0.88,'9/1 12:00am'],
            ['Verizon Communications',35.57,0.39,1.11,'9/1 12:00am'],            
            ['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am']
        ];
    
        /**
         * Custom function used for column renderer
         * @param {Object} val
         */
        function change(val){
            if(val > 0){
                return '<span style="color:green;">' + val + '</span>';
            }else if(val < 0){
                return '<span style="color:red;">' + val + '</span>';
            }
            return val;
        }
    
        /**
         * Custom function used for column renderer
         * @param {Object} val
         */
        function pctChange(val){
            if(val > 0){
                return '<span style="color:green;">' + val + '%</span>';
            }else if(val < 0){
                return '<span style="color:red;">' + val + '%</span>';
            }
            return val;
        }
    
        // create the data store
        var store = new Ext.data.ArrayStore({
            fields: [
               {name: 'company'},
               {name: 'price', type: 'float'},
               {name: 'change', type: 'float'},
               {name: 'pctChange', type: 'float'},
               {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
            ]
        });
    
        // manually load local data
        store.loadData(myData);
    
        // create the Grid
        var grid = new Ext.grid.GridPanel({
            store: store,
            columns: [
                {id:'company',header: 'Company', width: 160, sortable: true, dataIndex: 'company'},
                {header: 'Price', width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},
                {header: 'Change', width: 75, sortable: true, renderer: change, dataIndex: 'change'},
                {header: '% Change', width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},
                {header: 'Last Updated', width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
            ],
            stripeRows: true,
            autoExpandColumn: 'company',
            border: false
        });
    
        new Ext.Window({
            title: 'Test Float Toolbar',
            height: 300,
            width: 600,
            tbar: tb,
            layout: 'fit',
            items: grid
        }).show();
    
        // functions to display feedback
        function onButtonClick(btn){
            Ext.example.msg('Button Click','You clicked the "{0}" button.', btn.text);
        }
    
        function onItemClick(item){
            Ext.example.msg('Menu Click', 'You clicked the "{0}" menu item.', item.text);
        }
    
        function onItemCheck(item, checked){
            Ext.example.msg('Item Check', 'You {1} the "{0}" menu item.', item.text, checked ? 'checked' : 'unchecked');
        }
    
        function onItemToggle(item, pressed){
            Ext.example.msg('Button Toggled', 'Button "{0}" was toggled to {1}.', item.text, pressed);
        }
        
        var it = [];
        for (var i = 0; i < 30; i++) {
            it.push({
                xtype: 'box',
                autoEl: {
                    cls: 'test-item',
                    cn: [{
                        cls: 'test-item-inner'
                    }, {
                        cls: 'test-item-desc',
                        html: 'Item ' + (i + 1)
                    }]
                }
            });
        }
        new Ext.Window({
            title: 'Flow Layout',
            x: 100,
            y: 100,
            width: 314,
            height: 521,
            autoScroll: true,
            layout: {
                type: 'float',
                animate: true
            },
            items: it,
            bbar: {
                xtype: 'container',
                layout: {
                    type: 'hbox'
                },
                cls: 'x-toolbar',
                style: {
                    overflow: 'hidden',
                    paddingLeft: 0,
                    paddingRight: 0,
                },
                defaultType: 'container',
                items: [{
                    flex: 1,
                    autoHeight: true,
                    layout: {
                        type: 'float',
                        padding: '0 0 0 2'
                    },
                    items: {
                        xtype: 'button',
                        text: 'Left Button'
                    }
                }, { 
                    xtype: 'button',
                    text: 'Centre Button'
                }, {
                    flex: 1,
                    autoHeight: true,
                    layout: {
                        type: 'float',
                        horizontalAlign: 'right',
                        padding: '0 2 0 0'
                    },
                    items: {
                        xtype: 'button',
                        text: 'Right Button'
                    }
                }]
            }
        }).show();
    
        it = [];
        it.push({
            xtype: 'button',
            iconCls: 'test-button',
            text: '1. First Button',
            width: 140,
            height: 56
        });
        it.push({
            xtype: 'button',
            iconCls: 'test-button',
            text: '2. Second longer Button...',
            width: 200,
            height: 56,
            clear: 'right'
        });
        it.push({
            xtype: 'button',
            iconCls: 'test-button',
            text: '3. Third really, really long Button',
            width: 240,
            height: 100
        });
        it.push({
            xtype: 'button',
            iconCls: 'test-button',
            text: 'Number 4',
            width: 120,
            height: 56,
            verticalAlign: 'bottom'
        });
        it.push({
            xtype: 'button',
            text: '20px Margins around the great big 5th button!',
            width: 240,
            height: 100,
            clear: 'right',
            style: {
                margin: '20px'
            }
        });
        it.push({
            xtype: 'button',
            iconCls: 'test-button',
            text: 'Number 6',
            width: 120,
            height: 56
        });
        it.push({
            xtype: 'button',
            text: '7th a wide, short button',
            width: 120,
            verticalAlign: 'top'
        });
    
        new Ext.Window({
            title: 'Flow Layout',
            x: 500,
            y: 100,
            width: 500,
            height: 400,
            autoScroll: true,
            layout: {
                type: 'float',
                horizontalAlign: 'justify',
                animate: true
            },
            items: it
        }).show();
    
    });
    </script>
    </head>
    <body>
    <h1>FloatLayout Toolbar with Menus</h1>
    <p>The js is inline.</p>
    </body>
    </html>

  3. #13
    Sencha User Saint Father's Avatar
    Join Date
    Jan 2010
    Posts
    13
    Vote Rating
    0
    Saint Father is on a distinguished road

      0  

    Default


    many thanks for this stuff, you saved me a lot of work!

    Interesting observation:
    The block "friendsBlock" comprises 8 pictures customised on width so to take places in 2 strings.
    Code:
    var it = [];
        for (var i = 0; i < 8; i++) {
      it.push({
        xtype: 'box',
        margins: '0 0 0 2px',
        autoEl: {
          tag: 'img',
          src: '/images/friend_0' + (i + 1) + '.jpg',
          alt: 'Pers #'+(i + 1),
        }
      });
        }
        var friendsBlock = {
                  layout: {
                         type: 'float',
        animate: true
                   },
                   items: it,
            };
    I have placed this block "friendsBlock" in the "Portal" block.
    Code:
    var indexCenterPanel = {
                                      xtype:'portal',
                                      items:[
                                         {
                                              columnWidth:.33,
                                              items:[    friendsBlock ]
                                         } ...
    And when I drag and drop the block "friendsBlock" (portal item) - pictures in the block "friendsBlock" take places already in 3 strings.
    Changing width of pictures I has calculated that at calculation of a parent window width the skroll-bar width is considered.

    At refresh the browser - the block "friendsBlock" is drawn again without skroll-bar width.

    autoScroll: false - has solved this problem ... But it- in my opinion - is "not sports"

  4. #14
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,501
    Vote Rating
    47
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Possibly image size is not known at the time the boxes are evaluated by the layout manager.

    Images are loaded asynchronously.

    You might have to use a load event on each image, and when it has fired <# of images> times, call doLayout.

  5. #15
    Sencha User
    Join Date
    Oct 2008
    Posts
    7
    Vote Rating
    0
    mestrona is on a distinguished road

      0  

    Default


    great layout! I was looking for a floating layout and this one works very well. Thank you for your contribution.
    I added one feature: tightFitting

    with thightFitting: true it looks like that:
    float_layout.JPG


    here is the code
    PHP Code:
    <html>
    <
    head>
    <
    meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <
    title>Toolbar with Menus</title>



        <!-- 
    Ext Libraray CSS -->
        <
    link rel="stylesheet" type="text/css" href="/_files/ext/resources/css/ext-all.css"/>

        
        <!-- 
    Ext 3.2.1 Library JS -->
        <
    script type="text/javascript" src="/_files/ext/adapter/ext/ext-base-debug.js"></script>
        <script type="text/javascript" src="/_files/ext/ext-all-debug.js"></script>
        <script type="text/javascript" src="/_files/ext/examples/form/states.js"></script>

    <style type="text/css">
    .ux-float-layout-ct {
        position: relative;
    }
    .ux-float-layout-ct .ux-float-layout-sizer {
        background: transparent none;
        border: 0 none;
        padding: 0;
        margin: 0;
        width: 0;
    }

    .ux-float-layout-ct .x-box-inner {
        overflow: visible;
    }

    .x-box-item {
        position: absolute!important;
    }

    .test-item {
        height: 77px;
        width: 60px;
    }

    .test-item-inner {
        margin-left: 5px;
        margin-top: 5px;
        background-image: url(http://demo.qooxdoo.org/current/demobrowser/resource/qx/icon/Tango/48/devices/computer.png);
        height:48px;
        width:48px;
    }

    .test-item-desc {
        margin-top: 5px;
        text-align: center;
    }

    .x-btn-text-icon em {
        display: block;
        height: 100%;
    }

    button.test-button {
        height: 100%!important;
        width: 100%!important;
        background-image: url(http://demo.qooxdoo.org/current/demobrowser/resource/qx/icon/Tango/48/devices/computer.png)!important;
        padding-left: 40px!important;
    }

    </style>
    <script type="text/javascript">
    Ext.override(Ext.Element, (function(){
        var pxMatch = /(\d+\.?\d+)px/;

        return {
            // private.
            // Return the addressable area of the element using explicit CSS style in preference to offsetHeight/offsetWidth.
            // Optionally subtract padding if contentBox parameter is truthy
            getStyleSize : function(contentBox){
                var doc = document,
                    me = this,
                    d = me.dom,
                    extdom = Ext.lib.Dom,
                    isDoc = (d == doc || d == doc.body),
                    isBB, w, h, tbBorder = 0, lrBorder = 0,
                    tbPadding = 0, lrPadding = 0;
                if (isDoc) {
                    return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };
                }
                isBB = me.isBorderBox();
                tbBorder = me.getBorderWidth('tb');
                lrBorder = me.getBorderWidth('lr');
                tbPadding = me.getPadding('tb');
                lrPadding = me.getPadding('lr');

                // Width calcs
                // Try the style first, then offsetWidth
                if (w = me.getStyle('width').match(pxMatch)){
                    if ((w = parseFloat(w[1])) && isBB){
                        // Style includes the padding and border if isBB
                        w -= (lrBorder + lrPadding);
                    }
                    w += lrPadding;
                } else if (w = d.offsetWidth){
                    w -= lrBorder;
                }
                w && contentBox && (w -= lrPadding);

                // Height calcs
                // Try the style first, then offsetHeight
                if (h = me.getStyle('height').match(pxMatch)){
                    if ((h = parseFloat(h[1])) && isBB){
                        // Style includes the padding and border if isBB
                        h -= (tbBorder + tbPadding);
                    }
                    h += tbPadding;
                } else if (h = d.offsetHeight){
                    h -= tbBorder;
                }
                h && contentBox && (h -= tbPadding);

                return {
                    width : w,
                    height : h
                };
            },

            /**
             * <p>Returns the dimensions of the element available to lay content out in.<p>
             * <p>If the element (or any ancestor element) has CSS style <code>display : none</code>, the dimensions will be zero.</p>
             * example:<pre><code>
            var vpSize = Ext.getBody().getViewSize();

            // all Windows created afterwards will have a default value of 90% height and 95% width
            Ext.Window.override({
                width: vpSize.width * 0.9,
                height: vpSize.height * 0.95
            });
            // To handle window resizing you would have to hook onto onWindowResize.
            </code></pre>
             * @param {Boolean} contentBox True to return the W3 content box <i>within</i> the padding area of the element. False
             * or omitted to return the full area of the element within the border. See <a href="http://www.w3.org/TR/CSS2/box.html">http://www.w3.org/TR/CSS2/box.html</a>
             * @return {Object} An object containing the elements's area: <code>{width: &lt;element width>, height: &lt;element height>}</code>
             */
            getViewSize : function(contentBox){
                var doc = document,
                    me = this,
                    d = me.dom,
                    extdom = Ext.lib.Dom,
                    isDoc = (d == doc || d == doc.body),
                    ss = Ext.isIE ? me.getStyleSize(contentBox) : null, w, h;
                if (isDoc) {
                    return { width: extdom.getViewWidth(), height: extdom.getViewHeight() };
                }

                // Width calcs
                // Try clientWidth, then styleWidth
                if (w = d.clientWidth){

    //              IE sometimes overestimates client size
                    Ext.isIE && w > ss.width && (w = ss.width);

                    if (contentBox){
                        w -= me.getPadding('lr');
                    }
                } else {
                    if (!ss) ss = me.getStyleSize(contentBox);
                    w = ss.width;
                }

                // Height calcs
                // Try clientHeight, then styleHeight
                if (h = d.clientHeight){

    //              IE sometimes overestimates client size
                    Ext.isIE && h > ss.height && (h = ss.height);
                    if (contentBox){
                        h -= me.getPadding('tb');
                    }
                } else {
                    if (!ss) ss = me.getStyleSize(contentBox);
                    h = ss.height;
                }

                return {
                    width : w,
                    height : h
                };
            }
        };
    })());

    /**
     * @class Ext.layout.FloatLayout
     * @extends Ext.layout.BoxLayout
     * <p>A layout that arranges items in a left to right flow similar to using HTML's <code>float: left</code> style.</p>
     * <p>When a Component's width (including its padding) won't fit within the available width of the Container (within its padding)
     * then the Component is wrapped to the beginning of a new line, clearing the tallest item on the current line.</p>
     * <p>Items may be vertically aligned with the row they happen to fall within. A line's height is the height of its tallest child
     * item (including its margins), and vertical alignment take place within this space. Vertical alignment is specified for the layout using the
     * {@link #verticalAlign} config, and may be overriden for a single item by configuring an item with a verticalAlign value.</p>
     * <p>Row content may be aligned within the available width of the Container using the {@link #horizontalAlign} config.</p>
     * <p>Child items may be cleared left or right by configuring a <b>clear</b> value in the item.</p>
     * <p>Row and column spacing may be specified using the {@link #verticalSpacing} and {@link #horizontalSpacing} options.
     */
    Ext.layout.FloatLayout = Ext.extend(Ext.layout.BoxLayout, {
        /**
         * @cfg {Boolean} animate
         * <p><code>true</code> to animate child items into their calculated positions.</p>
         * <p>Defaults to <code>false</code>.</p>
         */

        /**
         * @cfg {String} verticalAlign
         * <p>Vertical alignment of child items within each row. Defaults to 'middle'. Values may be</p>
         * <code>'top'</code>, <code>'middle'</code> or <code>'bottom'</code>
         * <p>May be overriden by an individual child item.</p>
         */
        verticalAlign: 'middle',

        /**
         * @cfg {String} horizontalAlign
         * <p>Horizontal alignment of child items within each row. Defaults to 'left'. Values may be</p>
         * <code>'left'</code>, <code>'center'</code>, <code>'right'</code> or <code>'justify'</code>
         * <p>May be overriden by an individual child item.</p>
         */
        horizontalAlign: 'left',

        /**
         * @cfg {Number} horizontalSpacing
         * <p>Horizontal space to leave between items.</p>
         */
        horizontalSpacing: 0,

        /**
         * @cfg {Number} verticalSpacing
         * <p>Vertical space to leave between rows.</p>
         */
        verticalSpacing: 0,

        /**
         * @cfg {Boolean} verticalSpacing
         * <p>Vertical space to leave between rows.</p>
         */
         tightFitting: false,    

        targetCls : 'ux-float-layout-ct',

        updateChildBoxes: function(b) {
            for (var i = 0, l = b.length; i < l; i++) {
                if (this.animate) {
                    Ext.lib.Anim.motion(b[i].component.getPositionEl().dom, {left: {to: b[i].left}, top: {to: b[i].top}}).animate();
                } else {
                    b[i].component.setPosition([b[i].left, b[i].top]);
                }
            }
        },
        
        calculateChildBoxes: function() {
            var ct = this.container,
                ce = ct.getLayoutTarget(),
                paddingLeft = this.padding.left + ce.getPadding('l'),
                paddingTop = this.padding.top + ce.getPadding('t'),
                s = ce.getStyleSize(),
                rightLimit = (s.width -= (this.padding.right + ce.getPadding('r'))),
                bottomLimit = s.height - (this.padding.bottom + ce.getPadding('b')),
                rowStart = 0,
                rowHeight = 0,
                rowWidth = 0,
                rowNum = 0,
                x = paddingLeft,
                y = paddingTop,
                items = this.getRenderedItems(ct),
                l = items.length, i, c, cs, m, r,
                boxes = [], a, maxHeight;

    //      We never want to see horizontal scroll bars if possible
            ce.setStyle('overflow-x', 'hidden');

    //      Content Width.
            s.width -= paddingLeft;

            for (var i = 0, l = items.length; i < l; i++) {
                c = items[i];
                cs = c.getSize();
                cs.width += c.getPositionEl().getMargins('lr');
                cs.height += c.getPositionEl().getMargins('tb');
                m = c.margins;
                r = x + m.left + cs.width + m.right;

    //          This item won't fit on the row.
                if ((r > rightLimit) || (c.clear == 'left') || ((i > 0) && items[i - 1].clear == 'right')) {
                    this.adjustRow(boxes, rowStart, i - 1, rowHeight, rowWidth, s.width);
                    x = paddingLeft;
                    y += rowHeight + this.verticalSpacing;
                    r = x + m.left + cs.width + m.right;
                    rowStart = i;
                    rowHeight = 0;
                    rowWidth = 0;
                    rowNum++;
                }

                rowHeight = Math.max(rowHeight, cs.height);
                rowWidth += cs.width;

    //          We are laying out an autoScroll Container, and this item is going to cause a vertical scrollbar:
    //          Adjust the right padding to account for that scrollbar, and reflow.
                if (ct.autoScroll && !this.reflow && ((y + rowHeight) > bottomLimit)) {
                    r = this.padding.right;
                    this.padding.right += Ext.getScrollBarWidth();
                    this.reflow = true;
                    this.onLayout(ct, ce);
                    delete this.reflow;
                    this.padding.right = r;
                    return this.childBoxCache;
                }

                // adjust top value
                maxHeight = 0;
                if(rowNum > 0 && this.tightFitting) {
                    for (var j = 0; j < i; j++) {
                        if(boxes[j].row == (rowNum - 1)) {
                            if((boxes[j].left <= (x + cs.width)) && ((boxes[j].left + boxes[j].width) >= x)) {
                                if(maxHeight < boxes[j].height) {
                                    maxHeight = boxes[j].height;
                                    y = boxes[j].top + boxes[j].height + this.verticalSpacing;
                                }
                            }
                        }
                    }
                }

                boxes.push({
                    component: c,
                    left     : x,
                    top      : y,
                    height   : cs.height,
                    width    : cs.width,
                    row      : rowNum
                });
                x = r + this.horizontalSpacing;
            }

    //      Adjust the last row
            this.adjustRow(boxes, rowStart, i - 1, rowHeight, rowWidth, s.width);

    //      Stretch the container heightwise.
            if (!this.sizer) {
                this.sizer = this.innerCt.insertFirst({
                    cls: 'ux-float-layout-sizer'
                });
            }
            this.sizer.setHeight(y + rowHeight - paddingTop);

            return {
                boxes: boxes
            };
        },

    //  Adjust vertical alignment within row.
    //  Adjust horizontal alignment if required.
        adjustRow: function(boxes, rowStart, rowEnd, rowHeight, rowWidth, availWidth) {
            var i, c, h, j = 0, spareWidth = availWidth - rowWidth, gaps = rowEnd - rowStart, alignmentIncrement = 0;

            switch (this.horizontalAlign) {
                case 'middle':
                case 'center':
                    alignmentIncrement = Math.max(spareWidth / 2, 0);
                    break;
                case 'right':
                    alignmentIncrement = Math.max(spareWidth, 0);
                    break;
                case 'justify':
                    if (gaps) {
                        j = Math.max(spareWidth / gaps, 0);
                    }
            }

            for (i = rowStart; i <= rowEnd; i++) {
                c = boxes[i].component;
                h = c.getHeight() + c.getPositionEl().getMargins('tb');
                boxes[i].left += alignmentIncrement;
                alignmentIncrement += j;
                switch (c.verticalAlign || this.verticalAlign) {
                    case 'middle':
                    case 'center':
                        boxes[i].top += (rowHeight - h) / 2;
                        break;
                    case 'bottom':
                        boxes[i].top += (rowHeight - h);
                }
            }
        }
    });
    Ext.Container.LAYOUTS['float'] = Ext.layout.FloatLayout;

    Ext.onReady(function(){
        Ext.QuickTips.init();

        new Ext.Window({
            title: 'Flow Layout',
            x: 500,
            y: 100,
            width: 500,
            height: 400,
            autoScroll: true,
            layout: {
                type: 'float',
                horizontalAlign: 'left',
                verticalAlign: 'top',
                animate: false,
                horizontalSpacing: 10,
                verticalSpacing: 10,
                tightFitting: true,
                padding: 10
            },
            items: [
                {xtype:'panel',title:'Title',width:100,height:150,html:'test'},
                {xtype:'panel',title:'Title',width:210,height:100,html:'test'},
                {xtype:'panel',title:'Title',width:100,height:80,html:'test'},
                {xtype:'panel',title:'Title',width:100,height:100,html:'test'},
                {xtype:'panel',title:'Title',width:320,height:100,html:'test'},
                {xtype:'panel',title:'Title',width:100,height:50,html:'test'},
                {xtype:'panel',title:'Title',width:100,height:70,html:'test'},
                {xtype:'panel',title:'Title',width:100,height:90,html:'test'}
            ]
        }).show();    

    });
    </script>
    </head>
    <body>
    <h1>FloatLayout Toolbar with Menus</h1>
    <p>The js is inline.</p>
    </body>
    </html> 

  6. #16
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,501
    Vote Rating
    47
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    Cool feature!

    I have been wondering about how to do that. How to allow overflowed components to fit more snugly.

    What's the order there? 3 across the top, but then the "next row" is what, the long rectangle or the square. I couldn't work out an algorithm for this.

  7. #17
    Sencha User
    Join Date
    Oct 2008
    Posts
    7
    Vote Rating
    0
    mestrona is on a distinguished road

      0  

    Default


    both. the second row is the square an the long rectangle. it really simple, i just added:
    Code:
    // adjust top value
    maxHeight = 0;
    if(rowNum > 0 && this.tightFitting) {
        for (var j = 0; j < i; j++) {
            if(boxes[j].row == (rowNum - 1)) {
                if((boxes[j].left <= (x + cs.width)) && ((boxes[j].left + boxes[j].width) >= x)) {
                    if(maxHeight < boxes[j].height) {
                        maxHeight = boxes[j].height;
                        y = boxes[j].top + boxes[j].height + this.verticalSpacing;
                    }
                }
            }
        }
    }
    i recalculated only the top-values of the boxes ;-)

    I tested it in FF3.6.8 and IE8 so far. Works with all horizontal/vertical alignments and spacings.

  8. #18
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,501
    Vote Rating
    47
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    calculateChildBoxes just needs

    Code:
            return {
                boxes: boxes,
                meta: {}
            };
    at the end to be compatible with Ext 3.3.

    I just tweaked the example to show which child items were which:


  9. #19
    Sencha - Ext JS Dev Team Animal's Avatar
    Join Date
    Mar 2007
    Location
    Notts/Redwood City
    Posts
    30,501
    Vote Rating
    47
    Animal has a spectacular aura about Animal has a spectacular aura about

      0  

    Default


    This is a very nice layout now. Does almost everything.

    I think it should be adopted as part of the framework. But called "FlowLayout" which makes more sense.

    I really like watching the animate: true config working. That should be a standard part of the layout system too!

    We have app components where an arbitrary number informational blocks (They are FieldSets containing tabular consignment information) must be "flowed" across and then down in whatever space is available.

    Of course I couldn't tight fit them before which wasted a lot of space. This will help a lot! Thanks!

  10. #20
    Sencha User
    Join Date
    Oct 2008
    Posts
    7
    Vote Rating
    0
    mestrona is on a distinguished road

      0  

    Default


    you re right. its a nice animation, especially if you add more chaos:
    Code:
    {xtype:'panel',title:'Title',width:100,height:150,html:'test1'},
                {xtype:'panel',title:'Title',width:210,height:100,html:'test2'},
                {xtype:'panel',title:'Title',width:100,height:80,html:'test3'},
                {xtype:'panel',title:'Title',width:100,height:100,html:'test4'},
                {xtype:'panel',title:'Title',width:320,height:100,html:'test5'},
                {xtype:'panel',title:'Title',width:80,height:80,html:'test6'},
                {xtype:'panel',title:'Title',width:70,height:100,html:'test7'},
                {xtype:'panel',title:'Title',width:30,height:100,html:'test8'},
                {xtype:'panel',title:'Title',width:90,height:80,html:'test9'},
                {xtype:'panel',title:'Title',width:105,height:100,html:'test10'},
                {xtype:'panel',title:'Title',width:320,height:100,html:'test11'},
                {xtype:'panel',title:'Title',width:100,height:50,html:'test12'},
                {xtype:'panel',title:'Title',width:33,height:70,html:'test13'},
                {xtype:'panel',title:'Title',width:100,height:90,html:'test14'}
    Thank you for the hint regarding Ext 3.3!
    I also would like to see FlowLayout as part of Ext.layout.* - it is the only layout, missing right from the start

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi