Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>I took the accepted answer to the next logical conclusion:</h2> <p>And made this into complete configurable <code>plugin</code> based solution, that requires very little configuration to use. And plays nicely with Sencha Architect.</p> <h3>Motivation</h3> <p>The main motivation for researching this and getting it to work is that the <code>DateColumn</code> has the <code>renderer</code> config parameter marked as <code>hidden</code> so that Sencha Architect doesn't allow you to modify it in the <code>Config</code> panel. I understand why and it drove me to this solution, which I think is the correct one and the most maintainable and reusable in the long run.</p> <h3>At the time of this writing:</h3> <p>I am using Sencha Architect 3.x and ExtJS 4.2.2, these instructions are included on how to apply these features in that environment. If you don't use Sencha Architect, you will just have to create and manage the files yourself. <em>I find it extremely productive when working on any size ExtJS project.</em></p> <p>First is the actual <code>GridPlugin</code>:</p> <p>Add a <code>JSResource</code> to your project, set the <code>url</code> to <code>js/CellToolTip.js</code>, and then copy the following code as its contents.</p> <h3>js/CellToolTip.js</h3> <pre><code>Ext.define('Ext.grid.plugin.CellToolTip', { extend: 'Ext.AbstractPlugin', alias: 'plugin.CellQTip', config: { debug: false }, init: function(grid) { // You may not need the scope, but if you do, this binding will // allow to preserve the scope configured in the column... var pluginRenderer = Ext.Function.bind(this.renderer, this); Ext.each(grid.query('gridcolumn'), function(col) { var renderer = col.renderer; col.renderer = renderer ? Ext.Function.createSequence(renderer, pluginRenderer) : pluginRenderer; }); }, renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { var col = view.getGridColumns()[colIndex]; var fn = this[col.itemId]; if (fn) { metaData.tdAttr = fn(value, metaData, record, rowIndex, colIndex, store, view); } return value; } }); </code></pre> <p>Here is how you apply it to a <code>GridPanel</code>:</p> <p>You add what is called a <a href="http://docs.sencha.com/architect/2/#!/guide/config_panel" rel="nofollow"><code>Process Config</code></a> function to each <code>GridPanel</code> that you want to apply the plugin to:</p> <p>What this does is it acts as an <em>interceptor</em> function and allows you to modify the <code>config</code> of the <code>Component</code> before it is actually applied.</p> <pre><code>processBlobInfoGridPanel: function(config) { var ttp = Ext.create('Ext.grid.plugin.CellToolTip', { createdOn: function(value, metaData, record, rowIndex, colIndex, store, view) { return 'data-qtip="' + value.toUTCString() + '"'; }, byteSize: function(value, metaData, record, rowIndex, colIndex, store, view) { return 'data-qtip="' + value + ' bytes"'; } }); config.plugins = [ttp]; return config; }, </code></pre> <h3>How to add these to a Sencha Architect project:</h3> <p>First what this does is creates the <code>plugin</code> with its own config where each attribute is the <code>itemId</code> of each <code>Column</code> that you want to apply the plugin to.</p> <p>The function that is associated with each <code>Column</code> has the exact same signature as the <a href="http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.grid.column.Column-cfg-renderer" rel="nofollow"><code>renderer</code></a> config.</p> <p>Here the function implementations are short and in a single line. This is just an and example is for brevity. </p> <h3>ToolTip functions explained:</h3> <p><code>createdOn</code> adds a <code>ToolTip</code> for each <code>Cell</code> in that <code>Column</code> as the time in <code>UTC</code>.</p> <p><code>byteSize</code> adds a <code>ToolTip</code> for each <code>Cell</code> in that <code>Column</code> that shows the raw number of bytes as a detail.</p> <p>Then it adds the instance of the configured plugin to the <code>config</code> of the <code>GridPanel</code> and returns the instance of the <code>config</code>.</p> <h3>Bonus Class</h3> <p>In Sencha Architect I created a <code>Column</code> to represent the <code>Size</code> of <code>Resources</code>, I wanted to show the byte size as a human readable format with the largest appropriate interval. So I added a <code>renderer</code> function to do this.</p> <p>I realized I was going to need this <code>Column</code> on multiple <code>GridPanel</code> instances so <em>promoted it to a Class</em>.</p> <p>The way you do this is you right click on the <code>Column</code> and pick <code>Promote to Class</code>. Sencha Architect then creates the following code and puts it in a file in your <code>app/view</code> directory with the name of the file equal to the <code>userClassName</code> you specified in the <code>Config</code> panel.</p> <pre><code>Ext.define('AdminApp.view.ByteSize', { extend: 'Ext.grid.column.Column', alias: 'widget.byteSize', itemId: 'byteSize', dataIndex: 'size', text: 'Size', tooltip: 'Byte size in human readable format', initComponent: function() { var me = this; me.callParent(arguments); }, renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { // convert bytes into a human readable format" var bytes = value; if (bytes&gt;=1073741824) {bytes=(bytes/1073741824).toFixed(2)+' GB';} else if (bytes&gt;=1048576) {bytes=(bytes/1048576).toFixed(2)+' MB';} else if (bytes&gt;=1024) {bytes=(bytes/1024).toFixed(2)+' KB';} else if (bytes&gt;1) {bytes=bytes+' bytes';} else if (bytes==1) {bytes=bytes+' byte';} else {bytes='0 byte';} return bytes; } }); </code></pre> <p>Now the original instance of this <code>Column</code> is pointing to this new <code>Class</code>:</p> <pre><code>columns: [ { xtype: 'byteSize', itemId: 'byteSize' } ] </code></pre> <p>Now to use this in other <code>GridPanel</code> instances in Sencha Architect, just right click on the <code>Column</code> instance that is linked to this new class and select <code>Duplicate</code>. Then drag the duplicated instance to the <code>GridPanel</code> you want to use the <code>ByteSize</code> class and drop it in the list of <code>Columns</code>. Then configure each cloned instance independently of the others.</p> <p>Any changes to the default or behavior of the <code>ByteClass</code> automatically affect all the instances.</p> <h2>Roadmap</h2> <p>This is a first working minimally viable solution, there are obvious enhancements that can be made. For example, I am want to fix it where it appends to <code>metaData.tdAttr</code> if there is already content instead of blindly over-writing what is there. </p> <p>Any enhancements will be done to this <a href="https://gist.github.com/jarrodhroberson/7763558" rel="nofollow">Gist on GitHub</a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload