JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.0
[ckeditor.git] / _source / core / htmlparser / element.js
diff --git a/_source/core/htmlparser/element.js b/_source/core/htmlparser/element.js
new file mode 100644 (file)
index 0000000..6ad0264
--- /dev/null
@@ -0,0 +1,196 @@
+/*\r
+Copyright (c) 2003-2009, 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;\r
+\r
+       /**\r
+        * The nodes that are direct children of this element.\r
+        * @type Array\r
+        * @example\r
+        */\r
+       this.children = [];\r
+\r
+       var dtd                 = CKEDITOR.dtd,\r
+               isBlockLike     = !!( dtd.$block[ name ] || dtd.$listItem[ name ] || dtd.$tableContent[ name ] ),\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
+                       // 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
+\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
+                                       if ( element.name == writeName )\r
+                                               break;\r
+\r
+                                       writeName = element.name;\r
+                                       if ( !writeName )       // Send children.\r
+                                       {\r
+                                               CKEDITOR.htmlParser.fragment.prototype.writeHtml.apply( element, arguments );\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
+                       if ( writer.sortAttributes )\r
+                       {\r
+                               // Copy all attributes to an array.\r
+                               var attribsArray = [];\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
+                                       attribsArray.push( [ a, value ] );\r
+                               }\r
+\r
+                               // Sort the attributes by name.\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
+                       {\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
+                       }\r
+\r
+                       // Close the tag.\r
+                       writer.openTagClose( writeName, element.isEmpty );\r
+\r
+                       if ( !element.isEmpty )\r
+                       {\r
+                               // Send children.\r
+                               CKEDITOR.htmlParser.fragment.prototype.writeHtml.apply( element, arguments );\r
+\r
+                               // Close the element.\r
+                               writer.closeTag( writeName );\r
+                       }\r
+               }\r
+       };\r
+})();\r