Hybrid View

  1. #1
    Sencha Premium Member harrydeluxe's Avatar
    Join Date
    Jul 2007
    Location
    Nürnberg, Germany
    Posts
    78
    Vote Rating
    29
    harrydeluxe has a spectacular aura about harrydeluxe has a spectacular aura about

      3  

    Default Thumbnails in Grid with switching between views.

    Thumbnails in Grid with switching between views.


    Ext.ux.grid.feature.Tileview



    Source on Github:
    https://github.com/harrydeluxe/extjs-ux/

    Demo:
    http://harrydeluxe.github.com/extjs-.../tileview.html
    DELACAP | Github
    "don't code today what you can't debug tomorrow"

  2. #2
    Sencha - Senior Software Engineer mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    38,044
    Vote Rating
    992
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    Looks pretty good! I like this!
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Software Engineer
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  3. #3
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,247
    Vote Rating
    485
    scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute scottmartin has a reputation beyond repute

      0  

    Default


    Nice ...

    Are the dual scrollbars so we can scroll twice as fast? <bg>

    Regards,
    Scot.

  4. #4
    Sencha Premium Member ajaxvador's Avatar
    Join Date
    Nov 2007
    Location
    PARIS, FRANCE
    Posts
    211
    Vote Rating
    0
    ajaxvador is on a distinguished road

      0  

    Default


    GREAT
    +1

    TINY BUG : DOUBLE SCROLL BAR IN GOOGLE CHROME.

    screen00.jpg
    Vador

  5. #5
    Sencha Premium Member harrydeluxe's Avatar
    Join Date
    Jul 2007
    Location
    Nürnberg, Germany
    Posts
    78
    Vote Rating
    29
    harrydeluxe has a spectacular aura about harrydeluxe has a spectacular aura about

      0  

    Default


    Thanks for the note. Fixed.
    DELACAP | Github
    "don't code today what you can't debug tomorrow"

  6. #6
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    17,544
    Vote Rating
    743
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    Cool extension, very nice.
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

  7. #7
    Sencha User
    Join Date
    May 2007
    Posts
    191
    Vote Rating
    0
    temporary is on a distinguished road

      0  

    Default


    Hey folks,

    I managed to port this to ExtJS 4.2+

    Its still work in progress, and I would love to see others contribute, since I am in desperate need of this component for 4.2 ;-)

    The basic functionality works, haven't checked if it still works with other features like grouping.
    And I only tested it with current stable Chrome on MacOS.

    Will create a github repo for this soon.

    Right now, you can find the changed code here:
    https://fiddle.sencha.com/#fiddle/2u6

  8. #8
    Ext JS Premium Member
    Join Date
    Feb 2009
    Posts
    481
    Vote Rating
    4
    Jangla is on a distinguished road

      0  

    Default


    Quote Originally Posted by temporary View Post
    Hey folks,

    I managed to port this to ExtJS 4.2+

    Its still work in progress, and I would love to see others contribute, since I am in desperate need of this component for 4.2 ;-)

    The basic functionality works, haven't checked if it still works with other features like grouping.
    And I only tested it with current stable Chrome on MacOS.

    Will create a github repo for this soon.

    Right now, you can find the changed code here:
    https://fiddle.sencha.com/#fiddle/2u6
    The link to tileview.js is broken so although the fiddle works, we can't check out the code

    Edit: Also, I was previously using getAdditionalData on the tileview feature to manipulate and inject more data for my tileview. This doesn't get called in Ext 4.2. Anyone know of a solution for this?

  9. #9
    Sencha User
    Join Date
    Nov 2007
    Posts
    2
    Vote Rating
    0
    wlady is on a distinguished road

      0  

    Default


    You shouldn't remove template items like it was in Tileview.js line 21:

    Code:
    grid.view.tableTpl.html = grid.view.tableTpl.html.replace(/\{\[view.renderColumnSizer\(out\)\]\}/, '');
    In this way all other grids will be created without colgroups (ie with wrong size).
    The simplest solution is to add your own table template into initConfig:

    Code:
    Ext.create('Ext.ux.grid.feature.Tileview', {
        viewMode: 'default',
        tableTpl: [
            '{%',
                // Add the row/column line classes to the table element.
                'var view=values.view,tableCls=["' + Ext.baseCSSPrefix + '" + view.id + "-table ' + Ext.baseCSSPrefix + 'grid-table"];',
                'if (view.columnLines) tableCls[tableCls.length]=view.ownerCt.colLinesCls;',
                'if (view.rowLines) tableCls[tableCls.length]=view.ownerCt.rowLinesCls;',
            '%}',
            '<table role="presentation" id="{view.id}-table" class="{[tableCls.join(" ")]}" border="0" cellspacing="0" cellpadding="0" style="{tableStyle}" tabIndex="-1">',
                '{[view.renderTHead(values, out)]}',
                '{[view.renderTFoot(values, out)]}',
                '<tbody id="{view.id}-body">',
                '{%',
                    'view.renderRows(values.rows, values.viewStartIndex, out);',
                '%}',
                '</tbody>',
            '</table>',
            {
                priority: 0
            }
        ],
        viewTpls:
        {
            // custom row tpls
        }
    })
    and add tableTpl switching in setView method. Please remember you have to save original tableTpl and use it when necessary:
    Code:
    Ext.define('Ext.ux.grid.feature.Tileview', {
        extend: 'Ext.grid.feature.Feature',
        alias: 'feature.tileview',
        metaTableTplOrig: null, // stores the original template
        viewMode: null,
        viewTpls: {},
        tableTpls: {},
    
    
        init: function(grid) {
    
    
            var me = this,
                view = me.view;
    
    
            me.metaTableTplOrig = me.view.tableTpl;
            view.tileViewFeature = me;
    
    
            Ext.Object.each(this.viewTpls, function(key, rowTpl) {
                view.addRowTpl(new Ext.XTemplate(rowTpl));
            })
    
    
    
    
            me.callParent(arguments);
        },
    
    
        getColumnValues: function(columns, record) {
            var columnValues = {};
            Ext.each(columns, function(column) {
                var key = column.dataIndex,
                    value = record.data[column.dataIndex];
    
    
                columnValues[key] = value;
            });
            return columnValues;
        },
    
    
        getRowBody: function(values, viewMode)
        {
            if(this.viewTpls[viewMode])
            {
                return this.viewTpls[viewMode];
            }
        },
    
    
        setView: function(mode)
        {
            var me = this;
    
    
            if(me.viewMode != mode)
            {
                me.viewMode = mode;
                if (mode!='default') {
                    me.view.addTableTpl(new Ext.XTemplate(me.tableTpl))
                } else {
                    me.view.addTableTpl(me.metaTableTplOrig)
                }
                me.view.refresh();
             }
        }
    });

  10. #10
    Ext JS Premium Member
    Join Date
    Feb 2009
    Posts
    481
    Vote Rating
    4
    Jangla is on a distinguished road

      0  

    Default


    I'm trying to implement this for a pretty complex grid we have and I've been getting an issue:

    http://puu.sh/ehIft/ea8c90fd68.png

    Notice in the screenshot how the rows are *outside* the x-grid-table-resizer table.

    I will post some of my code as soon as I can but if anyone has come across this issue in the meantime, please chime in


    Edit: Code

    Code:
    
    
    /**
     * Small override
     * @see http://www.sencha.com/forum/showthread.php?183860-Feature-Request-for-Ext.view.TableChunker
     * This will be used with the tile view feature in Grid.js
     */
    
    
    
    
    Ext.grid.feature.Feature.override({
        mutateMetaTableTpl: function (metaTableTplArray) {
        }
    });
    
    
    Ext.view.TableChunker.getTableTpl = function (cfg, textOnly) {
        var tpl,
            tableTplMemberFns = {
                openRows      : this.openRows,
                closeRows     : this.closeRows,
                embedFeature  : this.embedFeature,
                embedFullWidth: this.embedFullWidth,
                openTableWrap : this.openTableWrap,
                closeTableWrap: this.closeTableWrap
            },
            tplMemberFns = {},
            features = cfg.features || [],
            ln = features.length,
            i = 0,
            memberFns = {
                embedRowCls   : this.embedRowCls,
                embedRowAttr  : this.embedRowAttr,
                firstOrLastCls: this.firstOrLastCls
            },
            metaRowTpl = Array.prototype.slice.call(this.metaRowTpl, 0),
            metaTableTpl = Array.prototype.slice.call(this.metaTableTpl, 0);
    
    
    
    
        for (; i < ln; i++) {
            if (!features[i].disabled) {
                features[i].mutateMetaTableTpl(metaTableTpl); // new
                features[i].mutateMetaRowTpl(metaRowTpl);
                Ext.apply(memberFns, features[i].getMetaRowTplFragments());
                Ext.apply(tplMemberFns, features[i].getFragmentTpl());
                Ext.apply(tableTplMemberFns, features[i].getTableFragments());
            }
        }
    
    
        metaRowTpl = new Ext.XTemplate(metaRowTpl.join(''), memberFns);
        cfg.row = metaRowTpl.applyTemplate(cfg);
    
    
        metaTableTpl = new Ext.XTemplate(metaTableTpl.join(''), tableTplMemberFns);	// new
    
    
        tpl = metaTableTpl.applyTemplate(cfg);
    
    
        // TODO: Investigate eliminating.
        if (!textOnly) {
            tpl = new Ext.XTemplate(tpl, tplMemberFns);
        }
        return tpl;
    
    
    };
    
    
    /**
     * Grid
     * All the grid components should go in here
     * Ideally this should be the place only the base classes go and fully fledged grids should be created as views.
     * Legacy grids will be moved into here for safe keeping in the hope we someday have the time to convert them to views
     */
    
    
    
    
    /**
     * @class Ext.ux.grid.feature.Tileview
     * @extends Ext.grid.feature.Feature
     *
     * @author Harald Hanek (c) 2011-2012
     * @license http://harrydeluxe.mit-license.org
     */
    
    
    Ext.define('Ext.ux.grid.feature.Tileview', {
        extend          : 'Ext.grid.feature.Feature',
        alias           : 'feature.tileview',
        metaTableTplOrig: null, // stores the original template
        viewMode        : null,
        viewTpls        : {},
        metaTableTpl    : ['{[this.openTableWrap()]}',
            '<table class="' + Ext.baseCSSPrefix + 'grid-table tileview" border="0" cellspacing="0" cellpadding="0" style="width: auto;">',
            '<tbody class="dragselect">',
            '{[this.openRows()]}',
            '{row}',
            '<tpl for="features">',
            '{[this.embedFeature(values, parent, xindex, xcount)]}',
            '</tpl>',
            '{[this.closeRows()]}',
            '</tbody>',
            '</table>',
            '{[this.closeTableWrap()]}'
        ],
    
    
        getRowBody: function (values, viewMode) {
            if (this.viewTpls[viewMode]) {
                return this.viewTpls[viewMode];
            }
        },
    
    
        mutateMetaTableTpl: function (metaTableTpl) {
            var me = this;
    
    
            if (me.viewMode && me.viewMode != 'default') {
                metaTableTpl[1] = '<table class="' + Ext.baseCSSPrefix + 'grid-table tileview" border="0" cellspacing="0" cellpadding="0" style="width: auto;">';
                metaTableTpl[2] = '<tbody class="dragselect">';
                metaTableTpl[3] = null;
                metaTableTpl[4] = null;
                metaTableTpl[5] = null;
                metaTableTpl[6] = null;
                metaTableTpl[7] = null;
            }
        },
    
    
        mutateMetaRowTpl: function (metaRowTpl) {
            var me = this;
    
    
            if (me.viewMode && me.viewMode != 'default') {
                metaRowTpl[0] = '<tr class="' + Ext.baseCSSPrefix + 'grid-row tileview {[this.embedRowCls()]}" {[this.embedRowAttr()]}>';
                metaRowTpl[1] = null;
                metaRowTpl[2] = '{[this.getRowBody(values, this.viewMode)]}';
                metaRowTpl[3] = null;
                metaRowTpl[4] = null;
                metaRowTpl[5] = null;
                metaRowTpl[6] = "</tr>";
            }
        },
    
    
        getMetaRowTplFragments: function () {
            return {
                getRowBody: this.getRowBody,
                viewMode  : this.viewMode,
                viewTpls  : this.viewTpls
            };
        },
    
    
        setView: function (mode) {
            var me = this;
    
    
            if (me.viewMode != mode) {
                me.viewMode = mode;
                me.view.refresh();
            }
        }
    });
    
    
    
    // the grid itself has this in it's build function
    
            me.TileViewFeature = Ext.create('Ext.ux.grid.feature.Tileview', {
                viewMode         : 'default',          // default will be rows
                getAdditionalData: function(data, index, record, orig)
                {
                    return Ext.apply({}, {
                        contentType : (data.thumbnailAssetRef || data.mainAssetRef) ? 'image' : 'text',
                        backgroundAsset :  data.thumbnailAssetRef ? data.thumbnailAssetRef : (data.mainAssetRef ? data.mainAssetRef : '')
                    }, data);
                },
                viewTpls: {
                    tileView: '\
                        <div class="ngx-grid-tile-item ngx-grid-content-{contentType} ngx-grid-network-twitter">\
                            <div class="ngx-grid-tile-item-inner" style="background-image: url(\'{backgroundAsset:assetRefToPath}\')">\
                                <div class="ngx-item-actions">\
                                    <div class="ngx-item-actions-inner">\
                                        <div data-tooltip="Review &amp; edit" class="item-action-icon"><i data-icon="e"></i></div>\
                                        <div data-tooltip="Link to advocacy" class="item-action-icon"><i data-icon="&"></i></div>\
                                        <div data-tooltip="Go to campaign" class="item-action-icon"><i data-icon="9"></i></div>\
                                        <div data-tooltip="Request content rights" class="item-action-icon"><i data-icon="©"></i></div>\
                                        <div data-tooltip="Mark as favourite" class="item-action-icon"><i data-icon="*"></i></div>\
                                    </div>\
                                </div>\
                                <div class="ngx-user-profile">\
                                    <div class="ngx-user-profile-inner">\
                                        <div class="ngx-network-icon">\
                                            <i data-icon="{externalService:dataIcon}"></i>\
                                        </div>\
                                        <div class="ngx-user-avatar">{[NGXUtils.createAvatar(values.avatar, values.userName, "entry-avatar")]}</div>\
                                        <div class="user-details">\
                                            <tpl if="profile">\
                                                <div class="name">{profile:sanitize}</div>\
                                                <div class="handle">{userName:userHandle(values.externalService)}</div>\
                                            <tpl else>\
                                                <div class="name">{userName:sanitize}</div>\
                                            </tpl>\
                                        </div>\
                                    </div>\
                                </div>\
                                <div class="ngx-grid-content">\
                                    <p class="grid-content">{content:shorten(140)}</p>\
                                </div>\
                            </div>\
                        </div>'
                }
            });
    
    // and then this in the initComponent:
    
            Ext.apply(me, {
                id          : me.id || Ext.id(),
                selModel    : {
                    pruneRemoved: true
                },
                features    : [me.TileViewFeature],
                viewConfig  : Ext.apply({}, {
                    chunker                : Ext.view.TableChunker,
                    deferEmptyText         : false,
                    emptyText              : '<div class="grid-data-empty"><div class="empty-grid-icon"><i data-icon="/"></i></div><div class="empty-grid-headline">Nothing to see here</div><div class="empty-grid-byline">There are no records to show you right now. There may be no content or your filters may be too tightly defined.</div></div>',
                    preserveScrollOnRefresh: true,
                    getRowClass            : function (record, rowIndex, rowParams, store) {
                        return 'ngx-grid-fixed-height-row row-height-medium'
                    }
                }, me.viewDefaultViewConfig),
                columns     : [
    ...