1. #1
    Sencha User
    Join Date
    Mar 2010
    Posts
    39
    Vote Rating
    0
    Answers
    2
    WBX is on a distinguished road

      0  

    Default Answered: Grid cell tooltips for Ext.grid.column.Column convenience subclasses?

    Answered: Grid cell tooltips for Ext.grid.column.Column convenience subclasses?


    I used the example posted here: http://www.sencha.com/forum/showthread.php?179016 to successfully implement grid cell tooltips. Unfortunately, when used with a Ext.grid.column.Date column it overrides the defaultRenderer method and its associated formatting and this should also be the case with the other Ext.grid.column.Column convenience subclasses. Is there an alternative method for implementing tooltips for these column types?

    Thanks
    Last edited by WBX; 28 Nov 2012 at 1:26 PM. Reason: Changed title

  2. I got this to work on a per column basis:

    http://jsfiddle.net/GDW13/y3DHn/1/

    Code:
    Ext.tip.QuickTipManager.init();
    
    Ext.create('Ext.data.Store', {
        storeId:'employeeStore',
        fields:['firstname', 'lastname', 'seniority', 'dep', 'hired'],
        data:[
            {firstname:"Michael", lastname:"Scott", seniority:7, dep:"Management", hired:"01/10/2004"},
            {firstname:"Dwight", lastname:"Schrute", seniority:2, dep:"Sales", hired:"04/01/2004"},
            {firstname:"Jim", lastname:"Halpert", seniority:3, dep:"Sales", hired:"02/22/2006"},
            {firstname:"Kevin", lastname:"Malone", seniority:4, dep:"Accounting", hired:"06/10/2007"},
            {firstname:"Angela", lastname:"Martin", seniority:5, dep:"Accounting", hired:"10/21/2008"}
        ]
    });
    
    cellTooltipRenderer = function(value, metaData, record, rowIdx, colIdx, store) {
        var column = this.headerCt.getGridColumns()[colIdx];
        var newVal;
        switch (column.xtype) {
        case 'booleancolumn':
            newVal = Ext.create('Ext.grid.column.Boolean').defaultRenderer(value);
            break;
        case 'datecolumn':
            newVal = Ext.create('Ext.grid.column.Date', {format: column.format}).defaultRenderer(value);
            break;
        case 'numbercolumn':
            newVal = Ext.create('Ext.grid.column.Number').defaultRenderer(value, column.format);
            break;
        case 'templatecolumn':
            newVal = Ext.create('Ext.grid.column.Template', {tpl: column.tpl}).defaultRenderer(value, metaData, record);
            break;
        case 'actioncolumn':
        default:
            newVal = value;
        }                        
        metaData.tdAttr = 'data-qtip="' + newVal + '"';
        return newVal;
    };
            
    Ext.create('Ext.grid.Panel', {
        title: 'Column Demo',
        store: Ext.data.StoreManager.lookup('employeeStore'),
        columns: [
            {text: 'First Name',  dataIndex:'firstname', renderer: cellTooltipRenderer},
            {text: 'Last Name',  dataIndex:'lastname', renderer: cellTooltipRenderer},
            {text: 'Hired Month',  dataIndex:'hired', xtype:'datecolumn', format:'M', renderer: cellTooltipRenderer},
            {text: 'Department (Yrs)', xtype:'templatecolumn', tpl:'{dep} ({seniority})', renderer: cellTooltipRenderer}
        ],
        width: 400,
        forceFit: true,
        renderTo: Ext.getBody()
    });
    It's not intended to be used with Action columns but it works with the other column types.

  3. #2
    Sencha User
    Join Date
    Mar 2010
    Posts
    39
    Vote Rating
    0
    Answers
    2
    WBX is on a distinguished road

      0  

    Default


    I was looking into the possibility that I could do something in a beforerender or render listener but I've been unable to determine how to hook into cell data in these listeners. I set up a couple of test functions/listeners mapped to these events and ran them through a debugger to see what was available but couldn't come up with anything. Any ideas? Am I barking up the wrong tree?

  4. #3
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,027
    Vote Rating
    213
    Answers
    480
    slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of

      1  

    Default


    See if this works for you. Has some undocumented stuff in there so who knows how it'll work in 4.2 and beyond, but...

    http://jsfiddle.net/slemmon/GEwkG/

    Code:
    Ext.tip.QuickTipManager.init();
     
    Ext.create('Ext.data.Store', {
        storeId:'simpsonsStore',
        fields:['name', 'email', 'phone'],
        data:{'items':[
            { 'name': 'Lisa',  "email":"lisa@simpsons.com",  "phone":"555-111-1224"  },
            { 'name': 'Bart',  "email":"bart@simpsons.com",  "phone":"555-222-1234" },
            { 'name': 'Homer', "email":"home@simpsons.com",  "phone":"555-222-1244"  },
            { 'name': 'Marge', "email":"marge@simpsons.com", "phone":"555-222-1254"  }
        ]},
        proxy: {
            type: 'memory',
            reader: {
                type: 'json',
                root: 'items'
            }
        }
    });
     
    Ext.create('Ext.grid.Panel', {
        title: 'Simpsons',
        store: Ext.data.StoreManager.lookup('simpsonsStore'),
        columns: [
            { text: 'Name',  dataIndex: 'name' },
            { text: 'Email', dataIndex: 'email', flex: 1 },
            { text: 'Phone', dataIndex: 'phone' }
        ],
        height: 200,
        width: 400,
        renderTo: Ext.getBody()
        , listeners: {
            viewready: function (grid) {
                var view = grid.view;
               
                // record the current cellIndex
                grid.mon(view, {
                    uievent: function (type, view, cell, recordIndex, cellIndex, e) {
                        grid.cellIndex = cellIndex;
                        grid.recordIndex = recordIndex;
                    }
                });
               
                grid.tip = Ext.create('Ext.tip.ToolTip', {
                    target: view.el,
                    delegate: '.x-grid-cell',
                    trackMouse: true,
                    renderTo: Ext.getBody(),
                    listeners: {
                        beforeshow: function updateTipBody(tip) {
                            if (!Ext.isEmpty(grid.cellIndex) && grid.cellIndex !== -1) {
                                header = grid.headerCt.getGridColumns()[grid.cellIndex];
                                tip.update(grid.getStore().getAt(grid.recordIndex).get(header.dataIndex));
                            }
                        }
                    }
                });
     
            }
        }
    });

  5. #4
    Sencha User
    Join Date
    Mar 2010
    Posts
    39
    Vote Rating
    0
    Answers
    2
    WBX is on a distinguished road

      0  

    Default


    Thanks. This retains the formatting for the cells but the tooltip is unformatted. I'm wondering if defaultRenderer (or renderer) can be called in order to format the tooltip. Thoughts?

  6. #5
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,027
    Vote Rating
    213
    Answers
    480
    slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of

      1  

    Default


    This snippet assumes your date column is an xtype: 'datecolumn' and that it has a format

    http://jsfiddle.net/slemmon/GEwkG/1/

    Code:
    Ext.create('Ext.data.Store', {
        storeId:'employeeStore',
        fields:['firstname', 'lastname', 'seniority', 'dep', 'hired'],
        data:[
            {firstname:"Michael", lastname:"Scott", seniority:7, dep:"Management", hired:"01/10/2004"},
            {firstname:"Dwight", lastname:"Schrute", seniority:2, dep:"Sales", hired:"04/01/2004"},
            {firstname:"Jim", lastname:"Halpert", seniority:3, dep:"Sales", hired:"02/22/2006"},
            {firstname:"Kevin", lastname:"Malone", seniority:4, dep:"Accounting", hired:"06/10/2007"},
            {firstname:"Angela", lastname:"Martin", seniority:5, dep:"Accounting", hired:"10/21/2008"}
        ]
    });
    
    Ext.create('Ext.grid.Panel', {
        title: 'Column Demo',
        store: Ext.data.StoreManager.lookup('employeeStore'),
        columns: [
            {text: 'First Name',  dataIndex:'firstname'},
            {text: 'Last Name',  dataIndex:'lastname'},
            {text: 'Hired Month',  dataIndex:'hired', xtype:'datecolumn', format:'M'},
            {text: 'Department (Yrs)', xtype:'templatecolumn', tpl:'{dep} ({seniority})'}
        ],
        width: 400,
        forceFit: true,
        renderTo: Ext.getBody()
        , listeners: {
            viewready: function (grid) {
                var view = grid.view;
                
                // record the current cellIndex
                grid.mon(view, {
                    uievent: function (type, view, cell, recordIndex, cellIndex, e) {
                        grid.cellIndex = cellIndex;
                        grid.recordIndex = recordIndex;
                    }
                });
                
                grid.tip = Ext.create('Ext.tip.ToolTip', {
                    target: view.el,
                    delegate: '.x-grid-cell',
                    trackMouse: true,
                    renderTo: Ext.getBody(),
                    listeners: {
                        beforeshow: function updateTipBody(tip) {
                            if (!Ext.isEmpty(grid.cellIndex) && grid.cellIndex !== -1) {
                                var header = grid.headerCt.getGridColumns()[grid.cellIndex];
                                var val = grid.getStore().getAt(grid.recordIndex).get(header.dataIndex);
                                var isDateColumn = header.xtype == 'datecolumn';
                                tip.update(isDateColumn ? Ext.util.Format.date(val, header.format) : val);
                            }
                        }
                    }
                });
    
            }
        }
    });

  7. #6
    Sencha User
    Join Date
    Mar 2010
    Posts
    39
    Vote Rating
    0
    Answers
    2
    WBX is on a distinguished road

      0  

    Default


    I'm trying to understand how this works. It looks as if a single tooltip is being created for the entire grid and is being constantly updated to reflect the contents of the underlying cell as the mouse moves (via the beforeshow listener) and is shown only for cells (via delegate: '.x-grid-cell'). Is this correct? I had originally hoped to extract this code and apply it to individual columns but that wouldn't work if it applies to the entire grid. Plan B would be to detect the column type and format accordingly.

    I noticed that there are frequently multiple overlapping tooltips with this implementation. I thought that I might get rid of this side effect by setting trackMouse to false but this didn't help. Any ideas?

  8. #7
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,027
    Vote Rating
    213
    Answers
    480
    slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of

      0  

    Default


    Your understanding seems right. I just modified the example under the DELEGATION heading on this doc:
    http://docs.sencha.com/ext-js/4-1/#!...xt.tip.ToolTip

    Not sure about the overlapping tooltips - worked ok for me on Chrome, FF, and IE10.

  9. #8
    Sencha User
    Join Date
    Mar 2010
    Posts
    39
    Vote Rating
    0
    Answers
    2
    WBX is on a distinguished road

      0  

    Default


    I discovered what was causing the overlapping tooltips: I forgot to remove the renderer that I was previously using.

    Thanks again.

  10. #9
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,027
    Vote Rating
    213
    Answers
    480
    slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of slemmon has much to be proud of

      0  

    Default


    Right on. So, this one can be marked 'Answered'?

  11. #10
    Sencha User
    Join Date
    Mar 2010
    Posts
    39
    Vote Rating
    0
    Answers
    2
    WBX is on a distinguished road

      0  

    Default


    I'm trying to get this to work for all column types by tapping into the renderer for each column if it exists:

    http://jsfiddle.net/GDW13/tAkhU/

    Code:
    Ext.create('Ext.data.Store', {
        storeId:'employeeStore',
        fields:['firstname', 'lastname', 'seniority', 'dep', 'hired'],
        data:[
            {firstname:"Michael", lastname:"Scott", seniority:7, dep:"Management", hired:"01/10/2004"},
            {firstname:"Dwight", lastname:"Schrute", seniority:2, dep:"Sales", hired:"04/01/2004"},
            {firstname:"Jim", lastname:"Halpert", seniority:3, dep:"Sales", hired:"02/22/2006"},
            {firstname:"Kevin", lastname:"Malone", seniority:4, dep:"Accounting", hired:"06/10/2007"},
            {firstname:"Angela", lastname:"Martin", seniority:5, dep:"Accounting", hired:"10/21/2008"}
        ]
    });
    
    
    Ext.create('Ext.grid.Panel', {
        title: 'Column Demo',
        store: Ext.data.StoreManager.lookup('employeeStore'),
        columns: [
            {text: 'First Name',  dataIndex:'firstname'},
            {text: 'Last Name',  dataIndex:'lastname'},
            {text: 'Hired Month',  dataIndex:'hired', xtype:'datecolumn', format:'M'},
            {text: 'Department (Yrs)', xtype:'templatecolumn', tpl:'{dep} ({seniority})'}
        ],
        width: 400,
        forceFit: true,
        renderTo: Ext.getBody()
        , listeners: {
            viewready: function (grid) {
                var view = grid.view;
                
                // record the current cellIndex
                grid.mon(view, {
                    uievent: function (type, view, cell, recordIndex, cellIndex, e) {
                        grid.cellIndex = cellIndex;
                        grid.recordIndex = recordIndex;
                    }
                });
                
                grid.tip = Ext.create('Ext.tip.ToolTip', {
                    target: view.el,
                    delegate: '.x-grid-cell',
                    trackMouse: true,
                    renderTo: Ext.getBody(),
                    listeners: {
                        beforeshow: function updateTipBody(tip) {
                            var metaData = {
                                tdCls: '',
                                style: ''
                            };
                            var record = grid.getStore().getAt(grid.recordIndex);
                            var column = grid.headerCt.getGridColumns()[grid.cellIndex];
                            var val = record.get(column.dataIndex);
    
                            var tipVal
                            if (column.renderer) {
                                switch (column.xtype) {
                                case 'booleancolumn':
                                case 'datecolumn':
                                case 'numbercolumn':
                                    tipVal = column.renderer(val);
                                    break;
                                case 'templatecolumn':
                                    tipVal = column.renderer(val, metaData, record);
                                    break;
                                case 'actioncolumn':
                                    tipVal = column.renderer(val, metaData);
                                    break;
                                default:
                                    tipVal = val;
                                }
                            } else {
                                tipVal = val;
                            }
    
    
                            tip.update(tipVal);
                        }
                    }
                });
    
    
            }
        }
    });
    This works for booleancolumn, datecolumn, numbercolumn and templatecolumn xtypes but I haven't tried it yet for actioncolumn. It seems a bit iffy as to whether it will work with actioncolumn due to the nature of and variations in its construction.

    This catch-all mechanism is useful but not really optimal. I was really looking for a mechanism that allowed setting this up at the column level so that I could still deal with use cases such as the actioncolumn in this example: http://http://dev.sencha.com/deploy/...rray-grid.html. This and the fact that I was working on the above code are the main reasons that I haven't marked this as answered.

    Regardless, I really appreciate your help.

Thread Participants: 1

Tags for this Thread