      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, corner, 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 					var noUnlock = true;
     58 					menu.hide();
     59
     60 					if ( CKEDITOR.env.ie )
     61 						menu.onEscape();
     62
     63 					if ( item.onClick )
     64 						item.onClick();
     65 					else if ( item.command )
     66 						editor.execCommand( item.command );
     67
     68 					noUnlock = false;
     69 				}, this );
     70
     71 				menu.onEscape = function()
     72 				{
     73 					editor.focus();
     74
     75 					if ( CKEDITOR.env.ie )
     76 						editor.getSelection().unlock( true );
     77 				};
     78 			}
     79
     80 			var listeners = this._.listeners,
     81 				includedItems = [];
     82
     83 			var selection = this.editor.getSelection(),
     84 				element = selection && selection.getStartElement();
     85
     86 			// Lock the selection in IE, so it can be restored when closing the
     87 			// menu.
     88 			if ( CKEDITOR.env.ie )
     89 				selection.lock();
     90
     91 			menu.onHide = CKEDITOR.tools.bind( function()
     92 				{
     93 					menu.onHide = null;
     94
     95 					if ( CKEDITOR.env.ie )
     96 						editor.getSelection().unlock();
     97
     98 					this.onHide && this.onHide();
     99 				},
    100 				this );
    101
    102 			// Call all listeners, filling the list of items to be displayed.
    103 			for ( var i = 0 ; i < listeners.length ; i++ )
    104 			{
    105 				var listenerItems = listeners[ i ]( element, selection );
    106
    107 				if ( listenerItems )
    108 				{
    109 					for ( var itemName in listenerItems )
    110 					{
    111 						var item = this.editor.getMenuItem( itemName );
    112
    113 						if ( item )
    114 						{
    115 							item.state = listenerItems[ itemName ];
    116 							menu.add( item );
    117 						}
    118 					}
    119 				}
    120 			}
    121
    122 			menu.show( offsetParent, corner || ( editor.lang.dir == 'rtl' ? 2 : 1 ), offsetX, offsetY );
    123 		}
    124 	},
    125
    126 	proto :
    127 	{
    128 		addTarget : function( element )
    129 		{
    130 			element.on( 'contextmenu', function( event )
    131 				{
    132 					var domEvent = event.data;
    133
    134 					// Cancel the browser context menu.
    135 					domEvent.preventDefault();
    136
    137 					var offsetParent = domEvent.getTarget().getDocument().getDocumentElement(),
    138 						offsetX = domEvent.$.clientX,
    139 						offsetY = domEvent.$.clientY;
    140
    141 					CKEDITOR.tools.setTimeout( function()
    142 						{
    143 							this._.onMenu( offsetParent, null, offsetX, offsetY );
    144 						},
    145 						0, this );
    146 				},
    147 				this );
    148 		},
    149
    150 		addListener : function( listenerFn )
    151 		{
    152 			this._.listeners.push( listenerFn );
    153 		},
    154
    155 		show : function( offsetParent, corner, offsetX, offsetY )
    156 		{
    157 			this.editor.focus();
    158 			this._.onMenu( offsetParent || CKEDITOR.document.getDocumentElement(), corner, offsetX || 0, offsetY || 0 );
    159 		}
    160 	}
    161 });
    162
    163 // Fix the "contextmenu" event for DOM elements.
    164 // We may do this if we identify browsers that don't support the context meny
    165 // event on element directly. Leaving here for reference.
    166 //if ( <specific browsers> )
    167 //{
    168 //	CKEDITOR.dom.element.prototype.on = CKEDITOR.tools.override( CKEDITOR.dom.element.prototype.on, function( originalOn )
    169 //		{
    170 //			return function( eventName )
    171 //				{
    172 //					if ( eventName != 'contextmenu' )
    173 //						return originalOn.apply( this, arguments );
    174 //
    175 //					// TODO : Implement the fix.
    176 //				};
    177 //		});
    178 //}
    179