/*\r
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
For licensing, see LICENSE.html or http://ckeditor.com/license\r
*/\r
\r
* @type Object\r
* @example\r
*/\r
- this.attributes = attributes;\r
+ this.attributes = attributes || ( attributes = {} );\r
\r
/**\r
* The nodes that are direct children of this element.\r
*/\r
this.children = [];\r
\r
+ var tagName = attributes._cke_real_element_type || name;\r
+\r
var dtd = CKEDITOR.dtd,\r
- isBlockLike = !!( dtd.$block[ name ] || dtd.$listItem[ name ] || dtd.$tableContent[ name ] ),\r
+ isBlockLike = !!( dtd.$nonBodyContent[ tagName ] || dtd.$block[ tagName ] || dtd.$listItem[ tagName ] || dtd.$tableContent[ tagName ] || dtd.$nonEditable[ tagName ] || tagName == 'br' ),\r
isEmpty = !!dtd.$empty[ name ];\r
\r
this.isEmpty = isEmpty;\r
{\r
var attributes = this.attributes;\r
\r
- // The "_cke_replacedata" indicates that this element is replacing\r
- // a data snippet, which should be outputted as is.\r
- if ( attributes._cke_replacedata )\r
- {\r
- writer.write( attributes._cke_replacedata );\r
- return;\r
- }\r
-\r
// Ignore cke: prefixes when writing HTML.\r
var element = this,\r
writeName = element.name,\r
- a, value;\r
+ a, newAttrName, value;\r
+\r
+ var isChildrenFiltered;\r
+\r
+ /**\r
+ * Providing an option for bottom-up filtering order ( element\r
+ * children to be pre-filtered before the element itself ).\r
+ */\r
+ element.filterChildren = function()\r
+ {\r
+ if ( !isChildrenFiltered )\r
+ {\r
+ var writer = new CKEDITOR.htmlParser.basicWriter();\r
+ CKEDITOR.htmlParser.fragment.prototype.writeChildrenHtml.call( element, writer, filter );\r
+ element.children = new CKEDITOR.htmlParser.fragment.fromHtml( writer.getHtml() ).children;\r
+ isChildrenFiltered = 1;\r
+ }\r
+ };\r
\r
if ( filter )\r
{\r
if ( !( element = filter.onElement( element ) ) )\r
return;\r
\r
+ element.parent = this.parent;\r
+\r
if ( element.name == writeName )\r
break;\r
\r
+ // If the element has been replaced with something of a\r
+ // different type, then make the replacement write itself.\r
+ if ( element.type != CKEDITOR.NODE_ELEMENT )\r
+ {\r
+ element.writeHtml( writer, filter );\r
+ return;\r
+ }\r
+\r
writeName = element.name;\r
- if ( !writeName ) // Send children.\r
+\r
+ // This indicate that the element has been dropped by\r
+ // filter but not the children.\r
+ if ( !writeName )\r
{\r
- CKEDITOR.htmlParser.fragment.prototype.writeHtml.apply( element, arguments );\r
+ this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );\r
return;\r
}\r
}\r
// Open element tag.\r
writer.openTag( writeName, attributes );\r
\r
- if ( writer.sortAttributes )\r
+ // Copy all attributes to an array.\r
+ var attribsArray = [];\r
+ // Iterate over the attributes twice since filters may alter\r
+ // other attributes.\r
+ for ( var i = 0 ; i < 2; i++ )\r
{\r
- // Copy all attributes to an array.\r
- var attribsArray = [];\r
for ( a in attributes )\r
{\r
+ newAttrName = a;\r
value = attributes[ a ];\r
-\r
- if ( filter && ( !( a = filter.onAttributeName( a ) ) || ( value = filter.onAttribute( element, a, value ) ) === false ) )\r
- continue;\r
-\r
- attribsArray.push( [ a, value ] );\r
+ if ( i == 1 )\r
+ attribsArray.push( [ a, value ] );\r
+ else if ( filter )\r
+ {\r
+ while ( true )\r
+ {\r
+ if ( !( newAttrName = filter.onAttributeName( a ) ) )\r
+ {\r
+ delete attributes[ a ];\r
+ break;\r
+ }\r
+ else if ( newAttrName != a )\r
+ {\r
+ delete attributes[ a ];\r
+ a = newAttrName;\r
+ continue;\r
+ }\r
+ else\r
+ break;\r
+ }\r
+ if ( newAttrName )\r
+ {\r
+ if ( ( value = filter.onAttribute( element, newAttrName, value ) ) === false )\r
+ delete attributes[ newAttrName ];\r
+ else\r
+ attributes [ newAttrName ] = value;\r
+ }\r
+ }\r
}\r
-\r
- // Sort the attributes by name.\r
+ }\r
+ // Sort the attributes by name.\r
+ if ( writer.sortAttributes )\r
attribsArray.sort( sortAttribs );\r
\r
- // Send the attributes.\r
- for ( var i = 0, len = attribsArray.length ; i < len ; i++ )\r
- {\r
- var attrib = attribsArray[ i ];\r
- writer.attribute( attrib[0], attrib[1] );\r
- }\r
- }\r
- else\r
+ // Send the attributes.\r
+ var len = attribsArray.length;\r
+ for ( i = 0 ; i < len ; i++ )\r
{\r
- for ( a in attributes )\r
- {\r
- value = attributes[ a ];\r
-\r
- if ( filter && ( !( a = filter.onAttributeName( a ) ) || ( value = filter.onAttribute( element, a, value ) ) === false ) )\r
- continue;\r
-\r
- writer.attribute( a, value );\r
- }\r
+ var attrib = attribsArray[ i ];\r
+ writer.attribute( attrib[0], attrib[1] );\r
}\r
\r
// Close the tag.\r
\r
if ( !element.isEmpty )\r
{\r
- // Send children.\r
- CKEDITOR.htmlParser.fragment.prototype.writeHtml.apply( element, arguments );\r
-\r
+ this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );\r
// Close the element.\r
writer.closeTag( writeName );\r
}\r
+ },\r
+\r
+ writeChildrenHtml : function( writer, filter )\r
+ {\r
+ // Send children.\r
+ CKEDITOR.htmlParser.fragment.prototype.writeChildrenHtml.apply( this, arguments );\r
+\r
}\r
};\r
})();\r