Ticket #3152: 3152_3.patch

File 3152_3.patch, 9.5 KB (added by garry.yao, 6 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 – 2015 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy