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 /**
  7  * @file Justify commands.
  8  */
  9
 10 (function()
 11 {
 12 	var alignRemoveRegex = /(-moz-|-webkit-|start|auto)/i;
 13
 14 	function getState( editor, path )
 15 	{
 16 		var firstBlock = path.block || path.blockLimit;
 17
 18 		if ( !firstBlock || firstBlock.getName() == 'body' )
 19 			return CKEDITOR.TRISTATE_OFF;
 20
 21 		var currentAlign = firstBlock.getComputedStyle( 'text-align' ).replace( alignRemoveRegex, '' );
 22 		if ( ( !currentAlign && this.isDefaultAlign ) || currentAlign == this.value )
 23 			return CKEDITOR.TRISTATE_ON;
 24 		return CKEDITOR.TRISTATE_OFF;
 25 	}
 26
 27 	function onSelectionChange( evt )
 28 	{
 29 		var command = evt.editor.getCommand( this.name );
 30 		command.state = getState.call( this, evt.editor, evt.data.path );
 31 		command.fire( 'state' );
 32 	}
 33
 34 	function justifyCommand( editor, name, value )
 35 	{
 36 		this.name = name;
 37 		this.value = value;
 38
 39 		var contentDir = editor.config.contentsLangDirection;
 40 		this.isDefaultAlign = ( value == 'left' && contentDir == 'ltr' ) ||
 41 			( value == 'right' && contentDir == 'rtl' );
 42
 43 		var classes = editor.config.justifyClasses;
 44 		if ( classes )
 45 		{
 46 			switch ( value )
 47 			{
 48 				case 'left' :
 49 					this.cssClassName = classes[0];
 50 					break;
 51 				case 'center' :
 52 					this.cssClassName = classes[1];
 53 					break;
 54 				case 'right' :
 55 					this.cssClassName = classes[2];
 56 					break;
 57 				case 'justify' :
 58 					this.cssClassName = classes[3];
 59 					break;
 60 			}
 61
 62 			this.cssClassRegex = new RegExp( '(?:^|\\s+)(?:' + classes.join( '|' ) + ')(?=$|\\s)' );
 63 		}
 64 	}
 65
 66 	justifyCommand.prototype = {
 67 		exec : function( editor )
 68 		{
 69 			var selection = editor.getSelection();
 70 			if ( !selection )
 71 				return;
 72
 73 			var bookmarks = selection.createBookmarks(),
 74 				ranges = selection.getRanges();
 75
 76
 77 			var cssClassName = this.cssClassName,
 78 				iterator,
 79 				block;
 80 			for ( var i = ranges.length - 1 ; i >= 0 ; i-- )
 81 			{
 82 				iterator = ranges[ i ].createIterator();
 83 				while ( ( block = iterator.getNextParagraph() ) )
 84 				{
 85 					block.removeAttribute( 'align' );
 86
 87 					if ( cssClassName )
 88 					{
 89 						// Remove any of the alignment classes from the className.
 90 						var className = block.$.className =
 91 							CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) );
 92
 93 						// Append the desired class name.
 94 						if ( this.state == CKEDITOR.TRISTATE_OFF && !this.isDefaultAlign )
 95 							block.addClass( cssClassName );
 96 						else if ( !className )
 97 							block.removeAttribute( 'class' );
 98 					}
 99 					else
100 					{
101 						if ( this.state == CKEDITOR.TRISTATE_OFF && !this.isDefaultAlign )
102 							block.setStyle( 'text-align', this.value );
103 						else
104 							block.removeStyle( 'text-align' );
105 					}
106 				}
107
108 			}
109
110 			editor.focus();
111 			editor.forceNextSelectionCheck();
112 			selection.selectBookmarks( bookmarks );
113 		}
114 	};
115
116 	CKEDITOR.plugins.add( 'justify',
117 	{
118 		init : function( editor )
119 		{
120 			var left = new justifyCommand( editor, 'justifyleft', 'left' ),
121 				center = new justifyCommand( editor, 'justifycenter', 'center' ),
122 				right = new justifyCommand( editor, 'justifyright', 'right' ),
123 				justify = new justifyCommand( editor, 'justifyblock', 'justify' );
124
125 			editor.addCommand( 'justifyleft', left );
126 			editor.addCommand( 'justifycenter', center );
127 			editor.addCommand( 'justifyright', right );
128 			editor.addCommand( 'justifyblock', justify );
129
130 			editor.ui.addButton( 'JustifyLeft',
131 				{
132 					label : editor.lang.justify.left,
133 					command : 'justifyleft'
134 				} );
135 			editor.ui.addButton( 'JustifyCenter',
136 				{
137 					label : editor.lang.justify.center,
138 					command : 'justifycenter'
139 				} );
140 			editor.ui.addButton( 'JustifyRight',
141 				{
142 					label : editor.lang.justify.right,
143 					command : 'justifyright'
144 				} );
145 			editor.ui.addButton( 'JustifyBlock',
146 				{
147 					label : editor.lang.justify.block,
148 					command : 'justifyblock'
149 				} );
150
151 			editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, left ) );
152 			editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, right ) );
153 			editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, center ) );
154 			editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, justify ) );
155 		},
156
157 		requires : [ 'domiterator' ]
158 	});
159 })();
160
161 CKEDITOR.tools.extend( CKEDITOR.config,
162 	{
163 		justifyClasses : null
164 	} );
165