2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
8 CKEDITOR.htmlParser.filter = CKEDITOR.tools.createClass(
16 elements : { $length : 0 },
17 attributes : { $length : 0 }
21 this.addRules( rules, 10 );
26 addRules : function( rules, priority )
28 if ( typeof priority != 'number' )
31 // Add the elementNames.
32 addItemsToList( this._.elementNames, rules.elementNames, priority );
34 // Add the attributeNames.
35 addItemsToList( this._.attributeNames, rules.attributeNames, priority );
38 addNamedItems( this._.elements, rules.elements, priority );
40 // Add the attributes.
41 addNamedItems( this._.attributes, rules.attributes, priority );
44 this._.text = transformNamedItem( this._.text, rules.text, priority ) || this._.text;
47 this._.comment = transformNamedItem( this._.comment, rules.comment, priority ) || this._.comment;
50 this._.root = transformNamedItem( this._.root, rules.root, priority ) || this._.root;
53 onElementName : function( name )
55 return filterName( name, this._.elementNames );
58 onAttributeName : function( name )
60 return filterName( name, this._.attributeNames );
63 onText : function( text )
65 var textFilter = this._.text;
66 return textFilter ? textFilter.filter( text ) : text;
69 onComment : function( commentText, comment )
71 var textFilter = this._.comment;
72 return textFilter ? textFilter.filter( commentText, comment ) : commentText;
75 onFragment : function( element )
77 var rootFilter = this._.root;
78 return rootFilter ? rootFilter.filter( element ) : element;
81 onElement : function( element )
83 // We must apply filters set to the specific element name as
84 // well as those set to the generic $ name. So, add both to an
85 // array and process them in a small loop.
86 var filters = [ this._.elements[ '^' ], this._.elements[ element.name ], this._.elements.$ ],
89 for ( var i = 0 ; i < 3 ; i++ )
91 filter = filters[ i ];
94 ret = filter.filter( element, this );
99 if ( ret && ret != element )
100 return this.onNode( ret );
102 // The non-root element has been dismissed by one of the filters.
103 if ( element.parent && !element.name )
111 onNode : function( node )
113 var type = node.type;
115 return type == CKEDITOR.NODE_ELEMENT ? this.onElement( node ) :
116 type == CKEDITOR.NODE_TEXT ? new CKEDITOR.htmlParser.text( this.onText( node.value ) ) :
117 type == CKEDITOR.NODE_COMMENT ? new CKEDITOR.htmlParser.comment( this.onComment( node.value ) ):
121 onAttribute : function( element, name, value )
123 var filter = this._.attributes[ name ];
127 var ret = filter.filter( value, element, this );
132 if ( typeof ret != 'undefined' )
141 function filterName( name, filters )
143 for ( var i = 0 ; name && i < filters.length ; i++ )
145 var filter = filters[ i ];
146 name = name.replace( filter[ 0 ], filter[ 1 ] );
151 function addItemsToList( list, items, priority )
153 if ( typeof items == 'function' )
157 listLength = list.length,
158 itemsLength = items && items.length;
162 // Find the index to insert the items at.
163 for ( i = 0 ; i < listLength && list[ i ].pri < priority ; i++ )
166 // Add all new items to the list at the specific index.
167 for ( j = itemsLength - 1 ; j >= 0 ; j-- )
169 var item = items[ j ];
173 list.splice( i, 0, item );
179 function addNamedItems( hashTable, items, priority )
183 for ( var name in items )
185 var current = hashTable[ name ];
199 function transformNamedItem( current, item, priority )
207 // If the current item is not an Array, transform it.
208 if ( !current.splice )
210 if ( current.pri > priority )
211 current = [ item, current ];
213 current = [ current, item ];
215 current.filter = callItems;
218 addItemsToList( current, item, priority );
230 // Invoke filters sequentially on the array, break the iteration
231 // when it doesn't make sense to continue anymore.
232 function callItems( currentEntry )
234 var isNode = currentEntry.type
235 || currentEntry instanceof CKEDITOR.htmlParser.fragment;
237 for ( var i = 0 ; i < this.length ; i++ )
239 // Backup the node info before filtering.
242 var orgType = currentEntry.type,
243 orgName = currentEntry.name;
246 var item = this[ i ],
247 ret = item.apply( window, arguments );
252 // We're filtering node (element/fragment).
255 // No further filtering if it's not anymore
256 // fitable for the subsequent filters.
257 if ( ret && ( ret.name != orgName
258 || ret.type != orgType ) )
263 // Filtering value (nodeName/textValue/attrValue).
266 // No further filtering if it's not
268 if ( typeof ret != 'string' )
272 ret != undefined && ( currentEntry = ret );
282 text : function( text )
284 // TODO : Process entities.
285 return text.toUpperCase();