ExtJs - Copying GridPanel single row data to clipboard

rahul's picture

This blog post is more of a continuation of 2 of my earlier blog posts, Cross-browser approach to copy content to clipboard in javascript, and Copying GridPanel content to clipboard. I would advise reading of the above blog posts if you haven't already to understand the code being discussed below.

But this time, my requirement was to allow copying of GridPanel's individual row content to clipboard. The basis for implementing the new code was already available (as you would know from the above 2 blog posts).

The first task was to have the clipboard flash movie in each row of the GridPanel. This was accomplished easily with the GridPanel's TemplateColumn. An object tag was specified for the flash movie in the XTemplate for the column as follows:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }{ dataIndex: 'company', width: 30, xtype: "templatecolumn", tpl: new Ext.XTemplate( "<object id='clipboard{[this.getClipboardId(values)]}' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#vers...' width='16' height='16' align='middle'>", "<param name='allowScriptAccess' value='always' />", "<param name='allowFullScreen' value='false' />", "<param name='movie' value='/sites/default/files/content/blog/javascript_clipboard/clipboard.swf' />", "<param name='quality' value='high' />", "<param name='bgcolor' value='#ffffff' />", "<param name='flashvars' value='callback=f1&callbackArg={[this.getClipboardId(values)]}' />", "<embed src='/sites/default/files/content/blog/javascript_clipboard/clipboard.swf' flashvars='callback=f1&callbackArg={[this.getClipboardId(values)]}' quality='high' bgcolor='#ffffff' width='16' height='16' name='clipboard{[this.getClipboardId(values)]}' align='middle' allowscriptaccess='always' allowfullscreen='false' type='application/x-shockwave-flash' pluginspage='http://www.adobe.com/go/getflashplayer' />", "</object>", { getClipboardId: getClipboardId }) }{/syntaxhighlighter}

Notice the use of the template member function getClipboardId. More on it below.

Now, the real challenge was to identify the row in which the flash movie was placed when it was clicked. After some thinking, I thought flashvars was a good place to do so.

I updated my clipboard flash movie to support a new flash var called, callbackArg (discussed here). This variable is passed back to the javascript callback function by the flash movie, and the javascript function can easily use this to maintain any state it wants (in our case, identify the GridPanel row that was clicked).

So, in the column template, I used XTemplate's member function feature to add each row's id value for the callbackArg. When the Flash movie is clicked, it passes this id back to the callback method, which uses it to identify the row that was clicked and then appropriately return data to the flash movie that can be placed on the clipboard.

Here's the code for the javascript callback method:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }function f1(company) { var store = Ext.getCmp('grid').store; var record = store.getById(company); var s = ''; for (key in record.data) { s += key + ': ' + record.data[key] + '\n'; } alert('Following data copied to clipboard:\n\n' + s); if (window.clipboardData) window.clipboardData.setData('text', s); else return (s); }{/syntaxhighlighter}

And here's the first-hand experience for copying each individual row. Try clicking the icon in each row of the GridPanel below and then try pasting into Notepad or any other editor to see how easily you can copy each individual row:

The html file for the above demonstration is attached below. You can easily modify the javascript callback method to transform or format data before it is copied to the clipboard.

A very important thing to note above is that the flash movie should not have its window mode (wmode) set to transparent. Otherwise the click event on the movie is not passed to the movie but to the underlying grid, which prevents the movie from executing its functionality.

 

AttachmentSize
grid-row-copy-clipboard.htm6.53 KB

Comments

Thanks for the code mate. Really helped me out there. I edited some of the functions a bit so it worked with multiple instances of an EditorGrid. I sent all the values of the record in an JSON encoded string to the clipboard.swf

getClipboardId: function(values){
return Ext.encode(values);
}

f1: function(values){
var p = Ext.decode(values);
var s = p.orderid + p.etc;
return (s)

This way I don't have to look up the grid and store and the code is nicely contained in it's own class.

By Daniel (not verified)
rahul's picture

Daniel, take note that for IE, you set data to clipboard using the setClipboardData method and not through Flash.

By rahul

I used the code for extjs 3 and it worked.  Now that I switched over to extjs 4.  It no longer works.  FYI, put the object <object id .... > in the dockedArea.  How can I debug the problem?

By jianping roth (not verified)

Seems the flash doesn't work for some special character?

When I click the sixth row(AT&T Inc.) , it has no response. Other rows have response.

By roc (not verified)
rahul's picture

Hi roc, seems like you are correct. Maybe xml/html encoding might work. I haven't tried though and won't be able to do so in the near future.

By rahul

Rahul, Thanks for your reply.Very helpful.

I found it went wrong when trying to execute this statement:

var record = store.getById(company);

Maybe store.getById will not function properly when company has special char.

So I think another solution is to add a hidden column called companyId (only using numbers). and change this line to var record = store.getById(companyId);

By roc (not verified)
rahul's picture

Oh okay then, this is an ExtJs issue and not with the clipboard code. Thanks for sharing that information roc...

By rahul

Add new comment