Ticket #3152: 3152.patch

File 3152.patch, 9.6 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,
     
    204204                                                return false;
    205205                                }
    206206                        }
     207       
     208                        // Check if the element can be somehow overriden.
     209                        var override = this.getOverrides()[ element.getName() ] ;
     210                        if ( override )
     211                        {
     212                                // If no attributes have been defined, remove the element.
     213                                if ( !( attribs = override.attributes ) )
     214                                        return true;
     215       
     216                                for ( var i = 0; i < attribs.length; i++ )
     217                                {
     218                                        var attName = attribs[i][0], actualAttrValue;
     219                                        if ( actualAttrValue = element.getAttribute( attName ) )
     220                                        {
     221                                                var attValue = attribs[i][1];
     222       
     223                                                // Remove the attribute if:
     224                                                //    - The override definition value is null;
     225                                                //    - The override definition valie is a string that
     226                                                //      matches the attribute value exactly.
     227                                                //    - The override definition value is a regex that
     228                                                //      has matches in the attribute value.
     229                                                if ( attValue == null ||
     230                                                                ( typeof attValue == 'string' && actualAttrValue == attValue ) ||
     231                                                                attValue.test( actualAttrValue ) )
     232                                                        return true;
     233                                        }
     234                                }
     235                        }
     236                       
     237                },
    207238
    208                         return true;
    209                 }
     239                /**
     240                 * Get the the collection used to compare the elements and attributes,
     241                 * defined in this style overrides, with other element. All information in
     242                 * it is lowercased.
     243                 */
     244                getOverrides: function()
     245                {
     246                        var overrides = {},
     247                                definition = this._.definition.overrides;
     248       
     249                        if ( definition )
     250                        {
     251                                // The override description can be a string, object or array.
     252                                // Internally, well handle arrays only, so transform it if needed.
     253                                if ( !CKEDITOR.tools.isArray( definition ) )
     254                                        definition = [ definition ];
     255       
     256                                // Loop through all override definitions.
     257                                for ( var i = 0; i < definition.length; i++ )
     258                                {
     259                                        var override = definition[i];
     260                                        var elementName;
     261                                        var overrideEl;
     262                                        var attrs;
     263       
     264                                        // If can be a string with the element name.
     265                                        if ( typeof override == 'string' )
     266                                                elementName = override.toLowerCase();
     267                                        // Or an object.
     268                                        else
     269                                        {
     270                                                elementName = override.element ? override.element.toLowerCase() : this.element;
     271                                                attrs = override.attributes;
     272                                        }
     273       
     274                                        // We can have more than one override definition for the same
     275                                        // element name, so we attempt to simply append information to
     276                                        // it if it already exists.
     277                                        overrideEl = overrides[ elementName ] || ( overrides[ elementName ] = {} );
     278       
     279                                        if ( attrs )
     280                                        {
     281                                                // The returning attributes list is an array, because we
     282                                                // could have different override definitions for the same
     283                                                // attribute name.
     284                                                var overrideAttrs = ( overrideEl.attributes = overrideEl.attributes || new Array() );
     285                                                for ( var attName in attrs )
     286                                                {
     287                                                        // Each item in the attributes array is also an array,
     288                                                        // where [0] is the attribute name and [1] is the
     289                                                        // override value.
     290                                                        overrideAttrs.push( [ attName.toLowerCase(), attrs[ attName ] ] );
     291                                                }
     292                                        }
     293                                }
     294                        }
     295                       
     296                        // Cache the overrides resolution.
     297                        return ( this.getOverrides = function(){
     298                                return overrides;
     299                        } )();
     300                },
     301               
    210302        };
    211303
    212304        // Build the cssText based on the styles definition.
     
    483575                         * elements, until a block boundary is reached.
    484576                         */
    485577                        var startPath = new CKEDITOR.dom.elementPath( startNode.getParent() );
    486                         for ( var i = 0, element ; i < startPath.elements.length && ( element = startPath.elements[i] ) ; i++ )
     578                        for ( var i = 0, element; i < startPath.elements.length && ( element = startPath.elements[i] ) ; i++ )
    487579                        {
    488580                                if ( element == startPath.block || element == startPath.blockLimit )
    489581                                        break;
     
    520612                                        endPath = new CKEDITOR.dom.elementPath( endNode.getParent() ),
    521613                                        breakStart = null,
    522614                                        breakEnd = null;
    523                                 for ( var i = 0 ; i < startPath.elements.length ; i++ )
     615                                for ( var i = 0; i < startPath.elements.length; i++ )
    524616                                {
    525617                                        var element = startPath.elements[ i ];
    526618
     
    530622                                        if ( me.checkElementRemovable( element ) )
    531623                                                breakStart = element;
    532624                                }
    533                                 for ( i = 0 ; i < endPath.elements.length ; i++ )
     625                                for ( i = 0; i < endPath.elements.length; i++ )
    534626                                {
    535627                                        element = endPath.elements[ i ];
    536628
     
    559651                                var nextNode = currentNode.getNextSourceNode();
    560652                                if ( currentNode.type == CKEDITOR.NODE_ELEMENT && this.checkElementRemovable( currentNode ) )
    561653                                {
    562                                         removeFromElement( this, currentNode );
     654                                        // Remove style from element or overriding element.
     655                                        if( currentNode.getName() == this.element )
     656                                                removeFromElement( this, currentNode );
     657                                        else   
     658                                                removeOverrides( currentNode, this.getOverrides()[ currentNode.getName() ] );
    563659
    564660                                        /*
    565661                                         * removeFromElement() may have merged the next node with something before
     
    620716//                      if ( newBlockIsPre )
    621717//                      {
    622718//                              if ( previousPreBlock )
    623 //                                      this._CheckAndMergePre( previousPreBlock, newBlock ) ;  // Merge successive <pre> blocks.
     719//                                      this._CheckAndMergePre( previousPreBlock, newBlock );   // Merge successive <pre> blocks.
    624720//                              previousPreBlock = newBlock;
    625721//                      }
    626722//                      else if ( fromPre )
    627 //                              this._CheckAndSplitPre( newBlock ) ;    // Split <br><br> in successive <pre>s.
     723//                              this._CheckAndSplitPre( newBlock );     // Split <br><br> in successive <pre>s.
    628724                }
    629725
    630726                range.moveToBookmark( bookmark );
     
    635731        {
    636732                var def = style._.definition,
    637733                        attributes = def.attributes,
    638                         styles = def.styles;
    639 
     734                        styles = def.styles,
     735                        overrides = style.getOverrides();
     736               
    640737                for ( var attName in attributes )
    641738                {
    642739                        // The 'class' element value must match (#1318).
     
    648745                for ( var styleName in styles )
    649746                        element.removeStyle( styleName );
    650747
     748                // Now scan override styles on the element.
     749                attributes = overrides[ element.getName() ];
     750                if( attributes )
     751                {
     752                        for( attName in attributes )
     753                        {
     754                                // The 'class' element value must match (#1318).
     755                                if ( attName == 'class' && element.getAttribute( attName ) != attributes[ attName ] )
     756                                        continue;
     757                                element.removeAttribute( attName );
     758                        }
     759                }
    651760                removeNoAttribsElement( element );
    652761        }
    653762
     
    654763        // Removes a style from inside an element.
    655764        function removeFromInsideElement( style, element )
    656765        {
    657                 var def = style._.definition;
    658                 var attribs = def.attributes;
    659                 var styles = def.styles;
     766                var def = style._.definition,
     767                        attribs = def.attributes,
     768                        styles = def.styles,
     769                        overrides = style.getOverrides();
    660770
    661771                var innerElements = element.getElementsByTag( style.element );
    662772
    663                 for ( var i = innerElements.count() ; --i >= 0 ; )
    664                         removeFromElement( style, innerElements.getItem( i ) );
     773                for ( var i = innerElements.count(); --i >= 0; )
     774                        removeFromElement( style,  innerElements.getItem( i ) );
     775
     776                // Now remove any other element with different name that is
     777                // defined to be overriden.
     778                for ( var overrideElement in overrides )
     779                {
     780                        if ( overrideElement != style.element )
     781                        {
     782                                var innerElements = element.getElementsByTag( overrideElement ) ;
     783                                for ( var i = innerElements.count() - 1; i >= 0 ; i-- )
     784                                {
     785                                        var innerElement = innerElements.getItem( i );
     786                                        removeOverrides( innerElement, overrides[ overrideElement ] ) ;
     787                                }
     788                        }
     789                }
     790
    665791        }
     792       
     793        /**
     794         *  Remove overriding styles/attributes from the specific element.
     795         *  Note: Remove the element if no attributes remain.
     796         * @param {Object} element
     797         * @param {Object} overrides
     798         */
     799        function removeOverrides( element, overrides )
     800        {
     801                var attributes = overrides && overrides.attributes ;
    666802
     803                if ( attributes )
     804                {
     805                        for ( var i = 0 ; i < attributes.length ; i++ )
     806                        {
     807                                var attName = attributes[i][0], actualAttrValue ;
     808
     809                                if ( actualAttrValue = element.getAttribute( attName ) )
     810                                {
     811                                        var attValue    = attributes[i][1] ;
     812
     813                                        // Remove the attribute if:
     814                                        //    - The override definition value is null ;
     815                                        //    - The override definition valie is a string that
     816                                        //      matches the attribute value exactly.
     817                                        //    - The override definition value is a regex that
     818                                        //      has matches in the attribute value.
     819                                        if ( attValue == null ||
     820                                                        ( attValue.test && attValue.test( actualAttrValue ) ) ||
     821                                                        ( typeof attValue == 'string' && actualAttrValue == attValue ) )
     822                                                element.removeAttribute( attName ) ;
     823                                }
     824                        }
     825                }
     826               
     827                removeNoAttribsElement( element );
     828        }
     829       
    667830        // If the element has no more attributes, remove it.
    668831        function removeNoAttribsElement( element )
    669832        {
     
    821984                // Return it, saving it to the next request.
    822985                return ( styleDefinition._AC = attribs );
    823986        }
    824 
     987       
    825988        function normalizeCssText( unparsedCssText )
    826989        {
    827990                // Injects the style in a temporary span object, so the browser parses it,
     
    8611024                var func = remove ? this.removeFromRange : this.applyToRange;
    8621025
    8631026                // Apply the style to the ranges.
    864                 for ( var i = 0 ; i < ranges.length ; i++ )
     1027                for ( var i = 0; i < ranges.length; i++ )
    8651028                        func.call( this, ranges[ i ] );
    8661029
    8671030                // Select the ranges again.
© 2003 – 2015 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy