JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.6.3
[ckeditor.git] / _source / plugins / contextmenu / plugin.js
1 /*\r
2 Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 CKEDITOR.plugins.add( 'contextmenu',\r
7 {\r
8         requires : [ 'menu' ],\r
9 \r
10         // Make sure the base class (CKEDITOR.menu) is loaded before it (#3318).\r
11         onLoad : function()\r
12         {\r
13                 CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass(\r
14                 {\r
15                         base : CKEDITOR.menu,\r
16 \r
17                         $ : function( editor )\r
18                         {\r
19                                 this.base.call( this, editor,\r
20                                 {\r
21                                         panel:\r
22                                         {\r
23                                                 className : editor.skinClass + ' cke_contextmenu',\r
24                                                 attributes :\r
25                                                 {\r
26                                                         'aria-label' : editor.lang.contextmenu.options\r
27                                                 }\r
28                                         }\r
29                                 });\r
30                         },\r
31 \r
32                         proto :\r
33                         {\r
34                                 addTarget : function( element, nativeContextMenuOnCtrl )\r
35                                 {\r
36                                         // Opera doesn't support 'contextmenu' event, we have duo approaches employed here:\r
37                                         // 1. Inherit the 'button override' hack we introduced in v2 (#4530), while this require the Opera browser\r
38                                         //  option 'Allow script to detect context menu/right click events' to be always turned on.\r
39                                         // 2. Considering the fact that ctrl/meta key is not been occupied\r
40                                         //  for multiple range selecting (like Gecko), we use this key\r
41                                         //  combination as a fallback for triggering context-menu. (#4530)\r
42                                         if ( CKEDITOR.env.opera && !( 'oncontextmenu' in document.body ))\r
43                                         {\r
44                                                 var contextMenuOverrideButton;\r
45                                                 element.on( 'mousedown', function( evt )\r
46                                                 {\r
47                                                         evt = evt.data;\r
48                                                         if ( evt.$.button != 2 )\r
49                                                         {\r
50                                                                 if ( evt.getKeystroke() == CKEDITOR.CTRL + 1 )\r
51                                                                         element.fire( 'contextmenu', evt );\r
52                                                                 return;\r
53                                                         }\r
54 \r
55                                                         if ( nativeContextMenuOnCtrl\r
56                                                                  && ( CKEDITOR.env.mac ? evt.$.metaKey : evt.$.ctrlKey ) )\r
57                                                                 return;\r
58 \r
59                                                         var target = evt.getTarget();\r
60 \r
61                                                         if ( !contextMenuOverrideButton )\r
62                                                         {\r
63                                                                 var ownerDoc =  target.getDocument();\r
64                                                                 contextMenuOverrideButton = ownerDoc.createElement( 'input' ) ;\r
65                                                                 contextMenuOverrideButton.$.type = 'button' ;\r
66                                                                 ownerDoc.getBody().append( contextMenuOverrideButton ) ;\r
67                                                         }\r
68 \r
69                                                         contextMenuOverrideButton.setAttribute( 'style', 'position:absolute;top:' + ( evt.$.clientY - 2 ) +\r
70                                                                 'px;left:' + ( evt.$.clientX - 2 ) +\r
71                                                                 'px;width:5px;height:5px;opacity:0.01' );\r
72 \r
73                                                 } );\r
74 \r
75                                                 element.on( 'mouseup', function ( evt )\r
76                                                 {\r
77                                                         if ( contextMenuOverrideButton )\r
78                                                         {\r
79                                                                 contextMenuOverrideButton.remove();\r
80                                                                 contextMenuOverrideButton = undefined;\r
81                                                                 // Simulate 'contextmenu' event.\r
82                                                                 element.fire( 'contextmenu', evt.data );\r
83                                                         }\r
84                                                 } );\r
85                                         }\r
86 \r
87                                         element.on( 'contextmenu', function( event )\r
88                                                 {\r
89                                                         var domEvent = event.data;\r
90 \r
91                                                         if ( nativeContextMenuOnCtrl &&\r
92                                                                  // Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event,\r
93                                                                 // which make this property unreliable. (#4826)\r
94                                                                  ( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) ) )\r
95                                                                 return;\r
96 \r
97 \r
98                                                         // Cancel the browser context menu.\r
99                                                         domEvent.preventDefault();\r
100 \r
101                                                         var offsetParent = domEvent.getTarget().getDocument().getDocumentElement(),\r
102                                                                 offsetX = domEvent.$.clientX,\r
103                                                                 offsetY = domEvent.$.clientY;\r
104 \r
105                                                         CKEDITOR.tools.setTimeout( function()\r
106                                                                 {\r
107                                                                         this.open( offsetParent, null, offsetX, offsetY );\r
108 \r
109                                                                 // IE needs a short while to allow selection change before opening menu. (#7908)\r
110                                                                 }, CKEDITOR.env.ie? 200 : 0, this );\r
111                                                 },\r
112                                                 this );\r
113 \r
114                                         if ( CKEDITOR.env.opera )\r
115                                         {\r
116                                                 // 'contextmenu' event triggered by Windows menu key is unpreventable,\r
117                                                 // cancel the key event itself. (#6534)\r
118                                                 element.on( 'keypress' , function ( evt )\r
119                                                 {\r
120                                                         var domEvent = evt.data;\r
121 \r
122                                                         if ( domEvent.$.keyCode === 0 )\r
123                                                                 domEvent.preventDefault();\r
124                                                 });\r
125                                         }\r
126 \r
127                                         if ( CKEDITOR.env.webkit )\r
128                                         {\r
129                                                 var holdCtrlKey,\r
130                                                         onKeyDown = function( event )\r
131                                                         {\r
132                                                                 holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey ;\r
133                                                         },\r
134                                                         resetOnKeyUp = function()\r
135                                                         {\r
136                                                                 holdCtrlKey = 0;\r
137                                                         };\r
138 \r
139                                                 element.on( 'keydown', onKeyDown );\r
140                                                 element.on( 'keyup', resetOnKeyUp );\r
141                                                 element.on( 'contextmenu', resetOnKeyUp );\r
142                                         }\r
143                                 },\r
144 \r
145                                 open : function( offsetParent, corner, offsetX, offsetY )\r
146                                 {\r
147                                         this.editor.focus();\r
148                                         offsetParent = offsetParent || CKEDITOR.document.getDocumentElement();\r
149                                         this.show( offsetParent, corner, offsetX, offsetY );\r
150                                 }\r
151                         }\r
152                 });\r
153         },\r
154 \r
155         beforeInit : function( editor )\r
156         {\r
157                 editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor );\r
158 \r
159                 editor.addCommand( 'contextMenu',\r
160                         {\r
161                                 exec : function()\r
162                                         {\r
163                                                 editor.contextMenu.open( editor.document.getBody() );\r
164                                         }\r
165                         });\r
166         }\r
167 });\r
168 \r
169 /**\r
170  * Whether to show the browser native context menu when the <em>Ctrl</em> or\r
171  * <em>Meta</em> (Mac) key is pressed on opening the context menu with the\r
172  * right mouse button click or the <em>Menu</em> key.\r
173  * @name CKEDITOR.config.browserContextMenuOnCtrl\r
174  * @since 3.0.2\r
175  * @type Boolean\r
176  * @default <code>true</code>\r
177  * @example\r
178  * config.browserContextMenuOnCtrl = false;\r
179  */\r