2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
6 CKEDITOR
.plugins
.add( 'removeformat',
8 requires
: [ 'selection' ],
10 init : function( editor
)
12 editor
.addCommand( 'removeFormat', CKEDITOR
.plugins
.removeformat
.commands
.removeformat
);
13 editor
.ui
.addButton( 'RemoveFormat',
15 label
: editor
.lang
.removeFormat
,
16 command
: 'removeFormat'
19 editor
._
.removeFormat
= { filters
: [] };
23 CKEDITOR
.plugins
.removeformat
=
29 exec : function( editor
)
31 var tagsRegex
= editor
._
.removeFormatRegex
||
32 ( editor
._
.removeFormatRegex
= new RegExp( '^(?:' + editor
.config
.removeFormatTags
.replace( /,/g
,'|' ) + ')$', 'i' ) );
34 var removeAttributes
= editor
._
.removeAttributes
||
35 ( editor
._
.removeAttributes
= editor
.config
.removeFormatAttributes
.split( ',' ) );
37 var filter
= CKEDITOR
.plugins
.removeformat
.filter
;
38 var ranges
= editor
.getSelection().getRanges( 1 ),
39 iterator
= ranges
.createIterator(),
42 while ( ( range
= iterator
.getNextRange() ) )
44 if ( ! range
.collapsed
)
45 range
.enlarge( CKEDITOR
.ENLARGE_ELEMENT
);
47 // Bookmark the range so we can re-select it after processing.
48 var bookmark
= range
.createBookmark(),
49 // The style will be applied within the bookmark boundaries.
50 startNode
= bookmark
.startNode
,
51 endNode
= bookmark
.endNode
,
54 // We need to check the selection boundaries (bookmark spans) to break
55 // the code in a way that we can properly remove partially selected nodes.
56 // For example, removing a <b> style from
57 // <b>This is [some text</b> to show <b>the] problem</b>
58 // ... where [ and ] represent the selection, must result:
59 // <b>This is </b>[some text to show the]<b> problem</b>
60 // The strategy is simple, we just break the partial nodes before the
61 // removal logic, having something that could be represented this way:
62 // <b>This is </b>[<b>some text</b> to show <b>the</b>]<b> problem</b>
64 var breakParent = function( node
)
66 // Let's start checking the start boundary.
67 var path
= new CKEDITOR
.dom
.elementPath( node
),
68 pathElements
= path
.elements
;
70 for ( var i
= 1, pathElement
; pathElement
= pathElements
[ i
] ; i
++ )
72 if ( pathElement
.equals( path
.block
) || pathElement
.equals( path
.blockLimit
) )
75 // If this element can be removed (even partially).
76 if ( tagsRegex
.test( pathElement
.getName() ) && filter( editor
, pathElement
) )
77 node
.breakParent( pathElement
);
81 breakParent( startNode
);
84 breakParent( endNode
);
86 // Navigate through all nodes between the bookmarks.
87 currentNode
= startNode
.getNextSourceNode( true, CKEDITOR
.NODE_ELEMENT
);
91 // If we have reached the end of the selection, stop looping.
92 if ( currentNode
.equals( endNode
) )
95 // Cache the next node to be processed. Do it now, because
96 // currentNode may be removed.
97 var nextNode
= currentNode
.getNextSourceNode( false, CKEDITOR
.NODE_ELEMENT
);
99 // This node must not be a fake element.
100 if ( !( currentNode
.getName() == 'img'
101 && currentNode
.data( 'cke-realelement' ) )
102 && filter( editor
, currentNode
) )
104 // Remove elements nodes that match with this style rules.
105 if ( tagsRegex
.test( currentNode
.getName() ) )
106 currentNode
.remove( 1 );
109 currentNode
.removeAttributes( removeAttributes
);
110 editor
.fire( 'removeFormatCleanup', currentNode
);
114 currentNode
= nextNode
;
118 range
.moveToBookmark( bookmark
);
121 editor
.getSelection().selectRanges( ranges
);
127 * Perform the remove format filters on the passed element.
128 * @param {CKEDITOR.editor} editor
129 * @param {CKEDITOR.dom.element} element
131 filter : function ( editor
, element
)
133 var filters
= editor
._
.removeFormat
.filters
;
134 for ( var i
= 0; i
< filters
.length
; i
++ )
136 if ( filters
[ i
]( element
) === false )
144 * Add to a collection of functions to decide whether a specific
145 * element should be considered as formatting element and thus
146 * could be removed during <b>removeFormat</b> command,
147 * Note: Only available with the existence of 'removeformat' plugin.
149 * @param {Function} func The function to be called, which will be passed a {CKEDITOR.dom.element} element to test.
151 * // Don't remove empty span
152 * editor.addRemoveFormatFilter.push( function( element )
154 * return !( element.is( 'span' ) && CKEDITOR.tools.isEmpty( element.getAttributes() ) );
157 CKEDITOR
.editor
.prototype.addRemoveFormatFilter = function( func
)
159 this._
.removeFormat
.filters
.push( func
);
163 * A comma separated list of elements to be removed when executing the "remove
164 " format" command. Note that only inline elements are allowed.
166 * @default 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var'
169 CKEDITOR
.config
.removeFormatTags
= 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var';
172 * A comma separated list of elements attributes to be removed when executing
173 * the "remove format" command.
175 * @default 'class,style,lang,width,height,align,hspace,valign'
178 CKEDITOR
.config
.removeFormatAttributes
= 'class,style,lang,width,height,align,hspace,valign';
181 * Fired after an element was cleaned by the removeFormat plugin.
182 * @name CKEDITOR.editor#removeFormatCleanup
184 * @param {Object} data.element The element that was cleaned up.