/*\r
-Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.\r
For licensing, see LICENSE.html or http://ckeditor.com/license\r
*/\r
\r
\r
(function()\r
{\r
- var alignRemoveRegex = /(-moz-|-webkit-|start|auto)/i;\r
-\r
- function getState( editor, path )\r
+ function getAlignment( element, useComputedState )\r
{\r
- var firstBlock = path.block || path.blockLimit;\r
+ useComputedState = useComputedState === undefined || useComputedState;\r
+\r
+ var align;\r
+ if ( useComputedState )\r
+ align = element.getComputedStyle( 'text-align' );\r
+ else\r
+ {\r
+ while ( !element.hasAttribute || !( element.hasAttribute( 'align' ) || element.getStyle( 'text-align' ) ) )\r
+ {\r
+ var parent = element.getParent();\r
+ if ( !parent )\r
+ break;\r
+ element = parent;\r
+ }\r
+ align = element.getStyle( 'text-align' ) || element.getAttribute( 'align' ) || '';\r
+ }\r
+\r
+ // Sometimes computed values doesn't tell.\r
+ align && ( align = align.replace( /(?:-(?:moz|webkit)-)?(?:start|auto)/i, '' ) );\r
\r
- if ( !firstBlock || firstBlock.getName() == 'body' )\r
- return CKEDITOR.TRISTATE_OFF;\r
+ !align && useComputedState && ( align = element.getComputedStyle( 'direction' ) == 'rtl' ? 'right' : 'left' );\r
\r
- var currentAlign = firstBlock.getComputedStyle( 'text-align' ).replace( alignRemoveRegex, '' );\r
- if ( ( !currentAlign && this.isDefaultAlign ) || currentAlign == this.value )\r
- return CKEDITOR.TRISTATE_ON;\r
- return CKEDITOR.TRISTATE_OFF;\r
+ return align;\r
}\r
\r
function onSelectionChange( evt )\r
{\r
- var command = evt.editor.getCommand( this.name );\r
- command.state = getState.call( this, evt.editor, evt.data.path );\r
- command.fire( 'state' );\r
+ if ( evt.editor.readOnly )\r
+ return;\r
+\r
+ evt.editor.getCommand( this.name ).refresh( evt.data.path );\r
}\r
\r
function justifyCommand( editor, name, value )\r
{\r
+ this.editor = editor;\r
this.name = name;\r
this.value = value;\r
\r
- var contentDir = editor.config.contentsLangDirection;\r
- this.isDefaultAlign = ( value == 'left' && contentDir == 'ltr' ) ||\r
- ( value == 'right' && contentDir == 'rtl' );\r
-\r
var classes = editor.config.justifyClasses;\r
if ( classes )\r
{\r
}\r
}\r
\r
+ function onDirChanged( e )\r
+ {\r
+ var editor = e.editor;\r
+\r
+ var range = new CKEDITOR.dom.range( editor.document );\r
+ range.setStartBefore( e.data.node );\r
+ range.setEndAfter( e.data.node );\r
+\r
+ var walker = new CKEDITOR.dom.walker( range ),\r
+ node;\r
+\r
+ while ( ( node = walker.next() ) )\r
+ {\r
+ if ( node.type == CKEDITOR.NODE_ELEMENT )\r
+ {\r
+ // A child with the defined dir is to be ignored.\r
+ if ( !node.equals( e.data.node ) && node.getDirection() )\r
+ {\r
+ range.setStartAfter( node );\r
+ walker = new CKEDITOR.dom.walker( range );\r
+ continue;\r
+ }\r
+\r
+ // Switch the alignment.\r
+ var classes = editor.config.justifyClasses;\r
+ if ( classes )\r
+ {\r
+ // The left align class.\r
+ if ( node.hasClass( classes[ 0 ] ) )\r
+ {\r
+ node.removeClass( classes[ 0 ] );\r
+ node.addClass( classes[ 2 ] );\r
+ }\r
+ // The right align class.\r
+ else if ( node.hasClass( classes[ 2 ] ) )\r
+ {\r
+ node.removeClass( classes[ 2 ] );\r
+ node.addClass( classes[ 0 ] );\r
+ }\r
+ }\r
+\r
+ // Always switch CSS margins.\r
+ var style = 'text-align';\r
+ var align = node.getStyle( style );\r
+\r
+ if ( align == 'left' )\r
+ node.setStyle( style, 'right' );\r
+ else if ( align == 'right' )\r
+ node.setStyle( style, 'left' );\r
+ }\r
+ }\r
+ }\r
+\r
justifyCommand.prototype = {\r
exec : function( editor )\r
{\r
return;\r
\r
var bookmarks = selection.createBookmarks(),\r
- ranges = selection.getRanges();\r
-\r
+ ranges = selection.getRanges( true );\r
\r
var cssClassName = this.cssClassName,\r
iterator,\r
block;\r
+\r
+ var useComputedState = editor.config.useComputedState;\r
+ useComputedState = useComputedState === undefined || useComputedState;\r
+\r
for ( var i = ranges.length - 1 ; i >= 0 ; i-- )\r
{\r
iterator = ranges[ i ].createIterator();\r
iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;\r
\r
- while ( ( block = iterator.getNextParagraph() ) )\r
+ while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) )\r
{\r
block.removeAttribute( 'align' );\r
+ block.removeStyle( 'text-align' );\r
+\r
+ // Remove any of the alignment classes from the className.\r
+ var className = cssClassName && ( block.$.className =\r
+ CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) ) );\r
+\r
+ var apply =\r
+ ( this.state == CKEDITOR.TRISTATE_OFF ) &&\r
+ ( !useComputedState || ( getAlignment( block, true ) != this.value ) );\r
\r
if ( cssClassName )\r
{\r
- // Remove any of the alignment classes from the className.\r
- var className = block.$.className =\r
- CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) );\r
-\r
// Append the desired class name.\r
- if ( this.state == CKEDITOR.TRISTATE_OFF && !this.isDefaultAlign )\r
+ if ( apply )\r
block.addClass( cssClassName );\r
else if ( !className )\r
block.removeAttribute( 'class' );\r
}\r
- else\r
- {\r
- if ( this.state == CKEDITOR.TRISTATE_OFF && !this.isDefaultAlign )\r
- block.setStyle( 'text-align', this.value );\r
- else\r
- block.removeStyle( 'text-align' );\r
- }\r
+ else if ( apply )\r
+ block.setStyle( 'text-align', this.value );\r
}\r
\r
}\r
editor.focus();\r
editor.forceNextSelectionCheck();\r
selection.selectBookmarks( bookmarks );\r
+ },\r
+\r
+ refresh : function( path )\r
+ {\r
+ var firstBlock = path.block || path.blockLimit;\r
+\r
+ this.setState( firstBlock.getName() != 'body' &&\r
+ getAlignment( firstBlock, this.editor.config.useComputedState ) == this.value ?\r
+ CKEDITOR.TRISTATE_ON :\r
+ CKEDITOR.TRISTATE_OFF );\r
}\r
};\r
\r
editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, right ) );\r
editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, center ) );\r
editor.on( 'selectionChange', CKEDITOR.tools.bind( onSelectionChange, justify ) );\r
+ editor.on( 'dirChanged', onDirChanged );\r
},\r
\r
requires : [ 'domiterator' ]\r
});\r
})();\r
\r
-CKEDITOR.tools.extend( CKEDITOR.config,\r
- {\r
- justifyClasses : null\r
- } );\r
+ /**\r
+ * List of classes to use for aligning the contents. If it's null, no classes will be used\r
+ * and instead the corresponding CSS values will be used. The array should contain 4 members, in the following order: left, center, right, justify.\r
+ * @name CKEDITOR.config.justifyClasses\r
+ * @type Array\r
+ * @default null\r
+ * @example\r
+ * // Use the classes 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify'\r
+ * config.justifyClasses = [ 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify' ];\r
+ */\r