[2000] | 1 | /*
|
---|
| 2 | Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
|
---|
| 3 | For licensing, see LICENSE.html or http://ckeditor.com/license
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | CKEDITOR.plugins.add( 'removeformat',
|
---|
| 7 | {
|
---|
| 8 | requires : [ 'selection' ],
|
---|
| 9 |
|
---|
| 10 | init : function( editor )
|
---|
| 11 | {
|
---|
| 12 | editor.addCommand( 'removeFormat', CKEDITOR.plugins.removeformat.commands.removeformat );
|
---|
| 13 | editor.ui.addButton( 'RemoveFormat',
|
---|
| 14 | {
|
---|
| 15 | label : editor.lang.removeFormat,
|
---|
| 16 | command : 'removeFormat'
|
---|
| 17 | });
|
---|
| 18 | }
|
---|
| 19 | });
|
---|
| 20 |
|
---|
| 21 | CKEDITOR.plugins.removeformat =
|
---|
| 22 | {
|
---|
| 23 | commands :
|
---|
| 24 | {
|
---|
| 25 | removeformat :
|
---|
| 26 | {
|
---|
| 27 | exec : function( editor )
|
---|
| 28 | {
|
---|
| 29 | var tagsRegex = editor._.removeFormatRegex ||
|
---|
| 30 | ( editor._.removeFormatRegex = new RegExp( '^(?:' + editor.config.removeFormatTags.replace( /,/g,'|' ) + ')$', 'i' ) );
|
---|
| 31 |
|
---|
| 32 | var removeAttributes = editor._.removeAttributes ||
|
---|
| 33 | ( editor._.removeAttributes = editor.config.removeFormatAttributes.split( ',' ) );
|
---|
| 34 |
|
---|
| 35 | var ranges = editor.getSelection().getRanges();
|
---|
| 36 |
|
---|
| 37 | for ( var i = 0, range ; range = ranges[ i ] ; i++ )
|
---|
| 38 | {
|
---|
| 39 | if ( range.collapsed )
|
---|
| 40 | continue;
|
---|
| 41 |
|
---|
| 42 | range.enlarge( CKEDITOR.ENLARGE_ELEMENT );
|
---|
| 43 |
|
---|
| 44 | // Bookmark the range so we can re-select it after processing.
|
---|
| 45 | var bookmark = range.createBookmark();
|
---|
| 46 |
|
---|
| 47 | // The style will be applied within the bookmark boundaries.
|
---|
| 48 | var startNode = bookmark.startNode;
|
---|
| 49 | var endNode = bookmark.endNode;
|
---|
| 50 |
|
---|
| 51 | // We need to check the selection boundaries (bookmark spans) to break
|
---|
| 52 | // the code in a way that we can properly remove partially selected nodes.
|
---|
| 53 | // For example, removing a <b> style from
|
---|
| 54 | // <b>This is [some text</b> to show <b>the] problem</b>
|
---|
| 55 | // ... where [ and ] represent the selection, must result:
|
---|
| 56 | // <b>This is </b>[some text to show the]<b> problem</b>
|
---|
| 57 | // The strategy is simple, we just break the partial nodes before the
|
---|
| 58 | // removal logic, having something that could be represented this way:
|
---|
| 59 | // <b>This is </b>[<b>some text</b> to show <b>the</b>]<b> problem</b>
|
---|
| 60 |
|
---|
| 61 | var breakParent = function( node )
|
---|
| 62 | {
|
---|
| 63 | // Let's start checking the start boundary.
|
---|
| 64 | var path = new CKEDITOR.dom.elementPath( node );
|
---|
| 65 | var pathElements = path.elements;
|
---|
| 66 |
|
---|
| 67 | for ( var i = 1, pathElement ; pathElement = pathElements[ i ] ; i++ )
|
---|
| 68 | {
|
---|
| 69 | if ( pathElement.equals( path.block ) || pathElement.equals( path.blockLimit ) )
|
---|
| 70 | break;
|
---|
| 71 |
|
---|
| 72 | // If this element can be removed (even partially).
|
---|
| 73 | if ( tagsRegex.test( pathElement.getName() ) )
|
---|
| 74 | node.breakParent( pathElement );
|
---|
| 75 | }
|
---|
| 76 | };
|
---|
| 77 |
|
---|
| 78 | breakParent( startNode );
|
---|
| 79 | breakParent( endNode );
|
---|
| 80 |
|
---|
| 81 | // Navigate through all nodes between the bookmarks.
|
---|
| 82 | var currentNode = startNode.getNextSourceNode( true, CKEDITOR.NODE_ELEMENT );
|
---|
| 83 |
|
---|
| 84 | while ( currentNode )
|
---|
| 85 | {
|
---|
| 86 | // If we have reached the end of the selection, stop looping.
|
---|
| 87 | if ( currentNode.equals( endNode ) )
|
---|
| 88 | break;
|
---|
| 89 |
|
---|
| 90 | // Cache the next node to be processed. Do it now, because
|
---|
| 91 | // currentNode may be removed.
|
---|
| 92 | var nextNode = currentNode.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT );
|
---|
| 93 |
|
---|
| 94 | // This node must not be a fake element.
|
---|
| 95 | if ( currentNode.getName() != 'img' || !currentNode.getAttribute( '_cke_protected_html' ) )
|
---|
| 96 | {
|
---|
| 97 | // Remove elements nodes that match with this style rules.
|
---|
| 98 | if ( tagsRegex.test( currentNode.getName() ) )
|
---|
| 99 | currentNode.remove( true );
|
---|
| 100 | else
|
---|
| 101 | currentNode.removeAttributes( removeAttributes );
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | currentNode = nextNode;
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 107 | range.moveToBookmark( bookmark );
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | editor.getSelection().selectRanges( ranges );
|
---|
| 111 | }
|
---|
| 112 | }
|
---|
| 113 | }
|
---|
| 114 | };
|
---|
| 115 |
|
---|
| 116 | /**
|
---|
| 117 | * A comma separated list of elements to be removed when executing the "remove
|
---|
| 118 | " format" command. Note that only inline elements are allowed.
|
---|
| 119 | * @type String
|
---|
| 120 | * @default 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var'
|
---|
| 121 | * @example
|
---|
| 122 | */
|
---|
| 123 | CKEDITOR.config.removeFormatTags = 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var';
|
---|
| 124 |
|
---|
| 125 | /**
|
---|
| 126 | * A comma separated list of elements attributes to be removed when executing
|
---|
| 127 | * the "remove format" command.
|
---|
| 128 | * @type String
|
---|
| 129 | * @default 'class,style,lang,width,height,align,hspace,valign'
|
---|
| 130 | * @example
|
---|
| 131 | */
|
---|
| 132 | CKEDITOR.config.removeFormatAttributes = 'class,style,lang,width,height,align,hspace,valign';
|
---|