Ticket #4652: 4652_3.patch
File 4652_3.patch, 22.1 KB (added by , 15 years ago) |
---|
-
_source/plugins/menubutton/plugin.js
5 5 6 6 CKEDITOR.plugins.add( 'menubutton', 7 7 { 8 requires : [ 'button', ' contextmenu' ],8 requires : [ 'button', 'menu' ], 9 9 beforeInit : function( editor ) 10 10 { 11 11 editor.ui.addHandler( CKEDITOR.UI_MENUBUTTON, CKEDITOR.ui.menuButton.handler ); … … 35 35 var menu = _.menu; 36 36 if ( !menu ) 37 37 { 38 menu = _.menu = new CKEDITOR.plugins.contextMenu( editor ); 39 menu.definition.panel.attributes[ 'aria-label' ] = editor.lang.common.options; 38 menu = _.menu = new CKEDITOR.menu( editor, 39 { 40 panel: 41 { 42 className : editor.skinClass + ' cke_contextmenu', 43 attributes : { 'aria-label' : editor.lang.common.options } 44 } 45 }); 40 46 41 47 menu.onHide = CKEDITOR.tools.bind( function() 42 48 { -
_source/plugins/menu/plugin.js
53 53 54 54 this.editor = editor; 55 55 this.items = []; 56 this._.listeners = []; 56 57 57 58 this._.level = definition.level || 1; 58 59 … … 71 72 72 73 _ : 73 74 { 75 onShow : function() 76 { 77 var selection = this.editor.getSelection(); 78 79 // Selection will be unavailable after menu shows up 80 // in IE, lock it now. 81 if ( CKEDITOR.env.ie ) 82 selection && selection.lock(); 83 84 var element = selection && selection.getStartElement(), 85 listeners = this._.listeners, 86 includedItems = []; 87 88 this.removeAll(); 89 // Call all listeners, filling the list of items to be displayed. 90 for ( var i = 0 ; i < listeners.length ; i++ ) 91 { 92 var listenerItems = listeners[ i ]( element, selection ); 93 94 if ( listenerItems ) 95 { 96 for ( var itemName in listenerItems ) 97 { 98 var item = this.editor.getMenuItem( itemName ); 99 100 if ( item ) 101 { 102 item.state = listenerItems[ itemName ]; 103 this.add( item ); 104 } 105 } 106 } 107 } 108 }, 109 110 onClick : function( item ) 111 { 112 this.hide(); 113 114 if ( item.onClick ) 115 item.onClick(); 116 else if ( item.command ) 117 this.editor.execCommand( item.command ); 118 }, 119 120 onEscape : function( keystroke ) 121 { 122 var parent = this.parent; 123 // 1. If it's sub-menu, restore the last focused item 124 // of upper level menu. 125 // 2. In case of a top-menu, close it. 126 if ( parent ) 127 { 128 parent._.panel.hideChild(); 129 // Restore parent block item focus. 130 var parentBlock = parent._.panel._.panel._.currentBlock, 131 parentFocusIndex = parentBlock._.focusIndex; 132 parentBlock._.markItem( parentFocusIndex ); 133 } 134 else if ( keystroke == 27 ) 135 { 136 this.hide(); 137 this.editor.focus(); 138 } 139 return false; 140 }, 141 142 onHide : function() 143 { 144 if ( CKEDITOR.env.ie ) 145 { 146 var selection = this.editor.getSelection(); 147 selection && selection.unlock(); 148 } 149 150 this.onHide && this.onHide(); 151 }, 152 74 153 showSubMenu : function( index ) 75 154 { 76 155 var menu = this._.subMenu, … … 98 177 menu = this._.subMenu = new CKEDITOR.menu( this.editor, 99 178 CKEDITOR.tools.extend( {}, this._.definition, { level : this._.level + 1 }, true ) ); 100 179 menu.parent = this; 101 menu.onClick = CKEDITOR.tools.bind( this.onClick, this ); 102 // Sub menu use their own scope for binding onEscape. 103 menu.onEscape = this.onEscape; 180 menu._.onClick = CKEDITOR.tools.bind( this._.onClick, this ); 104 181 } 105 182 106 183 // Add all submenu items to the menu. … … 142 219 143 220 show : function( offsetParent, corner, offsetX, offsetY ) 144 221 { 222 // Not for sub menu. 223 if ( !this.parent ) 224 { 225 this._.onShow(); 226 // Don't menu with zero items. 227 if ( ! this.items.length ) 228 return; 229 } 230 231 corner = corner || ( this.editor.lang.dir == 'rtl' ? 2 : 1 ); 232 145 233 var items = this.items, 146 234 editor = this.editor, 147 235 panel = this._.panel, … … 157 245 158 246 panel.onEscape = CKEDITOR.tools.bind( function( keystroke ) 159 247 { 160 if ( this. onEscape && this.onEscape( keystroke ) === false )248 if ( this._.onEscape( keystroke ) === false ) 161 249 return false; 162 250 }, 163 251 this ); 164 252 165 253 panel.onHide = CKEDITOR.tools.bind( function() 166 254 { 167 this. onHide && this.onHide();255 this._.onHide && this._.onHide(); 168 256 }, 169 257 this ); 170 258 … … 213 301 if ( item.getItems ) 214 302 this._.showSubMenu( index ); 215 303 else 216 this. onClick && this.onClick( item );304 this._.onClick( item ); 217 305 }, 218 306 this); 219 307 } … … 256 344 editor.fire( 'menuShow', [ panel ] ); 257 345 }, 258 346 347 addListener : function( listenerFn ) 348 { 349 this._.listeners.push( listenerFn ); 350 }, 351 259 352 hide : function() 260 353 { 354 this._.onHide && this._.onHide(); 261 355 this._.panel && this._.panel.hide(); 262 356 } 263 357 } … … 277 371 0; 278 372 }); 279 373 } 280 })(); 281 282 CKEDITOR.menuItem = CKEDITOR.tools.createClass( 283 { 284 $ : function( editor, name, definition ) 285 { 286 CKEDITOR.tools.extend( this, definition, 287 // Defaults 288 { 289 order : 0, 290 className : 'cke_button_' + name 291 }); 374 CKEDITOR.menuItem = CKEDITOR.tools.createClass( 375 { 376 $ : function( editor, name, definition ) 377 { 378 CKEDITOR.tools.extend( this, definition, 379 // Defaults 380 { 381 order : 0, 382 className : 'cke_button_' + name 383 }); 292 384 293 // Transform the group name into its order number.294 this.group = editor._.menuGroups[ this.group ];385 // Transform the group name into its order number. 386 this.group = editor._.menuGroups[ this.group ]; 295 387 296 this.editor = editor;297 this.name = name;298 },388 this.editor = editor; 389 this.name = name; 390 }, 299 391 300 proto :301 {302 render : function( menu, index, output )303 {304 var id = menu.id + String( index ),305 state = ( typeof this.state == 'undefined' ) ? CKEDITOR.TRISTATE_OFF : this.state;392 proto : 393 { 394 render : function( menu, index, output ) 395 { 396 var id = menu.id + String( index ), 397 state = ( typeof this.state == 'undefined' ) ? CKEDITOR.TRISTATE_OFF : this.state; 306 398 307 var classes = ' cke_' + (308 state == CKEDITOR.TRISTATE_ON ? 'on' :309 state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' :310 'off' );399 var classes = ' cke_' + ( 400 state == CKEDITOR.TRISTATE_ON ? 'on' : 401 state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' : 402 'off' ); 311 403 312 var htmlLabel = this.label;404 var htmlLabel = this.label; 313 405 314 if ( this.className )315 classes += ' ' + this.className;406 if ( this.className ) 407 classes += ' ' + this.className; 316 408 317 var hasSubMenu = this.getItems;409 var hasSubMenu = this.getItems; 318 410 319 output.push(320 '<span class="cke_menuitem">' +321 '<a id="', id, '"' +322 ' class="', classes, '" href="javascript:void(\'', ( this.label || '' ).replace( "'", '' ), '\')"' +323 ' title="', this.label, '"' +324 ' tabindex="-1"' +325 '_cke_focus=1' +326 ' hidefocus="true"' +327 ' role="menuitem"' +328 ( hasSubMenu ? 'aria-haspopup="true"' : '' ) +329 ( state == CKEDITOR.TRISTATE_DISABLED ? 'aria-disabled="true"' : '' ) +330 ( state == CKEDITOR.TRISTATE_ON ? 'aria-pressed="true"' : '' ) );411 output.push( 412 '<span class="cke_menuitem">' + 413 '<a id="', id, '"' + 414 ' class="', classes, '" href="javascript:void(\'', ( this.label || '' ).replace( "'", '' ), '\')"' + 415 ' title="', this.label, '"' + 416 ' tabindex="-1"' + 417 '_cke_focus=1' + 418 ' hidefocus="true"' + 419 ' role="menuitem"' + 420 ( hasSubMenu ? 'aria-haspopup="true"' : '' ) + 421 ( state == CKEDITOR.TRISTATE_DISABLED ? 'aria-disabled="true"' : '' ) + 422 ( state == CKEDITOR.TRISTATE_ON ? 'aria-pressed="true"' : '' ) ); 331 423 332 // Some browsers don't cancel key events in the keydown but in the333 // keypress.334 // TODO: Check if really needed for Gecko+Mac.335 if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) )336 {337 output.push(338 ' onkeypress="return false;"' );339 }424 // Some browsers don't cancel key events in the keydown but in the 425 // keypress. 426 // TODO: Check if really needed for Gecko+Mac. 427 if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) ) 428 { 429 output.push( 430 ' onkeypress="return false;"' ); 431 } 340 432 341 // With Firefox, we need to force the button to redraw, otherwise it342 // will remain in the focus state.343 if ( CKEDITOR.env.gecko )344 {345 output.push(346 ' onblur="this.style.cssText = this.style.cssText;"' );347 }433 // With Firefox, we need to force the button to redraw, otherwise it 434 // will remain in the focus state. 435 if ( CKEDITOR.env.gecko ) 436 { 437 output.push( 438 ' onblur="this.style.cssText = this.style.cssText;"' ); 439 } 348 440 349 var offset = ( this.iconOffset || 0 ) * -16;350 output.push(441 var offset = ( this.iconOffset || 0 ) * -16; 442 output.push( 351 443 // ' onkeydown="return CKEDITOR.ui.button._.keydown(', index, ', event);"' + 352 ' onmouseover="CKEDITOR.tools.callFunction(', menu._.itemOverFn, ',', index, ');"' +353 ' onmouseout="CKEDITOR.tools.callFunction(', menu._.itemOutFn, ',', index, ');"' +354 ' onclick="CKEDITOR.tools.callFunction(', menu._.itemClickFn, ',', index, '); return false;"' +355 '>' +356 '<span class="cke_icon_wrapper"><span class="cke_icon"' +357 ( this.icon ? ' style="background-image:url(' + CKEDITOR.getUrl( this.icon ) + ');background-position:0 ' + offset + 'px;"'358 : '' ) +359 '></span></span>' +360 '<span class="cke_label">' );444 ' onmouseover="CKEDITOR.tools.callFunction(', menu._.itemOverFn, ',', index, ');"' + 445 ' onmouseout="CKEDITOR.tools.callFunction(', menu._.itemOutFn, ',', index, ');"' + 446 ' onclick="CKEDITOR.tools.callFunction(', menu._.itemClickFn, ',', index, '); return false;"' + 447 '>' + 448 '<span class="cke_icon_wrapper"><span class="cke_icon"' + 449 ( this.icon ? ' style="background-image:url(' + CKEDITOR.getUrl( this.icon ) + ');background-position:0 ' + offset + 'px;"' 450 : '' ) + 451 '></span></span>' + 452 '<span class="cke_label">' ); 361 453 362 if ( hasSubMenu )363 {364 output.push(365 '<span class="cke_menuarrow">',366 '<span>&#',367 ( this.editor.lang.dir == 'rtl' ?368 '9668' : // BLACK LEFT-POINTING POINTER369 '9658' ), // BLACK RIGHT-POINTING POINTER370 ';</span>',371 '</span>' );372 }454 if ( hasSubMenu ) 455 { 456 output.push( 457 '<span class="cke_menuarrow">', 458 '<span>&#', 459 ( this.editor.lang.dir == 'rtl' ? 460 '9668' : // BLACK LEFT-POINTING POINTER 461 '9658' ), // BLACK RIGHT-POINTING POINTER 462 ';</span>', 463 '</span>' ); 464 } 373 465 374 output.push(375 htmlLabel,376 '</span>' +377 '</a>' +378 '</span>' );379 }380 }381 });466 output.push( 467 htmlLabel, 468 '</span>' + 469 '</a>' + 470 '</span>' ); 471 } 472 } 473 }); 382 474 475 })(); 476 477 383 478 /** 384 479 * The amount of time, in milliseconds, the editor waits before showing submenu 385 480 * options when moving the mouse over options that contains submenus, like the -
_source/plugins/contextmenu/plugin.js
6 6 CKEDITOR.plugins.add( 'contextmenu', 7 7 { 8 8 requires : [ 'menu' ], 9 10 beforeInit : function( editor ) 9 10 // Make sure the base class (CKEDITOR.menu) is loaded before it (#3318). 11 onLoad : function() 11 12 { 12 editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor ); 13 14 editor.addCommand( 'contextMenu', 15 { 16 exec : function() 17 { 18 editor.contextMenu.show( editor.document.getBody() ); 19 } 20 }); 21 } 22 }); 23 24 CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass( 25 { 26 $ : function( editor ) 27 { 28 this.id = 'cke_' + CKEDITOR.tools.getNextNumber(); 29 this.editor = editor; 30 this._.listeners = []; 31 this._.functionId = CKEDITOR.tools.addFunction( function( commandName ) 32 { 33 this._.panel.hide(); 34 editor.focus(); 35 editor.execCommand( commandName ); 36 }, 37 this); 38 39 this.definition = 40 { 41 panel: 42 { 43 className : editor.skinClass + ' cke_contextmenu', 44 attributes : 45 { 46 'aria-label' : editor.lang.contextmenu.options 47 } 48 } 49 }; 50 }, 13 CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass( 14 { 15 base : CKEDITOR.menu, 16 17 $ : function( editor ) 18 { 19 this.base.call( this, editor, 20 { 21 panel: 22 { 23 className : editor.skinClass + ' cke_contextmenu', 24 attributes : 25 { 26 'aria-label' : editor.lang.contextmenu.options 27 } 28 } 29 }); 30 }, 51 31 52 _ : 53 { 54 onMenu : function( offsetParent, corner, offsetX, offsetY ) 55 { 56 var menu = this._.menu, 57 editor = this.editor; 58 59 if ( menu ) 60 { 61 menu.hide(); 62 menu.removeAll(); 63 } 64 else 65 { 66 menu = this._.menu = new CKEDITOR.menu( editor, this.definition ); 67 menu.onClick = CKEDITOR.tools.bind( function( item ) 68 { 69 menu.hide(); 70 71 if ( item.onClick ) 72 item.onClick(); 73 else if ( item.command ) 74 editor.execCommand( item.command ); 75 76 }, this ); 77 78 menu.onEscape = function( keystroke ) 79 { 80 var parent = this.parent; 81 // 1. If it's sub-menu, restore the last focused item 82 // of upper level menu. 83 // 2. In case of a top-menu, close it. 84 if ( parent ) 85 { 86 parent._.panel.hideChild(); 87 // Restore parent block item focus. 88 var parentBlock = parent._.panel._.panel._.currentBlock, 89 parentFocusIndex = parentBlock._.focusIndex; 90 parentBlock._.markItem( parentFocusIndex ); 91 } 92 else if ( keystroke == 27 ) 93 { 94 this.hide(); 95 editor.focus(); 96 } 97 return false; 98 }; 99 } 100 101 var listeners = this._.listeners, 102 includedItems = []; 103 104 var selection = this.editor.getSelection(), 105 element = selection && selection.getStartElement(); 106 107 menu.onHide = CKEDITOR.tools.bind( function() 108 { 109 menu.onHide = null; 110 111 if ( CKEDITOR.env.ie ) 112 { 113 var selection = editor.getSelection(); 114 selection && selection.unlock(); 115 } 116 117 this.onHide && this.onHide(); 118 }, 119 this ); 120 121 // Call all listeners, filling the list of items to be displayed. 122 for ( var i = 0 ; i < listeners.length ; i++ ) 123 { 124 var listenerItems = listeners[ i ]( element, selection ); 125 126 if ( listenerItems ) 127 { 128 for ( var itemName in listenerItems ) 129 { 130 var item = this.editor.getMenuItem( itemName ); 131 132 if ( item ) 133 { 134 item.state = listenerItems[ itemName ]; 135 menu.add( item ); 136 } 137 } 138 } 139 } 140 141 // Don't show context menu with zero items. 142 menu.items.length && menu.show( offsetParent, corner || ( editor.lang.dir == 'rtl' ? 2 : 1 ), offsetX, offsetY ); 143 } 144 }, 145 146 proto : 147 { 148 addTarget : function( element, nativeContextMenuOnCtrl ) 149 { 150 // Opera doesn't support 'contextmenu' event, we have duo approaches employed here: 151 // 1. Inherit the 'button override' hack we introduced in v2 (#4530), while this require the Opera browser 152 // option 'Allow script to detect context menu/right click events' to be always turned on. 153 // 2. Considering the fact that ctrl/meta key is not been occupied 154 // for multiple range selecting (like Gecko), we use this key 155 // combination as a fallback for triggering context-menu. (#4530) 156 if ( CKEDITOR.env.opera ) 157 { 158 var contextMenuOverrideButton; 159 element.on( 'mousedown', function( evt ) 160 { 161 evt = evt.data; 162 if ( evt.$.button != 2 ) 163 { 164 if ( evt.getKeystroke() == CKEDITOR.CTRL + 1 ) 165 element.fire( 'contextmenu', evt ); 166 return; 167 } 32 proto : 33 { 34 addTarget : function( element, nativeContextMenuOnCtrl ) 35 { 36 // Opera doesn't support 'contextmenu' event, we have duo approaches employed here: 37 // 1. Inherit the 'button override' hack we introduced in v2 (#4530), while this require the Opera browser 38 // option 'Allow script to detect context menu/right click events' to be always turned on. 39 // 2. Considering the fact that ctrl/meta key is not been occupied 40 // for multiple range selecting (like Gecko), we use this key 41 // combination as a fallback for triggering context-menu. (#4530) 42 if ( CKEDITOR.env.opera ) 43 { 44 var contextMenuOverrideButton; 45 element.on( 'mousedown', function( evt ) 46 { 47 evt = evt.data; 48 if ( evt.$.button != 2 ) 49 { 50 if ( evt.getKeystroke() == CKEDITOR.CTRL + 1 ) 51 element.fire( 'contextmenu', evt ); 52 return; 53 } 168 54 169 if ( nativeContextMenuOnCtrl170 && ( CKEDITOR.env.mac ? evt.$.metaKey : evt.$.ctrlKey ) )171 return;55 if ( nativeContextMenuOnCtrl 56 && ( CKEDITOR.env.mac ? evt.$.metaKey : evt.$.ctrlKey ) ) 57 return; 172 58 173 var target = evt.getTarget();59 var target = evt.getTarget(); 174 60 175 if ( !contextMenuOverrideButton )176 {177 var ownerDoc = target.getDocument();178 contextMenuOverrideButton = ownerDoc.createElement( 'input' ) ;179 contextMenuOverrideButton.$.type = 'button' ;180 ownerDoc.getBody().append( contextMenuOverrideButton ) ;181 }61 if ( !contextMenuOverrideButton ) 62 { 63 var ownerDoc = target.getDocument(); 64 contextMenuOverrideButton = ownerDoc.createElement( 'input' ) ; 65 contextMenuOverrideButton.$.type = 'button' ; 66 ownerDoc.getBody().append( contextMenuOverrideButton ) ; 67 } 182 68 183 contextMenuOverrideButton.setAttribute( 'style', 'position:absolute;top:' + ( evt.$.clientY - 2 ) +184 'px;left:' + ( evt.$.clientX - 2 ) +185 'px;width:5px;height:5px;opacity:0.01' );69 contextMenuOverrideButton.setAttribute( 'style', 'position:absolute;top:' + ( evt.$.clientY - 2 ) + 70 'px;left:' + ( evt.$.clientX - 2 ) + 71 'px;width:5px;height:5px;opacity:0.01' ); 186 72 187 } );73 } ); 188 74 189 element.on( 'mouseup', function ( evt )190 {191 if ( contextMenuOverrideButton )192 {193 contextMenuOverrideButton.remove();194 contextMenuOverrideButton = undefined;195 // Simulate 'contextmenu' event.196 element.fire( 'contextmenu', evt.data );197 }198 } );199 }75 element.on( 'mouseup', function ( evt ) 76 { 77 if ( contextMenuOverrideButton ) 78 { 79 contextMenuOverrideButton.remove(); 80 contextMenuOverrideButton = undefined; 81 // Simulate 'contextmenu' event. 82 element.fire( 'contextmenu', evt.data ); 83 } 84 } ); 85 } 200 86 201 element.on( 'contextmenu', function( event )202 {203 var domEvent = event.data;87 element.on( 'contextmenu', function( event ) 88 { 89 var domEvent = event.data; 204 90 205 if ( nativeContextMenuOnCtrl &&206 207 // which make this property unreliable. (#4826)208 209 return;91 if ( nativeContextMenuOnCtrl && 92 // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event, 93 // which make this property unreliable. (#4826) 94 ( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) ) ) 95 return; 210 96 211 97 212 // Cancel the browser context menu.213 domEvent.preventDefault();98 // Cancel the browser context menu. 99 domEvent.preventDefault(); 214 100 215 var offsetParent = domEvent.getTarget().getDocument().getDocumentElement(),216 offsetX = domEvent.$.clientX,217 offsetY = domEvent.$.clientY;101 var offsetParent = domEvent.getTarget().getDocument().getDocumentElement(), 102 offsetX = domEvent.$.clientX, 103 offsetY = domEvent.$.clientY; 218 104 219 CKEDITOR.tools.setTimeout( function()220 {221 this.show( offsetParent, null, offsetX, offsetY );222 },223 0, this );224 },225 this );105 CKEDITOR.tools.setTimeout( function() 106 { 107 this.open( offsetParent, null, offsetX, offsetY ); 108 }, 109 0, this ); 110 }, 111 this ); 226 112 227 if ( CKEDITOR.env.webkit )228 {229 var holdCtrlKey,230 onKeyDown = function( event )231 {232 holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey ;233 },234 resetOnKeyUp = function()235 {236 holdCtrlKey = 0;237 };113 if ( CKEDITOR.env.webkit ) 114 { 115 var holdCtrlKey, 116 onKeyDown = function( event ) 117 { 118 holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey ; 119 }, 120 resetOnKeyUp = function() 121 { 122 holdCtrlKey = 0; 123 }; 238 124 239 element.on( 'keydown', onKeyDown );240 element.on( 'keyup', resetOnKeyUp );241 element.on( 'contextmenu', resetOnKeyUp );242 }243 },125 element.on( 'keydown', onKeyDown ); 126 element.on( 'keyup', resetOnKeyUp ); 127 element.on( 'contextmenu', resetOnKeyUp ); 128 } 129 }, 244 130 245 addListener : function( listenerFn ) 246 { 247 this._.listeners.push( listenerFn ); 248 }, 131 open : function( offsetParent, corner, offsetX, offsetY ) 132 { 133 this.editor.focus(); 134 offsetParent = offsetParent || CKEDITOR.document.getDocumentElement(); 135 this.show( offsetParent, corner, offsetX, offsetY ); 136 } 137 } 138 }); 139 }, 249 140 250 show : function( offsetParent, corner, offsetX, offsetY)251 252 this.editor.focus();141 beforeInit : function( editor ) 142 { 143 editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor ); 253 144 254 // Selection will be unavailable after context menu shows up 255 // in IE, lock it now. 256 if ( CKEDITOR.env.ie ) 145 editor.addCommand( 'contextMenu', 257 146 { 258 var selection = this.editor.getSelection(); 259 selection && selection.lock(); 260 } 261 262 this._.onMenu( offsetParent || CKEDITOR.document.getDocumentElement(), corner, offsetX || 0, offsetY || 0 ); 263 } 264 } 147 exec : function() 148 { 149 editor.contextMenu.open( editor.document.getBody() ); 150 } 151 }); 152 } 265 153 }); 266 154 267 155 /**