]> git.immae.eu Git - perso/Immae/Projets/packagist/ludivine-ckeditor-component.git/blame - sources/plugins/justify/plugin.js
Update to 4.7.3
[perso/Immae/Projets/packagist/ludivine-ckeditor-component.git] / sources / plugins / justify / plugin.js
CommitLineData
c63493c8
IB
1/**\r
2 * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.\r
3 * For licensing, see LICENSE.md or http://ckeditor.com/license\r
4 */\r
5\r
6/**\r
7 * @fileOverview Justify commands.\r
8 */\r
9\r
10( function() {\r
11 function getAlignment( element, useComputedState ) {\r
12 useComputedState = useComputedState === undefined || useComputedState;\r
13\r
14 var align;\r
15 if ( useComputedState )\r
16 align = element.getComputedStyle( 'text-align' );\r
17 else {\r
18 while ( !element.hasAttribute || !( element.hasAttribute( 'align' ) || element.getStyle( 'text-align' ) ) ) {\r
19 var parent = element.getParent();\r
20 if ( !parent )\r
21 break;\r
22 element = parent;\r
23 }\r
24 align = element.getStyle( 'text-align' ) || element.getAttribute( 'align' ) || '';\r
25 }\r
26\r
27 // Sometimes computed values doesn't tell.\r
28 align && ( align = align.replace( /(?:-(?:moz|webkit)-)?(?:start|auto)/i, '' ) );\r
29\r
30 !align && useComputedState && ( align = element.getComputedStyle( 'direction' ) == 'rtl' ? 'right' : 'left' );\r
31\r
32 return align;\r
33 }\r
34\r
35 function justifyCommand( editor, name, value ) {\r
36 this.editor = editor;\r
37 this.name = name;\r
38 this.value = value;\r
39 this.context = 'p';\r
c63493c8
IB
40 var classes = editor.config.justifyClasses,\r
41 blockTag = editor.config.enterMode == CKEDITOR.ENTER_P ? 'p' : 'div';\r
42\r
43 if ( classes ) {\r
44 switch ( value ) {\r
45 case 'left':\r
46 this.cssClassName = classes[ 0 ];\r
47 break;\r
48 case 'center':\r
49 this.cssClassName = classes[ 1 ];\r
50 break;\r
51 case 'right':\r
52 this.cssClassName = classes[ 2 ];\r
53 break;\r
54 case 'justify':\r
55 this.cssClassName = classes[ 3 ];\r
56 break;\r
57 }\r
58\r
59 this.cssClassRegex = new RegExp( '(?:^|\\s+)(?:' + classes.join( '|' ) + ')(?=$|\\s)' );\r
60 this.requiredContent = blockTag + '(' + this.cssClassName + ')';\r
61 }\r
62 else {\r
63 this.requiredContent = blockTag + '{text-align}';\r
64 }\r
65\r
66 this.allowedContent = {\r
67 'caption div h1 h2 h3 h4 h5 h6 p pre td th li': {\r
68 // Do not add elements, but only text-align style if element is validated by other rule.\r
69 propertiesOnly: true,\r
70 styles: this.cssClassName ? null : 'text-align',\r
71 classes: this.cssClassName || null\r
72 }\r
73 };\r
74\r
75 // In enter mode BR we need to allow here for div, because when non other\r
76 // feature allows div justify is the only plugin that uses it.\r
77 if ( editor.config.enterMode == CKEDITOR.ENTER_BR )\r
78 this.allowedContent.div = true;\r
79 }\r
80\r
81 function onDirChanged( e ) {\r
82 var editor = e.editor;\r
83\r
84 var range = editor.createRange();\r
85 range.setStartBefore( e.data.node );\r
86 range.setEndAfter( e.data.node );\r
87\r
88 var walker = new CKEDITOR.dom.walker( range ),\r
89 node;\r
90\r
91 while ( ( node = walker.next() ) ) {\r
92 if ( node.type == CKEDITOR.NODE_ELEMENT ) {\r
93 // A child with the defined dir is to be ignored.\r
94 if ( !node.equals( e.data.node ) && node.getDirection() ) {\r
95 range.setStartAfter( node );\r
96 walker = new CKEDITOR.dom.walker( range );\r
97 continue;\r
98 }\r
99\r
100 // Switch the alignment.\r
101 var classes = editor.config.justifyClasses;\r
102 if ( classes ) {\r
103 // The left align class.\r
104 if ( node.hasClass( classes[ 0 ] ) ) {\r
105 node.removeClass( classes[ 0 ] );\r
106 node.addClass( classes[ 2 ] );\r
107 }\r
108 // The right align class.\r
109 else if ( node.hasClass( classes[ 2 ] ) ) {\r
110 node.removeClass( classes[ 2 ] );\r
111 node.addClass( classes[ 0 ] );\r
112 }\r
113 }\r
114\r
115 // Always switch CSS margins.\r
116 var style = 'text-align';\r
117 var align = node.getStyle( style );\r
118\r
119 if ( align == 'left' )\r
120 node.setStyle( style, 'right' );\r
121 else if ( align == 'right' )\r
122 node.setStyle( style, 'left' );\r
123 }\r
124 }\r
125 }\r
126\r
127 justifyCommand.prototype = {\r
128 exec: function( editor ) {\r
129 var selection = editor.getSelection(),\r
130 enterMode = editor.config.enterMode;\r
131\r
132 if ( !selection )\r
133 return;\r
134\r
135 var bookmarks = selection.createBookmarks(),\r
136 ranges = selection.getRanges();\r
137\r
138 var cssClassName = this.cssClassName,\r
139 iterator, block;\r
140\r
141 var useComputedState = editor.config.useComputedState;\r
142 useComputedState = useComputedState === undefined || useComputedState;\r
143\r
144 for ( var i = ranges.length - 1; i >= 0; i-- ) {\r
145 iterator = ranges[ i ].createIterator();\r
146 iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR;\r
147\r
148 while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) ) {\r
149 if ( block.isReadOnly() )\r
150 continue;\r
151\r
1794320d
IB
152 // Check if style or class might be applied to currently processed element (#455).\r
153 var tag = block.getName(),\r
154 isAllowedTextAlign, isAllowedCssClass;\r
155\r
156 isAllowedTextAlign = editor.activeFilter.check( tag + '{text-align}' );\r
157 isAllowedCssClass = editor.activeFilter.check( tag + '(' + cssClassName + ')' );\r
158\r
159 if ( !isAllowedCssClass && !isAllowedTextAlign ) {\r
160 continue;\r
161 }\r
162\r
c63493c8
IB
163 block.removeAttribute( 'align' );\r
164 block.removeStyle( 'text-align' );\r
165\r
166 // Remove any of the alignment classes from the className.\r
167 var className = cssClassName && ( block.$.className = CKEDITOR.tools.ltrim( block.$.className.replace( this.cssClassRegex, '' ) ) );\r
168\r
169 var apply = ( this.state == CKEDITOR.TRISTATE_OFF ) && ( !useComputedState || ( getAlignment( block, true ) != this.value ) );\r
170\r
1794320d 171 if ( cssClassName && isAllowedCssClass ) {\r
c63493c8
IB
172 // Append the desired class name.\r
173 if ( apply )\r
174 block.addClass( cssClassName );\r
175 else if ( !className )\r
176 block.removeAttribute( 'class' );\r
1794320d 177 } else if ( apply && isAllowedTextAlign ) {\r
c63493c8
IB
178 block.setStyle( 'text-align', this.value );\r
179 }\r
180 }\r
181\r
182 }\r
183\r
184 editor.focus();\r
185 editor.forceNextSelectionCheck();\r
186 selection.selectBookmarks( bookmarks );\r
187 },\r
188\r
189 refresh: function( editor, path ) {\r
1794320d
IB
190 var firstBlock = path.block || path.blockLimit,\r
191 name = firstBlock.getName(),\r
192 isEditable = firstBlock.equals( editor.editable() ),\r
193 isStylable = this.cssClassName ? editor.activeFilter.check( name + '(' + this.cssClassName + ')' ) :\r
194 editor.activeFilter.check( name + '{text-align}' );\r
195\r
196 // #455\r
197 // 1. Check if we are directly in editbale. Justification should be always allowed, and not highlighted.\r
198 // Checking path.elements.length is required to filter out situation `body > ul` where ul is selected and path.blockLimit returns editable.\r
199 // 2. Check if current element can have applied specific class.\r
200 // 3. Check if current element can have applied text-align style.\r
201 if ( isEditable && path.elements.length === 1 ) {\r
202 this.setState( CKEDITOR.TRISTATE_OFF );\r
203 } else if ( !isEditable && isStylable ) {\r
204 // 2 & 3 in one condition.\r
205 this.setState( getAlignment( firstBlock, this.editor.config.useComputedState ) == this.value ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );\r
206 } else {\r
207 this.setState( CKEDITOR.TRISTATE_DISABLED );\r
208 }\r
c63493c8
IB
209 }\r
210 };\r
211\r
212 CKEDITOR.plugins.add( 'justify', {\r
213 // jscs:disable maximumLineLength\r
1794320d 214 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%\r
c63493c8
IB
215 // jscs:enable maximumLineLength\r
216 icons: 'justifyblock,justifycenter,justifyleft,justifyright', // %REMOVE_LINE_CORE%\r
217 hidpi: true, // %REMOVE_LINE_CORE%\r
218 init: function( editor ) {\r
219 if ( editor.blockless )\r
220 return;\r
221\r
222 var left = new justifyCommand( editor, 'justifyleft', 'left' ),\r
223 center = new justifyCommand( editor, 'justifycenter', 'center' ),\r
224 right = new justifyCommand( editor, 'justifyright', 'right' ),\r
225 justify = new justifyCommand( editor, 'justifyblock', 'justify' );\r
226\r
227 editor.addCommand( 'justifyleft', left );\r
228 editor.addCommand( 'justifycenter', center );\r
229 editor.addCommand( 'justifyright', right );\r
230 editor.addCommand( 'justifyblock', justify );\r
231\r
232 if ( editor.ui.addButton ) {\r
233 editor.ui.addButton( 'JustifyLeft', {\r
234 label: editor.lang.justify.left,\r
235 command: 'justifyleft',\r
236 toolbar: 'align,10'\r
237 } );\r
238 editor.ui.addButton( 'JustifyCenter', {\r
239 label: editor.lang.justify.center,\r
240 command: 'justifycenter',\r
241 toolbar: 'align,20'\r
242 } );\r
243 editor.ui.addButton( 'JustifyRight', {\r
244 label: editor.lang.justify.right,\r
245 command: 'justifyright',\r
246 toolbar: 'align,30'\r
247 } );\r
248 editor.ui.addButton( 'JustifyBlock', {\r
249 label: editor.lang.justify.block,\r
250 command: 'justifyblock',\r
251 toolbar: 'align,40'\r
252 } );\r
253 }\r
c63493c8
IB
254 editor.on( 'dirChanged', onDirChanged );\r
255 }\r
256 } );\r
257} )();\r
258\r
259/**\r
260 * List of classes to use for aligning the contents. If it's `null`, no classes will be used\r
261 * and instead the corresponding CSS values will be used.\r
262 *\r
263 * The array should contain 4 members, in the following order: left, center, right, justify.\r
264 *\r
265 * // Use the classes 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify'\r
266 * config.justifyClasses = [ 'AlignLeft', 'AlignCenter', 'AlignRight', 'AlignJustify' ];\r
267 *\r
268 * @cfg {Array} [justifyClasses=null]\r
269 * @member CKEDITOR.config\r
270 */\r