JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1
[ckeditor.git] / _source / core / htmlparser / element.js
index 10109e7..2e9a9c3 100644 (file)
@@ -1,5 +1,5 @@
 /*\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
@@ -25,7 +25,7 @@ CKEDITOR.htmlParser.element = function( name, attributes )
         * @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
@@ -34,8 +34,10 @@ CKEDITOR.htmlParser.element = function( name, attributes )
         */\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 ] || dtd.$nonEditable[ name ] || name == 'br' ),\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
@@ -99,18 +101,27 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                {\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
@@ -124,13 +135,26 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                                        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
@@ -143,41 +167,56 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                        // 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
@@ -185,12 +224,17 @@ CKEDITOR.htmlParser.element = function( name, attributes )
 \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