diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2016-02-19 23:38:52 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2016-02-19 23:38:52 +0100 |
commit | 3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5 (patch) | |
tree | a4f77655fe55b79606e7d3416504686a1ab8b058 /sources/plugins/indentblock | |
download | piedsjaloux-ckeditor-component-3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5.tar.gz piedsjaloux-ckeditor-component-3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5.tar.zst piedsjaloux-ckeditor-component-3332bebe4da6dfa0fe3e4b2abddc84b1cc62f8f5.zip |
Initial commit4.5.7
Diffstat (limited to 'sources/plugins/indentblock')
-rw-r--r-- | sources/plugins/indentblock/plugin.js | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/sources/plugins/indentblock/plugin.js b/sources/plugins/indentblock/plugin.js new file mode 100644 index 0000000..9d31b98 --- /dev/null +++ b/sources/plugins/indentblock/plugin.js | |||
@@ -0,0 +1,298 @@ | |||
1 | /** | ||
2 | * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. | ||
3 | * For licensing, see LICENSE.md or http://ckeditor.com/license | ||
4 | */ | ||
5 | |||
6 | /** | ||
7 | * @fileOverview Handles the indentation of block elements. | ||
8 | */ | ||
9 | |||
10 | ( function() { | ||
11 | 'use strict'; | ||
12 | |||
13 | var $listItem = CKEDITOR.dtd.$listItem, | ||
14 | $list = CKEDITOR.dtd.$list, | ||
15 | TRISTATE_DISABLED = CKEDITOR.TRISTATE_DISABLED, | ||
16 | TRISTATE_OFF = CKEDITOR.TRISTATE_OFF; | ||
17 | |||
18 | CKEDITOR.plugins.add( 'indentblock', { | ||
19 | requires: 'indent', | ||
20 | init: function( editor ) { | ||
21 | var globalHelpers = CKEDITOR.plugins.indent, | ||
22 | classes = editor.config.indentClasses; | ||
23 | |||
24 | // Register commands. | ||
25 | globalHelpers.registerCommands( editor, { | ||
26 | indentblock: new commandDefinition( editor, 'indentblock', true ), | ||
27 | outdentblock: new commandDefinition( editor, 'outdentblock' ) | ||
28 | } ); | ||
29 | |||
30 | function commandDefinition() { | ||
31 | globalHelpers.specificDefinition.apply( this, arguments ); | ||
32 | |||
33 | this.allowedContent = { | ||
34 | 'div h1 h2 h3 h4 h5 h6 ol p pre ul': { | ||
35 | // Do not add elements, but only text-align style if element is validated by other rule. | ||
36 | propertiesOnly: true, | ||
37 | styles: !classes ? 'margin-left,margin-right' : null, | ||
38 | classes: classes || null | ||
39 | } | ||
40 | }; | ||
41 | |||
42 | if ( this.enterBr ) | ||
43 | this.allowedContent.div = true; | ||
44 | |||
45 | this.requiredContent = ( this.enterBr ? 'div' : 'p' ) + | ||
46 | ( classes ? '(' + classes.join( ',' ) + ')' : '{margin-left}' ); | ||
47 | |||
48 | this.jobs = { | ||
49 | '20': { | ||
50 | refresh: function( editor, path ) { | ||
51 | var firstBlock = path.block || path.blockLimit; | ||
52 | |||
53 | // Switch context from somewhere inside list item to list item, | ||
54 | // if not found just assign self (doing nothing). | ||
55 | if ( !firstBlock.is( $listItem ) ) { | ||
56 | var ascendant = firstBlock.getAscendant( $listItem ); | ||
57 | |||
58 | firstBlock = ( ascendant && path.contains( ascendant ) ) || firstBlock; | ||
59 | } | ||
60 | |||
61 | // Switch context from list item to list | ||
62 | // because indentblock can indent entire list | ||
63 | // but not a single list element. | ||
64 | |||
65 | if ( firstBlock.is( $listItem ) ) | ||
66 | firstBlock = firstBlock.getParent(); | ||
67 | |||
68 | // [-] Context in the path or ENTER_BR | ||
69 | // | ||
70 | // Don't try to indent if the element is out of | ||
71 | // this plugin's scope. This assertion is omitted | ||
72 | // if ENTER_BR is in use since there may be no block | ||
73 | // in the path. | ||
74 | |||
75 | if ( !this.enterBr && !this.getContext( path ) ) | ||
76 | return TRISTATE_DISABLED; | ||
77 | |||
78 | else if ( classes ) { | ||
79 | |||
80 | // [+] Context in the path or ENTER_BR | ||
81 | // [+] IndentClasses | ||
82 | // | ||
83 | // If there are indentation classes, check if reached | ||
84 | // the highest level of indentation. If so, disable | ||
85 | // the command. | ||
86 | |||
87 | if ( indentClassLeft.call( this, firstBlock, classes ) ) | ||
88 | return TRISTATE_OFF; | ||
89 | else | ||
90 | return TRISTATE_DISABLED; | ||
91 | } else { | ||
92 | |||
93 | // [+] Context in the path or ENTER_BR | ||
94 | // [-] IndentClasses | ||
95 | // [+] Indenting | ||
96 | // | ||
97 | // No indent-level limitations due to indent classes. | ||
98 | // Indent-like command can always be executed. | ||
99 | |||
100 | if ( this.isIndent ) | ||
101 | return TRISTATE_OFF; | ||
102 | |||
103 | // [+] Context in the path or ENTER_BR | ||
104 | // [-] IndentClasses | ||
105 | // [-] Indenting | ||
106 | // [-] Block in the path | ||
107 | // | ||
108 | // No block in path. There's no element to apply indentation | ||
109 | // so disable the command. | ||
110 | |||
111 | else if ( !firstBlock ) | ||
112 | return TRISTATE_DISABLED; | ||
113 | |||
114 | // [+] Context in the path or ENTER_BR | ||
115 | // [-] IndentClasses | ||
116 | // [-] Indenting | ||
117 | // [+] Block in path. | ||
118 | // | ||
119 | // Not using indentClasses but there is firstBlock. | ||
120 | // We can calculate current indentation level and | ||
121 | // try to increase/decrease it. | ||
122 | |||
123 | else { | ||
124 | return CKEDITOR[ | ||
125 | ( getIndent( firstBlock ) || 0 ) <= 0 ? 'TRISTATE_DISABLED' : 'TRISTATE_OFF' | ||
126 | ]; | ||
127 | } | ||
128 | } | ||
129 | }, | ||
130 | |||
131 | exec: function( editor ) { | ||
132 | var selection = editor.getSelection(), | ||
133 | range = selection && selection.getRanges()[ 0 ], | ||
134 | nearestListBlock; | ||
135 | |||
136 | // If there's some list in the path, then it will be | ||
137 | // a full-list indent by increasing or decreasing margin property. | ||
138 | if ( ( nearestListBlock = editor.elementPath().contains( $list ) ) ) | ||
139 | indentElement.call( this, nearestListBlock, classes ); | ||
140 | |||
141 | // If no list in the path, use iterator to indent all the possible | ||
142 | // paragraphs in the range, creating them if necessary. | ||
143 | else { | ||
144 | var iterator = range.createIterator(), | ||
145 | enterMode = editor.config.enterMode, | ||
146 | block; | ||
147 | |||
148 | iterator.enforceRealBlocks = true; | ||
149 | iterator.enlargeBr = enterMode != CKEDITOR.ENTER_BR; | ||
150 | |||
151 | while ( ( block = iterator.getNextParagraph( enterMode == CKEDITOR.ENTER_P ? 'p' : 'div' ) ) ) { | ||
152 | if ( !block.isReadOnly() ) | ||
153 | indentElement.call( this, block, classes ); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | return true; | ||
158 | } | ||
159 | } | ||
160 | }; | ||
161 | } | ||
162 | |||
163 | CKEDITOR.tools.extend( commandDefinition.prototype, globalHelpers.specificDefinition.prototype, { | ||
164 | // Elements that, if in an elementpath, will be handled by this | ||
165 | // command. They restrict the scope of the plugin. | ||
166 | context: { div: 1, dl: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, ul: 1, ol: 1, p: 1, pre: 1, table: 1 }, | ||
167 | |||
168 | // A regex built on config#indentClasses to detect whether an | ||
169 | // element has some indentClass or not. | ||
170 | classNameRegex: classes ? new RegExp( '(?:^|\\s+)(' + classes.join( '|' ) + ')(?=$|\\s)' ) : null | ||
171 | } ); | ||
172 | } | ||
173 | } ); | ||
174 | |||
175 | // Generic indentation procedure for indentation of any element | ||
176 | // either with margin property or config#indentClass. | ||
177 | function indentElement( element, classes, dir ) { | ||
178 | if ( element.getCustomData( 'indent_processed' ) ) | ||
179 | return; | ||
180 | |||
181 | var editor = this.editor, | ||
182 | isIndent = this.isIndent; | ||
183 | |||
184 | if ( classes ) { | ||
185 | // Transform current class f to indent step index. | ||
186 | var indentClass = element.$.className.match( this.classNameRegex ), | ||
187 | indentStep = 0; | ||
188 | |||
189 | if ( indentClass ) { | ||
190 | indentClass = indentClass[ 1 ]; | ||
191 | indentStep = CKEDITOR.tools.indexOf( classes, indentClass ) + 1; | ||
192 | } | ||
193 | |||
194 | // Operate on indent step index, transform indent step index | ||
195 | // back to class name. | ||
196 | if ( ( indentStep += isIndent ? 1 : -1 ) < 0 ) | ||
197 | return; | ||
198 | |||
199 | indentStep = Math.min( indentStep, classes.length ); | ||
200 | indentStep = Math.max( indentStep, 0 ); | ||
201 | element.$.className = CKEDITOR.tools.ltrim( element.$.className.replace( this.classNameRegex, '' ) ); | ||
202 | |||
203 | if ( indentStep > 0 ) | ||
204 | element.addClass( classes[ indentStep - 1 ] ); | ||
205 | } else { | ||
206 | var indentCssProperty = getIndentCss( element, dir ), | ||
207 | currentOffset = parseInt( element.getStyle( indentCssProperty ), 10 ), | ||
208 | indentOffset = editor.config.indentOffset || 40; | ||
209 | |||
210 | if ( isNaN( currentOffset ) ) | ||
211 | currentOffset = 0; | ||
212 | |||
213 | currentOffset += ( isIndent ? 1 : -1 ) * indentOffset; | ||
214 | |||
215 | if ( currentOffset < 0 ) | ||
216 | return; | ||
217 | |||
218 | currentOffset = Math.max( currentOffset, 0 ); | ||
219 | currentOffset = Math.ceil( currentOffset / indentOffset ) * indentOffset; | ||
220 | |||
221 | element.setStyle( | ||
222 | indentCssProperty, | ||
223 | currentOffset ? currentOffset + ( editor.config.indentUnit || 'px' ) : '' | ||
224 | ); | ||
225 | |||
226 | if ( element.getAttribute( 'style' ) === '' ) | ||
227 | element.removeAttribute( 'style' ); | ||
228 | } | ||
229 | |||
230 | CKEDITOR.dom.element.setMarker( this.database, element, 'indent_processed', 1 ); | ||
231 | |||
232 | return; | ||
233 | } | ||
234 | |||
235 | // Method that checks if current indentation level for an element | ||
236 | // reached the limit determined by config#indentClasses. | ||
237 | function indentClassLeft( node, classes ) { | ||
238 | var indentClass = node.$.className.match( this.classNameRegex ), | ||
239 | isIndent = this.isIndent; | ||
240 | |||
241 | // If node has one of the indentClasses: | ||
242 | // * If it holds the topmost indentClass, then | ||
243 | // no more classes have left. | ||
244 | // * If it holds any other indentClass, it can use the next one | ||
245 | // or the previous one. | ||
246 | // * Outdent is always possible. We can remove indentClass. | ||
247 | if ( indentClass ) | ||
248 | return isIndent ? indentClass[ 1 ] != classes.slice( -1 ) : true; | ||
249 | |||
250 | // If node has no class which belongs to indentClasses, | ||
251 | // then it is at 0-level. It can be indented but not outdented. | ||
252 | else | ||
253 | return isIndent; | ||
254 | } | ||
255 | |||
256 | // Determines indent CSS property for an element according to | ||
257 | // what is the direction of such element. It can be either `margin-left` | ||
258 | // or `margin-right`. | ||
259 | function getIndentCss( element, dir ) { | ||
260 | return ( dir || element.getComputedStyle( 'direction' ) ) == 'ltr' ? 'margin-left' : 'margin-right'; | ||
261 | } | ||
262 | |||
263 | // Return the numerical indent value of margin-left|right of an element, | ||
264 | // considering element's direction. If element has no margin specified, | ||
265 | // NaN is returned. | ||
266 | function getIndent( element ) { | ||
267 | return parseInt( element.getStyle( getIndentCss( element ) ), 10 ); | ||
268 | } | ||
269 | } )(); | ||
270 | |||
271 | /** | ||
272 | * A list of classes to use for indenting the contents. If set to `null`, no classes will be used | ||
273 | * and instead the {@link #indentUnit} and {@link #indentOffset} properties will be used. | ||
274 | * | ||
275 | * // Use the 'Indent1', 'Indent2', 'Indent3' classes. | ||
276 | * config.indentClasses = ['Indent1', 'Indent2', 'Indent3']; | ||
277 | * | ||
278 | * @cfg {Array} [indentClasses=null] | ||
279 | * @member CKEDITOR.config | ||
280 | */ | ||
281 | |||
282 | /** | ||
283 | * The size in {@link CKEDITOR.config#indentUnit indentation units} of each indentation step. | ||
284 | * | ||
285 | * config.indentOffset = 4; | ||
286 | * | ||
287 | * @cfg {Number} [indentOffset=40] | ||
288 | * @member CKEDITOR.config | ||
289 | */ | ||
290 | |||
291 | /** | ||
292 | * The unit used for {@link CKEDITOR.config#indentOffset indentation offset}. | ||
293 | * | ||
294 | * config.indentUnit = 'em'; | ||
295 | * | ||
296 | * @cfg {String} [indentUnit='px'] | ||
297 | * @member CKEDITOR.config | ||
298 | */ | ||