Ticket #3152: 3152_3.patch

File 3152_3.patch, 9.5 KB (added by garry.yao, 5 years ago)
  • _source/plugins/styles/plugin.js

     
    176176                // current style definition. 
    177177                checkElementRemovable : function( element, fullMatch ) 
    178178                { 
    179                         if ( !element || element.getName() != this.element ) 
     179                        if ( !element ) 
    180180                                return false; 
    181181 
    182182                        var def = this._.definition, 
     
    182182                        var def = this._.definition, 
    183183                                attribs; 
    184184 
    185                         // If no attributes are defined in the element. 
    186                         if ( !fullMatch && !element.hasAttributes() ) 
    187                                 return true; 
    188  
    189                         attribs = getAttributesForComparison( def ); 
     185                        // If the element name is the same as the style name. 
     186                        if ( element.getName() == this.element )  
     187                        { 
     188                                // If no attributes are defined in the element. 
     189                                if ( !fullMatch && !element.hasAttributes() )  
     190                                        return true; 
     191                                 
     192                                attribs = getAttributesForComparison( def ); 
     193                                 
     194                                if ( attribs._length )  
     195                                { 
     196                                        for ( var attName in attribs )  
     197                                        { 
     198                                                if ( attName == '_length' )  
     199                                                        continue; 
     200                                                 
     201                                                if ( compareAttributeValues(attName, attribs[attName], element.getAttribute( attName ) ) )  
     202                                                { 
     203                                                        if ( !fullMatch )  
     204                                                                return true; 
     205                                                } 
     206                                                else if ( fullMatch )  
     207                                                                return false; 
     208                                        } 
     209                                } 
     210                                else 
     211                                        return true; 
     212                        } 
    190213 
    191                         if ( attribs._length ) 
     214                        // Check if the element can be somehow overriden. 
     215                        var override = getOverrides( this )[ element.getName() ] ; 
     216                        if ( override ) 
    192217                        { 
    193                                 for ( var attName in attribs ) 
     218                                // If no attributes have been defined, remove the element. 
     219                                if ( !( attribs = override.attributes ) )  
     220                                        return true; 
     221         
     222                                for ( var i = 0 ; i < attribs.length ; i++ ) 
    194223                                { 
    195                                         if ( attName == '_length' ) 
    196                                                 continue; 
    197  
    198                                         if ( compareAttributeValues( attName, attribs[ attName ], element.getAttribute( attName ) ) ) 
     224                                        var attName = attribs[i][0], actualAttrValue; 
     225                                        if ( actualAttrValue = element.getAttribute( attName ) ) 
    199226                                        { 
    200                                                 if ( !fullMatch ) 
     227                                                var attValue = attribs[i][1]; 
     228         
     229                                                // Remove the attribute if: 
     230                                                //    - The override definition value is null; 
     231                                                //    - The override definition valie is a string that 
     232                                                //      matches the attribute value exactly. 
     233                                                //    - The override definition value is a regex that 
     234                                                //      has matches in the attribute value. 
     235                                                if ( attValue == null || 
     236                                                                ( typeof attValue == 'string' && actualAttrValue == attValue ) || 
     237                                                                attValue.test( actualAttrValue ) ) 
    201238                                                        return true; 
    202239                                        } 
    203                                         else if ( fullMatch ) 
    204                                                 return false; 
    205240                                } 
    206241                        } 
    207  
    208                         return true; 
     242                        return false; 
    209243                } 
    210244        }; 
    211245 
     
    483517                         * elements, until a block boundary is reached. 
    484518                         */ 
    485519                        var startPath = new CKEDITOR.dom.elementPath( startNode.getParent() ); 
    486                         for ( var i = 0, element ; i < startPath.elements.length && ( element = startPath.elements[i] )  ; i++ ) 
     520                        for ( var i = 0, element ; i < startPath.elements.length && ( element = startPath.elements[i] ) ; i++ ) 
    487521                        { 
    488522                                if ( element == startPath.block || element == startPath.blockLimit ) 
    489523                                        break; 
     
    559593                                var nextNode = currentNode.getNextSourceNode(); 
    560594                                if ( currentNode.type == CKEDITOR.NODE_ELEMENT && this.checkElementRemovable( currentNode ) ) 
    561595                                { 
    562                                         removeFromElement( this, currentNode ); 
     596                                        // Remove style from element or overriding element. 
     597                                        if( currentNode.getName() == this.element ) 
     598                                                removeFromElement( this, currentNode ); 
     599                                        else     
     600                                                removeOverrides( currentNode, getOverrides( this )[ currentNode.getName() ] ); 
    563601 
    564602                                        /* 
    565603                                         * removeFromElement() may have merged the next node with something before 
     
    635673        { 
    636674                var def = style._.definition, 
    637675                        attributes = def.attributes, 
    638                         styles = def.styles; 
     676                        styles = def.styles, 
     677                        overrides = getOverrides( style ); 
    639678 
    640                 for ( var attName in attributes ) 
     679                function removeAttrs() 
    641680                { 
    642                         // The 'class' element value must match (#1318). 
    643                         if ( attName == 'class' && element.getAttribute( attName ) != attributes[ attName ] ) 
    644                                 continue; 
    645                         element.removeAttribute( attName ); 
     681                        for ( var attName in attributes ) 
     682                        { 
     683                                // The 'class' element value must match (#1318). 
     684                                if ( attName == 'class' && element.getAttribute( attName ) != attributes[ attName ] ) 
     685                                        continue; 
     686                                element.removeAttribute( attName ); 
     687                        } 
    646688                } 
    647  
     689                 
     690                // Remove definition attributes/style from the elemnt.           
     691                removeAttrs(); 
    648692                for ( var styleName in styles ) 
    649693                        element.removeStyle( styleName ); 
    650694 
     695                // Now remove override styles on the element. 
     696                attributes = overrides[ element.getName() ]; 
     697                if( attributes ) 
     698                        removeAttrs(); 
    651699                removeNoAttribsElement( element ); 
    652700        } 
    653701 
     
    654702        // Removes a style from inside an element. 
    655703        function removeFromInsideElement( style, element ) 
    656704        { 
    657                 var def = style._.definition; 
    658                 var attribs = def.attributes; 
    659                 var styles = def.styles; 
     705                var def = style._.definition, 
     706                        attribs = def.attributes, 
     707                        styles = def.styles, 
     708                        overrides = getOverrides( style ); 
    660709 
    661710                var innerElements = element.getElementsByTag( style.element ); 
    662711 
    663                 for ( var i = innerElements.count() ; --i >= 0 ; ) 
    664                         removeFromElement( style, innerElements.getItem( i ) ); 
     712                for ( var i = innerElements.count(); --i >= 0 ; ) 
     713                        removeFromElement( style,  innerElements.getItem( i ) ); 
     714 
     715                // Now remove any other element with different name that is 
     716                // defined to be overriden. 
     717                for ( var overrideElement in overrides ) 
     718                { 
     719                        if ( overrideElement != style.element ) 
     720                        { 
     721                                var innerElements = element.getElementsByTag( overrideElement ) ; 
     722                                for ( var i = innerElements.count() - 1 ; i >= 0 ; i-- ) 
     723                                { 
     724                                        var innerElement = innerElements.getItem( i ); 
     725                                        removeOverrides( innerElement, overrides[ overrideElement ] ) ; 
     726                                } 
     727                        } 
     728                } 
     729 
    665730        } 
     731         
     732        /** 
     733         *  Remove overriding styles/attributes from the specific element. 
     734         *  Note: Remove the element if no attributes remain. 
     735         * @param {Object} element 
     736         * @param {Object} overrides 
     737         */ 
     738        function removeOverrides( element, overrides ) 
     739        { 
     740                var attributes = overrides && overrides.attributes ; 
    666741 
     742                if ( attributes ) 
     743                { 
     744                        for ( var i = 0 ; i < attributes.length ; i++ ) 
     745                        { 
     746                                var attName = attributes[i][0], actualAttrValue ; 
     747 
     748                                if ( actualAttrValue = element.getAttribute( attName ) ) 
     749                                { 
     750                                        var attValue    = attributes[i][1] ; 
     751 
     752                                        // Remove the attribute if: 
     753                                        //    - The override definition value is null ; 
     754                                        //    - The override definition valie is a string that 
     755                                        //      matches the attribute value exactly. 
     756                                        //    - The override definition value is a regex that 
     757                                        //      has matches in the attribute value. 
     758                                        if ( attValue == null || 
     759                                                        ( attValue.test && attValue.test( actualAttrValue ) ) || 
     760                                                        ( typeof attValue == 'string' && actualAttrValue == attValue ) ) 
     761                                                element.removeAttribute( attName ) ; 
     762                                } 
     763                        } 
     764                } 
     765                 
     766                removeNoAttribsElement( element ); 
     767        } 
     768         
    667769        // If the element has no more attributes, remove it. 
    668770        function removeNoAttribsElement( element ) 
    669771        { 
     
    822924                return ( styleDefinition._AC = attribs ); 
    823925        } 
    824926 
     927        /** 
     928         * Get the the collection used to compare the elements and attributes, 
     929         * defined in this style overrides, with other element. All information in 
     930         * it is lowercased. 
     931         * @param {CKEDITOR.style} style 
     932         */ 
     933        function getOverrides( style ) 
     934        { 
     935                if( style._.overrides ) 
     936                        return style._.overrides; 
     937 
     938                var overrides = ( style._.overrides = {} ),  
     939                        definition = style._.definition.overrides; 
     940                 
     941                if ( definition ) 
     942                { 
     943                        // The override description can be a string, object or array. 
     944                        // Internally, well handle arrays only, so transform it if needed. 
     945                        if ( !CKEDITOR.tools.isArray( definition ) ) 
     946                                definition = [ definition ]; 
     947 
     948                        // Loop through all override definitions. 
     949                        for ( var i = 0 ; i < definition.length ; i++ ) 
     950                        { 
     951                                var override = definition[i]; 
     952                                var elementName; 
     953                                var overrideEl; 
     954                                var attrs; 
     955 
     956                                // If can be a string with the element name. 
     957                                if ( typeof override == 'string' ) 
     958                                        elementName = override.toLowerCase(); 
     959                                // Or an object. 
     960                                else 
     961                                { 
     962                                        elementName = override.element ? override.element.toLowerCase() : style.element; 
     963                                        attrs = override.attributes; 
     964                                } 
     965 
     966                                // We can have more than one override definition for the same 
     967                                // element name, so we attempt to simply append information to 
     968                                // it if it already exists. 
     969                                overrideEl = overrides[ elementName ] || ( overrides[ elementName ] = {} ); 
     970 
     971                                if ( attrs ) 
     972                                { 
     973                                        // The returning attributes list is an array, because we 
     974                                        // could have different override definitions for the same 
     975                                        // attribute name. 
     976                                        var overrideAttrs = ( overrideEl.attributes = overrideEl.attributes || new Array() ); 
     977                                        for ( var attName in attrs ) 
     978                                        { 
     979                                                // Each item in the attributes array is also an array, 
     980                                                // where [0] is the attribute name and [1] is the 
     981                                                // override value. 
     982                                                overrideAttrs.push( [ attName.toLowerCase(), attrs[ attName ] ] ); 
     983                                        } 
     984                                } 
     985                        } 
     986                } 
     987                 
     988                return overrides; 
     989        } 
     990         
    825991        function normalizeCssText( unparsedCssText ) 
    826992        { 
    827993                // Injects the style in a temporary span object, so the browser parses it, 
© 2003 – 2012 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy