2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license
\r
6 CKEDITOR.plugins.add( 'contextmenu',
\r
8 requires : [ 'menu' ],
\r
10 beforeInit : function( editor )
\r
12 editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor );
\r
14 editor.addCommand( 'contextMenu',
\r
18 editor.contextMenu.show( editor.document.getBody() );
\r
24 CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass(
\r
26 $ : function( editor )
\r
28 this.id = CKEDITOR.tools.getNextId();
\r
29 this.editor = editor;
\r
30 this._.listeners = [];
\r
31 this._.functionId = CKEDITOR.tools.addFunction( function( commandName )
\r
33 this._.panel.hide();
\r
35 editor.execCommand( commandName );
\r
43 className : editor.skinClass + ' cke_contextmenu',
\r
46 'aria-label' : editor.lang.contextmenu.options
\r
54 onMenu : function( offsetParent, corner, offsetX, offsetY )
\r
56 var menu = this._.menu,
\r
57 editor = this.editor;
\r
66 menu = this._.menu = new CKEDITOR.menu( editor, this.definition );
\r
67 menu.onClick = CKEDITOR.tools.bind( function( item )
\r
73 else if ( item.command )
\r
74 editor.execCommand( item.command );
\r
78 menu.onEscape = function( keystroke )
\r
80 var parent = this.parent;
\r
81 // 1. If it's sub-menu, restore the last focused item
\r
82 // of upper level menu.
\r
83 // 2. In case of a top-menu, close it.
\r
86 parent._.panel.hideChild();
\r
87 // Restore parent block item focus.
\r
88 var parentBlock = parent._.panel._.panel._.currentBlock,
\r
89 parentFocusIndex = parentBlock._.focusIndex;
\r
90 parentBlock._.markItem( parentFocusIndex );
\r
92 else if ( keystroke == 27 )
\r
101 var listeners = this._.listeners,
\r
102 includedItems = [];
\r
104 var selection = this.editor.getSelection(),
\r
105 element = selection && selection.getStartElement();
\r
107 menu.onHide = CKEDITOR.tools.bind( function()
\r
109 menu.onHide = null;
\r
111 if ( CKEDITOR.env.ie )
\r
113 var selection = editor.getSelection();
\r
114 selection && selection.unlock();
\r
117 this.onHide && this.onHide();
\r
121 // Call all listeners, filling the list of items to be displayed.
\r
122 for ( var i = 0 ; i < listeners.length ; i++ )
\r
124 var listenerItems = listeners[ i ]( element, selection );
\r
126 if ( listenerItems )
\r
128 for ( var itemName in listenerItems )
\r
130 var item = this.editor.getMenuItem( itemName );
\r
134 item.state = listenerItems[ itemName ];
\r
141 // Don't show context menu with zero items.
\r
142 menu.items.length && menu.show( offsetParent, corner || ( editor.lang.dir == 'rtl' ? 2 : 1 ), offsetX, offsetY );
\r
148 addTarget : function( element, nativeContextMenuOnCtrl )
\r
151 // For browsers (Opera <=10a) that doesn't support 'contextmenu' event, we have duo approaches employed here:
\r
152 // 1. Inherit the 'button override' hack we introduced in v2 (#4530) (In Opera browser, this require the
\r
153 // option 'Allow script to detect context menu/right click events' to be always turned on).
\r
154 // 2. Considering the fact that ctrl/meta key is not been occupied
\r
155 // for multiple range selecting (like Gecko), we use this key
\r
156 // combination as a fallback for triggering context-menu. (#4530)
\r
157 if ( CKEDITOR.env.opera && !( 'oncontextmenu' in document.body ) )
\r
159 var contextMenuOverrideButton;
\r
160 element.on( 'mousedown', function( evt )
\r
163 if ( evt.$.button != 2 )
\r
165 if ( evt.getKeystroke() == CKEDITOR.CTRL + 1 )
\r
166 element.fire( 'contextmenu', evt );
\r
170 if ( nativeContextMenuOnCtrl
\r
171 && ( CKEDITOR.env.mac ? evt.$.metaKey : evt.$.ctrlKey ) )
\r
174 var target = evt.getTarget();
\r
176 if ( !contextMenuOverrideButton )
\r
178 var ownerDoc = target.getDocument();
\r
179 contextMenuOverrideButton = ownerDoc.createElement( 'input' ) ;
\r
180 contextMenuOverrideButton.$.type = 'button' ;
\r
181 ownerDoc.getBody().append( contextMenuOverrideButton ) ;
\r
184 contextMenuOverrideButton.setAttribute( 'style', 'position:absolute;top:' + ( evt.$.clientY - 2 ) +
\r
185 'px;left:' + ( evt.$.clientX - 2 ) +
\r
186 'px;width:5px;height:5px;opacity:0.01' );
\r
190 element.on( 'mouseup', function ( evt )
\r
192 if ( contextMenuOverrideButton )
\r
194 contextMenuOverrideButton.remove();
\r
195 contextMenuOverrideButton = undefined;
\r
196 // Simulate 'contextmenu' event.
\r
197 element.fire( 'contextmenu', evt.data );
\r
202 element.on( 'contextmenu', function( event )
\r
204 var domEvent = event.data;
\r
206 if ( nativeContextMenuOnCtrl &&
\r
207 // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event,
\r
208 // which make this property unreliable. (#4826)
\r
209 ( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) ) )
\r
213 // Cancel the browser context menu.
\r
214 domEvent.preventDefault();
\r
216 var offsetParent = domEvent.getTarget().getDocument().getDocumentElement(),
\r
217 offsetX = domEvent.$.clientX,
\r
218 offsetY = domEvent.$.clientY;
\r
220 CKEDITOR.tools.setTimeout( function()
\r
222 this.show( offsetParent, null, offsetX, offsetY );
\r
228 if ( CKEDITOR.env.opera )
\r
230 // 'contextmenu' event triggered by Windows menu key is unpreventable,
\r
231 // cancel the key event itself. (#6534)
\r
232 element.on( 'keypress' , function ( evt )
\r
234 var domEvent = evt.data;
\r
236 if ( domEvent.$.keyCode === 0 )
\r
237 domEvent.preventDefault();
\r
241 if ( CKEDITOR.env.webkit )
\r
244 onKeyDown = function( event )
\r
246 holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey ;
\r
248 resetOnKeyUp = function()
\r
253 element.on( 'keydown', onKeyDown );
\r
254 element.on( 'keyup', resetOnKeyUp );
\r
255 element.on( 'contextmenu', resetOnKeyUp );
\r
259 addListener : function( listenerFn )
\r
261 this._.listeners.push( listenerFn );
\r
264 show : function( offsetParent, corner, offsetX, offsetY )
\r
266 this.editor.focus();
\r
268 // Selection will be unavailable after context menu shows up
\r
269 // in IE, lock it now.
\r
270 if ( CKEDITOR.env.ie )
\r
272 var selection = this.editor.getSelection();
\r
273 selection && selection.lock();
\r
276 this._.onMenu( offsetParent || CKEDITOR.document.getDocumentElement(), corner, offsetX || 0, offsetY || 0 );
\r
282 * Whether to show the browser native context menu when the CTRL or the
\r
283 * META (Mac) key is pressed while opening the context menu.
\r
284 * @name CKEDITOR.config.browserContextMenuOnCtrl
\r
289 * config.browserContextMenuOnCtrl = false;
\r