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
64 * Object presentation of CSS style declaration text.
65 * @param {CKEDITOR.htmlParser.element|String} elementOrStyleText A html parser element or the inline style text.
67 CKEDITOR
.htmlParser
.cssStyle = function()
73 styleText
= arg
instanceof CKEDITOR
.htmlParser
.element
? arg
.attributes
.style
: arg
;
75 // html-encoded quote might be introduced by 'font-family'
76 // from MS-Word which confused the following regexp. e.g.
77 //'font-family: "Lucida, Console"'
79 .replace( /"/g, '"' )
80 .replace( /\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,
81 function( match
, name
, value
)
83 name
== 'font-family' && ( value
= value
.replace( /["']/g, '' ) );
84 rules
[ name
.toLowerCase() ] = value
;
92 * Apply the styles onto the specified element or object.
93 * @param {CKEDITOR.htmlParser.element|CKEDITOR.dom.element|Object} obj
95 populate : function( obj
)
97 var style
= this.toString();
100 obj
instanceof CKEDITOR
.dom
.element
?
101 obj
.setAttribute( 'style', style
) :
102 obj
instanceof CKEDITOR
.htmlParser
.element
?
103 obj
.attributes
.style
= style
:
108 toString : function()
111 for ( var i
in rules
)
112 rules
[ i
] && output
.push( i
, ':', rules
[ i
], ';' );
113 return output
.join( '' );
120 // Used to sort attribute entries in an array, where the first element of
121 // each object is the attribute name.
122 var sortAttribs = function( a
, b
)
126 return a
< b
? -1 : a
> b
? 1 : 0;
129 CKEDITOR
.htmlParser
.element
.prototype =
132 * The node type. This is a constant value set to {@link CKEDITOR.NODE_ELEMENT}.
136 type
: CKEDITOR
.NODE_ELEMENT
,
139 * Adds a node to the element children list.
140 * @param {Object} node The node to be added. It can be any of of the
141 * following types: {@link CKEDITOR.htmlParser.element},
142 * {@link CKEDITOR.htmlParser.text} and
143 * {@link CKEDITOR.htmlParser.comment}.
147 add
: CKEDITOR
.htmlParser
.fragment
.prototype.add
,
150 * Clone this element.
151 * @returns {CKEDITOR.htmlParser.element} The element clone.
156 return new CKEDITOR
.htmlParser
.element( this.name
, this.attributes
);
160 * Writes the element HTML to a CKEDITOR.htmlWriter.
161 * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.
164 writeHtml : function( writer
, filter
)
166 var attributes
= this.attributes
;
168 // Ignore cke: prefixes when writing HTML.
170 writeName
= element
.name
,
171 a
, newAttrName
, value
;
173 var isChildrenFiltered
;
176 * Providing an option for bottom-up filtering order ( element
177 * children to be pre-filtered before the element itself ).
179 element
.filterChildren = function()
181 if ( !isChildrenFiltered
)
183 var writer
= new CKEDITOR
.htmlParser
.basicWriter();
184 CKEDITOR
.htmlParser
.fragment
.prototype.writeChildrenHtml
.call( element
, writer
, filter
);
185 element
.children
= new CKEDITOR
.htmlParser
.fragment
.fromHtml( writer
.getHtml(), 0, element
.clone() ).children
;
186 isChildrenFiltered
= 1;
194 if ( !( writeName
= filter
.onElementName( writeName
) ) )
197 element
.name
= writeName
;
199 if ( !( element
= filter
.onElement( element
) ) )
202 element
.parent
= this.parent
;
204 if ( element
.name
== writeName
)
207 // If the element has been replaced with something of a
208 // different type, then make the replacement write itself.
209 if ( element
.type
!= CKEDITOR
.NODE_ELEMENT
)
211 element
.writeHtml( writer
, filter
);
215 writeName
= element
.name
;
217 // This indicate that the element has been dropped by
218 // filter but not the children.
221 // Fix broken parent refs.
222 for ( var c
= 0, length
= this.children
.length
; c
< length
; c
++ )
223 this.children
[ c
].parent
= element
.parent
;
225 this.writeChildrenHtml
.call( element
, writer
, isChildrenFiltered
? null : filter
);
230 // The element may have been changed, so update the local
232 attributes
= element
.attributes
;
236 writer
.openTag( writeName
, attributes
);
238 // Copy all attributes to an array.
239 var attribsArray
= [];
240 // Iterate over the attributes twice since filters may alter
242 for ( var i
= 0 ; i
< 2; i
++ )
244 for ( a
in attributes
)
247 value
= attributes
[ a
];
249 attribsArray
.push( [ a
, value
] );
254 if ( !( newAttrName
= filter
.onAttributeName( a
) ) )
256 delete attributes
[ a
];
259 else if ( newAttrName
!= a
)
261 delete attributes
[ a
];
270 if ( ( value
= filter
.onAttribute( element
, newAttrName
, value
) ) === false )
271 delete attributes
[ newAttrName
];
273 attributes
[ newAttrName
] = value
;
278 // Sort the attributes by name.
279 if ( writer
.sortAttributes
)
280 attribsArray
.sort( sortAttribs
);
282 // Send the attributes.
283 var len
= attribsArray
.length
;
284 for ( i
= 0 ; i
< len
; i
++ )
286 var attrib
= attribsArray
[ i
];
287 writer
.attribute( attrib
[0], attrib
[1] );
291 writer
.openTagClose( writeName
, element
.isEmpty
);
293 if ( !element
.isEmpty
)
295 this.writeChildrenHtml
.call( element
, writer
, isChildrenFiltered
? null : filter
);
296 // Close the element.
297 writer
.closeTag( writeName
);
301 writeChildrenHtml : function( writer
, filter
)
304 CKEDITOR
.htmlParser
.fragment
.prototype.writeChildrenHtml
.apply( this, arguments
);