1 /*
  2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
  3 For licensing, see LICENSE.html or http://ckeditor.com/license
  4 */
  5
  6 CKEDITOR.plugins.add( 'contextmenu',
  7 {
  8 	requires : [ 'menu' ],
  9
 10 	beforeInit : function( editor )
 11 	{
 12 		editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor );
 13
 14 		editor.addCommand( 'contextMenu',
 15 			{
 16 				exec : function()
 17 					{
 18 						editor.contextMenu.show();
 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
 40 	_ :
 41 	{
 42 		onMenu : function( offsetParent, offsetX, offsetY )
 43 		{
 44 			var menu = this._.menu,
 45 				editor = this.editor;
 46
 47 			if ( menu )
 48 			{
 49 				menu.hide();
 50 				menu.removeAll();
 51 			}
 52 			else
 53 			{
 54 				menu = this._.menu = new CKEDITOR.menu( editor );
 55 				menu.onClick = CKEDITOR.tools.bind( function( item )
 56 				{
 57 					menu.hide();
 58 					editor.focus();
 59
 60 					if ( item.onClick )
 61 						item.onClick();
 62 					else if ( item.command )
 63 					{
 64 						if ( CKEDITOR.env.ie )
 65 							this.restoreSelection();
 66
 67 						editor.execCommand( item.command );
 68 					}
 69 				}, this );
 70
 71 				menu.onEscape = function()
 72 				{
 73 					editor.focus();
 74 				};
 75 			}
 76
 77 			var listeners = this._.listeners,
 78 				includedItems = [];
 79
 80 			var selection = this.editor.getSelection(),
 81 				element = selection && selection.getStartElement();
 82
 83 			// Call all listeners, filling the list of items to be displayed.
 84 			for ( var i = 0 ; i < listeners.length ; i++ )
 85 			{
 86 				var listenerItems = listeners[ i ]( element, selection );
 87
 88 				if ( listenerItems )
 89 				{
 90 					for ( var itemName in listenerItems )
 91 					{
 92 						var item = this.editor.getMenuItem( itemName );
 93
 94 						if ( item )
 95 						{
 96 							item.state = listenerItems[ itemName ];
 97 							menu.add( item );
 98 						}
 99 					}
100 				}
101 			}
102
103 			if ( CKEDITOR.env.ie )
104 				this.saveSelection();
105
106 			menu.show( offsetParent, 1, offsetX, offsetY );
107 		}
108 	},
109
110 	proto :
111 	{
112 		addTarget : function( element )
113 		{
114 			element.on( 'contextmenu', function( event )
115 				{
116 					var domEvent = event.data;
117
118 					// Cancel the browser context menu.
119 					domEvent.preventDefault();
120
121 					var offsetParent = domEvent.getTarget().getDocument().getDocumentElement();
122 						offsetX = domEvent.$.clientX,
123 						offsetY = domEvent.$.clientY;
124
125 					CKEDITOR.tools.setTimeout( function()
126 						{
127 							this._.onMenu( offsetParent, offsetX, offsetY );
128 						},
129 						0, this );
130 				},
131 				this );
132 		},
133
134 		addListener : function( listenerFn )
135 		{
136 			this._.listeners.push( listenerFn );
137 		},
138
139 		show : function()
140 		{
141 			this.editor.focus();
142 			this._.onMenu( CKEDITOR.document.getDocumentElement(), 0, 0 );
143 		},
144
145 		/**
146 		 * Saves the current selection position in the editor.
147 		 */
148 		saveSelection : function()
149 		{
150 			if ( this.editor.mode == 'wysiwyg' )
151 			{
152 				this.editor.focus();
153
154 				var selection = new CKEDITOR.dom.selection( this.editor.document );
155 				this._.selectedRanges = selection.getRanges();
156 			}
157 			else
158 				delete this._.selectedRanges;
159 		},
160
161 		/**
162 		 * Restores the editor's selection from the previously saved position in this
163 		 * dialog.
164 		 */
165 		restoreSelection : function()
166 		{
167 			if ( this.editor.mode == 'wysiwyg' && this._.selectedRanges )
168 			{
169 				this.editor.focus();
170 				( new CKEDITOR.dom.selection( this.editor.document ) ).selectRanges( this._.selectedRanges );
171 			}
172 		}
173 	}
174 });
175
176 // Fix the "contextmenu" event for DOM elements.
177 // We may do this if we identify browsers that don't support the context meny
178 // event on element directly. Leaving here for reference.
179 //if ( <specific browsers> )
180 //{
181 //	CKEDITOR.dom.element.prototype.on = CKEDITOR.tools.override( CKEDITOR.dom.element.prototype.on, function( originalOn )
182 //		{
183 //			return function( eventName )
184 //				{
185 //					if ( eventName != 'contextmenu' )
186 //						return originalOn.apply( this, arguments );
187 //
188 //					// TODO : Implement the fix.
189 //				};
190 //		});
191 //}
192