--- /dev/null
+/*\r
+Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.\r
+For licensing, see LICENSE.html or http://ckeditor.com/license\r
+*/\r
+\r
+/**\r
+ * A lightweight representation of an HTML element.\r
+ * @param {String} name The element name.\r
+ * @param {Object} attributes And object holding all attributes defined for\r
+ * this element.\r
+ * @constructor\r
+ * @example\r
+ */\r
+CKEDITOR.htmlParser.element = function( name, attributes )\r
+{\r
+ /**\r
+ * The element name.\r
+ * @type String\r
+ * @example\r
+ */\r
+ this.name = name;\r
+\r
+ /**\r
+ * Holds the attributes defined for this element.\r
+ * @type Object\r
+ * @example\r
+ */\r
+ this.attributes = attributes || ( attributes = {} );\r
+\r
+ /**\r
+ * The nodes that are direct children of this element.\r
+ * @type Array\r
+ * @example\r
+ */\r
+ this.children = [];\r
+\r
+ var tagName = attributes[ 'data-cke-real-element-type' ] || name || '';\r
+\r
+ // Reveal the real semantic of our internal custom tag name (#6639).\r
+ var internalTag = tagName.match( /^cke:(.*)/ );\r
+ internalTag && ( tagName = internalTag[ 1 ] );\r
+\r
+ var dtd = CKEDITOR.dtd,\r
+ isBlockLike = !!( dtd.$nonBodyContent[ tagName ]\r
+ || dtd.$block[ tagName ]\r
+ || dtd.$listItem[ tagName ]\r
+ || dtd.$tableContent[ tagName ]\r
+ || dtd.$nonEditable[ tagName ]\r
+ || tagName == 'br' ),\r
+ isEmpty = !!dtd.$empty[ name ];\r
+\r
+ this.isEmpty = isEmpty;\r
+ this.isUnknown = !dtd[ name ];\r
+\r
+ /** @private */\r
+ this._ =\r
+ {\r
+ isBlockLike : isBlockLike,\r
+ hasInlineStarted : isEmpty || !isBlockLike\r
+ };\r
+};\r
+\r
+(function()\r
+{\r
+ // Used to sort attribute entries in an array, where the first element of\r
+ // each object is the attribute name.\r
+ var sortAttribs = function( a, b )\r
+ {\r
+ a = a[0];\r
+ b = b[0];\r
+ return a < b ? -1 : a > b ? 1 : 0;\r
+ };\r
+\r
+ CKEDITOR.htmlParser.element.prototype =\r
+ {\r
+ /**\r
+ * The node type. This is a constant value set to {@link CKEDITOR.NODE_ELEMENT}.\r
+ * @type Number\r
+ * @example\r
+ */\r
+ type : CKEDITOR.NODE_ELEMENT,\r
+\r
+ /**\r
+ * Adds a node to the element children list.\r
+ * @param {Object} node The node to be added. It can be any of of the\r
+ * following types: {@link CKEDITOR.htmlParser.element},\r
+ * {@link CKEDITOR.htmlParser.text} and\r
+ * {@link CKEDITOR.htmlParser.comment}.\r
+ * @function\r
+ * @example\r
+ */\r
+ add : CKEDITOR.htmlParser.fragment.prototype.add,\r
+\r
+ /**\r
+ * Clone this element.\r
+ * @returns {CKEDITOR.htmlParser.element} The element clone.\r
+ * @example\r
+ */\r
+ clone : function()\r
+ {\r
+ return new CKEDITOR.htmlParser.element( this.name, this.attributes );\r
+ },\r
+\r
+ /**\r
+ * Writes the element HTML to a CKEDITOR.htmlWriter.\r
+ * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML.\r
+ * @example\r
+ */\r
+ writeHtml : function( writer, filter )\r
+ {\r
+ var attributes = this.attributes;\r
+\r
+ // Ignore cke: prefixes when writing HTML.\r
+ var element = this,\r
+ writeName = element.name,\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(), 0, element.clone() ).children;\r
+ isChildrenFiltered = 1;\r
+ }\r
+ };\r
+\r
+ if ( filter )\r
+ {\r
+ while ( true )\r
+ {\r
+ if ( !( writeName = filter.onElementName( writeName ) ) )\r
+ return;\r
+\r
+ element.name = writeName;\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
+\r
+ // This indicate that the element has been dropped by\r
+ // filter but not the children.\r
+ if ( !writeName )\r
+ {\r
+ this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );\r
+ return;\r
+ }\r
+ }\r
+\r
+ // The element may have been changed, so update the local\r
+ // references.\r
+ attributes = element.attributes;\r
+ }\r
+\r
+ // Open element tag.\r
+ writer.openTag( writeName, attributes );\r
+\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
+ for ( a in attributes )\r
+ {\r
+ newAttrName = a;\r
+ value = attributes[ a ];\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
+ if ( writer.sortAttributes )\r
+ attribsArray.sort( sortAttribs );\r
+\r
+ // Send the attributes.\r
+ var len = attribsArray.length;\r
+ for ( i = 0 ; i < len ; i++ )\r
+ {\r
+ var attrib = attribsArray[ i ];\r
+ writer.attribute( attrib[0], attrib[1] );\r
+ }\r
+\r
+ // Close the tag.\r
+ writer.openTagClose( writeName, element.isEmpty );\r
+\r
+ if ( !element.isEmpty )\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