After you have seen the demo you may whant to know how its been done :)

I just pasted from Documentation.

Represents the base Plugin for adding Cut/Copy/Paste capabilities to a component.

The plugin Bases on a tricky little Bypass trick.
The plugin adds two hidden native HTMLElements to the body.
A Textarea for bypassing to clipboard. And a Iframe with editmode=On for bypassing from the Clipboard.

After a Component that instanciates this Plugin gets renderd the plugin attaches the
key events of ctrl+x ctrl+c ctrl+v two its own functions.

Since the browser fires the javascript keyevent before it does the native cutting, copieing and pasting stuff
we can use the time before the browser in example coping a text into the nativ System
Clipboard to selecting the text we want to have in the Clipboard.

This little hack makes the whole plugin possible.

Lets Clarify by explaining what the copyHandler, attached to the ctrl+c does.

First of all it saves a few states
- what was the caret State (the selection range)
- what was the marked Text (would normaly into the clipboard)

Than it asks the plugins client to build the copyIdentifier (this is what actualy does it way into the clipboard)
Than the the Magic Happens:
-The Value you returnd in the buildCopyIdentifierString function becomes the value of the Textarea attached to this component
-The Textarea gets its focus und all the text inside gets selected.
-Wait for about 10 Milliseconds and the Browser will have done the rest for you
-Woallla the value you just created via the buildCopyIdentifierString is now in the
native System Clipboard.
And the better thing about that: u exactly knwo about that string.
After all that, the copyToClipboard function with the IdentifierString gets called.

The cut Functionionalety is quiet similiar.

The Paste Function works a bit different.
First of all it saves a few states
- what was the caret State (the selection range)

Next Step is to focus the Iframe and set its innerHTML to '';
no we just wait for about 10 Milliseconds to let the browser paste the value from the
clipboard into the Iframe.
Now we call the plugins client pasteFromClipboard function under the scope of the client with the string from the iframes innerHTML
If this function retunrns undfined we simulate the default behavior.

If you got any questions just ask. Maybe you could try the demo and send some feedback + ?bugs?.

In the next Post I will place in the whole readable code for the plugin used in the Example

crp_spaeth

2 Apr 2009, 4:41 AM

First of all there is a litte Plugin i wrote that once it is instantiated, it registers the the component in a Singleton called Ext.ComponentFocusMgr automatically when it gets focused (indicated by contextmenu or click event).

Ext.namespace('Ext', 'Ext.plugins');

/**
* @class Ext.ComponentFocusMgr
*
* A global Manager that stores the information about the last focused Components.
* Since there is no bubling in the Ext events yet Focus just bases on the on Clickevent
* and on the oncontextmenu. To make your component focusable just use the Focus detector Plugin
*
* @author Martin Späth
* @date April 2, 2009
* @singleton
*/
Ext.ComponentFocusMgr = (function(){
var focusChain = new Ext.util.MixedCollection(false, function(item){return item.id});
var currentTarget = null;

return {

/**
* adds the passed cmpId to the focusChain if the currentTarget
* is the same as the eventTarget otherwise it will clear the list
* and add this cmpId to the list.
*
* @param {eventTarget} indicator for a new focus Chain. If the eventTarget change the focus Chain gets resetet
* @param {Ext.Component} the Component that been Focused
*/
addToFocusList: function(eventTarget, cmp){
if(currentTarget != eventTarget) {
focusChain.clear();
currentTarget = eventTarget;
}

if(!focusChain.contains(cmp)){
focusChain.add(cmp.id, cmp);
}
},

/**
* Gets the first element of the Focus Chain
* @returns {Ext.Component} The Top Element of the Focus Chain
*/
getTopFocus: function(){
return focusChain.itemAt(0);
},

/**
* Get the whole Focus Chain 0 ist the uppest Element
* @retunrs {Ext.util.MixedCollection} a mixed Collection with all the Elements of that have focus in it.
*/
getFocusChain: function(){
return focusChain;
}

/**
* Represents the base Plugin for adding Cut/Copy/Paste capabilities to a component.
*
* The plugin Bases on a tricky little Bypass trick.
* The plugin adds two hidden native HTMLElements to the body.
* A Textarea for bypassing to clipboard. And a Iframe with editmode=On for bypassing from the Clipboard.
*
* After a Component that instanciates this Plugin gets renderd the plugin attaches the
* key events of ctrl+x ctrl+c ctrl+v two its own functions.
*
* Since the browser fires the javascript keyevent before it does the native cutting, copieing and pasting stuff
* we can use the time before the browser in example coping a text into the nativ System
* Clipboard to selecting the text we want to have in the Clipboard.
*
* This little hack makes the whole plugin possible.
*
* Lets Clarify by explaining what the copyHandler, attached to the ctrl+c does.
*
* First of all it saves a few states
* - what was the caret State (the selection range)
* - what was the marked Text (would normaly into the clipboard)
*
* Than it asks the plugins client to build the copyIdentifier (this is what actualy does it way into the clipboard)
* Than the the Magic Happens:
* -The Value you returnd in the buildCopyIdentifierString function becomes the value of the Textarea attached to this component
* -The Textarea gets its focus und all the text inside gets selected.
* -Wait for about 10 Milliseconds and the Browser will have done the rest for you
* -Woallla the value you just created via the buildCopyIdentifierString is now in the
* native System Clipboard.
* And the better thing about that: u exactly knwo about that string.
* After all that, the copyToClipboard function with the IdentifierString gets called.
*
* The cut Functionionalety is quiet similiar.
*
* The Paste Function works a bit different.
* First of all it saves a few states
* - what was the caret State (the selection range)
*
* Next Step is to focus the Iframe and set its innerHTML to '';
* no we just wait for about 10 Milliseconds to let the browser paste the value from the
* clipboard into the Iframe.
* Now we call the plugins client pasteFromClipboard function under the scope of the client with the string from the iframes innerHTML
* If this function retunrns undfined we simulate the default behavior.
*
*
* @author Martin Späth
* @date April 2, 2009
* @class Ext.plugins.CopyPasteable
* @extends Ext.util.Observable
*/
Ext.extend(Ext.plugins.CopyPasteable, Ext.util.Observable, {
init:function(client) {
this.client = client;

/**
* gets called when the copy bypass was successfull Use this method for storing information in the
* Ext.Clipboard
* @param {string} identifierString (optional) Sting that links the clipboardData with the string in the system clipboard
*/
copyToClipboard: function(identifierString) {
Ext.ClipBoard.setData(identifierString, identifierString);
},

/**
* gets called when the cut bypass was successfull Use this method for storing information in the
* Ext.Clipboard
* @param {string} identifierString (optional) Sting that links the clipboardData with the string in the system clipboard
*/
cutToClipboard: function(identifierString){
Ext.ClipBoard.setData(identifierString, identifierString);
},

/**
* gets called when the paste bypass was successfull
* @param {string} orginalString the Parameter that was pasted from the System-Clipboard. You can use this information to get Data form the Ext.Clipboard
* @return {String} the string with which the normal browser behavior should get simulated
*/
pasteFromClipboard: function(orginalString){
return orginalString;
},

/**
* builds the IdentifierString that gets copied into the System clipboard
* you can override this with any string generating function you want.
* @param {string} orginalValue the orginal selected text/content (to develop)
* @return {string} the value that will get copied
*/
buildCopyIdentifierString: function(orginalValue){
// i didn't find a way to say what will make its way into the clipboad if i dont bypass it for all cases.
// so by default i just fill it with a uniq key.
if(typeof orginalValue == 'undefined' || orginalValue =='') {
return Ext.id();
}
return orginalValue;
},

/**
* builds the IdentifierString that gets cutted into the System clipboard
* you can override this with any string generating function you want.
* @param {string} orginalValue the orginal selected text/content (to develop)
* @return {string} the value that will get cutted
*/
buildCutIdentifierString: function(orginalValue){
// i didn't find a way to say what will make its way into the clipboad if i dont bypass it for all cases.
// so by default i just fill it with a uniq key.
if(typeof orginalValue == 'undefined' || orginalValue =='') {
return Ext.id();
}
return orginalValue;
},

var elfly = Ext.fly(el);
elfly.setCaretPosition(caretState);
// and do what the browser would do if you wouldn't have bypass
elfly.setCaretText();
}).defer(10, this, [el]);
} else {
// if the bypass wasn't used, save the copied text into the lastExtCopyString for later purpose
value = Ext.fly(el).getCaretText();
}

// now call the components copyToClipboard Function with the identifier value just created
(this.copyToClipboard.createDelegate(this.client))(value);
}
return true;
},

/**
* Bypasses the string in dataToByPass to the Clipboard
* @param {String} dataToByPass the string that should get stored into the System Clipboard
*/
bypassToClipboard: function(dataToByPass){
// bypass over the textarea
this.bypassTextarea.value = dataToByPass;
this.bypassTextarea.focus();
this.bypassTextarea.select();
},

/**
* gets called from the keyhandler when ctrl+v was pressed in the scope of the clients events
*/
pasteHandler: function(key, event){
el = event.target;

// give the browser about 10ms to paste the stuff into the bypass area
(function(el){
// And Wholla we know what is in the Clipboard
// call the paste manipulation function
var pastVal = (this.pasteFromClipboard.createDelegate(this.client))(this.getIframeBody().innerHTML);
// by returning nothing we let the plugin prevent to simulate the normal browser behavior
if(typeof pastVailue != 'undefined'){

// re-set the caret of the field to the state before the bypass
el.focus();

var elfly = Ext.fly(el);
elfly.setCaretPosition(caretState);
// and do what the browser would do if you wouldn't have bypass
elfly.setCaretText(pastVal);

/**
* Example Subclass of the CopyPasteable Plugin. Created for the Grid.
*
* it overwrites the buildCopyIdentifier to create a string that gets interpreted well by Excel
* @class Ext.plugins.CopyPasteableGrid
* @extends Ext.plugins.CopyPasteable
*/
Ext.extend(Ext.plugins.CopyPasteableGrid, Ext.plugins.CopyPasteable, {

/**
* Overwritten to create a string that gets well interpreted by Excel
* @param {string} orgVal the Value that would go its way into the Clipboard if you wouldnt bypass
* @return {string} the Value that should get bypassed into the Clipboard
*/
buildCopyIdentifierString: function (orgVal) {

/**
* Overwritten to create a string that gets well interpreted by Excel
* @param {string} orgVal the Value that would go its way into the Clipboard if you wouldnt bypass
* @return {string} the Value that should get bypassed into the Clipboard
*/
buildCutIdentifierString: function (orgVal) {

// store the created object in the clipboard
Ext.ClipBoard.setData(clipBoardObject, identifierString);

},

/**
* Overwritten to get the data from the Clipboard and insert all the records found
* into the Grid
* @param {string} identifierString
*/
pasteFromClipboard: function(identifierString){
var clipboardObject = Ext.ClipBoard.getData(identifierString);

I did not start to write real extensions of the plugin jet. I just implemented the base functionality and a proprietary example for the grid to let you guys see what can be done with this little trick.

@mxracer: I know about this little issue in Firefox but this is a known Extjs - Bug see: Focus Bug (http://extjs.com/forum/showthread.php?t=63661)

I will give the Bug you came up with a try tomorrow.

@TopKatz: Nice Idea but notice, the extension is just proprietary and written as easy as possible to give you the ability to write your own extension of my plugin for other components like the tree or dataview and so one. But btw. I would really love to see your Idea implemented! So give it a try!! :)

@DigitalSkyline: Since the HTMLEditor bases on another iframe you will need to overwrite the bypass to work on an iframe but I dont think it is that hard.

Since i been using an iframe to let the browser paste stuff in you could use the existing iframe from the HTMLEditor and you could compare the innerHTML before the browser finishes the native ctrl+v event and after it...

@all: By the way did one of you try to paste into MS *duck* Excel after you copied a few rows via ctrl+c ?

best regards

bernd01

13 Apr 2009, 2:21 PM

Hi srt_spaeth,

Thanks for the great plugin! Works like a charm.

I guess, I might have found a typo in the class Ext.ClipBoard:

setData: function(dataObj, identifierString){

if(typeof identifieSring != 'undefined') {

lastInExtCopiedString = identifieString;

}

dataObject = dataObj;

},

I guess identifieSring should be identifierString

Thanks,
Bernd

crp_spaeth

13 Apr 2009, 10:58 PM

Hi bernd01,
Thank you for your attention and reporting this typo.

The bad news is that fixing this typo will break the whole mechannisem.
Since i am using a Textareas value property to bypass the content to the Clipboard but using an Iframes innerHTML property with designmod = on to bypass content from the Clipboard back to the Ext Plugin the copied and the pasted value differ even if the should be the same in a few cases.

This is happening cause the Browser will parse the sting you try to insert into the Iframe as a HTML. So if you try to past a text with a break in it "testvalue1 testvalue2 \n testvalue3 testvalue4\n", like i do in the Grid example you will end up with something like this:
"testvalue1 testvalue2<br> testvalue3 testvalue4<br>"

So if you compare those two strings in the getData function you will end up getting back the pasted string and not the dataObject. Cause of the typo you just found bernd2 and the other typo in the getData function you will end up getting the last copied Ext.Dataobject even if the user copies a text from another Application.

Maybe some of you got an idea how to solve this problem. Is there a property or method i dont know yet to get a javascript string from a dom element?

The other solution would be to use a Textarea to bypass from the clipboard but this means a few other thinks I was thinking about to implement will not be possible anymore since you cant Paste the same stuff into a Textarea like into an Iframe...

bernd01

14 Apr 2009, 10:44 AM

Hi!

Thanks for your reply. To be honest, I think in general I understand how your use the browser trick, however in detail I am not really sure...

I corrected the typo in my code and it is still working for my example (the grid). Not sure what is different...

crp_spaeth

14 Apr 2009, 1:02 PM

Did you change the getData methode too?

I think I will reimplement the Bypass for the Paste process with an Textarea to avoid the parse Problem I came up with.

bernd01

14 Apr 2009, 1:34 PM

Yes, I have overwritten that too - still working.

However, I faced another javascript error. I could eliminate that by overwriting your Ext.Element.setCaretText function like this:

});I am not sure if anybody is interested in the next code part. It allows you to enable/disable the keymap with a toogle button. In that way the user can choose between using your cool plugin or the standard copy/paste behaviour (unfortunatly I cannot find the forum post anymore for that).
Code for enable/disable keymap:

Hi,
Congralutions! Nice Plugin, very usefull; but there is a probleme with ExtJS 3.0.0
All works just only one thing don't want work!
When I copy there is data and a string representation
With CTRL+C no problem
but with a action and a copyToClipboard there is data but not a string representation?
Can you solve it? or give us a way to solve it?
Thanks
Have a nice day

crp_spaeth

8 Jul 2009, 4:42 AM

You ask for the possibilty to have a string representation in the nativ system clipboard by pressing a button in Extjs?

My Plugin uses a neat workaround to deal with this by bypassing data into the clipboard as descriped in the first post. The Bypass uses the Browsers Nativ Copy Command which gets Fired if the User press CTRL+C.

I know there is a way to write Data in the System-Clipboard using Javascript in the Internetexplorerer, but I think there is no way to access it in Firefox and Safari.

There is another missing thing which is not supported yet. The Ext.Clipboard will not work if the User uses the Internet-Explorer Menu Funktion Edit-->Copy.

I think I have an Idea to deal with that as well but therefore Ill need an Focusable Panel as descriped in the Following thread.

If you would like to see a better Implementation of this Plugin you may "+1" my Featurerequest in this thread...

http://extjs.com/forum/showthread.php?t=73555

blackhorn

8 Jul 2009, 5:15 AM

Thanks for your quick reply.
There is another (proper) way to make a copy system like yours works?
I saw many page with a swf file but i can make it works!
Thanks !

hellogavin

25 Sep 2009, 7:09 PM

I cannot see the demo right now!

notjoshing

10 Dec 2009, 1:21 PM

For some applications, I want to send specific text to the clipboard without the user needing to press keys. For instance, clicking on a "get link" control. I'm not sure how I'd do something like that using your model; it seems to need an element to drive off of to get the text. Am I missing something?

Thanks,

Josh

crp_spaeth

10 Dec 2009, 2:54 PM

Since my solution bypasses the data into the clipboard its necessary that the user presses ctrl+c to get the data into the clipboard....

snehap.1284

22 Apr 2010, 11:40 PM

Hi crp_spaeth,

I am new to extjs. Infact this is my first post in extjs forum :)

I want to develop two things in an existing tree grid of our product:
1. Single Cell Selection instead of rowselection. Copy it using Ctrl + C,
2. Multi select cells in grid, Paste the copied value using Ctrl + V

I wanted to know whether this is possible and how.

Any links or examples on this will be appreciated :)

Thanks in advance. Awaiting response

aagocs

4 Nov 2010, 8:18 AM

Does anyone know if this plugin would work with Extjs 3.x -- and if so - where to get it?
thanks in advance

crp_spaeth

4 Nov 2010, 8:55 AM

Hey aagocs,

for shure you could implement it for Extjs 3.0. I would love to do so but the time I was able to spent so much time in such things has long gone...

You can read the first entry of this thread and since its well documented you should be able implement a simmiliar plugin for Extjs 3 without much pain.

Just a small advice: wait for the new Extjs4.0 before you got to do things twice ;)