Ticket #5268: 5268_2.patch

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

     
    400400                range.select( true );
    401401        }
    402402
    403         function buildTableMap( table )
    404         {
    405 
    406                 var aRows = table.$.rows ;
    407 
    408                 // Row and Column counters.
    409                 var r = -1 ;
    410 
    411                 var aMap = [];
    412 
    413                 for ( var i = 0 ; i < aRows.length ; i++ )
    414                 {
    415                         r++ ;
    416                         !aMap[r] && ( aMap[r] = [] );
    417 
    418                         var c = -1 ;
    419 
    420                         for ( var j = 0 ; j < aRows[i].cells.length ; j++ )
    421                         {
    422                                 var oCell = aRows[i].cells[j] ;
    423 
    424                                 c++ ;
    425                                 while ( aMap[r][c] )
    426                                         c++ ;
    427 
    428                                 var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ;
    429                                 var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ;
    430 
    431                                 for ( var rs = 0 ; rs < iRowSpan ; rs++ )
    432                                 {
    433                                         if ( !aMap[r + rs] )
    434                                                 aMap[r + rs] = new Array() ;
    435 
    436                                         for ( var cs = 0 ; cs < iColSpan ; cs++ )
    437                                         {
    438                                                 aMap[r + rs][c + cs] = aRows[i].cells[j] ;
    439                                         }
    440                                 }
    441 
    442                                 c += iColSpan - 1 ;
    443                         }
    444                 }
    445                 return aMap ;
    446         }
    447 
    448403        function cellInRow( tableMap, rowIndex, cell )
    449404        {
    450405                var oRow = tableMap[ rowIndex ];
     
    498453                var     cell,
    499454                        firstCell = cells[ 0 ],
    500455                        table = firstCell.getAscendant( 'table' ),
    501                         map = buildTableMap( table ),
     456                        map = CKEDITOR.tools.buildTableMap( table ),
    502457                        mapHeight = map.length,
    503458                        mapWidth = map[ 0 ].length,
    504459                        startRow = firstCell.getParent().$.rowIndex,
     
    633588                var cell = cells[ 0 ],
    634589                        tr = cell.getParent(),
    635590                        table = tr.getAscendant( 'table' ),
    636                         map = buildTableMap( table ),
     591                        map = CKEDITOR.tools.buildTableMap( table ),
    637592                        rowIndex = tr.$.rowIndex,
    638593                        colIndex = cellInRow( map, rowIndex, cell ),
    639594                        rowSpan = cell.$.rowSpan,
     
    709664                var cell = cells[ 0 ],
    710665                        tr = cell.getParent(),
    711666                        table = tr.getAscendant( 'table' ),
    712                         map = buildTableMap( table ),
     667                        map = CKEDITOR.tools.buildTableMap( table ),
    713668                        rowIndex = tr.$.rowIndex,
    714669                        colIndex = cellInRow( map, rowIndex, cell ),
    715670                        colSpan = cell.$.colSpan,
     
    11141069        };
    11151070        CKEDITOR.plugins.add( 'tabletools', CKEDITOR.plugins.tabletools );
    11161071})();
     1072
     1073/**
     1074 * Create a two-dimension array that reflects the actual layout of table cells,
     1075 * with cell spans, with mappings to the original td elements.
     1076 * @param table {CKEDITOR.dom.element}
     1077 */
     1078CKEDITOR.tools.buildTableMap = function ( table )
     1079{
     1080        var aRows = table.$.rows ;
     1081
     1082        // Row and Column counters.
     1083        var r = -1 ;
     1084
     1085        var aMap = [];
     1086
     1087        for ( var i = 0 ; i < aRows.length ; i++ )
     1088        {
     1089                r++ ;
     1090                !aMap[r] && ( aMap[r] = [] );
     1091
     1092                var c = -1 ;
     1093
     1094                for ( var j = 0 ; j < aRows[i].cells.length ; j++ )
     1095                {
     1096                        var oCell = aRows[i].cells[j] ;
     1097
     1098                        c++ ;
     1099                        while ( aMap[r][c] )
     1100                                c++ ;
     1101
     1102                        var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ;
     1103                        var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ;
     1104
     1105                        for ( var rs = 0 ; rs < iRowSpan ; rs++ )
     1106                        {
     1107                                if ( !aMap[r + rs] )
     1108                                        aMap[r + rs] = [];
     1109
     1110                                for ( var cs = 0 ; cs < iColSpan ; cs++ )
     1111                                {
     1112                                        aMap[r + rs][c + cs] = aRows[i].cells[j] ;
     1113                                }
     1114                        }
     1115
     1116                        c += iColSpan - 1 ;
     1117                }
     1118        }
     1119        return aMap ;
     1120};
     1121
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy