462 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			462 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| 
								 | 
							
								/**
							 | 
						|||
| 
								 | 
							
								 * @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
							 | 
						|||
| 
								 | 
							
								 * For licensing, see LICENSE.md or http://ckeditor.com/license
							 | 
						|||
| 
								 | 
							
								 */
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/**
							 | 
						|||
| 
								 | 
							
								 * @fileOverview Increase and Decrease Indent commands.
							 | 
						|||
| 
								 | 
							
								 */
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								( function() {
							 | 
						|||
| 
								 | 
							
									'use strict';
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									var TRISTATE_DISABLED = CKEDITOR.TRISTATE_DISABLED,
							 | 
						|||
| 
								 | 
							
										TRISTATE_OFF = CKEDITOR.TRISTATE_OFF;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									CKEDITOR.plugins.add( 'indent', {
							 | 
						|||
| 
								 | 
							
										lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,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,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
							 | 
						|||
| 
								 | 
							
										icons: 'indent,indent-rtl,outdent,outdent-rtl', // %REMOVE_LINE_CORE%
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										init: function( editor ) {
							 | 
						|||
| 
								 | 
							
											var genericDefinition = CKEDITOR.plugins.indent.genericDefinition;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											// Register generic commands.
							 | 
						|||
| 
								 | 
							
											setupGenericListeners( editor, editor.addCommand( 'indent', new genericDefinition( true ) ) );
							 | 
						|||
| 
								 | 
							
											setupGenericListeners( editor, editor.addCommand( 'outdent', new genericDefinition() ) );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											// Create and register toolbar button if possible.
							 | 
						|||
| 
								 | 
							
											if ( editor.ui.addButton ) {
							 | 
						|||
| 
								 | 
							
												editor.ui.addButton( 'Indent', {
							 | 
						|||
| 
								 | 
							
													label: editor.lang.indent.indent,
							 | 
						|||
| 
								 | 
							
													command: 'indent',
							 | 
						|||
| 
								 | 
							
													directional: true,
							 | 
						|||
| 
								 | 
							
													toolbar: 'indent,20'
							 | 
						|||
| 
								 | 
							
												} );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												editor.ui.addButton( 'Outdent', {
							 | 
						|||
| 
								 | 
							
													label: editor.lang.indent.outdent,
							 | 
						|||
| 
								 | 
							
													command: 'outdent',
							 | 
						|||
| 
								 | 
							
													directional: true,
							 | 
						|||
| 
								 | 
							
													toolbar: 'indent,10'
							 | 
						|||
| 
								 | 
							
												} );
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											// Register dirChanged listener.
							 | 
						|||
| 
								 | 
							
											editor.on( 'dirChanged', function( evt ) {
							 | 
						|||
| 
								 | 
							
												var range = editor.createRange(),
							 | 
						|||
| 
								 | 
							
													dataNode = evt.data.node;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												range.setStartBefore( dataNode );
							 | 
						|||
| 
								 | 
							
												range.setEndAfter( dataNode );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												var walker = new CKEDITOR.dom.walker( range ),
							 | 
						|||
| 
								 | 
							
													node;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
												while ( ( node = walker.next() ) ) {
							 | 
						|||
| 
								 | 
							
													if ( node.type == CKEDITOR.NODE_ELEMENT ) {
							 | 
						|||
| 
								 | 
							
														// A child with the defined dir is to be ignored.
							 | 
						|||
| 
								 | 
							
														if ( !node.equals( dataNode ) && node.getDirection() ) {
							 | 
						|||
| 
								 | 
							
															range.setStartAfter( node );
							 | 
						|||
| 
								 | 
							
															walker = new CKEDITOR.dom.walker( range );
							 | 
						|||
| 
								 | 
							
															continue;
							 | 
						|||
| 
								 | 
							
														}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
														// Switch alignment classes.
							 | 
						|||
| 
								 | 
							
														var classes = editor.config.indentClasses;
							 | 
						|||
| 
								 | 
							
														if ( classes ) {
							 | 
						|||
| 
								 | 
							
															var suffix = ( evt.data.dir == 'ltr' ) ? [ '_rtl', '' ] : [ '', '_rtl' ];
							 | 
						|||
| 
								 | 
							
															for ( var i = 0; i < classes.length; i++ ) {
							 | 
						|||
| 
								 | 
							
																if ( node.hasClass( classes[ i ] + suffix[ 0 ] ) ) {
							 | 
						|||
| 
								 | 
							
																	node.removeClass( classes[ i ] + suffix[ 0 ] );
							 | 
						|||
| 
								 | 
							
																	node.addClass( classes[ i ] + suffix[ 1 ] );
							 | 
						|||
| 
								 | 
							
																}
							 | 
						|||
| 
								 | 
							
															}
							 | 
						|||
| 
								 | 
							
														}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
														// Switch the margins.
							 | 
						|||
| 
								 | 
							
														var marginLeft = node.getStyle( 'margin-right' ),
							 | 
						|||
| 
								 | 
							
															marginRight = node.getStyle( 'margin-left' );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
														marginLeft ? node.setStyle( 'margin-left', marginLeft ) : node.removeStyle( 'margin-left' );
							 | 
						|||
| 
								 | 
							
														marginRight ? node.setStyle( 'margin-right', marginRight ) : node.removeStyle( 'margin-right' );
							 | 
						|||
| 
								 | 
							
													}
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											} );
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									} );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									/**
							 | 
						|||
| 
								 | 
							
									 * Global command class definitions and global helpers.
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 * @class
							 | 
						|||
| 
								 | 
							
									 * @singleton
							 | 
						|||
| 
								 | 
							
									 */
							 | 
						|||
| 
								 | 
							
									CKEDITOR.plugins.indent = {
							 | 
						|||
| 
								 | 
							
										/**
							 | 
						|||
| 
								 | 
							
										 * A base class for a generic command definition, responsible mainly for creating
							 | 
						|||
| 
								 | 
							
										 * Increase Indent and Decrease Indent toolbar buttons as well as for refreshing
							 | 
						|||
| 
								 | 
							
										 * UI states.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * Commands of this class do not perform any indentation by themselves. They
							 | 
						|||
| 
								 | 
							
										 * delegate this job to content-specific indentation commands (i.e. indentlist).
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * @class CKEDITOR.plugins.indent.genericDefinition
							 | 
						|||
| 
								 | 
							
										 * @extends CKEDITOR.commandDefinition
							 | 
						|||
| 
								 | 
							
										 * @param {CKEDITOR.editor} editor The editor instance this command will be
							 | 
						|||
| 
								 | 
							
										 * applied to.
							 | 
						|||
| 
								 | 
							
										 * @param {String} name The name of the command.
							 | 
						|||
| 
								 | 
							
										 * @param {Boolean} [isIndent] Defines the command as indenting or outdenting.
							 | 
						|||
| 
								 | 
							
										 */
							 | 
						|||
| 
								 | 
							
										genericDefinition: function( isIndent ) {
							 | 
						|||
| 
								 | 
							
											/**
							 | 
						|||
| 
								 | 
							
											 * Determines whether the command belongs to the indentation family.
							 | 
						|||
| 
								 | 
							
											 * Otherwise it is assumed to be an outdenting command.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * @readonly
							 | 
						|||
| 
								 | 
							
											 * @property {Boolean} [=false]
							 | 
						|||
| 
								 | 
							
											 */
							 | 
						|||
| 
								 | 
							
											this.isIndent = !!isIndent;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											// Mimic naive startDisabled behavior for outdent.
							 | 
						|||
| 
								 | 
							
											this.startDisabled = !this.isIndent;
							 | 
						|||
| 
								 | 
							
										},
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										/**
							 | 
						|||
| 
								 | 
							
										 * A base class for specific indentation command definitions responsible for
							 | 
						|||
| 
								 | 
							
										 * handling a pre-defined set of elements i.e. indentlist for lists or
							 | 
						|||
| 
								 | 
							
										 * indentblock for text block elements.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * Commands of this class perform indentation operations and modify the DOM structure.
							 | 
						|||
| 
								 | 
							
										 * They listen for events fired by {@link CKEDITOR.plugins.indent.genericDefinition}
							 | 
						|||
| 
								 | 
							
										 * and execute defined actions.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * **NOTE**: This is not an {@link CKEDITOR.command editor command}.
							 | 
						|||
| 
								 | 
							
										 * Context-specific commands are internal, for indentation system only.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * @class CKEDITOR.plugins.indent.specificDefinition
							 | 
						|||
| 
								 | 
							
										 * @param {CKEDITOR.editor} editor The editor instance this command will be
							 | 
						|||
| 
								 | 
							
										 * applied to.
							 | 
						|||
| 
								 | 
							
										 * @param {String} name The name of the command.
							 | 
						|||
| 
								 | 
							
										 * @param {Boolean} [isIndent] Defines the command as indenting or outdenting.
							 | 
						|||
| 
								 | 
							
										 */
							 | 
						|||
| 
								 | 
							
										specificDefinition: function( editor, name, isIndent ) {
							 | 
						|||
| 
								 | 
							
											this.name = name;
							 | 
						|||
| 
								 | 
							
											this.editor = editor;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											/**
							 | 
						|||
| 
								 | 
							
											 * An object of jobs handled by the command. Each job consists
							 | 
						|||
| 
								 | 
							
											 * of two functions: `refresh` and `exec` as well as the execution priority.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 *	* The `refresh` function determines whether a job is doable for
							 | 
						|||
| 
								 | 
							
											 *	  a particular context. These functions are executed in the
							 | 
						|||
| 
								 | 
							
											 *	  order of priorities, one by one, for all plugins that registered
							 | 
						|||
| 
								 | 
							
											 *	  jobs. As jobs are related to generic commands, refreshing
							 | 
						|||
| 
								 | 
							
											 *	  occurs when the global command is firing the `refresh` event.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 *	  **Note**: This function must return either {@link CKEDITOR#TRISTATE_DISABLED}
							 | 
						|||
| 
								 | 
							
											 *	  or {@link CKEDITOR#TRISTATE_OFF}.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 *	* The `exec` function modifies the DOM if possible. Just like
							 | 
						|||
| 
								 | 
							
											 *	  `refresh`, `exec` functions are executed in the order of priorities
							 | 
						|||
| 
								 | 
							
											 *	  while the generic command is executed. This function is not executed
							 | 
						|||
| 
								 | 
							
											 *	  if `refresh` for this job returned {@link CKEDITOR#TRISTATE_DISABLED}.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 *	  **Note**: This function must return a Boolean value, indicating whether it
							 | 
						|||
| 
								 | 
							
											 *	  was successful. If a job was successful, then no other jobs are being executed.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * Sample definition:
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 *		command.jobs = {
							 | 
						|||
| 
								 | 
							
											 *			// Priority = 20.
							 | 
						|||
| 
								 | 
							
											 *			'20': {
							 | 
						|||
| 
								 | 
							
											 *				refresh( editor, path ) {
							 | 
						|||
| 
								 | 
							
											 *					if ( condition )
							 | 
						|||
| 
								 | 
							
											 *						return CKEDITOR.TRISTATE_OFF;
							 | 
						|||
| 
								 | 
							
											 *					else
							 | 
						|||
| 
								 | 
							
											 *						return CKEDITOR.TRISTATE_DISABLED;
							 | 
						|||
| 
								 | 
							
											 *				},
							 | 
						|||
| 
								 | 
							
											 *				exec( editor ) {
							 | 
						|||
| 
								 | 
							
											 *					// DOM modified! This was OK.
							 | 
						|||
| 
								 | 
							
											 *					return true;
							 | 
						|||
| 
								 | 
							
											 *				}
							 | 
						|||
| 
								 | 
							
											 *			},
							 | 
						|||
| 
								 | 
							
											 *			// Priority = 60. This job is done later.
							 | 
						|||
| 
								 | 
							
											 *			'60': {
							 | 
						|||
| 
								 | 
							
											 *				// Another job.
							 | 
						|||
| 
								 | 
							
											 *			}
							 | 
						|||
| 
								 | 
							
											 *		};
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * For additional information, please check comments for
							 | 
						|||
| 
								 | 
							
											 * the `setupGenericListeners` function.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * @readonly
							 | 
						|||
| 
								 | 
							
											 * @property {Object} [={}]
							 | 
						|||
| 
								 | 
							
											 */
							 | 
						|||
| 
								 | 
							
											this.jobs = {};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											/**
							 | 
						|||
| 
								 | 
							
											 * Determines whether the editor that the command belongs to has
							 | 
						|||
| 
								 | 
							
											 * {@link CKEDITOR.config#enterMode config.enterMode} set to {@link CKEDITOR#ENTER_BR}.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * @readonly
							 | 
						|||
| 
								 | 
							
											 * @see CKEDITOR.config#enterMode
							 | 
						|||
| 
								 | 
							
											 * @property {Boolean} [=false]
							 | 
						|||
| 
								 | 
							
											 */
							 | 
						|||
| 
								 | 
							
											this.enterBr = editor.config.enterMode == CKEDITOR.ENTER_BR;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											/**
							 | 
						|||
| 
								 | 
							
											 * Determines whether the command belongs to the indentation family.
							 | 
						|||
| 
								 | 
							
											 * Otherwise it is assumed to be an outdenting command.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * @readonly
							 | 
						|||
| 
								 | 
							
											 * @property {Boolean} [=false]
							 | 
						|||
| 
								 | 
							
											 */
							 | 
						|||
| 
								 | 
							
											this.isIndent = !!isIndent;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											/**
							 | 
						|||
| 
								 | 
							
											 * The name of the global command related to this one.
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * @readonly
							 | 
						|||
| 
								 | 
							
											 */
							 | 
						|||
| 
								 | 
							
											this.relatedGlobal = isIndent ? 'indent' : 'outdent';
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											/**
							 | 
						|||
| 
								 | 
							
											 * A keystroke associated with this command (*Tab* or *Shift+Tab*).
							 | 
						|||
| 
								 | 
							
											 *
							 | 
						|||
| 
								 | 
							
											 * @readonly
							 | 
						|||
| 
								 | 
							
											 */
							 | 
						|||
| 
								 | 
							
											this.indentKey = isIndent ? 9 : CKEDITOR.SHIFT + 9;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											/**
							 | 
						|||
| 
								 | 
							
											 * Stores created markers for the command so they can eventually be
							 | 
						|||
| 
								 | 
							
											 * purged after the `exec` function is run.
							 | 
						|||
| 
								 | 
							
											 */
							 | 
						|||
| 
								 | 
							
											this.database = {};
							 | 
						|||
| 
								 | 
							
										},
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										/**
							 | 
						|||
| 
								 | 
							
										 * Registers content-specific commands as a part of the indentation system
							 | 
						|||
| 
								 | 
							
										 * directed by generic commands. Once a command is registered,
							 | 
						|||
| 
								 | 
							
										 * it listens for events of a related generic command.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 *		CKEDITOR.plugins.indent.registerCommands( editor, {
							 | 
						|||
| 
								 | 
							
										 *			'indentlist': new indentListCommand( editor, 'indentlist' ),
							 | 
						|||
| 
								 | 
							
										 *			'outdentlist': new indentListCommand( editor, 'outdentlist' )
							 | 
						|||
| 
								 | 
							
										 *		} );
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * Content-specific commands listen for the generic command's `exec` and
							 | 
						|||
| 
								 | 
							
										 * try to execute their own jobs, one after another. If some execution is
							 | 
						|||
| 
								 | 
							
										 * successful, `evt.data.done` is set so no more jobs (commands) are involved.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * Content-specific commands also listen for the generic command's `refresh`
							 | 
						|||
| 
								 | 
							
										 * and fill the `evt.data.states` object with states of jobs. A generic command
							 | 
						|||
| 
								 | 
							
										 * uses this data to determine its own state and to update the UI.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * @member CKEDITOR.plugins.indent
							 | 
						|||
| 
								 | 
							
										 * @param {CKEDITOR.editor} editor The editor instance this command is
							 | 
						|||
| 
								 | 
							
										 * applied to.
							 | 
						|||
| 
								 | 
							
										 * @param {Object} commands An object of {@link CKEDITOR.command}.
							 | 
						|||
| 
								 | 
							
										 */
							 | 
						|||
| 
								 | 
							
										registerCommands: function( editor, commands ) {
							 | 
						|||
| 
								 | 
							
											editor.on( 'pluginsLoaded', function() {
							 | 
						|||
| 
								 | 
							
												for ( var name in commands ) {
							 | 
						|||
| 
								 | 
							
													( function( editor, command ) {
							 | 
						|||
| 
								 | 
							
														var relatedGlobal = editor.getCommand( command.relatedGlobal );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
														for ( var priority in command.jobs ) {
							 | 
						|||
| 
								 | 
							
															// Observe generic exec event and execute command when necessary.
							 | 
						|||
| 
								 | 
							
															// If the command was successfully handled by the command and
							 | 
						|||
| 
								 | 
							
															// DOM has been modified, stop event propagation so no other plugin
							 | 
						|||
| 
								 | 
							
															// will bother. Job is done.
							 | 
						|||
| 
								 | 
							
															relatedGlobal.on( 'exec', function( evt ) {
							 | 
						|||
| 
								 | 
							
																if ( evt.data.done )
							 | 
						|||
| 
								 | 
							
																	return;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
																// Make sure that anything this command will do is invisible
							 | 
						|||
| 
								 | 
							
																// for undoManager. What undoManager only can see and
							 | 
						|||
| 
								 | 
							
																// remember is the execution of the global command (relatedGlobal).
							 | 
						|||
| 
								 | 
							
																editor.fire( 'lockSnapshot' );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
																if ( command.execJob( editor, priority ) )
							 | 
						|||
| 
								 | 
							
																	evt.data.done = true;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
																editor.fire( 'unlockSnapshot' );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
																// Clean up the markers.
							 | 
						|||
| 
								 | 
							
																CKEDITOR.dom.element.clearAllMarkers( command.database );
							 | 
						|||
| 
								 | 
							
															}, this, null, priority );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
															// Observe generic refresh event and force command refresh.
							 | 
						|||
| 
								 | 
							
															// Once refreshed, save command state in event data
							 | 
						|||
| 
								 | 
							
															// so generic command plugin can update its own state and UI.
							 | 
						|||
| 
								 | 
							
															relatedGlobal.on( 'refresh', function( evt ) {
							 | 
						|||
| 
								 | 
							
																if ( !evt.data.states )
							 | 
						|||
| 
								 | 
							
																	evt.data.states = {};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
																evt.data.states[ command.name + '@' + priority ] =
							 | 
						|||
| 
								 | 
							
																	command.refreshJob( editor, priority, evt.data.path );
							 | 
						|||
| 
								 | 
							
															}, this, null, priority );
							 | 
						|||
| 
								 | 
							
														}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
														// Since specific indent commands have no UI elements,
							 | 
						|||
| 
								 | 
							
														// they need to be manually registered as a editor feature.
							 | 
						|||
| 
								 | 
							
														editor.addFeature( command );
							 | 
						|||
| 
								 | 
							
													} )( this, commands[ name ] );
							 | 
						|||
| 
								 | 
							
												}
							 | 
						|||
| 
								 | 
							
											} );
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									CKEDITOR.plugins.indent.genericDefinition.prototype = {
							 | 
						|||
| 
								 | 
							
										context: 'p',
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										exec: function() {}
							 | 
						|||
| 
								 | 
							
									};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									CKEDITOR.plugins.indent.specificDefinition.prototype = {
							 | 
						|||
| 
								 | 
							
										/**
							 | 
						|||
| 
								 | 
							
										 * Executes the content-specific procedure if the context is correct.
							 | 
						|||
| 
								 | 
							
										 * It calls the `exec` function of a job of the given `priority`
							 | 
						|||
| 
								 | 
							
										 * that modifies the DOM.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * @param {CKEDITOR.editor} editor The editor instance this command
							 | 
						|||
| 
								 | 
							
										 * will be applied to.
							 | 
						|||
| 
								 | 
							
										 * @param {Number} priority The priority of the job to be executed.
							 | 
						|||
| 
								 | 
							
										 * @returns {Boolean} Indicates whether the job was successful.
							 | 
						|||
| 
								 | 
							
										 */
							 | 
						|||
| 
								 | 
							
										execJob: function( editor, priority ) {
							 | 
						|||
| 
								 | 
							
											var job = this.jobs[ priority ];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											if ( job.state != TRISTATE_DISABLED )
							 | 
						|||
| 
								 | 
							
												return job.exec.call( this, editor );
							 | 
						|||
| 
								 | 
							
										},
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										/**
							 | 
						|||
| 
								 | 
							
										 * Calls the `refresh` function of a job of the given `priority`.
							 | 
						|||
| 
								 | 
							
										 * The function returns the state of the job which can be either
							 | 
						|||
| 
								 | 
							
										 * {@link CKEDITOR#TRISTATE_DISABLED} or {@link CKEDITOR#TRISTATE_OFF}.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * @param {CKEDITOR.editor} editor The editor instance this command
							 | 
						|||
| 
								 | 
							
										 * will be applied to.
							 | 
						|||
| 
								 | 
							
										 * @param {Number} priority The priority of the job to be executed.
							 | 
						|||
| 
								 | 
							
										 * @returns {Number} The state of the job.
							 | 
						|||
| 
								 | 
							
										 */
							 | 
						|||
| 
								 | 
							
										refreshJob: function( editor, priority, path ) {
							 | 
						|||
| 
								 | 
							
											var job = this.jobs[ priority ];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											if ( !editor.activeFilter.checkFeature( this ) )
							 | 
						|||
| 
								 | 
							
												job.state = TRISTATE_DISABLED;
							 | 
						|||
| 
								 | 
							
											else
							 | 
						|||
| 
								 | 
							
												job.state = job.refresh.call( this, editor, path );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											return job.state;
							 | 
						|||
| 
								 | 
							
										},
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										/**
							 | 
						|||
| 
								 | 
							
										 * Checks if the element path contains the element handled
							 | 
						|||
| 
								 | 
							
										 * by this indentation command.
							 | 
						|||
| 
								 | 
							
										 *
							 | 
						|||
| 
								 | 
							
										 * @param {CKEDITOR.dom.elementPath} node A path to be checked.
							 | 
						|||
| 
								 | 
							
										 * @returns {CKEDITOR.dom.element}
							 | 
						|||
| 
								 | 
							
										 */
							 | 
						|||
| 
								 | 
							
										getContext: function( path ) {
							 | 
						|||
| 
								 | 
							
											return path.contains( this.context );
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									/**
							 | 
						|||
| 
								 | 
							
									 * Attaches event listeners for this generic command. Since the indentation
							 | 
						|||
| 
								 | 
							
									 * system is event-oriented, generic commands communicate with
							 | 
						|||
| 
								 | 
							
									 * content-specific commands using the `exec` and `refresh` events.
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 * Listener priorities are crucial. Different indentation phases
							 | 
						|||
| 
								 | 
							
									 * are executed with different priorities.
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 * For the `exec` event:
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 *	* 0: Selection and bookmarks are saved by the generic command.
							 | 
						|||
| 
								 | 
							
									 *	* 1-99: Content-specific commands try to indent the code by executing
							 | 
						|||
| 
								 | 
							
									 *	  their own jobs ({@link CKEDITOR.plugins.indent.specificDefinition#jobs}).
							 | 
						|||
| 
								 | 
							
									 *	* 100: Bookmarks are re-selected by the generic command.
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 * The visual interpretation looks as follows:
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 *		  +------------------+
							 | 
						|||
| 
								 | 
							
									 *		  | Exec event fired |
							 | 
						|||
| 
								 | 
							
									 *		  +------ + ---------+
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		        0 -<----------+ Selection and bookmarks saved.
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		       25 -<---+ Exec 1st job of plugin#1 (return false, continuing...).
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		       50 -<---+ Exec 1st job of plugin#2 (return false, continuing...).
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		       75 -<---+ Exec 2nd job of plugin#1 (only if plugin#2 failed).
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		      100 -<-----------+ Re-select bookmarks, clean-up.
							 | 
						|||
| 
								 | 
							
									 *		          |
							 | 
						|||
| 
								 | 
							
									 *		+-------- v ----------+
							 | 
						|||
| 
								 | 
							
									 *		| Exec event finished |
							 | 
						|||
| 
								 | 
							
									 *		+---------------------+
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 * For the `refresh` event:
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 *	* <100: Content-specific commands refresh their job states according
							 | 
						|||
| 
								 | 
							
									 *	  to the given path. Jobs save their states in the `evt.data.states` object
							 | 
						|||
| 
								 | 
							
									 *	  passed along with the event. This can be either {@link CKEDITOR#TRISTATE_DISABLED}
							 | 
						|||
| 
								 | 
							
									 *	  or {@link CKEDITOR#TRISTATE_OFF}.
							 | 
						|||
| 
								 | 
							
									 *	* 100: Command state is determined according to what states
							 | 
						|||
| 
								 | 
							
									 *	  have been returned by content-specific jobs (`evt.data.states`).
							 | 
						|||
| 
								 | 
							
									 *	  UI elements are updated at this stage.
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 *	  **Note**: If there is at least one job with the {@link CKEDITOR#TRISTATE_OFF} state,
							 | 
						|||
| 
								 | 
							
									 *	  then the generic command state is also {@link CKEDITOR#TRISTATE_OFF}. Otherwise,
							 | 
						|||
| 
								 | 
							
									 *	  the command state is {@link CKEDITOR#TRISTATE_DISABLED}.
							 | 
						|||
| 
								 | 
							
									 *
							 | 
						|||
| 
								 | 
							
									 * @param {CKEDITOR.command} command The command to be set up.
							 | 
						|||
| 
								 | 
							
									 * @private
							 | 
						|||
| 
								 | 
							
									 */
							 | 
						|||
| 
								 | 
							
									function setupGenericListeners( editor, command ) {
							 | 
						|||
| 
								 | 
							
										var selection, bookmarks;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// Set the command state according to content-specific
							 | 
						|||
| 
								 | 
							
										// command states.
							 | 
						|||
| 
								 | 
							
										command.on( 'refresh', function( evt ) {
							 | 
						|||
| 
								 | 
							
											// If no state comes with event data, disable command.
							 | 
						|||
| 
								 | 
							
											var states = [ TRISTATE_DISABLED ];
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											for ( var s in evt.data.states )
							 | 
						|||
| 
								 | 
							
												states.push( evt.data.states[ s ] );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											this.setState( CKEDITOR.tools.search( states, TRISTATE_OFF ) ?
							 | 
						|||
| 
								 | 
							
													TRISTATE_OFF
							 | 
						|||
| 
								 | 
							
												:
							 | 
						|||
| 
								 | 
							
													TRISTATE_DISABLED );
							 | 
						|||
| 
								 | 
							
										}, command, null, 100 );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// Initialization. Save bookmarks and mark event as not handled
							 | 
						|||
| 
								 | 
							
										// by any plugin (command) yet.
							 | 
						|||
| 
								 | 
							
										command.on( 'exec', function( evt ) {
							 | 
						|||
| 
								 | 
							
											selection = editor.getSelection();
							 | 
						|||
| 
								 | 
							
											bookmarks = selection.createBookmarks( 1 );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											// Mark execution as not handled yet.
							 | 
						|||
| 
								 | 
							
											if ( !evt.data )
							 | 
						|||
| 
								 | 
							
												evt.data = {};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
											evt.data.done = false;
							 | 
						|||
| 
								 | 
							
										}, command, null, 0 );
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// Housekeeping. Make sure selectionChange will be called.
							 | 
						|||
| 
								 | 
							
										// Also re-select previously saved bookmarks.
							 | 
						|||
| 
								 | 
							
										command.on( 'exec', function( evt ) {
							 | 
						|||
| 
								 | 
							
											editor.forceNextSelectionCheck();
							 | 
						|||
| 
								 | 
							
											selection.selectBookmarks( bookmarks );
							 | 
						|||
| 
								 | 
							
										}, command, null, 100 );
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								} )();
							 |