Ticket #5268: 5268.patch

File 5268.patch, 12.9 KB (added by Garry Yao, 10 years ago)
  • _source/core/tools.js

     
    5252                        return true;
    5353                },
    5454
     55                buildTableMap : function ( table )
     56                {
     57                        var aRows = table.$.rows ;
     58
     59                        // Row and Column counters.
     60                        var r = -1 ;
     61
     62                        var aMap = [];
     63
     64                        for ( var i = 0 ; i < aRows.length ; i++ )
     65                        {
     66                                r++ ;
     67                                !aMap[r] && ( aMap[r] = [] );
     68
     69                                var c = -1 ;
     70
     71                                for ( var j = 0 ; j < aRows[i].cells.length ; j++ )
     72                                {
     73                                        var oCell = aRows[i].cells[j] ;
     74
     75                                        c++ ;
     76                                        while ( aMap[r][c] )
     77                                                c++ ;
     78
     79                                        var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ;
     80                                        var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ;
     81
     82                                        for ( var rs = 0 ; rs < iRowSpan ; rs++ )
     83                                        {
     84                                                if ( !aMap[r + rs] )
     85                                                        aMap[r + rs] = [];
     86
     87                                                for ( var cs = 0 ; cs < iColSpan ; cs++ )
     88                                                {
     89                                                        aMap[r + rs][c + cs] = aRows[i].cells[j] ;
     90                                                }
     91                                        }
     92
     93                                        c += iColSpan - 1 ;
     94                                }
     95                        }
     96                        return aMap ;
     97        },
     98
    5599                /**
    56100                 * Creates a deep copy of an object.
    57101                 * Attention: there is no support for recursive references.
  • _source/plugins/tableresize/plugin.js

     
     1/*
     2Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
     3For licensing, see LICENSE.html or http://ckeditor.com/license
     4*/
     5
     6( function()
     7{
     8        var pxUnit = CKEDITOR.tools.cssLength;
     9
     10        function getCellWidth( cell )
     11        {
     12                return CKEDITOR.env.ie ? cell.$.clientWidth : parseInt( cell.getComputedStyle( 'width' ) );
     13        }
     14
     15        function getCellBorderWidth( cell, side )
     16        {
     17                var computed = cell.getComputedStyle( 'border-' + side + '-width' ),
     18                        borderMap =
     19                        {
     20                                thin: '2px',
     21                                medium: '4px',
     22                                thick: '6px'
     23                        };
     24
     25                if ( computed.indexOf( 'px' ) < 0 )
     26                {
     27                        // look up keywords
     28                        if ( computed in borderMap && cell.getComputedStyle( 'border-style' ) != 'none' )
     29                                computed = borderMap[ computed ];
     30                        else
     31                                computed = 0;
     32                }
     33
     34                return computed;
     35        }
     36
     37        function getTableColumnPillarAtPosition( tableElement, position )
     38        {
     39                var table = tableElement.$;
     40                for ( var i = 0, rowCount = table.rows.length ; i < rowCount; i++ )
     41                {
     42                        var tr = table.rows[ i ],
     43                                        columnIndex = -1;
     44
     45                        for ( var j = 0, colCount = tr.cells.length ; j < colCount ; j++ )
     46                        {
     47                                var td = new CKEDITOR.dom.element( tr.cells[ j ] ),
     48                                                nextTd = tr.cells[ j + 1 ] && new CKEDITOR.dom.element( tr.cells[ j + 1 ] );
     49
     50                                columnIndex += td.$.colSpan || 1;
     51                                var cellPosition =  td.getDocumentPosition(),
     52                                                rangeLeft = cellPosition.x + td.$.offsetWidth - parseInt( getCellBorderWidth ( td, 'right' ) );
     53
     54                                if ( ( position.x > rangeLeft ) && nextTd )
     55                                {
     56                                        cellPosition =  nextTd.getDocumentPosition();
     57                                        var rangeRight = cellPosition.x + parseInt( getCellBorderWidth( nextTd, 'left' ) );
     58
     59                                        // Compsensate for too "slim" line between columns, make the pillar shown easier.
     60                                        if ( rangeRight - rangeLeft < 8 )
     61                                                rangeLeft-= 4, rangeRight += 4;
     62
     63                                        if ( position.x < rangeRight )
     64                                        {
     65                                                var columnWidth = rangeRight - rangeLeft;
     66                                                var tbody = new CKEDITOR.dom.element( table.tBodies[ 0 ] );
     67
     68                                                // The pillar should reflects exactly the shape of the hovered column border line.
     69                                                return { table : tableElement, index : columnIndex, x : rangeLeft, y :  tbody.getDocumentPosition().y, width : columnWidth, height: tbody.$.offsetHeight };
     70                                        }
     71                                }
     72                        }
     73                }
     74        }
     75       
     76        function ColumnResizer( editor )
     77        {
     78                this.document = editor.document;
     79                this.resizer = CKEDITOR.dom.element.createFromHtml( '<div style="position: absolute; cursor: col-resize; ' +
     80                        'filter:alpha(opacity=0);opacity:0;padding:0;background-color:#004;background-image:none;border: 0px none;"></div>' );
     81
     82                // Place the resizer after body to prevent it from being editable.
     83                new CKEDITOR.dom.element( editor.document.$.documentElement ).append( this.resizer );
     84        }
     85
     86        ColumnResizer.prototype =
     87        {
     88                attachTo : function( pillar )
     89                {
     90                        // Accept only one pillar at a time.
     91                        if ( this.pillar )
     92                                return;
     93
     94                        this.pillar = pillar;
     95                        this.table = pillar.table;
     96                        this.resizer.setStyles(
     97                        {
     98                                width: pxUnit( pillar.width ),
     99                                height : pxUnit( pillar.height ),
     100                                left : pxUnit( pillar.x ),
     101                                top : pxUnit( pillar.y )
     102                        });
     103
     104                        this.resizer.on( 'mousedown', this._.onMouseDown, this );
     105                        this.resizer.on( 'mouseout', this._.onMouseOut, this );
     106
     107                        // Display the resizer to receive events but don't show it,
     108                        // only change the cursor to resizable shape.
     109                        this.resizer.show();
     110                },
     111
     112                detach: function()
     113                {
     114                        delete this.pillar;
     115                        delete this.currentShift;
     116                        this.document.removeListener( 'mousemove', this._.onMouseMove );
     117                        this.document.removeListener( 'mouseup', this._.onMouseUp );
     118                        this.resizer.removeListener( 'mousedown', this._.onMouseDown );
     119                        this.resizer.removeListener( 'mouseout', this._.onMouseOut );
     120                        this.resizer.hide();
     121                },
     122
     123                resizeStart : function()
     124                {
     125                        // Before starting to resize, figure out which cells to change
     126                        // and the boundaries of this resizing shift.
     127                        var columnIndex = this.pillar.index,
     128                                        map = CKEDITOR.tools.buildTableMap( this.table ),
     129                                        leftColumnCells = [],
     130                                        rightColumnCells= [],
     131                                        leftMinSize =  Number.MAX_VALUE,
     132                                        rightMinSize = leftMinSize;
     133
     134                        for ( var i = 0, rowCount = map.length; i < rowCount; i++ )
     135                        {
     136                                var row = map[ i ],
     137                                                leftCell = new CKEDITOR.dom.element( row[ columnIndex ] ),
     138                                                rightCell = new CKEDITOR.dom.element( row[ columnIndex + 1 ] );
     139
     140                                if ( !leftCell.equals( rightCell ) )
     141                                {
     142                                        leftMinSize = Math.min( leftMinSize, getCellWidth( leftCell ) );
     143                                        rightMinSize = Math.min( rightMinSize, getCellWidth( rightCell ) );
     144                                        leftColumnCells.push( leftCell );
     145                                        rightColumnCells.push( rightCell );
     146                                }
     147                        }
     148
     149                        this.leftSideCells = leftColumnCells;
     150                        this.rightSideCells = rightColumnCells;
     151                        this.leftShiftBoundary =  this.pillar.x - leftMinSize;
     152                        this.rightShiftBoundary = this.pillar.x + rightMinSize;
     153                       
     154                        this.resizer.setOpacity( 0.5 );
     155                        this.startOffset = parseInt( this.resizer.getStyle( 'left' ) );
     156                        this.document.on( 'mousemove', this._.onMouseMove, this );
     157                        // Prevent the native drag behavior otherwise the above 'mousemove' won't fired.
     158                        this.document.on( 'dragstart', this._.onDragStart, this );
     159                },
     160
     161                resizeEnd : function()
     162                {
     163                        this.resizer.setOpacity( 0 );
     164                        this.resizeColumn();
     165                        this.detach();
     166                },
     167
     168                resizeColumn : function()
     169                {
     170                        // Perform the actual resize to table cells, only for those by side of the pillar.
     171                        for ( var i = 0, count = this.leftSideCells.length; i < count; i++ )
     172                        {
     173                                var leftCell = this.leftSideCells[ i ],
     174                                                rightCell = this.rightSideCells[ i ];
     175
     176                                // Defer the resizing to avoid any interference among cells.
     177                                ( function( leftCell, leftOldWidth, rightCell, rightOldWidth, sizeShift )
     178                                {
     179                                        CKEDITOR.tools.setTimeout( function()
     180                                        {
     181                                                leftCell.setStyle( 'width', pxUnit(  leftOldWidth + sizeShift ) );
     182                                                rightCell.setStyle( 'width', pxUnit(  rightOldWidth - sizeShift ) );
     183
     184                                        }, 0, this );
     185
     186                                }).call( this, leftCell, getCellWidth( leftCell ),
     187                                                rightCell, getCellWidth( rightCell ), this.currentShift );
     188                        }
     189                },
     190
     191                _ :
     192                {
     193                        onMouseMove : function( evt )
     194                        {
     195                                var mouseOffset = evt.data.$.clientX,
     196                                                resizerNewPosition = mouseOffset - parseInt( this.resizer.getComputedStyle( 'width' ) ) / 2;
     197
     198                                // Boundaries checking.
     199                                if ( resizerNewPosition > this.leftShiftBoundary
     200                                                && resizerNewPosition < this.rightShiftBoundary )
     201                                {
     202                                        this.resizer.setStyle( 'left', pxUnit( resizerNewPosition ) );
     203                                        this.currentShift = resizerNewPosition - this.startOffset;
     204                                }
     205                        },
     206
     207                        onMouseDown : function( evt )
     208                        {
     209                                evt.data.preventDefault();
     210                                this.resizeStart();
     211                                this.document.on( 'mouseup', this._.onMouseUp, this );
     212                        },
     213
     214                        onMouseUp : function()
     215                        {
     216                                this.resizeEnd();
     217                        },
     218
     219                        onMouseOut : function()
     220                        {
     221                                // Don't detach during resizing.
     222                                !this.currentShift && this.detach();
     223                        },
     224
     225                        onDragStart : function( evt )
     226                        {
     227                                evt.data.preventDefault();
     228                        }
     229                }
     230        };
     231
     232        CKEDITOR.plugins.add( 'tableresize',
     233        {
     234                requires : [ 'table' ],
     235                init : function( editor )
     236                {
     237                        editor.on( 'contentDom', function ()
     238                        {
     239                                var columnResizer;
     240                                editor.document.getBody().on( 'mousemove', function( evt )
     241                                {
     242                                        evt = evt.data;
     243
     244                                        // Considering table, tr, td, tbody but nothing else.
     245                                        var target = evt.getTarget();
     246                                        if ( !( target.is( 'table' ) || target.getAscendant( 'tbody', true ) ) )
     247                                                return;
     248
     249                                        var table = target.getAscendant( 'table', true );
     250                                        var pillar = getTableColumnPillarAtPosition( table, { x : evt.$.clientX, y : evt.$.clientY } );
     251                                        if ( pillar )
     252                                        {
     253                                                !columnResizer && ( columnResizer = new ColumnResizer( editor ) );
     254                                                columnResizer.attachTo( pillar );
     255                                        }
     256                                });
     257                        });
     258                }
     259        });
     260
     261} )( );
  • _source/core/config.js

     
    229229         * @type String
    230230         * @example
    231231         */
    232         plugins : 'about,a11yhelp,basicstyles,blockquote,button,clipboard,colorbutton,colordialog,contextmenu,div,elementspath,enterkey,entities,filebrowser,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,newpage,pagebreak,pastefromword,pastetext,popup,preview,print,removeformat,resize,save,scayt,smiley,showblocks,showborders,sourcearea,stylescombo,table,tabletools,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
     232        plugins : 'about,a11yhelp,basicstyles,blockquote,button,clipboard,colorbutton,colordialog,contextmenu,div,elementspath,enterkey,entities,filebrowser,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,newpage,pagebreak,pastefromword,pastetext,popup,preview,print,removeformat,resize,save,scayt,smiley,showblocks,showborders,sourcearea,stylescombo,table,tabletools,tableresize,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
    233233
    234234        /**
    235235         * List of additional plugins to be loaded. This is a tool setting which
  • _source/plugins/tabletools/plugin.js

     
    354354                range.select( true );
    355355        }
    356356
    357         function buildTableMap( table )
    358         {
    359 
    360                 var aRows = table.$.rows ;
    361 
    362                 // Row and Column counters.
    363                 var r = -1 ;
    364 
    365                 var aMap = [];
    366 
    367                 for ( var i = 0 ; i < aRows.length ; i++ )
    368                 {
    369                         r++ ;
    370                         !aMap[r] && ( aMap[r] = [] );
    371 
    372                         var c = -1 ;
    373 
    374                         for ( var j = 0 ; j < aRows[i].cells.length ; j++ )
    375                         {
    376                                 var oCell = aRows[i].cells[j] ;
    377 
    378                                 c++ ;
    379                                 while ( aMap[r][c] )
    380                                         c++ ;
    381 
    382                                 var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ;
    383                                 var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ;
    384 
    385                                 for ( var rs = 0 ; rs < iRowSpan ; rs++ )
    386                                 {
    387                                         if ( !aMap[r + rs] )
    388                                                 aMap[r + rs] = new Array() ;
    389 
    390                                         for ( var cs = 0 ; cs < iColSpan ; cs++ )
    391                                         {
    392                                                 aMap[r + rs][c + cs] = aRows[i].cells[j] ;
    393                                         }
    394                                 }
    395 
    396                                 c += iColSpan - 1 ;
    397                         }
    398                 }
    399                 return aMap ;
    400         }
    401 
    402357        function cellInRow( tableMap, rowIndex, cell )
    403358        {
    404359                var oRow = tableMap[ rowIndex ];
     
    452407                var     cell,
    453408                        firstCell = cells[ 0 ],
    454409                        table = firstCell.getAscendant( 'table' ),
    455                         map = buildTableMap( table ),
     410                        map = CKEDITOR.tools.buildTableMap( table ),
    456411                        mapHeight = map.length,
    457412                        mapWidth = map[ 0 ].length,
    458413                        startRow = firstCell.getParent().$.rowIndex,
     
    587542                var cell = cells[ 0 ],
    588543                        tr = cell.getParent(),
    589544                        table = tr.getAscendant( 'table' ),
    590                         map = buildTableMap( table ),
     545                        map = CKEDITOR.tools.buildTableMap( table ),
    591546                        rowIndex = tr.$.rowIndex,
    592547                        colIndex = cellInRow( map, rowIndex, cell ),
    593548                        rowSpan = cell.$.rowSpan,
     
    663618                var cell = cells[ 0 ],
    664619                        tr = cell.getParent(),
    665620                        table = tr.getAscendant( 'table' ),
    666                         map = buildTableMap( table ),
     621                        map = CKEDITOR.tools.buildTableMap( table ),
    667622                        rowIndex = tr.$.rowIndex,
    668623                        colIndex = cellInRow( map, rowIndex, cell ),
    669624                        colSpan = cell.$.colSpan,
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy