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