Ticket #2885: 2885_2.patch

File 2885_2.patch, 15.1 KB (added by Garry Yao, 9 years ago)
  • _source/plugins/toolbar/plugin.js

     
    214214                'Subscript', 'Superscript', '-',
    215215                'SelectAll', 'RemoveFormat', '-',
    216216                'Link', 'Unlink', 'Anchor', '-',
    217                 'Table', 'Smiley', 'HorizontalRule', 'SpecialChar', 'PageBreak'
     217                'Table', 'Smiley', 'HorizontalRule', 'SpecialChar', 'PageBreak','-',
     218                'CreateDiv'
    218219        ]
    219220];
  • _source/plugins/newcontainer/dialogs/newcontainer.js

     
     1/*
     2 * Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     3 * For licensing, see LICENSE.html or http://ckeditor.com/license
     4 */
     5
     6CKEDITOR.dialog.add('newcontainer', function(editor) {
     7
     8        /**
     9         * Init all fields' setup/commit function.
     10         * @memberof newcontainerDialog
     11         */
     12        function setupFields()
     13        {
     14                this.foreach( function( field )
     15                {
     16                        //Exclude layout container elements
     17                        if( /^(?!vbox|hbox)/.test( field.type ))       
     18                        {
     19                                if ( !field.setup )
     20                                {
     21                                        // Read the dialog fields values from the specified
     22                                        // element attributes.
     23                                        field.setup = function( element )
     24                                        {
     25                                                field.setValue( element.getAttribute( field.id ) || '' );
     26                                        };
     27                                }
     28                                if ( !field.commit )
     29                                {
     30                                        // Set element attributes assigned by the dialog
     31                                        // fields.
     32                                        field.commit = function( element )
     33                                        {
     34                                                var fieldValue = this.getValue();
     35                                                // ignore default element attribute values
     36                                                if ( 'dir' === field.id
     37                                                        && element.getComputedStyle( 'direction' ) === fieldValue )
     38                                                        return true;
     39                                                if ( fieldValue )
     40                                                        element.setAttribute( field.id, fieldValue );
     41                                        };
     42                                }
     43                        }
     44                } );
     45        }
     46       
     47        /**
     48         * Either create or detect the desired block containers among the selected ranges.
     49         * @param {Object} editor
     50         * @param {Object} containerTagName The tagName of the container.
     51         * @param {Object} isCreate Whether it's a creation process OR a detection process.
     52         */     
     53        function applyContainer(editor, containerTagName, isCreate)
     54        {
     55                // new adding containers OR detected pre-existed containers.
     56                var containers = [],
     57                // node markers store.
     58                database = {},
     59                // All block level elements which contained by the ranges.
     60                containedBlocks = [], block;
     61
     62                // Get all ranges from the selection.
     63                var selection = editor.document.getSelection();
     64                var ranges = selection.getRanges();
     65                var i, l = ranges.length, iterator;
     66
     67                // Get the DTD definition for the element.
     68                var dtd = CKEDITOR.dtd[ containerTagName ];
     69                // collect all included block level elements
     70                for( i = 0 ; i < l ; i++ )
     71                {
     72                        iterator = ranges[ i ].createIterator();
     73                        while( ( block = iterator.getNextParagraph() ) )
     74                        {
     75                                // bypass dtd disallowed elements.
     76                                while( !dtd[ block.getName() ] )
     77                                        block = block.getParent();
     78                                       
     79                                // avoid duplicate
     80                                if ( !block.getCustomData( 'block_processed' ) )
     81                                {
     82                                        CKEDITOR.dom.element.setMarker( database, block,
     83                                                'block_processed', true );
     84                                        containedBlocks.push( block );
     85                                }
     86                        }
     87                }
     88               
     89                CKEDITOR.dom.element.clearAllMarkers(database);
     90               
     91                var blockGroups = groupByBlockLimit( containedBlocks ), l = blockGroups.length, ancestor, blockEl, containerEl;
     92                for( i = 0 ; i < l ; i++ )
     93                {
     94                        // Calculate the common parent node of all content blocks.
     95                        ancestor = blockGroups[ i ][0].getParent();
     96                        var j  = 1, s = blockGroups[ i ].length;
     97                        for ( ; j < s; i++ )
     98                                ancestor = ancestor.getCommonAncestor( blockGroups[ i ][j]);
     99                       
     100                        if(isCreate)
     101                        {
     102                                containerEl = new CKEDITOR.dom.element( containerTagName ,
     103                                        editor.document );
     104                        }
     105                       
     106                        var j, s = blockGroups[ i ].length,
     107                        //Wrapped blocks counting
     108                        childCount = 0;
     109                        for( j = 0 ; j < s ; j++ )
     110                        {
     111                                blockEl = blockGroups[ i ][ j ];
     112
     113                                // Reconstruct the block list to only contain direct
     114                                // children of common ancestor.
     115                                while( !blockEl.getParent().equals( ancestor ) )
     116                                        blockEl = blockEl.getParent();
     117
     118                                // avoid duplicate
     119                                if ( !blockEl.getCustomData( 'block_processed' ) )
     120                                {
     121                                        CKEDITOR.dom.element.setMarker( database, blockEl, 'block_processed', true );
     122                                        if( isCreate )
     123                                        {
     124                                                // Establish new container, wrapping all
     125                                                // elements in this group.
     126                                                if( j === 0 )
     127                                                        containerEl.insertBefore( blockEl );
     128                                                containerEl.append( blockEl );
     129                                        }
     130                                        else
     131                                                childCount++;
     132                                }
     133                        }
     134                        CKEDITOR.dom.element.clearAllMarkers( database );
     135
     136                        if( isCreate )
     137                        {
     138                                // drop pre-existed container, since new container already
     139                                // established.
     140                                if ( !editor.config.newcontainer_alwaysCreate &&
     141                                                ancestor.getName() === containerTagName
     142                                                && 1 === ancestor.getNonEmptyChildren().length )
     143                                                ancestor.remove( true );
     144                                containers.push( containerEl );
     145                        }
     146                        else
     147                        {
     148                                // discover existed container
     149                                if ( ancestor.getName() === containerTagName
     150                                        && childCount === ancestor.getNonEmptyChildren().length )
     151                                        containers.push( ancestor );
     152                        }
     153                }
     154
     155                return containers;
     156        }
     157       
     158        /**
     159         * Divide a set of nodes to different groups by their path's blocklimit element.
     160         * Note: the specified nodes should be in source order naturally, which mean they are supposed to producea by following class:
     161         *  * CKEDITOR.dom.range.Iterator
     162         *  * CKEDITOR.dom.domWalker
     163         *  @return {Array []} the grouped nodes
     164         */
     165        function groupByBlockLimit(nodes)
     166        {
     167                var groups = [],
     168                        lastBlockLimit = null,
     169                        path, block;
     170                for ( var i = 0 ; i < nodes.length ; i++ )
     171                {
     172                        block = nodes[i] ;
     173                        path = new CKEDITOR.dom.elementPath( block ) ;
     174                        if ( !path.blockLimit.equals(lastBlockLimit ) )
     175                        {
     176                                groups.push( [] ) ;
     177                                lastBlockLimit = path.blockLimit ;
     178                        }
     179                        groups[groups.length - 1].push( block ) ;
     180                }
     181                return groups;
     182        }
     183       
     184       
     185        function compareNodes()
     186        {
     187                return arguments[0].equals(arguments[1]);
     188        }
     189       
     190        /**
     191         * Hold a collection of created block container elements. 
     192         */
     193        var containers = [];
     194        /**
     195         * @type newcontainerDialog
     196         */
     197        return {
     198                title : editor.lang.newcontainer.title,
     199                minWidth : 400,
     200                minHeight : 320,
     201                contents :
     202                [
     203                {
     204                        id :'info',
     205                        label :editor.lang.common.generalTab,
     206                        title :editor.lang.common.generalTab,
     207                        elements :
     208                        [
     209                                {
     210                                        type :'hbox',
     211                                        widths : [ '50%', '50%' ],
     212                                        children :
     213                                        [
     214                                                {
     215                                                        id :'elementStyle',
     216                                                        type :'select',
     217                                                        style :'width: 100%;',
     218                                                        label :editor.lang.newcontainer.styleSelectLabel,
     219                                                        'default' :editor.config.newcontainer_defaultStyle,
     220                                                        items : [],
     221                                                        setup : function(){
     222                                                                //TODO: Read 'elementStyle' field
     223                                                        },
     224                                                        commit: function()
     225                                                        {
     226                                                                //TODO: Commit 'elementStyle' field value
     227                                                        }
     228                                                // TODO: Fill 'elementStyle' selection options.
     229                                                },
     230                                                {
     231                                                        id :'class',
     232                                                        type :'text',
     233                                                        label :editor.lang.newcontainer.cssClassInputLabel,
     234                                                        'default' :editor.config.newcontainer_defaultCssClass
     235                                                }
     236                                        ]
     237                                }
     238                        ]
     239                },
     240                {
     241                                id :'advanced',
     242                                label :editor.lang.common.advancedTab,
     243                                title :editor.lang.common.advancedTab,
     244                                elements :
     245                                [
     246                                {
     247                                        type :'vbox',
     248                                        padding :1,
     249                                        children :
     250                                        [
     251                                                {
     252                                                        type :'hbox',
     253                                                        widths : [ '50%', '50%' ],
     254                                                        children :
     255                                                        [
     256                                                                {
     257                                                                        type :'text',
     258                                                                        id :'id',
     259                                                                        label :editor.lang.newcontainer.IdInputLabel,
     260                                                                        'default' :editor.config.newcontainer_defaultId
     261                                                                },
     262                                                                {
     263                                                                        type :'text',
     264                                                                        id :'lang',
     265                                                                        label :editor.lang.newcontainer.languageCodeInputLabel,
     266                                                                        'default' :editor.config.newcontainer_defaultLanguageCode
     267                                                                }
     268                                                        ]
     269                                                },
     270                                                {
     271                                                        type :'hbox',
     272                                                        children :
     273                                                        [
     274                                                                        {
     275                                                                                type :'text',
     276                                                                                id :'style',
     277                                                                                style :'width: 100%;',
     278                                                                                label :editor.lang.newcontainer.inlineStyleInputLabel,
     279                                                                                'default' :editor.config.newcontainer_defaultInlineStyle
     280                                                                        }
     281                                                        ]
     282                                                },
     283                                                {
     284                                                        type :'hbox',
     285                                                        children :
     286                                                        [
     287                                                                        {
     288                                                                                type :'text',
     289                                                                                id :'title',
     290                                                                                style :'width: 100%;',
     291                                                                                label :editor.lang.newcontainer.advisoryTitleInputLabel,
     292                                                                                'default' :editor.config.newcontainer_defaultAdvisoryTitle
     293                                                                        }
     294                                                        ]
     295                                                },
     296                                                {
     297                                                        type :'select',
     298                                                        id :'dir',
     299                                                        style :'width: 100%;',
     300                                                        label :editor.lang.newcontainer.langDirLabel,
     301                                                        'default' :editor.config.newcontainer_defaultLangDirLabel,
     302                                                        items :
     303                                                        [
     304                                                                [
     305                                                                        editor.lang.newcontainer.langDirOptions.langDirLTRLabel,
     306                                                                        'ltr'
     307                                                                ],
     308                                                                [
     309                                                                        editor.lang.newcontainer.langDirOptions.langDirRTLLabel,
     310                                                                        'rtl'
     311                                                                ]
     312                                                        ]
     313                                                }
     314                                        ]
     315                                }
     316                                ]
     317                        }
     318                ],
     319                onLoad : function()
     320                {
     321                        setupFields.call(this);
     322                },
     323                onShow : function()
     324                {
     325                        containers = [];
     326                        // Whether always create new container regardless of existed
     327                        // ones.
     328                        if( !editor.config.newcontainer_alwaysCreate )
     329                        {
     330                                if( CKEDITOR.env.ie )
     331                                        this.restoreSelection();
     332                                // Try to collect the containers that already existed in
     333                                // ranges
     334                                containers = applyContainer( editor, 'div' );
     335                                if( containers.length )
     336                                {
     337                                        this._element = containers[0];
     338                                        // update dialog field values
     339                                        this.setupContent(this._element);
     340                                }
     341                        }
     342                },
     343                onOk : function()
     344                {
     345                        if( CKEDITOR.env.ie )
     346                                this.restoreSelection();
     347                        containers = applyContainer( editor, 'div', true );
     348                       
     349                        // update elements attributes
     350                        var i, l = containers.length;
     351                        for( i = 0 ; i < l ; i++ )
     352                        {
     353                                this.commitContent( containers[ i ] );
     354                        }
     355                        this.hide();
     356                }
     357        };
     358});
  • _source/plugins/newcontainer/plugin.js

     
     1/*
     2Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     3For licensing, see LICENSE.html or http://ckeditor.com/license
     4*/
     5
     6/**
     7 * @fileOverview The "newcontainer" plugin. It wraps the selected block level elements with a 'div' element with specified styles and attributes.
     8 *
     9 */
     10
     11CKEDITOR.plugins.add( 'newcontainer',
     12{
     13        requires : [ 'editingblock', 'domiterator', 'elementspath' ],
     14
     15        init : function( editor ){
     16       
     17                editor.addCommand( 'creatediv', new CKEDITOR.dialogCommand(
     18                        'newcontainer' ) );
     19                editor.ui.addButton( 'CreateDiv', {
     20                        label :editor.lang.newcontainer.toolbar,
     21                        command :'creatediv'
     22                } );
     23                CKEDITOR.dialog.add( 'newcontainer',
     24                        this.path + 'dialogs/newcontainer.js' );
     25        }
     26} );
     27
     28CKEDITOR.tools.extend(CKEDITOR.config,
     29{
     30        /**
     31         * Whether ignore the pre-existed containers
     32         */
     33        newcontainer_alwaysCreate : false,
     34        newcontainer_defaultCssClass :'',
     35        newcontainer_defaultStyle :'',
     36        newcontainer_defaultId :'',
     37        newcontainer_defaultLanguageCode :'',
     38        newcontainer_defaultInlineStyle :'',
     39        newcontainer_defaultAdvisoryTitle :'',
     40        newcontainer_defaultLangDir :''
     41});
  • _source/core/dom/element.js

     
    9696        var names = element.getCustomData( 'list_marker_names' ),
    9797                id = element.getCustomData( 'list_marker_id' );
    9898        for ( var i in names )
    99                 element.removeCustomData( names[i] );
     99                element.removeCustomData( i );
    100100        element.removeCustomData( 'list_marker_names' );
    101101        if ( removeFromDatabase )
    102102        {
     
    392392                {
    393393                        return new CKEDITOR.dom.nodeList( this.$.childNodes );
    394394                },
     395               
     396                /**
     397                 * Same as CKEDITOR.dom.element::getChildren except this method ignore
     398                 * text nodes which contains only blank characters.
     399                 * @return {Array} 
     400                 */
     401                getNonEmptyChildren : function()
     402                {
     403                        var resultsChilds = [];
     404                        var children = this.getChildren();
     405                        var i, l = children.count(), child;
     406                        for( i = 0 ; i < l ; i++ )
     407                        {
     408                                child = children.getItem( i );
     409                                if( ! ( child.type === CKEDITOR.NODE_TEXT
     410                                        && /^[ \t\n\r]+$/.test( child.getText() ) ) )
     411                                        resultsChilds.push( child );
     412                        }
     413                        return resultsChilds;
     414                },
    395415
    396416                /**
    397417                 * Gets the current computed value of one of the element CSS style
  • _source/core/config.js

     
    147147         * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea';
    148148         */
    149149
    150         plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,preview,removeformat,smiley,indent,link,list,sourcearea,table,specialchar,tab,toolbar,wysiwygarea',
     150        plugins : 'basicstyles,button,elementspath,horizontalrule,htmldataprocessor,keystrokes,newpage,pagebreak,preview,removeformat,smiley,indent,link,list,sourcearea,table,specialchar,tab,toolbar,wysiwygarea,newcontainer',
    151151
    152152        /**
    153153         * The theme to be used to build the UI.
  • _source/lang/en.js

     
    379379        numberedlist : 'Insert/Remove Numbered List',
    380380        bulletedlist : 'Insert/Remove Bulleted List',
    381381        indent : 'Increase Indent',
    382         outdent : 'Decrease Indent'
     382        outdent : 'Decrease Indent',
     383       
     384        newcontainer :
     385        {
     386                title: 'Create Div Container',
     387                toolbar: 'Create Div Container',
     388                cssClassInputLabel : 'Stylesheet Classes',
     389                styleSelectLabel : 'Style',
     390                IdInputLabel: 'Id',
     391                languageCodeInputLabel : ' Language Code',
     392                inlineStyleInputLabel : 'Inline Style',
     393                advisoryTitleInputLabel : 'Advisory Title',
     394                langDirLabel : 'Language Direction',
     395                langDirOptions : {
     396                        langDirLTRLabel : 'Left to Right (LTR)',
     397                        langDirRTLLabel : 'Right to Left (RTL)'
     398                }
     399        }
    383400};
  • _source/skins/default/toolbar.css

     
    310310{
    311311        background-position: 0 -880px;
    312312}
    313 
     313.cke_skin_default a.cke_button_creatediv .cke_icon
     314{
     315        background-position: 0 -1168px;
     316}
    314317.cke_skin_default a.cke_button_numberedlist .cke_icon
    315318{
    316319        background-position: 0 -400px;
© 2003 – 2017 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy