

Courtesy SierraBlair

I had a rather long post on the pain of dealing with the system clipboard in Web applications now that Flash went and fixed some security hole :/

The solution in place at that time worked well in Safari, with the on[cut|copy|paste] and unfortunately not great with Firefox due to one crucial big of data being omitted.

Then Tom Robinson and a couple of others made the great point that I could get ALMOST everything I wanted with just the hidden textaraea trick. Instead of tying the trick to the on[cut|copy|paste] events, I can just manually grab the Cmd/Ctrl-C X V commands. The only downside to this is that if the user goes to the Edit menu and chooses something, it won’t work. Annoying, but that’s the world of the hacky Web sometimes.

I added in this new tactic, and copy and paste works OK for Firefox in the latest version of Bespin in code (not deployed to bespin.mozilla.com at the time of this writing):

dojo. declare ( "bespin.util.clipboard.HiddenWorld" , null , { install : function ( ) { // * Configure the hidden copynpaster element var copynpaster = dojo. create ( "textarea" , { tabIndex : '-1' , autocomplete : 'off' , id : 'copynpaster' , style : "position: absolute; z-index: -400; top: -100px; left: -100px; width: 0; height: 0; border: none;" } , dojo. body ( ) ) ; var grabAndGo = function ( text ) { copynpaster. value = text ; focusSelectAndGo ( ) ; } ; var focusSelectAndGo = function ( ) { copynpaster. focus ( ) ; copynpaster. select ( ) ; setTimeout ( function ( ) { dojo. byId ( 'canvas' ) . focus ( ) ; } , 0 ) ; } ; this . keyDown = dojo. connect ( document , "keydown" , function ( e ) { if ( ( bespin. util . isMac ( ) && e. metaKey ) || e. ctrlKey ) { // Copy if ( e. keyCode == 67 /*c*/ ) { // place the selection into the textarea var selectionText = _editor. getSelectionAsText ( ) ; if ( selectionText && selectionText != '' ) { grabAndGo ( selectionText ) ; } // Cut } else if ( e. keyCode == 88 /*x*/ ) { // place the selection into the textarea var selectionObject = _editor. getSelection ( ) ; if ( selectionObject ) { var selectionText = _editor. model . getChunk ( selectionObject ) ; if ( selectionText && selectionText != '' ) { grabAndGo ( selectionText ) ; _editor. ui . actions . deleteSelection ( selectionObject ) ; } } // Paste } else if ( e. keyCode == 86 /*v*/ ) { focusSelectAndGo ( ) ; setTimeout ( function ( ) { // wait just a TOUCH to make sure that it is selected var args = bespin. editor . utils . buildArgs ( ) ; args. chunk = copynpaster. value ; if ( args. chunk ) _editor. ui . actions . insertChunk ( args ) ; } , 1 ) ; } } } ) ; } , uninstall : function ( ) { dojo. disconnect ( this . keyDown ) ; } } ) ;

Because of the issues, I took out the UI buttons for cut/copy/paste, and am in fact wondering if the editor needs that row at all. I wonder if we can consolidate the header to one line, giving us more vertical space. A code editor for developers is not like Google Docs for average Joe users, so having the visual cues probably doesn’t matter in the same way for items like copy.

There are a few subtle annoyances such as running an action like killLine (Ctrl-K) which cuts the selection but has to do so in a non-work with the clipboard way.

End result: getting there, but still need to work on making this generally viable for any application on the Open Web Platform. What do you think?