2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
7 * A lightweight representation of an HTML element.
8 * @param {String} name The element name.
9 * @param {Object} attributes And object holding all attributes defined for
14 CKEDITOR.htmlParser.element = function( name, attributes )
24 * Holds the attributes defined for this element.
28 this.attributes = attributes || ( attributes = {} );
31 * The nodes that are direct children of this element.
37 var tagName = attributes[ 'data-cke-real-element-type' ] || name;
39 // Reveal the real semantic of our internal custom tag name (#6639).
40 var internalTag = tagName.match( /^cke:(.*)/ );
41 internalTag && ( tagName = internalTag[ 1 ] );
43 var dtd = CKEDITOR.dtd,
44 isBlockLike = !!( dtd.$nonBodyContent[ tagName ]
45 || dtd.$block[ tagName ]
46 || dtd.$listItem[ tagName ]
47 || dtd.$tableContent[ tagName ]
48 || dtd.$nonEditable[ tagName ]
50 isEmpty = !!dtd.$empty[ name ];
52 this.isEmpty = isEmpty;
53 this.isUnknown = !dtd[ name ];
58 isBlockLike : isBlockLike,
59 hasInlineStarted : isEmpty || !isBlockLike
65 // Used to sort attribute entries in an array, where the first element of
66 // each object is the attribute name.
67 var sortAttribs = function( a, b )
71 return a < b ? -1 : a > b ? 1 : 0;
74 CKEDITOR.htmlParser.element.prototype =
77 * The node type. This is a constant value set to {@link CKEDITOR.NODE_ELEMENT}.
81 type : CKEDITOR.NODE_ELEMENT,
84 * Adds a node to the element children list.
85 * @param {Object} node The node to be added. It can be any of of the
86 * following types: {@link CKEDITOR.htmlParser.element},
87 * {@link CKEDITOR.htmlParser.text} and
88 * {@link CKEDITOR.htmlParser.comment}.
92 add : CKEDITOR.htmlParser.fragment.prototype.add,
96 * @returns {CKEDITOR.htmlParser.element} The element clone.
101 return new CKEDITOR.htmlParser.element( this.name, this.attributes );
105 * Writes the element HTML to a CKEDITOR.htmlWriter.
106 * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.
109 writeHtml : function( writer, filter )
111 var attributes = this.attributes;
113 // Ignore cke: prefixes when writing HTML.
115 writeName = element.name,
116 a, newAttrName, value;
118 var isChildrenFiltered;
121 * Providing an option for bottom-up filtering order ( element
122 * children to be pre-filtered before the element itself ).
124 element.filterChildren = function()
126 if ( !isChildrenFiltered )
128 var writer = new CKEDITOR.htmlParser.basicWriter();
129 CKEDITOR.htmlParser.fragment.prototype.writeChildrenHtml.call( element, writer, filter );
130 element.children = new CKEDITOR.htmlParser.fragment.fromHtml( writer.getHtml() ).children;
131 isChildrenFiltered = 1;
139 if ( !( writeName = filter.onElementName( writeName ) ) )
142 element.name = writeName;
144 if ( !( element = filter.onElement( element ) ) )
147 element.parent = this.parent;
149 if ( element.name == writeName )
152 // If the element has been replaced with something of a
153 // different type, then make the replacement write itself.
154 if ( element.type != CKEDITOR.NODE_ELEMENT )
156 element.writeHtml( writer, filter );
160 writeName = element.name;
162 // This indicate that the element has been dropped by
163 // filter but not the children.
166 this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );
171 // The element may have been changed, so update the local
173 attributes = element.attributes;
177 writer.openTag( writeName, attributes );
179 // Copy all attributes to an array.
180 var attribsArray = [];
181 // Iterate over the attributes twice since filters may alter
183 for ( var i = 0 ; i < 2; i++ )
185 for ( a in attributes )
188 value = attributes[ a ];
190 attribsArray.push( [ a, value ] );
195 if ( !( newAttrName = filter.onAttributeName( a ) ) )
197 delete attributes[ a ];
200 else if ( newAttrName != a )
202 delete attributes[ a ];
211 if ( ( value = filter.onAttribute( element, newAttrName, value ) ) === false )
212 delete attributes[ newAttrName ];
214 attributes [ newAttrName ] = value;
219 // Sort the attributes by name.
220 if ( writer.sortAttributes )
221 attribsArray.sort( sortAttribs );
223 // Send the attributes.
224 var len = attribsArray.length;
225 for ( i = 0 ; i < len ; i++ )
227 var attrib = attribsArray[ i ];
228 writer.attribute( attrib[0], attrib[1] );
232 writer.openTagClose( writeName, element.isEmpty );
234 if ( !element.isEmpty )
236 this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );
237 // Close the element.
238 writer.closeTag( writeName );
242 writeChildrenHtml : function( writer, filter )
245 CKEDITOR.htmlParser.fragment.prototype.writeChildrenHtml.apply( this, arguments );