| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />  <script type="text/javascript" src="../resources/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-CheckboxGroup'>/**</span> * This layout implements the column arrangement for {@link Ext.form.CheckboxGroup} and {@link Ext.form.RadioGroup}. * It groups the component's sub-items into columns based on the component's * {@link Ext.form.CheckboxGroup#columns columns} and {@link Ext.form.CheckboxGroup#vertical} config properties. */Ext.define('Ext.layout.container.CheckboxGroup', {    extend: 'Ext.layout.container.Container',    alias: ['layout.checkboxgroup'],<span id='Ext-layout-container-CheckboxGroup-cfg-autoFlex'>    /**</span>     * @cfg {Boolean} [autoFlex=true]     * By default,  CheckboxGroup allocates all available space to the configured columns meaning that     * column are evenly spaced across the container.     *     * To have each column only be wide enough to fit the container Checkboxes (or Radios), set `autoFlex` to `false`     */    autoFlex: true,    type: 'checkboxgroup',    childEls: [        'innerCt'    ],    renderTpl: [        '<table id="{ownerId}-innerCt" role="presentation" style="{tableStyle}"><tbody><tr>',            '<tpl for="columns">',                '<td class="{parent.colCls}" valign="top" style="{style}">',                    '{% this.renderColumn(out,parent,xindex-1) %}',                '</td>',            '</tpl>',        '</tr></tbody></table>'    ],    lastOwnerItemsGeneration : null,    beginLayout: function(ownerContext) {        var me = this,            columns,            numCols,            i, width, cwidth,            totalFlex = 0, flexedCols = 0,            autoFlex = me.autoFlex,            innerCtStyle = me.innerCt.dom.style;        me.callParent(arguments);        columns = me.columnNodes;        ownerContext.innerCtContext = ownerContext.getEl('innerCt', me);        // The columns config may be an array of widths. Any value < 1 is taken to be a fraction:        if (!ownerContext.widthModel.shrinkWrap) {            numCols = columns.length;            // If columns is an array of numeric widths            if (me.columnsArray) {                // first calculate total flex                for (i = 0; i < numCols; i++) {                    width = me.owner.columns[i];                    if (width < 1) {                        totalFlex += width;                        flexedCols++;                    }                }                // now apply widths                for (i = 0; i < numCols; i++) {                    width = me.owner.columns[i];                    if (width < 1) {                        cwidth = ((width / totalFlex) * 100) + '%';                    } else {                        cwidth = width + 'px';                    }                    columns[i].style.width = cwidth;                }            }            // Otherwise it's the *number* of columns, so distributed the widths evenly            else {                for (i = 0; i < numCols; i++) {                    // autoFlex: true will automatically calculate % widths                    // autoFlex: false allows the table to decide (shrinkWrap, in effect)                    // on a per-column basis                    cwidth = autoFlex                        ? (1 / numCols * 100) + '%'                        : '';                    columns[i].style.width = cwidth;                    flexedCols++;                }            }            // no flexed cols -- all widths are fixed            if (!flexedCols) {                innerCtStyle.tableLayout = 'fixed';                innerCtStyle.width = '';            // some flexed cols -- need to fix some            } else if (flexedCols < numCols) {                innerCtStyle.tableLayout = 'fixed';                innerCtStyle.width = '100%';            // let the table decide            } else {                innerCtStyle.tableLayout = 'auto';                // if autoFlex, fill available space, else compact down                if (autoFlex) {                    innerCtStyle.width = '100%';                } else {                    innerCtStyle.width = '';                }            }        } else {            innerCtStyle.tableLayout = 'auto';            innerCtStyle.width = '';        }    },    cacheElements: function () {        var me = this;        // Grab defined childEls        me.callParent();        me.rowEl = me.innerCt.down('tr');        // Grab columns TDs        me.columnNodes = me.rowEl.dom.childNodes;    },    /*     * Just wait for the child items to all lay themselves out in the width we are configured     * to make available to them. Then we can measure our height.     */    calculate: function(ownerContext) {        var me = this,            targetContext, widthShrinkWrap, heightShrinkWrap, shrinkWrap, table, targetPadding;        // The columnNodes are widthed using their own width attributes, we just need to wait        // for all children to have arranged themselves in that width, and then collect our height.        if (!ownerContext.getDomProp('containerChildrenDone')) {            me.done = false;        } else {            targetContext = ownerContext.innerCtContext;            widthShrinkWrap = ownerContext.widthModel.shrinkWrap;            heightShrinkWrap = ownerContext.heightModel.shrinkWrap;            shrinkWrap = heightShrinkWrap || widthShrinkWrap;            table = targetContext.el.dom;            targetPadding = shrinkWrap && targetContext.getPaddingInfo();            if (widthShrinkWrap) {                ownerContext.setContentWidth(table.offsetWidth + targetPadding.width, true);            }            if (heightShrinkWrap) {                ownerContext.setContentHeight(table.offsetHeight + targetPadding.height, true);            }        }    },    doRenderColumn: function (out, renderData, columnIndex) {        // Careful! This method is bolted on to the renderTpl so all we get for context is        // the renderData! The "this" pointer is the renderTpl instance!        var me = renderData.$layout,            owner = me.owner,            columnCount = renderData.columnCount,            items = owner.items.items,            itemCount = items.length,            item, itemIndex, rowCount, increment, tree;        // Example:        //      columnCount = 3        //      items.length = 10        if (owner.vertical) {            //        0   1   2            //      +---+---+---+            //    0 | 0 | 4 | 8 |            //      +---+---+---+            //    1 | 1 | 5 | 9 |            //      +---+---+---+            //    2 | 2 | 6 |   |            //      +---+---+---+            //    3 | 3 | 7 |   |            //      +---+---+---+            rowCount = Math.ceil(itemCount / columnCount); // = 4            itemIndex = columnIndex * rowCount;            itemCount = Math.min(itemCount, itemIndex + rowCount);            increment = 1;        } else {            //        0   1   2            //      +---+---+---+            //    0 | 0 | 1 | 2 |            //      +---+---+---+            //    1 | 3 | 4 | 5 |            //      +---+---+---+            //    2 | 6 | 7 | 8 |            //      +---+---+---+            //    3 | 9 |   |   |            //      +---+---+---+            itemIndex = columnIndex;            increment = columnCount;        }        for ( ; itemIndex < itemCount; itemIndex += increment) {            item = items[itemIndex];            me.configureItem(item);            tree = item.getRenderTree();            Ext.DomHelper.generateMarkup(tree, out);        }    },<span id='Ext-layout-container-CheckboxGroup-method-getColumnCount'>    /**</span>     * Returns the number of columns in the checkbox group.     * @private     */    getColumnCount: function() {        var me = this,            owner = me.owner,            ownerColumns = owner.columns;        // Our columns config is an array of numeric widths.        // Calculate our total width        if (me.columnsArray) {            return ownerColumns.length;        }        if (Ext.isNumber(ownerColumns)) {            return ownerColumns;        }        return owner.items.length;    },    getItemSizePolicy: function (item) {        return this.autoSizePolicy;    },    getRenderData: function () {        var me = this,            data = me.callParent(),            owner = me.owner,            i, columns = me.getColumnCount(),            width, column, cwidth,            autoFlex = me.autoFlex,            totalFlex = 0, flexedCols = 0;        // calculate total flex        if (me.columnsArray) {            for (i=0; i < columns; i++) {                width = me.owner.columns[i];                if (width < 1) {                    totalFlex += width;                    flexedCols++;                }            }        }        data.colCls = owner.groupCls;        data.columnCount = columns;        data.columns = [];        for (i = 0; i < columns; i++) {            column = (data.columns[i] = {});            if (me.columnsArray) {                width = me.owner.columns[i];                if (width < 1) {                    cwidth = ((width / totalFlex) * 100) + '%';                } else {                    cwidth = width + 'px';                }                column.style = 'width:' + cwidth;            } else {                column.style = 'width:' + (1 / columns * 100) + '%';                flexedCols++;            }        }        // If the columns config was an array of column widths, allow table to auto width        data.tableStyle =            !flexedCols ? 'table-layout:fixed;' :            (flexedCols < columns) ? 'table-layout:fixed;width:100%' :            (autoFlex) ? 'table-layout:auto;width:100%' : 'table-layout:auto;';        return data;    },    initLayout: function () {        var me = this,            owner = me.owner;        me.columnsArray = Ext.isArray(owner.columns);        me.autoColumns = !owner.columns || owner.columns === 'auto';        me.vertical = owner.vertical;        me.callParent();    },    // Always valid. beginLayout ensures the encapsulating elements of all children are in the correct place    isValidParent: function() {        return true;    },    setupRenderTpl: function (renderTpl) {        this.callParent(arguments);        renderTpl.renderColumn = this.doRenderColumn;    },    renderChildren: function () {        var me = this,            generation = me.owner.items.generation;        if (me.lastOwnerItemsGeneration !== generation) {            me.lastOwnerItemsGeneration = generation;            me.renderItems(me.getLayoutItems());        }    },<span id='Ext-layout-container-CheckboxGroup-method-renderItems'>    /**</span>     * Iterates over all passed items, ensuring they are rendered.  If the items are already rendered,     * also determines if the items are in the proper place in the dom.     * @protected     */    renderItems : function(items) {        var me = this,            itemCount = items.length,            i,            item,            rowCount,            columnCount,            rowIndex,            columnIndex;        if (itemCount) {            Ext.suspendLayouts();            if (me.autoColumns) {                me.addMissingColumns(itemCount);            }            columnCount = me.columnNodes.length;            rowCount = Math.ceil(itemCount / columnCount);            for (i = 0; i < itemCount; i++) {                item = items[i];                rowIndex = me.getRenderRowIndex(i, rowCount, columnCount);                columnIndex = me.getRenderColumnIndex(i, rowCount, columnCount);                if (!item.rendered) {                    me.renderItem(item, rowIndex, columnIndex);                } else if (!me.isItemAtPosition(item, rowIndex, columnIndex)) {                    me.moveItem(item, rowIndex, columnIndex);                }            }            if (me.autoColumns) {                me.removeExceedingColumns(itemCount);            }            Ext.resumeLayouts(true);        }    },    isItemAtPosition : function(item, rowIndex, columnIndex) {        return item.el.dom === this.getNodeAt(rowIndex, columnIndex);    },    getRenderColumnIndex : function(itemIndex, rowCount, columnCount) {        if (this.vertical) {            return Math.floor(itemIndex / rowCount);        } else {            return itemIndex % columnCount;        }    },    getRenderRowIndex : function(itemIndex, rowCount, columnCount) {        var me = this;        if (me.vertical) {            return itemIndex % rowCount;        } else {            return Math.floor(itemIndex / columnCount);        }    },    getNodeAt : function(rowIndex, columnIndex) {        return this.columnNodes[columnIndex].childNodes[rowIndex];    },    addMissingColumns : function(itemsCount) {        var me = this,            existingColumnsCount = me.columnNodes.length,            missingColumnsCount,            row,            cls,            i;        if (existingColumnsCount < itemsCount) {            missingColumnsCount = itemsCount - existingColumnsCount;            row = me.rowEl;            cls = me.owner.groupCls;            for (i = 0; i < missingColumnsCount; i++) {                row.createChild({                    cls: cls,                    tag: 'td',                    vAlign: 'top'                });            }        }    },    removeExceedingColumns : function(itemsCount) {        var me = this,            existingColumnsCount = me.columnNodes.length,            exceedingColumnsCount,            row,            i;        if (existingColumnsCount > itemsCount) {            exceedingColumnsCount = existingColumnsCount - itemsCount;            row = me.rowEl;            for (i = 0; i < exceedingColumnsCount; i++) {                row.last().remove();            }        }    },<span id='Ext-layout-container-CheckboxGroup-method-renderItem'>    /**</span>     * Renders the given Component into the specified row and column     * @param {Ext.Component} item The Component to render     * @param {number} rowIndex row index     * @param {number} columnIndex column index     * @private     */    renderItem : function(item, rowIndex, columnIndex) {        var me = this;        me.configureItem(item);        item.render(Ext.get(me.columnNodes[columnIndex]), rowIndex);        me.afterRenderItem(item);    },<span id='Ext-layout-container-CheckboxGroup-method-moveItem'>    /**</span>     * Moves the given already rendered Component to the specified row and column     * @param {Ext.Component} item The Component to move     * @param {number} rowIndex row index     * @param {number} columnIndex column index     * @private     */    moveItem : function(item, rowIndex, columnIndex) {        var me = this,            column = me.columnNodes[columnIndex],            targetNode = column.childNodes[rowIndex];        column.insertBefore(item.el.dom, targetNode || null);    }});</pre></body></html>
 |