1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 /** 7 * @file Clipboard support 8 */ 9 10 (function() 11 { 12 // Tries to execute any of the paste, cut or copy commands in IE. Returns a 13 // boolean indicating that the operation succeeded. 14 var execIECommand = function( editor, command ) 15 { 16 var doc = editor.document, 17 body = doc.getBody(); 18 19 var enabled = false; 20 var onExec = function() 21 { 22 enabled = true; 23 }; 24 25 // The following seems to be the only reliable way to detect that 26 // clipboard commands are enabled in IE. It will fire the 27 // onpaste/oncut/oncopy events only if the security settings allowed 28 // the command to execute. 29 body.on( command, onExec ); 30 31 doc.$.execCommand( command ); 32 33 body.removeListener( command, onExec ); 34 35 return enabled; 36 }; 37 38 // Attempts to execute the Cut and Copy operations. 39 var tryToCutCopy = 40 CKEDITOR.env.ie ? 41 function( editor, type ) 42 { 43 return execIECommand( editor, type ); 44 } 45 : // !IE. 46 function( editor, type ) 47 { 48 try 49 { 50 // Other browsers throw an error if the command is disabled. 51 return editor.document.$.execCommand( type ); 52 } 53 catch( e ) 54 { 55 return false; 56 } 57 }; 58 59 // A class that represents one of the cut or copy commands. 60 var cutCopyCmd = function( type ) 61 { 62 this.type = type; 63 this.canUndo = ( this.type == 'cut' ); // We can't undo copy to clipboard. 64 }; 65 66 cutCopyCmd.prototype = 67 { 68 exec : function( editor, data ) 69 { 70 var success = tryToCutCopy( editor, this.type ); 71 72 if ( !success ) 73 alert( editor.lang.clipboard[ this.type + 'Error' ] ); // Show cutError or copyError. 74 75 return success; 76 } 77 }; 78 79 // Paste command. 80 var pasteCmd = 81 CKEDITOR.env.ie ? 82 { 83 exec : function( editor, data ) 84 { 85 // Prevent IE from pasting at the begining of the document. 86 editor.focus(); 87 88 if ( !editor.fire( 'beforePaste' ) 89 && !execIECommand( editor, 'paste' ) ) 90 { 91 editor.openDialog( 'paste' ); 92 } 93 } 94 } 95 : 96 { 97 exec : function( editor ) 98 { 99 try 100 { 101 if ( !editor.fire( 'beforePaste' ) 102 && !editor.document.$.execCommand( 'Paste', false, null ) ) 103 { 104 throw 0; 105 } 106 } 107 catch ( e ) 108 { 109 // Open the paste dialog. 110 editor.openDialog( 'paste' ); 111 } 112 } 113 }; 114 115 // Listens for some clipboard related keystrokes, so they get customized. 116 var onKey = function( event ) 117 { 118 switch ( event.data.keyCode ) 119 { 120 // Paste 121 case CKEDITOR.CTRL + 86 : // CTRL+V 122 case CKEDITOR.SHIFT + 45 : // SHIFT+INS 123 124 var editor = this; 125 editor.fire( 'saveSnapshot' ); // Save before paste 126 127 if ( editor.fire( 'beforePaste' ) ) 128 event.cancel(); 129 130 setTimeout( function() 131 { 132 editor.fire( 'saveSnapshot' ); // Save after paste 133 }, 0 ); 134 return; 135 136 // Cut 137 case CKEDITOR.CTRL + 88 : // CTRL+X 138 case CKEDITOR.SHIFT + 46 : // SHIFT+DEL 139 140 // Save Undo snapshot. 141 editor = this; 142 editor.fire( 'saveSnapshot' ); // Save before paste 143 setTimeout( function() 144 { 145 editor.fire( 'saveSnapshot' ); // Save after paste 146 }, 0 ); 147 } 148 }; 149 150 // Register the plugin. 151 CKEDITOR.plugins.add( 'clipboard', 152 { 153 init : function( editor ) 154 { 155 function addButtonCommand( buttonName, commandName, command, ctxMenuOrder ) 156 { 157 var lang = editor.lang[ commandName ]; 158 159 editor.addCommand( commandName, command ); 160 editor.ui.addButton( buttonName, 161 { 162 label : lang, 163 command : commandName 164 }); 165 166 // If the "menu" plugin is loaded, register the menu item. 167 if ( editor.addMenuItems ) 168 { 169 editor.addMenuItem( commandName, 170 { 171 label : lang, 172 command : commandName, 173 group : 'clipboard', 174 order : ctxMenuOrder 175 }); 176 } 177 } 178 179 addButtonCommand( 'Cut', 'cut', new cutCopyCmd( 'cut' ), 1 ); 180 addButtonCommand( 'Copy', 'copy', new cutCopyCmd( 'copy' ), 4 ); 181 addButtonCommand( 'Paste', 'paste', pasteCmd, 8 ); 182 183 CKEDITOR.dialog.add( 'paste', CKEDITOR.getUrl( this.path + 'dialogs/paste.js' ) ); 184 185 editor.on( 'key', onKey, editor ); 186 187 // If the "contextmenu" plugin is loaded, register the listeners. 188 if ( editor.contextMenu ) 189 { 190 function stateFromNamedCommand( command ) 191 { 192 return editor.document.$.queryCommandEnabled( command ) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED; 193 } 194 195 editor.contextMenu.addListener( function() 196 { 197 return { 198 cut : stateFromNamedCommand( 'Cut' ), 199 200 // Browser bug: 'Cut' has the correct states for both Copy and Cut. 201 copy : stateFromNamedCommand( 'Cut' ), 202 paste : CKEDITOR.env.webkit ? CKEDITOR.TRISTATE_OFF : stateFromNamedCommand( 'Paste' ) 203 }; 204 }); 205 } 206 } 207 }); 208 })(); 209