]>
git.immae.eu Git - perso/Immae/Projets/packagist/connexionswing-ckeditor-component.git/blob - sources/plugins/indentblock/plugin.js
102658016ea2cc3737542cb98ca42373e5d0c8bc
2 * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3 * For licensing, see LICENSE.md or http://ckeditor.com/license
7 * @fileOverview Handles the indentation of block elements.
13 var $listItem
= CKEDITOR
.dtd
.$listItem
,
14 $list
= CKEDITOR
.dtd
.$list
,
15 TRISTATE_DISABLED
= CKEDITOR
.TRISTATE_DISABLED
,
16 TRISTATE_OFF
= CKEDITOR
.TRISTATE_OFF
;
18 CKEDITOR
.plugins
.add( 'indentblock', {
20 init: function( editor
) {
21 var globalHelpers
= CKEDITOR
.plugins
.indent
,
22 classes
= editor
.config
.indentClasses
;
25 globalHelpers
.registerCommands( editor
, {
26 indentblock: new commandDefinition( editor
, 'indentblock', true ),
27 outdentblock: new commandDefinition( editor
, 'outdentblock' )
30 function commandDefinition() {
31 globalHelpers
.specificDefinition
.apply( this, arguments
);
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.
37 styles: !classes
? 'margin-left,margin-right' : null,
38 classes: classes
|| null
43 this.allowedContent
.div
= true;
45 this.requiredContent
= ( this.enterBr
? 'div' : 'p' ) +
46 ( classes
? '(' + classes
.join( ',' ) + ')' : '{margin-left}' );
50 refresh: function( editor
, path
) {
51 var firstBlock
= path
.block
|| path
.blockLimit
;
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
);
58 firstBlock
= ( ascendant
&& path
.contains( ascendant
) ) || firstBlock
;
61 // Switch context from list item to list
62 // because indentblock can indent entire list
63 // but not a single list element.
65 if ( firstBlock
.is( $listItem
) )
66 firstBlock
= firstBlock
.getParent();
68 // [-] Context in the path or ENTER_BR
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
75 if ( !this.enterBr
&& !this.getContext( path
) )
76 return TRISTATE_DISABLED
;
80 // [+] Context in the path or ENTER_BR
83 // If there are indentation classes, check if reached
84 // the highest level of indentation. If so, disable
87 if ( indentClassLeft
.call( this, firstBlock
, classes
) )
90 return TRISTATE_DISABLED
;
93 // [+] Context in the path or ENTER_BR
97 // No indent-level limitations due to indent classes.
98 // Indent-like command can always be executed.
103 // [+] Context in the path or ENTER_BR
106 // [-] Block in the path
108 // No block in path. There's no element to apply indentation
109 // so disable the command.
111 else if ( !firstBlock
)
112 return TRISTATE_DISABLED
;
114 // [+] Context in the path or ENTER_BR
117 // [+] Block in path.
119 // Not using indentClasses but there is firstBlock.
120 // We can calculate current indentation level and
121 // try to increase/decrease it.
125 ( getIndent( firstBlock
) || 0 ) <= 0 ? 'TRISTATE_DISABLED' : 'TRISTATE_OFF'
131 exec: function( editor
) {
132 var selection
= editor
.getSelection(),
133 range
= selection
&& selection
.getRanges()[ 0 ],
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
);
141 // If no list in the path, use iterator to indent all the possible
142 // paragraphs in the range, creating them if necessary.
144 var iterator
= range
.createIterator(),
145 enterMode
= editor
.config
.enterMode
,
148 iterator
.enforceRealBlocks
= true;
149 iterator
.enlargeBr
= enterMode
!= CKEDITOR
.ENTER_BR
;
151 while ( ( block
= iterator
.getNextParagraph( enterMode
== CKEDITOR
.ENTER_P
? 'p' : 'div' ) ) ) {
152 if ( !block
.isReadOnly() )
153 indentElement
.call( this, block
, classes
);
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 },
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
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' ) )
181 var editor
= this.editor
,
182 isIndent
= this.isIndent
;
185 // Transform current class f to indent step index.
186 var indentClass
= element
.$.className
.match( this.classNameRegex
),
190 indentClass
= indentClass
[ 1 ];
191 indentStep
= CKEDITOR
.tools
.indexOf( classes
, indentClass
) + 1;
194 // Operate on indent step index, transform indent step index
195 // back to class name.
196 if ( ( indentStep
+= isIndent
? 1 : -1 ) < 0 )
199 indentStep
= Math
.min( indentStep
, classes
.length
);
200 indentStep
= Math
.max( indentStep
, 0 );
201 element
.$.className
= CKEDITOR
.tools
.ltrim( element
.$.className
.replace( this.classNameRegex
, '' ) );
203 if ( indentStep
> 0 )
204 element
.addClass( classes
[ indentStep
- 1 ] );
206 var indentCssProperty
= getIndentCss( element
, dir
),
207 currentOffset
= parseInt( element
.getStyle( indentCssProperty
), 10 ),
208 indentOffset
= editor
.config
.indentOffset
|| 40;
210 if ( isNaN( currentOffset
) )
213 currentOffset
+= ( isIndent
? 1 : -1 ) * indentOffset
;
215 if ( currentOffset
< 0 )
218 currentOffset
= Math
.max( currentOffset
, 0 );
219 currentOffset
= Math
.ceil( currentOffset
/ indentOffset
) * indentOffset
;
223 currentOffset
? currentOffset
+ ( editor
.config
.indentUnit
|| 'px' ) : ''
226 if ( element
.getAttribute( 'style' ) === '' )
227 element
.removeAttribute( 'style' );
230 CKEDITOR
.dom
.element
.setMarker( this.database
, element
, 'indent_processed', 1 );
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
;
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.
248 return isIndent
? indentClass
[ 1 ] != classes
.slice( -1 ) : true;
250 // If node has no class which belongs to indentClasses,
251 // then it is at 0-level. It can be indented but not outdented.
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';
263 // Return the numerical indent value of margin-left|right of an element,
264 // considering element's direction. If element has no margin specified,
266 function getIndent( element
) {
267 return parseInt( element
.getStyle( getIndentCss( element
) ), 10 );
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.
275 * // Use the 'Indent1', 'Indent2', 'Indent3' classes.
276 * config.indentClasses = ['Indent1', 'Indent2', 'Indent3'];
278 * @cfg {Array} [indentClasses=null]
279 * @member CKEDITOR.config
283 * The size in {@link CKEDITOR.config#indentUnit indentation units} of each indentation step.
285 * config.indentOffset = 4;
287 * @cfg {Number} [indentOffset=40]
288 * @member CKEDITOR.config
292 * The unit used for {@link CKEDITOR.config#indentOffset indentation offset}.
294 * config.indentUnit = 'em';
296 * @cfg {String} [indentUnit='px']
297 * @member CKEDITOR.config