2 Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license
\r
7 * A lightweight representation of an HTML element.
\r
8 * @param {String} name The element name.
\r
9 * @param {Object} attributes And object holding all attributes defined for
\r
14 CKEDITOR.htmlParser.element = function( name, attributes )
\r
24 * Holds the attributes defined for this element.
\r
28 this.attributes = attributes || {};
\r
31 * The nodes that are direct children of this element.
\r
37 // Reveal the real semantic of our internal custom tag name (#6639),
\r
38 // when resolving whether it's block like.
\r
39 var realName = name || '',
\r
40 prefixed = realName.match( /^cke:(.*)/ );
\r
41 prefixed && ( realName = prefixed[ 1 ] );
\r
43 var isBlockLike = !!( CKEDITOR.dtd.$nonBodyContent[ realName ]
\r
44 || CKEDITOR.dtd.$block[ realName ]
\r
45 || CKEDITOR.dtd.$listItem[ realName ]
\r
46 || CKEDITOR.dtd.$tableContent[ realName ]
\r
47 || CKEDITOR.dtd.$nonEditable[ realName ]
\r
48 || realName == 'br' );
\r
50 this.isEmpty = !!CKEDITOR.dtd.$empty[ name ];
\r
51 this.isUnknown = !CKEDITOR.dtd[ name ];
\r
56 isBlockLike : isBlockLike,
\r
57 hasInlineStarted : this.isEmpty || !isBlockLike
\r
62 * Object presentation of CSS style declaration text.
\r
63 * @param {CKEDITOR.htmlParser.element|String} elementOrStyleText A html parser element or the inline style text.
\r
65 CKEDITOR.htmlParser.cssStyle = function()
\r
68 arg = arguments[ 0 ],
\r
71 styleText = arg instanceof CKEDITOR.htmlParser.element ? arg.attributes.style : arg;
\r
73 // html-encoded quote might be introduced by 'font-family'
\r
74 // from MS-Word which confused the following regexp. e.g.
\r
75 //'font-family: "Lucida, Console"'
\r
77 .replace( /"/g, '"' )
\r
78 .replace( /\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,
\r
79 function( match, name, value )
\r
81 name == 'font-family' && ( value = value.replace( /["']/g, '' ) );
\r
82 rules[ name.toLowerCase() ] = value;
\r
90 * Apply the styles onto the specified element or object.
\r
91 * @param {CKEDITOR.htmlParser.element|CKEDITOR.dom.element|Object} obj
\r
93 populate : function( obj )
\r
95 var style = this.toString();
\r
98 obj instanceof CKEDITOR.dom.element ?
\r
99 obj.setAttribute( 'style', style ) :
\r
100 obj instanceof CKEDITOR.htmlParser.element ?
\r
101 obj.attributes.style = style :
\r
106 toString : function()
\r
109 for ( var i in rules )
\r
110 rules[ i ] && output.push( i, ':', rules[ i ], ';' );
\r
111 return output.join( '' );
\r
118 // Used to sort attribute entries in an array, where the first element of
\r
119 // each object is the attribute name.
\r
120 var sortAttribs = function( a, b )
\r
124 return a < b ? -1 : a > b ? 1 : 0;
\r
127 CKEDITOR.htmlParser.element.prototype =
\r
130 * The node type. This is a constant value set to {@link CKEDITOR.NODE_ELEMENT}.
\r
134 type : CKEDITOR.NODE_ELEMENT,
\r
137 * Adds a node to the element children list.
\r
138 * @param {Object} node The node to be added. It can be any of of the
\r
139 * following types: {@link CKEDITOR.htmlParser.element},
\r
140 * {@link CKEDITOR.htmlParser.text} and
\r
141 * {@link CKEDITOR.htmlParser.comment}.
\r
145 add : CKEDITOR.htmlParser.fragment.prototype.add,
\r
148 * Clone this element.
\r
149 * @returns {CKEDITOR.htmlParser.element} The element clone.
\r
154 return new CKEDITOR.htmlParser.element( this.name, this.attributes );
\r
158 * Writes the element HTML to a CKEDITOR.htmlWriter.
\r
159 * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.
\r
162 writeHtml : function( writer, filter )
\r
164 var attributes = this.attributes;
\r
166 // Ignore cke: prefixes when writing HTML.
\r
167 var element = this,
\r
168 writeName = element.name,
\r
169 a, newAttrName, value;
\r
171 var isChildrenFiltered;
\r
174 * Providing an option for bottom-up filtering order ( element
\r
175 * children to be pre-filtered before the element itself ).
\r
177 element.filterChildren = function()
\r
179 if ( !isChildrenFiltered )
\r
181 var writer = new CKEDITOR.htmlParser.basicWriter();
\r
182 CKEDITOR.htmlParser.fragment.prototype.writeChildrenHtml.call( element, writer, filter );
\r
183 element.children = new CKEDITOR.htmlParser.fragment.fromHtml( writer.getHtml(), 0, element.clone() ).children;
\r
184 isChildrenFiltered = 1;
\r
192 if ( !( writeName = filter.onElementName( writeName ) ) )
\r
195 element.name = writeName;
\r
197 if ( !( element = filter.onElement( element ) ) )
\r
200 element.parent = this.parent;
\r
202 if ( element.name == writeName )
\r
205 // If the element has been replaced with something of a
\r
206 // different type, then make the replacement write itself.
\r
207 if ( element.type != CKEDITOR.NODE_ELEMENT )
\r
209 element.writeHtml( writer, filter );
\r
213 writeName = element.name;
\r
215 // This indicate that the element has been dropped by
\r
216 // filter but not the children.
\r
219 // Fix broken parent refs.
\r
220 for ( var c = 0, length = this.children.length ; c < length ; c++ )
\r
221 this.children[ c ].parent = element.parent;
\r
223 this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );
\r
228 // The element may have been changed, so update the local
\r
230 attributes = element.attributes;
\r
233 // Open element tag.
\r
234 writer.openTag( writeName, attributes );
\r
236 // Copy all attributes to an array.
\r
237 var attribsArray = [];
\r
238 // Iterate over the attributes twice since filters may alter
\r
239 // other attributes.
\r
240 for ( var i = 0 ; i < 2; i++ )
\r
242 for ( a in attributes )
\r
245 value = attributes[ a ];
\r
247 attribsArray.push( [ a, value ] );
\r
252 if ( !( newAttrName = filter.onAttributeName( a ) ) )
\r
254 delete attributes[ a ];
\r
257 else if ( newAttrName != a )
\r
259 delete attributes[ a ];
\r
268 if ( ( value = filter.onAttribute( element, newAttrName, value ) ) === false )
\r
269 delete attributes[ newAttrName ];
\r
271 attributes [ newAttrName ] = value;
\r
276 // Sort the attributes by name.
\r
277 if ( writer.sortAttributes )
\r
278 attribsArray.sort( sortAttribs );
\r
280 // Send the attributes.
\r
281 var len = attribsArray.length;
\r
282 for ( i = 0 ; i < len ; i++ )
\r
284 var attrib = attribsArray[ i ];
\r
285 writer.attribute( attrib[0], attrib[1] );
\r
289 writer.openTagClose( writeName, element.isEmpty );
\r
291 if ( !element.isEmpty )
\r
293 this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );
\r
294 // Close the element.
\r
295 writer.closeTag( writeName );
\r
299 writeChildrenHtml : function( writer, filter )
\r
302 CKEDITOR.htmlParser.fragment.prototype.writeChildrenHtml.apply( this, arguments );
\r