Ticket #4652: 4652.patch
File 4652.patch, 22.6 KB (added by , 14 years ago) |
---|
-
_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 = 13 CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass( 40 14 { 41 panel: 42 { 43 className : editor.skinClass + ' cke_contextmenu', 44 attributes : 45 { 46 'aria-label' : editor.lang.contextmenu.options 47 } 48 } 49 }; 50 }, 15 base : CKEDITOR.menu, 51 16 52 _ : 53 { 54 onMenu : function( offsetParent, corner, offsetX, offsetY ) 55 { 56 var menu = this._.menu, 57 editor = this.editor; 58 59 if ( menu ) 17 $ : function( editor ) 60 18 { 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 ) 19 this.base.call( this, editor, 68 20 { 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 ) 21 panel: 85 22 { 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 ) 23 className : editor.skinClass + ' cke_contextmenu', 24 attributes : 133 25 { 134 item.state = listenerItems[ itemName ]; 135 menu.add( item ); 26 'aria-label' : editor.lang.contextmenu.options 136 27 } 137 28 } 138 } 139 } 29 }); 30 }, 140 31 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 ) 32 proto : 157 33 { 158 var contextMenuOverrideButton; 159 element.on( 'mousedown', function( evt ) 34 addTarget : function( element, nativeContextMenuOnCtrl ) 160 35 { 161 evt = evt.data; 162 if ( evt.$.button != 2 ) 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 ) 163 43 { 164 if ( evt.getKeystroke() == CKEDITOR.CTRL + 1 ) 165 element.fire( 'contextmenu', evt ); 166 return; 167 } 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 ); 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 } ); 197 85 } 198 } );199 }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 ); 105 CKEDITOR.tools.setTimeout( function() 106 { 107 this.open( offsetParent, null, offsetX, offsetY ); 108 }, 109 0, this ); 222 110 }, 223 0, this ); 224 }, 225 this ); 111 this ); 226 112 227 if ( CKEDITOR.env.webkit ) 228 { 229 var holdCtrlKey, 230 onKeyDown = function( event ) 113 if ( CKEDITOR.env.webkit ) 231 114 { 232 holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey ; 233 }, 234 resetOnKeyUp = function() 235 { 236 holdCtrlKey = 0; 237 }; 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 ); 125 element.on( 'keydown', onKeyDown ); 126 element.on( 'keyup', resetOnKeyUp ); 127 element.on( 'contextmenu', resetOnKeyUp ); 128 } 129 }, 130 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 } 242 137 } 243 }, 138 }); 139 }, 244 140 245 addListener : function( listenerFn ) 246 { 247 this._.listeners.push( listenerFn ); 248 }, 141 beforeInit : function( editor ) 142 { 143 editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor ); 249 144 250 show : function( offsetParent, corner, offsetX, offsetY ) 251 { 252 this.editor.focus(); 253 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 } 147 exec : function() 148 { 149 editor.contextMenu.open( editor.document.getBody() ); 150 } 151 }); 264 152 } 265 153 }); 266 154 -
_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 = 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 ); … … 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 } … … 253 341 editor.fire( 'menuShow', [ panel ] ); 254 342 }, 255 343 344 addListener : function( listenerFn ) 345 { 346 this._.listeners.push( listenerFn ); 347 }, 348 256 349 hide : function() 257 350 { 258 351 this._.panel && this._.panel.hide(); … … 274 367 0; 275 368 }); 276 369 } 277 })(); 278 279 CKEDITOR.menuItem = CKEDITOR.tools.createClass( 280 { 281 $ : function( editor, name, definition ) 370 CKEDITOR.menuItem = CKEDITOR.tools.createClass( 282 371 { 283 CKEDITOR.tools.extend( this, definition, 284 // Defaults 285 { 286 order : 0, 287 className : 'cke_button_' + name 288 }); 372 $ : function( editor, name, definition ) 373 { 374 CKEDITOR.tools.extend( this, definition, 375 // Defaults 376 { 377 order : 0, 378 className : 'cke_button_' + name 379 }); 289 380 290 // Transform the group name into its order number.291 this.group = editor._.menuGroups[ this.group ];381 // Transform the group name into its order number. 382 this.group = editor._.menuGroups[ this.group ]; 292 383 293 this.editor = editor;294 this.name = name;295 },384 this.editor = editor; 385 this.name = name; 386 }, 296 387 297 proto : 298 { 299 render : function( menu, index, output ) 388 proto : 300 389 { 301 var id = menu.id + String( index ), 302 state = ( typeof this.state == 'undefined' ) ? CKEDITOR.TRISTATE_OFF : this.state; 390 render : function( menu, index, output ) 391 { 392 var id = menu.id + String( index ), 393 state = ( typeof this.state == 'undefined' ) ? CKEDITOR.TRISTATE_OFF : this.state; 303 394 304 var classes = ' cke_' + (305 state == CKEDITOR.TRISTATE_ON ? 'on' :306 state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' :307 'off' );395 var classes = ' cke_' + ( 396 state == CKEDITOR.TRISTATE_ON ? 'on' : 397 state == CKEDITOR.TRISTATE_DISABLED ? 'disabled' : 398 'off' ); 308 399 309 var htmlLabel = this.label;400 var htmlLabel = this.label; 310 401 311 if ( this.className )312 classes += ' ' + this.className;402 if ( this.className ) 403 classes += ' ' + this.className; 313 404 314 var hasSubMenu = this.getItems;405 var hasSubMenu = this.getItems; 315 406 316 output.push(317 '<span class="cke_menuitem">' +318 '<a id="', id, '"' +319 ' class="', classes, '" href="javascript:void(\'', ( this.label || '' ).replace( "'", '' ), '\')"' +320 ' title="', this.label, '"' +321 ' tabindex="-1"' +322 '_cke_focus=1' +323 ' hidefocus="true"' +324 ' role="menuitem"' +325 ( hasSubMenu ? 'aria-haspopup="true"' : '' ) +326 ( state == CKEDITOR.TRISTATE_DISABLED ? 'aria-disabled="true"' : '' ) +327 ( state == CKEDITOR.TRISTATE_ON ? 'aria-pressed="true"' : '' ) );328 329 // Some browsers don't cancel key events in the keydown but in the330 // keypress.331 // TODO: Check if really needed for Gecko+Mac.332 if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) )333 {334 407 output.push( 335 ' onkeypress="return false;"' ); 336 } 408 '<span class="cke_menuitem">' + 409 '<a id="', id, '"' + 410 ' class="', classes, '" href="javascript:void(\'', ( this.label || '' ).replace( "'", '' ), '\')"' + 411 ' title="', this.label, '"' + 412 ' tabindex="-1"' + 413 '_cke_focus=1' + 414 ' hidefocus="true"' + 415 ' role="menuitem"' + 416 ( hasSubMenu ? 'aria-haspopup="true"' : '' ) + 417 ( state == CKEDITOR.TRISTATE_DISABLED ? 'aria-disabled="true"' : '' ) + 418 ( state == CKEDITOR.TRISTATE_ON ? 'aria-pressed="true"' : '' ) ); 337 419 338 // With Firefox, we need to force the button to redraw, otherwise it 339 // will remain in the focus state. 340 if ( CKEDITOR.env.gecko ) 341 { 420 // Some browsers don't cancel key events in the keydown but in the 421 // keypress. 422 // TODO: Check if really needed for Gecko+Mac. 423 if ( CKEDITOR.env.opera || ( CKEDITOR.env.gecko && CKEDITOR.env.mac ) ) 424 { 425 output.push( 426 ' onkeypress="return false;"' ); 427 } 428 429 // With Firefox, we need to force the button to redraw, otherwise it 430 // will remain in the focus state. 431 if ( CKEDITOR.env.gecko ) 432 { 433 output.push( 434 ' onblur="this.style.cssText = this.style.cssText;"' ); 435 } 436 437 var offset = ( this.iconOffset || 0 ) * -16; 342 438 output.push( 343 ' onblur="this.style.cssText = this.style.cssText;"' );344 }345 346 var offset = ( this.iconOffset || 0 ) * -16;347 output.push(348 439 // ' onkeydown="return CKEDITOR.ui.button._.keydown(', index, ', event);"' + 349 ' onmouseover="CKEDITOR.tools.callFunction(', menu._.itemOverFn, ',', index, ');"' +350 ' onmouseout="CKEDITOR.tools.callFunction(', menu._.itemOutFn, ',', index, ');"' +351 ' onclick="CKEDITOR.tools.callFunction(', menu._.itemClickFn, ',', index, '); return false;"' +352 '>' +353 '<span class="cke_icon_wrapper"><span class="cke_icon"' +354 ( this.icon ? ' style="background-image:url(' + CKEDITOR.getUrl( this.icon ) + ');background-position:0 ' + offset + 'px;"'355 : '' ) +356 '></span></span>' +357 '<span class="cke_label">' );440 ' onmouseover="CKEDITOR.tools.callFunction(', menu._.itemOverFn, ',', index, ');"' + 441 ' onmouseout="CKEDITOR.tools.callFunction(', menu._.itemOutFn, ',', index, ');"' + 442 ' onclick="CKEDITOR.tools.callFunction(', menu._.itemClickFn, ',', index, '); return false;"' + 443 '>' + 444 '<span class="cke_icon_wrapper"><span class="cke_icon"' + 445 ( this.icon ? ' style="background-image:url(' + CKEDITOR.getUrl( this.icon ) + ');background-position:0 ' + offset + 'px;"' 446 : '' ) + 447 '></span></span>' + 448 '<span class="cke_label">' ); 358 449 359 if ( hasSubMenu ) 360 { 450 if ( hasSubMenu ) 451 { 452 output.push( 453 '<span class="cke_menuarrow">', 454 '<span>&#', 455 ( this.editor.lang.dir == 'rtl' ? 456 '9668' : // BLACK LEFT-POINTING POINTER 457 '9658' ), // BLACK RIGHT-POINTING POINTER 458 ';</span>', 459 '</span>' ); 460 } 461 361 462 output.push( 362 '<span class="cke_menuarrow">', 363 '<span>&#', 364 ( this.editor.lang.dir == 'rtl' ? 365 '9668' : // BLACK LEFT-POINTING POINTER 366 '9658' ), // BLACK RIGHT-POINTING POINTER 367 ';</span>', 368 '</span>' ); 463 htmlLabel, 464 '</span>' + 465 '</a>' + 466 '</span>' ); 369 467 } 370 371 output.push(372 htmlLabel,373 '</span>' +374 '</a>' +375 '</span>' );376 468 } 377 } 378 }); 469 }); 379 470 471 })(); 472 473 380 474 /** 381 475 * The amount of time, in milliseconds, the editor waits before showing submenu 382 476 * options when moving the mouse over options that contains submenus, like the -
_source/plugins/menubutton/plugin.js
1 /* 1 /* 2 2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. 3 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 4 */ 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 {