text: ﻿/**
   * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
   * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
   */
  
  CKEDITOR.plugins.add( 'contextmenu', {
  	requires: 'menu',
  
  	// jscs:disable maximumLineLength
  	lang: 'af,ar,az,bg,bn,bs,ca,cs,cy,da,de,de-ch,el,en,en-au,en-ca,en-gb,eo,es,es-mx,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,oc,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,tt,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
  	// jscs:enable maximumLineLength
  
  	// Make sure the base class (CKEDITOR.menu) is loaded before it (https://dev.ckeditor.com/ticket/3318).
  	onLoad: function() {
  		/**
  		 * Class replacing the non-configurable native context menu with a configurable CKEditor's equivalent.
  		 *
  		 * @class
  		 * @extends CKEDITOR.menu
  		 */
  		CKEDITOR.plugins.contextMenu = CKEDITOR.tools.createClass( {
  			base: CKEDITOR.menu,
  
  			/**
  			 * Creates the CKEDITOR.plugins.contextMenu class instance.
  			 *
  			 * @constructor
  			 * @param {CKEDITOR.editor} editor
  			 */
  			$: function( editor ) {
  				this.base.call( this, editor, {
  					panel: {
  						// Allow adding custom CSS (#2202).
  						css: editor.config.contextmenu_contentsCss,
  						className: 'cke_menu_panel',
  						attributes: {
  							'aria-label': editor.lang.contextmenu.options
  						}
  					}
  				} );
  			},
  
  			proto: {
  				/**
  				 * Starts watching on native context menu triggers (<kbd>Option</kbd> key, right click) on the given element.
  				 *
  				 * @param {CKEDITOR.dom.element} element
  				 * @param {Boolean} [nativeContextMenuOnCtrl] Whether to open native context menu if the
  				 * <kbd>Ctrl</kbd> key is held on opening the context menu. See {@link CKEDITOR.config#browserContextMenuOnCtrl}.
  				 */
  				addTarget: function( element, nativeContextMenuOnCtrl ) {
  					var holdCtrlKey,
  						keystrokeActive;
  
  					element.on( 'contextmenu', function( event ) {
  						var domEvent = event.data,
  							isCtrlKeyDown =
  								// Safari on Windows always show 'ctrlKey' as true in 'contextmenu' event,
  								// which make this property unreliable. (https://dev.ckeditor.com/ticket/4826)
  								( CKEDITOR.env.webkit ? holdCtrlKey : ( CKEDITOR.env.mac ? domEvent.$.metaKey : domEvent.$.ctrlKey ) );
  
  						if ( nativeContextMenuOnCtrl && isCtrlKeyDown ) {
  							return;
  						}
  
  						// Cancel the browser context menu.
  						domEvent.preventDefault();
  
  						// Do not react to this event, as it might open context menu in wrong position (#2548).
  						if ( keystrokeActive ) {
  							return;
  						}
  
  						// Fix selection when non-editable element in Webkit/Blink (Mac) (https://dev.ckeditor.com/ticket/11306).
  						if ( CKEDITOR.env.mac && CKEDITOR.env.webkit ) {
  							var editor = this.editor,
  								contentEditableParent = new CKEDITOR.dom.elementPath( domEvent.getTarget(), editor.editable() ).contains( function( el ) {
  									// Return when non-editable or nested editable element is found.
  									return el.hasAttribute( 'contenteditable' );
  								}, true ); // Exclude editor's editable.
  
  							// Fake selection for non-editables only (to exclude nested editables).
  							if ( contentEditableParent && contentEditableParent.getAttribute( 'contenteditable' ) == 'false' ) {
  								editor.getSelection().fake( contentEditableParent );
  							}
  						}
  
  						var doc = domEvent.getTarget().getDocument(),
  							offsetParent = domEvent.getTarget().getDocument().getDocumentElement(),
  							fromFrame = !doc.equals( CKEDITOR.document ),
  							scroll = doc.getWindow().getScrollPosition(),
  							offsetX = fromFrame ? domEvent.$.clientX : domEvent.$.pageX || scroll.x + domEvent.$.clientX,
  							offsetY = fromFrame ? domEvent.$.clientY : domEvent.$.pageY || scroll.y + domEvent.$.clientY;
  
  						CKEDITOR.tools.setTimeout( function() {
  							this.open( offsetParent, null, offsetX, offsetY );
  							// IE needs a short while to allow selection change before opening menu. (https://dev.ckeditor.com/ticket/7908)
  						}, CKEDITOR.env.ie ? 200 : 0, this );
  					}, this );
  
  					if ( CKEDITOR.env.webkit ) {
  						var onKeyDown = function( event ) {
  								holdCtrlKey = CKEDITOR.env.mac ? event.data.$.metaKey : event.data.$.ctrlKey;
  							},
  							resetOnKeyUp = function() {
  								holdCtrlKey = 0;
  							};
  
  						element.on( 'keydown', onKeyDown );
  						element.on( 'keyup', resetOnKeyUp );
  						element.on( 'contextmenu', resetOnKeyUp );
  					}
  
  					// Block subsequent contextmenu event, when Shift + F10 is pressed (#2548).
  					if ( CKEDITOR.env.gecko && !CKEDITOR.env.mac ) {
  						element.on( 'keydown', function( evt ) {
  							if ( evt.data.$.shiftKey && evt.data.$.keyCode === 121 ) {
  								keystrokeActive = true;
  							}
  						}, null, null, 0 );
  
  						element.on( 'keyup', resetKeystrokeState );
  						element.on( 'contextmenu', resetKeystrokeState );
  					}
  
  					function resetKeystrokeState() {
  						keystrokeActive = false;
  					}
  				},
  
  				/**
  				 * Opens the context menu in the given location. See the {@link CKEDITOR.menu#show} method.
  				 *
  				 * @param {CKEDITOR.dom.element} offsetParent
  				 * @param {Number} [corner]
  				 * @param {Number} [offsetX]
  				 * @param {Number} [offsetY]
  				 */
  				open: function( offsetParent, corner, offsetX, offsetY ) {
  					// Do not open context menu if it's disabled or there is no selection in the editor (#1181).
  					if ( this.editor.config.enableContextMenu === false ||
  						this.editor.getSelection().getType() === CKEDITOR.SELECTION_NONE ) {
  						return;
  					}
  
  					this.editor.focus();
  					offsetParent = offsetParent || CKEDITOR.document.getDocumentElement();
  
  					// https://dev.ckeditor.com/ticket/9362: Force selection check to update commands' states in the new context.
  					this.editor.selectionChange( 1 );
  					this.show( offsetParent, corner, offsetX, offsetY );
  				}
  			}
  		} );
  	},
  
  	beforeInit: function( editor ) {
  		/**
  		 * @readonly
  		 * @property {CKEDITOR.plugins.contextMenu} contextMenu
  		 * @member CKEDITOR.editor
  		 */
  		var contextMenu = editor.contextMenu = new CKEDITOR.plugins.contextMenu( editor );
  
  		editor.on( 'contentDom', function() {
  			contextMenu.addTarget( editor.editable(), editor.config.browserContextMenuOnCtrl !== false );
  		} );
  
  		editor.addCommand( 'contextMenu', {
  			exec: function( editor ) {
  				var offsetX = 0,
  					offsetY = 0,
  					ranges = editor.getSelection().getRanges(),
  					rects,
  					rect;
  
  				// When opening context menu via keystroke there is no offsetX and Y passed (#1451).
  				rects = ranges[ ranges.length - 1 ].getClientRects( editor.editable().isInline() );
  				rect = rects[ rects.length - 1 ];
  
  				if ( rect ) {
  					offsetX = rect[ editor.lang.dir === 'rtl' ? 'left' : 'right' ];
  					offsetY = rect.bottom;
  				}
  
  				editor.contextMenu.open( editor.document.getBody().getParent(), null, offsetX, offsetY );
  			}
  		} );
  
  		editor.setKeystroke( CKEDITOR.SHIFT + 121 /*F10*/, 'contextMenu' );
  		editor.setKeystroke( CKEDITOR.CTRL + CKEDITOR.SHIFT + 121 /*F10*/, 'contextMenu' );
  	}
  } );
  
  /**
   * Whether to show the browser native context menu when the <kbd>Ctrl</kbd> or
   * <kbd>Meta</kbd> (Mac) key is pressed on opening the context menu with the
   * right mouse button click or the <kbd>Menu</kbd> key.
   *
   * ```javascript
   * config.browserContextMenuOnCtrl = false;
   * ```
   *
   * @since 3.0.2
   * @cfg {Boolean} [browserContextMenuOnCtrl=true]
   * @member CKEDITOR.config
   */
  
  /**
   * Whether to enable the context menu. Regardless of the setting the [Context Menu](https://ckeditor.com/cke4/addon/contextmenu)
   * plugin is still loaded.
   *
   * ```javascript
   * config.enableContextMenu = false;
   * ```
   *
   * @since 4.7.0
   * @cfg {Boolean} [enableContextMenu=true]
   * @member CKEDITOR.config
   */
  
  /**
   * The CSS file(s) to be used to apply the style to the context menu content.
   *
   * ```javascript
   * config.contextmenu_contentsCss = '/css/myfile.css';
   * config.contextmenu_contentsCss = [ '/css/myfile.css', '/css/anotherfile.css' ];
   * ```
   *
   * @since 4.11.0
   * @cfg {String/String[]} [contextmenu_contentsCss=CKEDITOR.skin.getPath( 'editor' )]
   * @member CKEDITOR.config
   */
  