Ticket #2885: 2885_3.patch

File 2885_3.patch, 17.7 KB (added by garry.yao, 6 years ago)
  • _source/plugins/div/dialogs/div.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
     6(function()
     7{
     8       
     9        /**
     10         * Add to collection with DUP examination.
     11         * @param {Object} collection
     12         * @param {Object} element
     13         * @param {Object} database
     14         */
     15        function addSafely( collection, element, database )
     16        {
     17                // avoid duplicate
     18                if ( !element.getCustomData( 'block_processed' ) )
     19                {
     20                        CKEDITOR.dom.element.setMarker( database, element,
     21                                'block_processed', true );
     22                        collection.push( element );
     23                }
     24        }
     25       
     26        /**
     27         * Dialog reused by both 'creatediv' and 'editdiv' commands.
     28         * @param {Object} editor
     29         * @param {String} command      The command name which indicate what the current command is.
     30         */
     31        function divDialog( editor, command ) {
     32               
     33                // Definition of elements at which div operation should stopped.
     34                var divLimitDefiniton = (function(){
     35                       
     36                        // Customzie from specialize blockLimit elements
     37                        var definition = CKEDITOR.tools.extend( {},
     38                        CKEDITOR.dom.elementPath.pathBlockLimitElements );
     39                        // Exclude 'div' itself.
     40                        delete definition.div;
     41                        // Exclude 'td' and 'th' when 'wrapping table'
     42                        if( editor.config.div_wrapTable)
     43                        {
     44                                delete definition.td;
     45                                delete definition.th;
     46                        }
     47                        return definition;
     48                })();
     49               
     50                // DTD of 'div' element
     51                var dtd = CKEDITOR.dtd.div;
     52               
     53                /**
     54                 * Get the first div limit element on the element's path.
     55                 * @param {Object} element
     56                 */
     57                function getDivLimitElement( element )
     58                {
     59                        var pathElements = new CKEDITOR.dom.elementPath( element ).elements;
     60                        var i, l = pathElements.length, divLimit;
     61                        for ( i = 0; i < l; i++ )
     62                        {
     63                                if ( pathElements[ i ].getName() in divLimitDefiniton )
     64                                {
     65                                        divLimit = pathElements[ i ];
     66                                        break;
     67                                }
     68                        }
     69                        return divLimit;
     70                }
     71               
     72                /**
     73                 * Init all fields' setup/commit function.
     74                 * @memberof divDialog
     75                 */
     76                function setupFields()
     77                {
     78                        this.foreach( function( field )
     79                        {
     80                                //Exclude layout container elements
     81                                if( /^(?!vbox|hbox)/.test( field.type ))       
     82                                {
     83                                        if ( !field.setup )
     84                                        {
     85                                                // Read the dialog fields values from the specified
     86                                                // element attributes.
     87                                                field.setup = function( element )
     88                                                {
     89                                                        field.setValue( element.getAttribute( field.id ) || '' );
     90                                                };
     91                                        }
     92                                        if ( !field.commit )
     93                                        {
     94                                                // Set element attributes assigned by the dialog
     95                                                // fields.
     96                                                field.commit = function( element )
     97                                                {
     98                                                        var fieldValue = this.getValue();
     99                                                        // ignore default element attribute values
     100                                                        if ( 'dir' == field.id
     101                                                                && element.getComputedStyle( 'direction' ) == fieldValue )
     102                                                                return true;
     103                                                        if ( fieldValue )
     104                                                                element.setAttribute( field.id, fieldValue );
     105                                                };
     106                                        }
     107                                }
     108                        } );
     109                }
     110               
     111                /**
     112                 * Either create or detect the desired block containers among the selected ranges.
     113                 * @param {Object} editor
     114                 * @param {Object} containerTagName The tagName of the container.
     115                 * @param {Object} isCreate Whether it's a creation process OR a detection process.
     116                 */     
     117                function applyDiv( editor, isCreate )
     118                {
     119                        // new adding containers OR detected pre-existed containers.
     120                        var containers = [],
     121                        // node markers store.
     122                        database = {},
     123                        // All block level elements which contained by the ranges.
     124                        containedBlocks = [], block;
     125       
     126                        // Get all ranges from the selection.
     127                        var selection = editor.document.getSelection();
     128                        var ranges = selection.getRanges();
     129                        var i, l = ranges.length, iterator;
     130       
     131                        // collect all included elements from dom-iterator
     132                        for( i = 0 ; i < l ; i++ )
     133                        {
     134                                iterator = ranges[ i ].createIterator();
     135                                while( ( block = iterator.getNextParagraph() ) )
     136                                {
     137                                        // include contents of blockLimit elements.
     138                                        if( block.getName() in divLimitDefiniton )
     139                                        {
     140                                                var j, childNodes = block.getChildren(), s = childNodes.count();
     141                                                for ( j = 0; j < s; j++) {
     142                                                        addSafely( containedBlocks, childNodes.getItem( j ) , database );
     143                                                }
     144                                        }
     145                                        else
     146                                        {
     147                                                // Bypass dtd disallowed elements.     
     148                                                while( !dtd[ block.getName() ] && block.getName() != 'body' )
     149                                                {
     150                                                        block = block.getParent();
     151                                                }
     152                                                addSafely( containedBlocks, block, database );
     153                                        }
     154                                }
     155                        }
     156                       
     157                        CKEDITOR.dom.element.clearAllMarkers(database);
     158                       
     159                        var blockGroups = groupByDivLimit( containedBlocks ),
     160                                l = blockGroups.length, ancestor, blockEl, divElement;
     161                        for( i = 0 ; i < l ; i++ )
     162                        {
     163                                var currentBlock = blockGroups[ i ][0];
     164                               
     165                                // Calculate the common parent node of all contained elements.
     166                                ancestor = currentBlock .getParent();
     167                                var j  = 1, s = blockGroups[ i ].length;
     168                                for ( ; j < s; j++ )
     169                                        ancestor = ancestor.getCommonAncestor( blockGroups[ i ][ j ] );
     170                               
     171                                if(isCreate)
     172                                {
     173                                        divElement = new CKEDITOR.dom.element( 'div' ,
     174                                                editor.document );
     175                                }
     176                               
     177                                var j, s = blockGroups[ i ].length,
     178                                //Wrapped blocks counting
     179                                childCount = 0;
     180                                for( j = 0; j < s; j++ )
     181                                {
     182                                        currentBlock = blockGroups[ i ][ j ];
     183       
     184                                        // Reconstruct the block list to only contain direct
     185                                        // children of common ancestor.
     186                                        while( !currentBlock.getParent().equals( ancestor ) )
     187                                                currentBlock = currentBlock.getParent();
     188       
     189                                        // Avoid DUP
     190                                        if ( !currentBlock.getCustomData( 'block_processed' ) )
     191                                        {
     192                                                CKEDITOR.dom.element.setMarker( database, currentBlock, 'block_processed', true );
     193                                                if( isCreate )
     194                                                {
     195                                                        // Establish new container, wrapping all
     196                                                        // elements in this group.
     197                                                        if( j == 0 )
     198                                                                divElement.insertBefore( currentBlock );
     199                                                        divElement.append( currentBlock );
     200                                                }
     201                                                else
     202                                                        childCount++;
     203                                        }
     204                                }
     205                                CKEDITOR.dom.element.clearAllMarkers( database );
     206       
     207                                if( isCreate )
     208                                {
     209                                        // drop pre-existed container, since new container already
     210                                        // established.
     211                                        if ( command == 'editdiv' &&
     212                                                        ancestor.getName() == 'div'
     213                                                        && 1 == ancestor.getNonEmptyChildren().length )
     214                                                        ancestor.remove( true );
     215                                        containers.push( divElement );
     216                                }
     217                                else
     218                                {
     219                                        // discover existed container
     220                                        if ( ancestor.getName() == 'div'
     221                                                && childCount == ancestor.getNonEmptyChildren().length )
     222                                                containers.push( ancestor );
     223                                }
     224                        }
     225       
     226                        return containers;
     227                }
     228               
     229                /**
     230                 * Divide a set of nodes to different groups by their path's blocklimit element.
     231                 * Note: the specified nodes should be in source order naturally, which mean they are supposed to producea by following class:
     232                 *  * CKEDITOR.dom.range.Iterator
     233                 *  * CKEDITOR.dom.domWalker
     234                 *  @return {Array []} the grouped nodes
     235                 */
     236                function groupByDivLimit( nodes )
     237                {
     238                        var groups = [],
     239                                lastDivLimit = null,
     240                                path, block;
     241                        for ( var i = 0 ; i < nodes.length ; i++ )
     242                        {
     243                                block = nodes[i];
     244                                var limit = getDivLimitElement( block );
     245                                if ( !limit.equals( lastDivLimit ) )
     246                                {
     247                                        lastDivLimit = limit ;
     248                                        groups.push( [] ) ;
     249                                }
     250                                groups[ groups.length - 1 ].push( block ) ;
     251                        }
     252                        return groups;
     253                }
     254               
     255                function compareNodes()
     256                {
     257                        return arguments[ 0 ].equals( arguments[ 1 ] );
     258                }
     259               
     260                /**
     261                 * Hold a collection of created block container elements. 
     262                 */
     263                var containers = [];
     264                /**
     265                 * @type divDialog
     266                 */
     267                return {
     268                        title : editor.lang.div.title,
     269                        minWidth : 400,
     270                        minHeight : 320,
     271                        contents :
     272                        [
     273                        {
     274                                id :'info',
     275                                label :editor.lang.common.generalTab,
     276                                title :editor.lang.common.generalTab,
     277                                elements :
     278                                [
     279                                        {
     280                                                type :'hbox',
     281                                                widths : [ '50%', '50%' ],
     282                                                children :
     283                                                [
     284                                                        {
     285                                                                id :'elementStyle',
     286                                                                type :'select',
     287                                                                style :'width: 100%;',
     288                                                                label :editor.lang.div.styleSelectLabel,
     289                                                                'default' :editor.config.div_defaultStyle,
     290                                                                items : [],
     291                                                                setup : function(){
     292                                                                        //TODO: Read 'elementStyle' field
     293                                                                },
     294                                                                commit: function()
     295                                                                {
     296                                                                        //TODO: Commit 'elementStyle' field value
     297                                                                }
     298                                                        // TODO: Fill 'elementStyle' selection options.
     299                                                        },
     300                                                        {
     301                                                                id :'class',
     302                                                                type :'text',
     303                                                                label :editor.lang.common.cssClass,
     304                                                                'default' :editor.config.div_defaultCssClass
     305                                                        }
     306                                                ]
     307                                        }
     308                                ]
     309                        },
     310                        {
     311                                        id :'advanced',
     312                                        label :editor.lang.common.advancedTab,
     313                                        title :editor.lang.common.advancedTab,
     314                                        elements :
     315                                        [
     316                                        {
     317                                                type :'vbox',
     318                                                padding :1,
     319                                                children :
     320                                                [
     321                                                        {
     322                                                                type :'hbox',
     323                                                                widths : [ '50%', '50%' ],
     324                                                                children :
     325                                                                [
     326                                                                        {
     327                                                                                type :'text',
     328                                                                                id :'id',
     329                                                                                label :editor.lang.common.id,
     330                                                                                'default' :editor.config.div_defaultId
     331                                                                        },
     332                                                                        {
     333                                                                                type :'text',
     334                                                                                id :'lang',
     335                                                                                label :editor.lang.link.langCode,
     336                                                                                'default' :editor.config.div_defaultLanguageCode
     337                                                                        }
     338                                                                ]
     339                                                        },
     340                                                        {
     341                                                                type :'hbox',
     342                                                                children :
     343                                                                [
     344                                                                                {
     345                                                                                        type :'text',
     346                                                                                        id :'style',
     347                                                                                        style :'width: 100%;',
     348                                                                                        label :editor.lang.common.cssStyle,
     349                                                                                        'default' :editor.config.div_defaultInlineStyle
     350                                                                                }
     351                                                                ]
     352                                                        },
     353                                                        {
     354                                                                type :'hbox',
     355                                                                children :
     356                                                                [
     357                                                                                {
     358                                                                                        type :'text',
     359                                                                                        id :'title',
     360                                                                                        style :'width: 100%;',
     361                                                                                        label :editor.lang.common.advisoryTitle,
     362                                                                                        'default' :editor.config.div_defaultAdvisoryTitle
     363                                                                                }
     364                                                                ]
     365                                                        },
     366                                                        {
     367                                                                type :'select',
     368                                                                id :'dir',
     369                                                                style :'width: 100%;',
     370                                                                label :editor.lang.common.langDir,
     371                                                                'default' :editor.config.div_defaultLangDirLabel,
     372                                                                items :
     373                                                                [
     374                                                                        [
     375                                                                                editor.lang.common.langDirLtr,
     376                                                                                'ltr'
     377                                                                        ],
     378                                                                        [
     379                                                                                editor.lang.common.langDirRtl,
     380                                                                                'rtl'
     381                                                                        ]
     382                                                                ]
     383                                                        }
     384                                                ]
     385                                        }
     386                                        ]
     387                                }
     388                        ],
     389                        onLoad : function()
     390                        {
     391                                setupFields.call(this);
     392                        },
     393                        onShow : function()
     394                        {
     395                                containers = [];
     396                                // Whether always create new container regardless of existed
     397                                // ones.
     398                                if ( command == 'editdiv' )
     399                                {
     400                                        if( CKEDITOR.env.ie )
     401                                                this.restoreSelection();
     402                                               
     403                                        // Try to discover the containers that already existed in
     404                                        // ranges
     405                                        containers = applyDiv( editor );
     406                                        if( containers.length )
     407                                        {
     408                                                this._element = containers[ 0 ];
     409                                                // update dialog field values
     410                                                this.setupContent( this._element );
     411                                        }
     412                                }
     413                        },
     414                        onOk : function()
     415                        {
     416                                if( CKEDITOR.env.ie )
     417                                        this.restoreSelection();
     418                                containers = applyDiv( editor, true );
     419                               
     420                                // update elements attributes
     421                                var i, l = containers.length;
     422                                for( i = 0 ; i < l ; i++ )
     423                                {
     424                                        this.commitContent( containers[ i ] );
     425                                }
     426                                this.hide();
     427                        }
     428                };
     429        }
     430       
     431        CKEDITOR.dialog.add( 'creatediv', function( editor )
     432                {
     433                        return divDialog( editor, 'creatediv' );
     434                } );
     435        CKEDITOR.dialog.add( 'editdiv', function( editor )
     436                {
     437                        return divDialog( editor, 'editdiv' );
     438                } );
     439})();
     440 No newline at end of file
  • _source/plugins/div/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 "div" plugin. It wraps the selected block level elements with a 'div' element with specified styles and attributes.
     8 *
     9 */
     10
     11CKEDITOR.plugins.add( 'div',
     12{
     13        requires : [ 'editingblock', 'domiterator', 'elementspath' ],
     14
     15        init : function( editor ){
     16       
     17                editor.addCommand( 'creatediv', new CKEDITOR.dialogCommand(
     18                        'creatediv' ) );
     19                editor.addCommand( 'editdiv', new CKEDITOR.dialogCommand(
     20                        'editdiv' ) );
     21                       
     22                editor.ui.addButton( 'CreateDiv', {
     23                        label :editor.lang.div.toolbar,
     24                        command :'creatediv'
     25                } );
     26                // TODO: Adding 'editdiv' command button.
     27                editor.ui.addButton( 'EditDiv', {
     28                        label :editor.lang.div.toolbar,
     29                        command :'editdiv'
     30                } );
     31               
     32                CKEDITOR.dialog.add( 'creatediv',
     33                        this.path + 'dialogs/div.js' );
     34                CKEDITOR.dialog.add( 'editdiv',
     35                        this.path + 'dialogs/div.js' );
     36        }
     37} );
     38
     39CKEDITOR.tools.extend(CKEDITOR.config,
     40{
     41        /**
     42         * Whether wrapping the whole table when created 'div' in table cell.
     43         */
     44        div_wrapTable : false,
     45        div_defaultCssClass :'',
     46        div_defaultStyle :'',
     47        div_defaultId :'',
     48        div_defaultLanguageCode :'',
     49        div_defaultInlineStyle :'',
     50        div_defaultAdvisoryTitle :'',
     51        div_defaultLangDir :''
     52});
  • _source/plugins/toolbar/plugin.js

     
    217217        ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'],
    218218        '/',
    219219        ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
    220         ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
     220        ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote','CreateDiv'],
    221221        ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
    222222        ['Link','Unlink','Anchor'],     ['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
    223223        '/',
  • _source/lang/en.js

     
    453453                tag_h5 : 'Heading 5',
    454454                tag_h6 : 'Heading 6',
    455455                tag_div : 'Normal (DIV)'
     456        },
     457       
     458        div :
     459        {
     460                title: 'Create Div Container',
     461                toolbar: 'Create Div Container',
     462                cssClassInputLabel : 'Stylesheet Classes',
     463                styleSelectLabel : 'Style',
     464                IdInputLabel: 'Id',
     465                languageCodeInputLabel : ' Language Code',
     466                inlineStyleInputLabel : 'Inline Style',
     467                advisoryTitleInputLabel : 'Advisory Title',
     468                langDirLabel : 'Language Direction',
     469                langDirLTRLabel : 'Left to Right (LTR)',
     470                langDirRTLLabel : 'Right to Left (RTL)'
    456471        }
    457472};
  • _source/skins/default/toolbar.css

     
    415415{
    416416        background-position: 0 -160px;
    417417}
     418
     419.cke_skin_default a.cke_button_creatediv .cke_icon
     420{
     421        background-position: 0 -1168px;
     422}
  • _source/core/config.js

     
    147147         * config.plugins = 'basicstyles,button,htmldataprocessor,toolbar,wysiwygarea';
    148148         */
    149149
    150         plugins : 'basicstyles,blockquote,button,clipboard,elementspath,find,flash,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,showblocks,sourcearea,table,specialchar,tab,templates,toolbar,undo,wysiwygarea',
     150        plugins : 'basicstyles,blockquote,button,clipboard,elementspath,find,flash,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,div,newpage,pagebreak,pastefromword,pastetext,preview,print,removeformat,smiley,showblocks,sourcearea,table,specialchar,tab,templates,toolbar,undo,wysiwygarea',
    151151
    152152        /**
    153153         * The theme to be used to build the UI.
  • _source/core/dom/elementpath.js

     
    7474                this.blockLimit = blockLimit;
    7575                this.elements = elements;
    7676        };
     77        //Make bocklimit elements definition public visitable.
     78        CKEDITOR.dom.elementPath.pathBlockLimitElements = pathBlockLimitElements;
     79       
    7780})();
    7881
    7982CKEDITOR.dom.elementPath.prototype =
  • _source/core/dom/element.js

     
    409409                {
    410410                        return new CKEDITOR.dom.nodeList( this.$.childNodes );
    411411                },
     412               
     413                /**
     414                 * Same as CKEDITOR.dom.element::getChildren except this method ignore
     415                 * text nodes which contains only blank characters.
     416                 * @return {Array} 
     417                 */
     418                getNonEmptyChildren : function()
     419                {
     420                        var resultsChilds = [];
     421                        var children = this.getChildren();
     422                        var i, l = children.count(), child;
     423                        for( i = 0 ; i < l ; i++ )
     424                        {
     425                                child = children.getItem( i );
     426                                if( ! ( child.type === CKEDITOR.NODE_TEXT
     427                                        && /^[ \t\n\r]+$/.test( child.getText() ) ) )
     428                                        resultsChilds.push( child );
     429                        }
     430                        return resultsChilds;
     431                },
    412432
    413433                /**
    414434                 * Gets the current computed value of one of the element CSS style
© 2003 – 2015 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy