JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.6.4
[ckeditor.git] / _source / core / htmlparser / element.js
index 2e9a9c3..2795eb7 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2012, 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 || ( attributes = {} );\r
+       this.attributes = attributes || {};\r
 \r
        /**\r
         * The nodes that are direct children of this element.\r
@@ -34,20 +34,82 @@ CKEDITOR.htmlParser.element = function( name, attributes )
         */\r
        this.children = [];\r
 \r
-       var tagName = attributes._cke_real_element_type || name;\r
+       // Reveal the real semantic of our internal custom tag name (#6639),\r
+       // when resolving whether it's block like.\r
+       var realName = name || '',\r
+               prefixed = realName.match( /^cke:(.*)/ );\r
+       prefixed && ( realName = prefixed[ 1 ] );\r
 \r
-       var dtd                 = CKEDITOR.dtd,\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
+       var isBlockLike = !!( CKEDITOR.dtd.$nonBodyContent[ realName ]\r
+                               || CKEDITOR.dtd.$block[ realName ]\r
+                               || CKEDITOR.dtd.$listItem[ realName ]\r
+                               || CKEDITOR.dtd.$tableContent[ realName ]\r
+                               || CKEDITOR.dtd.$nonEditable[ realName ]\r
+                               || realName == 'br' );\r
 \r
-       this.isEmpty    = isEmpty;\r
-       this.isUnknown  = !dtd[ name ];\r
+       this.isEmpty    = !!CKEDITOR.dtd.$empty[ name ];\r
+       this.isUnknown  = !CKEDITOR.dtd[ name ];\r
 \r
        /** @private */\r
        this._ =\r
        {\r
                isBlockLike : isBlockLike,\r
-               hasInlineStarted : isEmpty || !isBlockLike\r
+               hasInlineStarted : this.isEmpty || !isBlockLike\r
+       };\r
+};\r
+\r
+/**\r
+ *  Object presentation of  CSS style declaration text.\r
+ *  @param {CKEDITOR.htmlParser.element|String} elementOrStyleText A html parser element or the inline style text.\r
+ */\r
+CKEDITOR.htmlParser.cssStyle = function()\r
+{\r
+        var styleText,\r
+               arg = arguments[ 0 ],\r
+               rules = {};\r
+\r
+       styleText = arg instanceof CKEDITOR.htmlParser.element ? arg.attributes.style : arg;\r
+\r
+       // html-encoded quote might be introduced by 'font-family'\r
+       // from MS-Word which confused the following regexp. e.g.\r
+       //'font-family: "Lucida, Console"'\r
+       ( styleText || '' )\r
+               .replace( /"/g, '"' )\r
+               .replace( /\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,\r
+                       function( match, name, value )\r
+                       {\r
+                               name == 'font-family' && ( value = value.replace( /["']/g, '' ) );\r
+                               rules[ name.toLowerCase() ] = value;\r
+                       });\r
+\r
+       return {\r
+\r
+               rules : rules,\r
+\r
+               /**\r
+                *  Apply the styles onto the specified element or object.\r
+                * @param {CKEDITOR.htmlParser.element|CKEDITOR.dom.element|Object} obj\r
+                */\r
+               populate : function( obj )\r
+               {\r
+                       var style = this.toString();\r
+                       if ( style )\r
+                       {\r
+                               obj instanceof CKEDITOR.dom.element ?\r
+                                       obj.setAttribute( 'style', style ) :\r
+                                       obj instanceof CKEDITOR.htmlParser.element ?\r
+                                               obj.attributes.style = style :\r
+                                               obj.style = style;\r
+                       }\r
+               },\r
+\r
+               toString : function()\r
+               {\r
+                       var output = [];\r
+                       for ( var i in rules )\r
+                               rules[ i ] && output.push( i, ':', rules[ i ], ';' );\r
+                       return output.join( '' );\r
+               }\r
        };\r
 };\r
 \r
@@ -114,11 +176,11 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                         */\r
                        element.filterChildren = function()\r
                        {\r
-                               if( !isChildrenFiltered )\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
+                                       element.children = new CKEDITOR.htmlParser.fragment.fromHtml( writer.getHtml(), 0, element.clone() ).children;\r
                                        isChildrenFiltered = 1;\r
                                }\r
                        };\r
@@ -154,6 +216,10 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                                        // filter but not the children.\r
                                        if ( !writeName )\r
                                        {\r
+                                               // Fix broken parent refs.\r
+                                               for ( var c = 0, length = this.children.length ; c < length ; c++ )\r
+                                                       this.children[ c ].parent = element.parent;\r
+\r
                                                this.writeChildrenHtml.call( element, writer, isChildrenFiltered ? null : filter );\r
                                                return;\r
                                        }\r
@@ -171,13 +237,13 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                        var attribsArray = [];\r
                        // Iterate over the attributes twice since filters may alter\r
                        // other attributes.\r
-                       for( var i = 0 ; i < 2; i++ )\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
+                                       if ( i == 1 )\r
                                                attribsArray.push( [ a, value ] );\r
                                        else if ( filter )\r
                                        {\r
@@ -188,7 +254,7 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                                                                delete attributes[ a ];\r
                                                                break;\r
                                                        }\r
-                                                       else if( newAttrName != a )\r
+                                                       else if ( newAttrName != a )\r
                                                        {\r
                                                                delete attributes[ a ];\r
                                                                a = newAttrName;\r
@@ -197,9 +263,9 @@ CKEDITOR.htmlParser.element = function( name, attributes )
                                                        else\r
                                                                break;\r
                                                }\r
-                                               if( newAttrName )\r
+                                               if ( newAttrName )\r
                                                {\r
-                                                       if( ( value = filter.onAttribute( element, newAttrName, value ) ) === false )\r
+                                                       if ( ( value = filter.onAttribute( element, newAttrName, value ) ) === false )\r
                                                                delete attributes[ newAttrName ];\r
                                                        else\r
                                                                attributes [ newAttrName ] = value;\r