JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
6001e681a538f243703c17b2bdc83e94ae588a1a
[ckeditor.git] / _source / core / htmlparser / filter.js
1 /*\r
2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 (function()\r
7 {\r
8         CKEDITOR.htmlParser.filter = CKEDITOR.tools.createClass(\r
9         {\r
10                 $ : function( rules )\r
11                 {\r
12                         this._ =\r
13                         {\r
14                                 elementNames : [],\r
15                                 attributeNames : [],\r
16                                 elements : { $length : 0 },\r
17                                 attributes : { $length : 0 }\r
18                         };\r
19 \r
20                         if ( rules )\r
21                                 this.addRules( rules, 10 );\r
22                 },\r
23 \r
24                 proto :\r
25                 {\r
26                         addRules : function( rules, priority )\r
27                         {\r
28                                 if ( typeof priority != 'number' )\r
29                                         priority = 10;\r
30 \r
31                                 // Add the elementNames.\r
32                                 addItemsToList( this._.elementNames, rules.elementNames, priority );\r
33 \r
34                                 // Add the attributeNames.\r
35                                 addItemsToList( this._.attributeNames, rules.attributeNames, priority );\r
36 \r
37                                 // Add the elements.\r
38                                 addNamedItems( this._.elements, rules.elements, priority );\r
39 \r
40                                 // Add the attributes.\r
41                                 addNamedItems( this._.attributes, rules.attributes, priority );\r
42 \r
43                                 // Add the text.\r
44                                 this._.text = transformNamedItem( this._.text, rules.text, priority ) || this._.text;\r
45 \r
46                                 // Add the comment.\r
47                                 this._.comment = transformNamedItem( this._.comment, rules.comment, priority ) || this._.comment;\r
48                         },\r
49 \r
50                         onElementName : function( name )\r
51                         {\r
52                                 return filterName( name, this._.elementNames );\r
53                         },\r
54 \r
55                         onAttributeName : function( name )\r
56                         {\r
57                                 return filterName( name, this._.attributeNames );\r
58                         },\r
59 \r
60                         onText : function( text )\r
61                         {\r
62                                 var textFilter = this._.text;\r
63                                 return textFilter ? textFilter.filter( text ) : text;\r
64                         },\r
65 \r
66                         onComment : function( commentText )\r
67                         {\r
68                                 var textFilter = this._.comment;\r
69                                 return textFilter ? textFilter.filter( commentText ) : commentText;\r
70                         },\r
71 \r
72                         onElement : function( element )\r
73                         {\r
74                                 // We must apply filters set to the specific element name as\r
75                                 // well as those set to the generic $ name. So, add both to an\r
76                                 // array and process them in a small loop.\r
77                                 var filters = [ this._.elements[ element.name ], this._.elements.$ ],\r
78                                         filter, ret;\r
79 \r
80                                 for ( var i = 0 ; i < 2 ; i++ )\r
81                                 {\r
82                                         filter = filters[ i ];\r
83                                         if ( filter )\r
84                                         {\r
85                                                 ret = filter.filter( element, this );\r
86 \r
87                                                 if ( ret === false )\r
88                                                         return null;\r
89 \r
90                                                 if ( ret && ret != element )\r
91                                                         return this.onElement( ret );\r
92                                         }\r
93                                 }\r
94 \r
95                                 return element;\r
96                         },\r
97 \r
98                         onAttribute : function( element, name, value )\r
99                         {\r
100                                 var filter = this._.attributes[ name ];\r
101 \r
102                                 if ( filter )\r
103                                 {\r
104                                         var ret = filter.filter( value, element, this );\r
105 \r
106                                         if ( ret === false )\r
107                                                 return false;\r
108 \r
109                                         if ( typeof ret != 'undefined' )\r
110                                                 return ret;\r
111                                 }\r
112 \r
113                                 return value;\r
114                         }\r
115                 }\r
116         });\r
117 \r
118         function filterName( name, filters )\r
119         {\r
120                 for ( var i = 0 ; name && i < filters.length ; i++ )\r
121                 {\r
122                         var filter = filters[ i ];\r
123                         name = name.replace( filter[ 0 ], filter[ 1 ] );\r
124                 }\r
125                 return name;\r
126         }\r
127 \r
128         function addItemsToList( list, items, priority )\r
129         {\r
130                 if( typeof items == 'function' )\r
131                         items = [ items ];\r
132 \r
133                 var i, j,\r
134                         listLength = list.length,\r
135                         itemsLength = items && items.length;\r
136 \r
137                 if ( itemsLength )\r
138                 {\r
139                         // Find the index to insert the items at.\r
140                         for ( i = 0 ; i < listLength && list[ i ].pri < priority ; i++ )\r
141                         { /*jsl:pass*/ }\r
142 \r
143                         // Add all new items to the list at the specific index.\r
144                         for ( j = itemsLength - 1 ; j >= 0 ; j-- )\r
145                         {\r
146                                 var item = items[ j ];\r
147                                 item.pri = priority;\r
148                                 list.splice( i, 0, item );\r
149                         }\r
150                 }\r
151         }\r
152 \r
153         function addNamedItems( hashTable, items, priority )\r
154         {\r
155                 if ( items )\r
156                 {\r
157                         for ( var name in items )\r
158                         {\r
159                                 var current = hashTable[ name ];\r
160 \r
161                                 hashTable[ name ] =\r
162                                         transformNamedItem(\r
163                                                 current,\r
164                                                 items[ name ],\r
165                                                 priority );\r
166 \r
167                                 if ( !current )\r
168                                         hashTable.$length++;\r
169                         }\r
170                 }\r
171         }\r
172 \r
173         function transformNamedItem( current, item, priority )\r
174         {\r
175                 if ( item )\r
176                 {\r
177                         item.pri = priority;\r
178 \r
179                         if ( current )\r
180                         {\r
181                                 // If the current item is not an Array, transform it.\r
182                                 if ( !current.splice )\r
183                                 {\r
184                                         if ( current.pri > priority )\r
185                                                 current = [ item, current ];\r
186                                         else\r
187                                                 current = [ current, item ];\r
188 \r
189                                         current.filter = callItems;\r
190                                 }\r
191                                 else\r
192                                         addItemsToList( current, item, priority );\r
193 \r
194                                 return current;\r
195                         }\r
196                         else\r
197                         {\r
198                                 item.filter = item;\r
199                                 return item;\r
200                         }\r
201                 }\r
202         }\r
203 \r
204         function callItems( currentEntry )\r
205         {\r
206                 var isObject = ( typeof currentEntry == 'object' );\r
207 \r
208                 for ( var i = 0 ; i < this.length ; i++ )\r
209                 {\r
210                         var item = this[ i ],\r
211                                 ret = item.apply( window, arguments );\r
212 \r
213                         if ( typeof ret != 'undefined' )\r
214                         {\r
215                                 if ( ret === false )\r
216                                         return false;\r
217 \r
218                                 if ( isObject && ret != currentEntry )\r
219                                         return ret;\r
220                         }\r
221                 }\r
222 \r
223                 return null;\r
224         }\r
225 })();\r
226 \r
227 // "entities" plugin\r
228 /*\r
229 {\r
230         text : function( text )\r
231         {\r
232                 // TODO : Process entities.\r
233                 return text.toUpperCase();\r
234         }\r
235 };\r
236 */\r