2
* @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
3
* For licensing, see LICENSE.md or http://ckeditor.com/license
7
* @fileOverview Justify commands.
11
function getAlignment( element, useComputedState ) {
12
useComputedState = useComputedState === undefined || useComputedState;
15
if ( useComputedState )
16
align = element.getComputedStyle( 'text-align' );
18
while ( !element.hasAttribute || !( element.hasAttribute( 'align' ) || element.getStyle( 'text-align' ) ) ) {
19
var parent = element.getParent();
24
align = element.getStyle( 'text-align' ) || element.getAttribute( 'align' ) || '';
27
// Sometimes computed values doesn't tell.
28
align && ( align = align.replace( /(?:-(?:moz|webkit)-)?(?:start|auto)/i, '' ) );
30
!align && useComputedState && ( align = element.getComputedStyle( 'direction' ) == 'rtl' ? 'right' : 'left' );
35
function justifyCommand( editor, name, value ) {
41
var classes = editor.config.justifyClasses,
42
blockTag = editor.config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div';
47
this.cssClassName = classes[ 0 ];
50
this.cssClassName = classes[ 1 ];
53
this.cssClassName = classes[ 2 ];
56
this.cssClassName = classes[ 3 ];
60
this.cssClassRegex = new RegExp( '(?:^|\\s+)(?:' + classes.join( '|' ) + ')(?=$|\\s)' );
61
this.requiredContent = blockTag + '(' + this.cssClassName + ')';
64
this.requiredContent = blockTag + '{text-align}';
66
this.allowedContent = {
67
'caption div h1 h2 h3 h4 h5 h6 p pre td th li': {
68
// Do not add elements, but only text-align style if element is validated by other rule.
70
styles: this.cssClassName ? null : 'text-align',
71
classes: this.cssClassName || null
75
// In enter mode BR we need to allow here for div, because when non other
76
// feature allows div justify is the only plugin that uses it.
77
if ( editor.config.enterMode == CKEDITOR.ENTER_BR )
78
this.allowedContent.div = true;
81
function onDirChanged( e ) {
82
var editor = e.editor;
84
var range = editor.createRange();
85
range.setStartBefore( e.data.node );
86
range.setEndAfter( e.data.node );
88
var walker = new CKEDITOR.dom.walker( range ),
91
while ( ( node = walker.next() ) ) {
92
if ( node.type == CKEDITOR.NODE_ELEMENT ) {
93
// A child with the defined dir is to be ignored.
94
if ( !node.equals( e.data.node ) && node.getDirection() ) {
95
range.setStartAfter( node );
96
walker = new CKEDITOR.dom.walker( range );
100
// Switch the alignment.
101
var classes = editor.config.justifyClasses;
103
// The left align class.
104
if ( node.hasClass( classes[ 0 ] ) ) {
105
node.removeClass( classes[ 0 ] );
106
node.addClass( classes[ 2 ] );
108
// The right align class.
109
else if ( node.hasClass( classes[ 2 ] ) ) {
110
node.removeClass( classes[ 2 ] );
111
node.addClass( classes[ 0 ] );
115
// Always switch CSS margins.
116
var style = 'text-align';
117
var align = node.getStyle( style );
119
if ( align == 'left' )
120
node.setStyle( style, 'right' );
121
else if ( align == 'right' )
122
node.setStyle( style, 'left' );
127
justifyCommand.prototype = {
128
exec: function( editor ) {
129
var selection = editor.getSelection(),
130
enterMode = editor.config.enterMode;
135
var bookmarks = selection.createBookmarks(),
136
ranges = selection.getRanges();
138
var cssClassName = this.cssClassName,
141
var useComputedState = editor.config.useComputedState;
142
useComputedState = useComputedState === undefined || useComputedState;
144
for ( var i = ranges.length - 1; i >= 0; i-- ) {
145
iterator = ranges[ i ].createIterator();
146
iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;
148
while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) ) {
149
if ( block.isReadOnly() )
152
block.removeAttribute( 'align' );
153
block.removeStyle( 'text-align' );
155
// Remove any of the alignment classes from the className.
156
var className = cssClassName && ( block.$.className = CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) ) );
158
var apply = ( this.state == CKEDITOR.TRISTATE_OFF ) && ( !useComputedState || ( getAlignment( block, true ) != this.value ) );
160
if ( cssClassName ) {
161
// Append the desired class name.
163
block.addClass( cssClassName );
164
else if ( !className )
165
block.removeAttribute( 'class' );
167
block.setStyle( 'text-align', this.value );
173
editor.forceNextSelectionCheck();
174
selection.selectBookmarks( bookmarks );
177
refresh: function( editor, path ) {
178
var firstBlock = path.block || path.blockLimit;
180
this.setState( firstBlock.getName() != 'body' && getAlignment( firstBlock, this.editor.config.useComputedState ) == this.value ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
184
CKEDITOR.plugins.add( 'justify', {
185
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%
186
icons: 'justifyblock,justifycenter,justifyleft,justifyright', // %REMOVE_LINE_CORE%
187
hidpi: true, // %REMOVE_LINE_CORE%
188
init: function( editor ) {
189
if ( editor.blockless )
192
var left = new justifyCommand( editor, 'justifyleft', 'left' ),
193
center = new justifyCommand( editor, 'justifycenter', 'center' ),
194
right = new justifyCommand( editor, 'justifyright', 'right' ),
195
justify = new justifyCommand( editor, 'justifyblock', 'justify' );
197
editor.addCommand( 'justifyleft', left );
198
editor.addCommand( 'justifycenter', center );
199
editor.addCommand( 'justifyright', right );
200
editor.addCommand( 'justifyblock', justify );
202
if ( editor.ui.addButton ) {
203
editor.ui.addButton( 'JustifyLeft', {
204
label: editor.lang.justify.left,
205
command: 'justifyleft',
208
editor.ui.addButton( 'JustifyCenter', {
209
label: editor.lang.justify.center,
210
command: 'justifycenter',
213
editor.ui.addButton( 'JustifyRight', {
214
label: editor.lang.justify.right,
215
command: 'justifyright',
218
editor.ui.addButton( 'JustifyBlock', {
219
label: editor.lang.justify.block,
220
command: 'justifyblock',
225
editor.on( 'dirChanged', onDirChanged );
231
* List of classes to use for aligning the contents. If it's `null`, no classes will be used
232
* and instead the corresponding CSS values will be used.
234
* The array should contain 4 members, in the following order: left, center, right, justify.
236
* // Use the classes 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify'
237
* config.justifyClasses = [ 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify' ];
239
* @cfg {Array} [justifyClasses=null]
240
* @member CKEDITOR.config