JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.0.2
[ckeditor.git] / _source / plugins / contextmenu / plugin.js
index 4e42a7b..6cbc3e7 100644 (file)
@@ -119,18 +119,76 @@ CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass(
                                }\r
                        }\r
 \r
-                       menu.show( offsetParent, corner || ( editor.lang.dir == 'rtl' ? 2 : 1 ), offsetX, offsetY );\r
+                       // Don't show context menu with zero items.\r
+                       menu.items.length && menu.show( offsetParent, corner || ( editor.lang.dir == 'rtl' ? 2 : 1 ), offsetX, offsetY );\r
                }\r
        },\r
 \r
        proto :\r
        {\r
-               addTarget : function( element )\r
+               addTarget : function( element, nativeContextMenuOnCtrl )\r
                {\r
+                       // Opera doesn't support 'contextmenu' event, we have duo approaches employed here:\r
+                       // 1. Inherit the 'button override' hack we introduced in v2 (#4530), while this require the Opera browser\r
+                       //  option 'Allow script to detect context menu/right click events' to be always turned on.\r
+                       // 2. Considering the fact that ctrl/meta key is not been occupied\r
+                       //  for multiple range selecting (like Gecko), we use this key\r
+                       //  combination as a fallback for triggering context-menu. (#4530)\r
+                       if ( CKEDITOR.env.opera )\r
+                       {\r
+                               var contextMenuOverrideButton;\r
+                               element.on( 'mousedown', function( evt )\r
+                               {\r
+                                       evt = evt.data;\r
+                                       if( evt.$.button != 2 )\r
+                                       {\r
+                                               if ( evt.getKeystroke() == CKEDITOR.CTRL + 1 )\r
+                                                       element.fire( 'contextmenu', evt );\r
+                                               return;\r
+                                       }\r
+\r
+                                       if ( nativeContextMenuOnCtrl\r
+                                                && ( evt.$.ctrlKey || evt.$.metaKey ) )\r
+                                               return;\r
+\r
+                                       var target = evt.getTarget();\r
+\r
+                                       if( !contextMenuOverrideButton )\r
+                                       {\r
+                                               var ownerDoc =  target.getDocument();\r
+                                               contextMenuOverrideButton = ownerDoc.createElement( 'input' ) ;\r
+                                               contextMenuOverrideButton.$.type = 'button' ;\r
+                                               ownerDoc.getBody().append( contextMenuOverrideButton ) ;\r
+                                       }\r
+\r
+                                       contextMenuOverrideButton.setAttribute( 'style', 'position:absolute;top:' + ( evt.$.clientY - 2 ) +\r
+                                               'px;left:' + ( evt.$.clientX - 2 ) +\r
+                                               'px;width:5px;height:5px;opacity:0.01' );\r
+\r
+                               } );\r
+\r
+                               element.on( 'mouseup', function ( evt )\r
+                               {\r
+                                       if ( contextMenuOverrideButton )\r
+                                       {\r
+                                               contextMenuOverrideButton.remove();\r
+                                               contextMenuOverrideButton = undefined;\r
+                                               // Simulate 'contextmenu' event.\r
+                                               element.fire( 'contextmenu', evt.data );\r
+                                       }\r
+                               } );\r
+                       }\r
+\r
                        element.on( 'contextmenu', function( event )\r
                                {\r
                                        var domEvent = event.data;\r
 \r
+                                       if ( nativeContextMenuOnCtrl &&\r
+                                            // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event,\r
+                                               // which make this property unreliable. (#4826)\r
+                                            ( CKEDITOR.env.webkit ? holdCtrlKey : domEvent.$.ctrlKey || domEvent.$.metaKey ) )\r
+                                               return;\r
+\r
                                        // Cancel the browser context menu.\r
                                        domEvent.preventDefault();\r
 \r
@@ -145,6 +203,23 @@ CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass(
                                                0, this );\r
                                },\r
                                this );\r
+\r
+                       if( CKEDITOR.env.webkit )\r
+                       {\r
+                               var holdCtrlKey,\r
+                                       onKeyDown = function( event )\r
+                                       {\r
+                                               holdCtrlKey = event.data.$.ctrlKey || event.data.$.metaKey;\r
+                                       },\r
+                                       resetOnKeyUp = function()\r
+                                       {\r
+                                               holdCtrlKey = 0;\r
+                                       };\r
+\r
+                               element.on( 'keydown', onKeyDown );\r
+                               element.on( 'keyup', resetOnKeyUp );\r
+                               element.on( 'contextmenu', resetOnKeyUp );\r
+                       }\r
                },\r
 \r
                addListener : function( listenerFn )\r
@@ -160,19 +235,13 @@ CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass(
        }\r
 });\r
 \r
-// Fix the "contextmenu" event for DOM elements.\r
-// We may do this if we identify browsers that don't support the context meny\r
-// event on element directly. Leaving here for reference.\r
-//if ( <specific browsers> )\r
-//{\r
-//     CKEDITOR.dom.element.prototype.on = CKEDITOR.tools.override( CKEDITOR.dom.element.prototype.on, function( originalOn )\r
-//             {\r
-//                     return function( eventName )\r
-//                             {\r
-//                                     if ( eventName != 'contextmenu' )\r
-//                                             return originalOn.apply( this, arguments );\r
-//\r
-//                                     // TODO : Implement the fix.\r
-//                             };\r
-//             });\r
-//}\r
+/**\r
+ * Whether to show the browser native context menu when the CTRL or the\r
+ * META (Mac) key is pressed while opening the context menu.\r
+ * @name CKEDITOR.config.browserContextMenuOnCtrl\r
+ * @since 3.0.2\r
+ * @type Boolean\r
+ * @default true\r
+ * @example\r
+ * config.browserContextMenuOnCtrl = false;\r
+ */\r