source: branches/1.2/workflow/js/fckeditor/editor/_source/internals/fcktablehandler.js @ 1349

Revision 1349, 9.9 KB checked in by niltonneto, 15 years ago (diff)

Ticket #561 - Inclusão do módulo Workflow faltante nessa versão.

  • Property svn:executable set to *
Line 
1/*
2 * FCKeditor - The text editor for Internet - http://www.fckeditor.net
3 * Copyright (C) 2003-2007 Frederico Caldeira Knabben
4 *
5 * == BEGIN LICENSE ==
6 *
7 * Licensed under the terms of any of the following licenses at your
8 * choice:
9 *
10 *  - GNU General Public License Version 2 or later (the "GPL")
11 *    http://www.gnu.org/licenses/gpl.html
12 *
13 *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
14 *    http://www.gnu.org/licenses/lgpl.html
15 *
16 *  - Mozilla Public License Version 1.1 or later (the "MPL")
17 *    http://www.mozilla.org/MPL/MPL-1.1.html
18 *
19 * == END LICENSE ==
20 *
21 * Manage table operations.
22 */
23
24var FCKTableHandler = new Object() ;
25
26FCKTableHandler.InsertRow = function()
27{
28        // Get the row where the selection is placed in.
29        var oRow = FCKSelection.MoveToAncestorNode( 'TR' ) ;
30        if ( !oRow ) return ;
31
32        // Create a clone of the row.
33        var oNewRow = oRow.cloneNode( true ) ;
34
35        // Insert the new row (copy) before of it.
36        oRow.parentNode.insertBefore( oNewRow, oRow ) ;
37
38        // Clean the row (it seems that the new row has been added after it).
39        FCKTableHandler.ClearRow( oRow ) ;
40}
41
42FCKTableHandler.DeleteRows = function( row )
43{
44        // If no row has been passed as a parameter,
45        // then get the row where the selection is placed in.
46        if ( !row )
47                row = FCKSelection.MoveToAncestorNode( 'TR' ) ;
48        if ( !row ) return ;
49
50        // Get the row's table.
51        var oTable = FCKTools.GetElementAscensor( row, 'TABLE' ) ;
52
53        // If just one row is available then delete the entire table.
54        if ( oTable.rows.length == 1 )
55        {
56                FCKTableHandler.DeleteTable( oTable ) ;
57                return ;
58        }
59
60        // Delete the row.
61        row.parentNode.removeChild( row ) ;
62}
63
64FCKTableHandler.DeleteTable = function( table )
65{
66        // If no table has been passed as a parameer,
67        // then get the table where the selection is placed in.
68        if ( !table )
69        {
70                table = FCKSelection.GetSelectedElement() ;
71                if ( !table || table.tagName != 'TABLE' )
72                        table = FCKSelection.MoveToAncestorNode( 'TABLE' ) ;
73        }
74        if ( !table ) return ;
75
76        // Delete the table.
77        FCKSelection.SelectNode( table ) ;
78        FCKSelection.Collapse();
79        table.parentNode.removeChild( table ) ;
80}
81
82FCKTableHandler.InsertColumn = function()
83{
84        // Get the cell where the selection is placed in.
85        var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ;
86
87        if ( !oCell ) return ;
88
89        // Get the cell's table.
90        var oTable = FCKTools.GetElementAscensor( oCell, 'TABLE' ) ;
91
92        // Get the index of the column to be created (based on the cell).
93        var iIndex = oCell.cellIndex + 1 ;
94
95        // Loop throw all rows available in the table.
96        for ( var i = 0 ; i < oTable.rows.length ; i++ )
97        {
98                // Get the row.
99                var oRow = oTable.rows[i] ;
100
101                // If the row doens't have enought cells, ignore it.
102                if ( oRow.cells.length < iIndex )
103                        continue ;
104
105                oCell = oRow.cells[iIndex-1].cloneNode(false) ;
106
107                if ( FCKBrowserInfo.IsGecko )
108                        oCell.innerHTML = GECKO_BOGUS ;
109
110                // Get the cell that is placed in the new cell place.
111                var oBaseCell = oRow.cells[iIndex] ;
112
113                // If the cell is available (we are not in the last cell of the row).
114                if ( oBaseCell )
115                        oRow.insertBefore( oCell, oBaseCell ) ; // Insert the new cell just before of it.
116                else
117                        oRow.appendChild( oCell ) ;                             // Append the cell at the end of the row.
118        }
119}
120
121FCKTableHandler.DeleteColumns = function()
122{
123        // Get the cell where the selection is placed in.
124        var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ;
125
126        if ( !oCell ) return ;
127
128        // Get the cell's table.
129        var oTable = FCKTools.GetElementAscensor( oCell, 'TABLE' ) ;
130
131        // Get the cell index.
132        var iIndex = oCell.cellIndex ;
133
134        // Loop throw all rows (from down to up, because it's possible that some
135        // rows will be deleted).
136        for ( var i = oTable.rows.length - 1 ; i >= 0 ; i-- )
137        {
138                // Get the row.
139                var oRow = oTable.rows[i] ;
140
141                // If the cell to be removed is the first one and the row has just one cell.
142                if ( iIndex == 0 && oRow.cells.length == 1 )
143                {
144                        // Remove the entire row.
145                        FCKTableHandler.DeleteRows( oRow ) ;
146                        continue ;
147                }
148
149                // If the cell to be removed exists the delete it.
150                if ( oRow.cells[iIndex] )
151                        oRow.removeChild( oRow.cells[iIndex] ) ;
152        }
153}
154
155FCKTableHandler.InsertCell = function( cell )
156{
157        // Get the cell where the selection is placed in.
158        var oCell = cell ? cell : FCKSelection.MoveToAncestorNode( 'TD' ) ;
159        if ( !oCell ) return null ;
160
161        // Create the new cell element to be added.
162        var oNewCell = FCK.EditorDocument.createElement( 'TD' ) ;
163        if ( FCKBrowserInfo.IsGecko )
164                oNewCell.innerHTML = GECKO_BOGUS ;
165//      oNewCell.innerHTML = "&nbsp;" ;
166
167        // If it is the last cell in the row.
168        if ( oCell.cellIndex == oCell.parentNode.cells.length - 1 )
169        {
170                // Add the new cell at the end of the row.
171                oCell.parentNode.appendChild( oNewCell ) ;
172        }
173        else
174        {
175                // Add the new cell before the next cell (after the active one).
176                oCell.parentNode.insertBefore( oNewCell, oCell.nextSibling ) ;
177        }
178
179        return oNewCell ;
180}
181
182FCKTableHandler.DeleteCell = function( cell )
183{
184        // If this is the last cell in the row.
185        if ( cell.parentNode.cells.length == 1 )
186        {
187                // Delete the entire row.
188                FCKTableHandler.DeleteRows( FCKTools.GetElementAscensor( cell, 'TR' ) ) ;
189                return ;
190        }
191
192        // Delete the cell from the row.
193        cell.parentNode.removeChild( cell ) ;
194}
195
196FCKTableHandler.DeleteCells = function()
197{
198        var aCells = FCKTableHandler.GetSelectedCells() ;
199
200        for ( var i = aCells.length - 1 ; i >= 0  ; i-- )
201        {
202                FCKTableHandler.DeleteCell( aCells[i] ) ;
203        }
204}
205
206FCKTableHandler.MergeCells = function()
207{
208        // Get all selected cells.
209        var aCells = FCKTableHandler.GetSelectedCells() ;
210
211        // At least 2 cells must be selected.
212        if ( aCells.length < 2 )
213                return ;
214
215        // The merge can occour only if the selected cells are from the same row.
216        if ( aCells[0].parentNode != aCells[aCells.length-1].parentNode )
217                return ;
218
219        // Calculate the new colSpan for the first cell.
220        var iColSpan = isNaN( aCells[0].colSpan ) ? 1 : aCells[0].colSpan ;
221
222        var sHtml = '' ;
223        var oCellsContents = FCK.EditorDocument.createDocumentFragment() ;
224
225        for ( var i = aCells.length - 1 ; i >= 0 ; i-- )
226        {
227                var eCell = aCells[i] ;
228
229                // Move its contents to the document fragment.
230                for ( var c = eCell.childNodes.length - 1 ; c >= 0 ; c-- )
231                {
232                        var eChild = eCell.removeChild( eCell.childNodes[c] ) ;
233
234                        if ( ( eChild.hasAttribute && eChild.hasAttribute('_moz_editor_bogus_node') ) || ( eChild.getAttribute && eChild.getAttribute( 'type', 2 ) == '_moz' ) )
235                                continue ;
236
237                                oCellsContents.insertBefore( eChild, oCellsContents.firstChild ) ;
238                }
239
240                if ( i > 0 )
241                {
242                        // Accumulate the colspan of the cell.
243                        iColSpan += isNaN( eCell.colSpan ) ? 1 : eCell.colSpan ;
244
245                        // Delete the cell.
246                        FCKTableHandler.DeleteCell( eCell ) ;
247                }
248        }
249
250        // Set the innerHTML of the remaining cell (the first one).
251        aCells[0].colSpan = iColSpan ;
252
253        if ( FCKBrowserInfo.IsGecko && oCellsContents.childNodes.length == 0 )
254                aCells[0].innerHTML = GECKO_BOGUS ;
255        else
256                aCells[0].appendChild( oCellsContents ) ;
257}
258
259FCKTableHandler.SplitCell = function()
260{
261        // Check that just one cell is selected, otherwise return.
262        var aCells = FCKTableHandler.GetSelectedCells() ;
263        if ( aCells.length != 1 )
264                return ;
265
266        var aMap = this._CreateTableMap( aCells[0].parentNode.parentNode ) ;
267        var iCellIndex = FCKTableHandler._GetCellIndexSpan( aMap, aCells[0].parentNode.rowIndex , aCells[0] ) ;
268
269        var aCollCells = this._GetCollumnCells( aMap, iCellIndex ) ;
270
271        for ( var i = 0 ; i < aCollCells.length ; i++ )
272        {
273                if ( aCollCells[i] == aCells[0] )
274                {
275                        var oNewCell = this.InsertCell( aCells[0] ) ;
276                        if ( !isNaN( aCells[0].rowSpan ) && aCells[0].rowSpan > 1 )
277                                oNewCell.rowSpan = aCells[0].rowSpan ;
278                }
279                else
280                {
281                        if ( isNaN( aCollCells[i].colSpan ) )
282                                aCollCells[i].colSpan = 2 ;
283                        else
284                                aCollCells[i].colSpan += 1 ;
285                }
286        }
287}
288
289// Get the cell index from a TableMap.
290FCKTableHandler._GetCellIndexSpan = function( tableMap, rowIndex, cell )
291{
292        if ( tableMap.length < rowIndex + 1 )
293                return null ;
294
295        var oRow = tableMap[ rowIndex ] ;
296
297        for ( var c = 0 ; c < oRow.length ; c++ )
298        {
299                if ( oRow[c] == cell )
300                        return c ;
301        }
302
303        return null ;
304}
305
306// Get the cells available in a collumn of a TableMap.
307FCKTableHandler._GetCollumnCells = function( tableMap, collumnIndex )
308{
309        var aCollCells = new Array() ;
310
311        for ( var r = 0 ; r < tableMap.length ; r++ )
312        {
313                var oCell = tableMap[r][collumnIndex] ;
314                if ( oCell && ( aCollCells.length == 0 || aCollCells[ aCollCells.length - 1 ] != oCell ) )
315                        aCollCells[ aCollCells.length ] = oCell ;
316        }
317
318        return aCollCells ;
319}
320
321// This function is quite hard to explain. It creates a matrix representing all cells in a table.
322// The difference here is that the "spanned" cells (colSpan and rowSpan) are duplicated on the matrix
323// cells that are "spanned". For example, a row with 3 cells where the second cell has colSpan=2 and rowSpan=3
324// will produce a bi-dimensional matrix with the following values (representing the cells):
325//              Cell1, Cell2, Cell2, Cell 3
326//              Cell4, Cell2, Cell2, Cell 5
327FCKTableHandler._CreateTableMap = function( table )
328{
329        var aRows = table.rows ;
330
331        // Row and Collumn counters.
332        var r = -1 ;
333
334        var aMap = new Array() ;
335
336        for ( var i = 0 ; i < aRows.length ; i++ )
337        {
338                r++ ;
339                if ( !aMap[r] )
340                        aMap[r] = new Array() ;
341
342                var c = -1 ;
343
344                for ( var j = 0 ; j < aRows[i].cells.length ; j++ )
345                {
346                        var oCell = aRows[i].cells[j] ;
347
348                        c++ ;
349                        while ( aMap[r][c] )
350                                c++ ;
351
352                        var iColSpan = isNaN( oCell.colSpan ) ? 1 : oCell.colSpan ;
353                        var iRowSpan = isNaN( oCell.rowSpan ) ? 1 : oCell.rowSpan ;
354
355                        for ( var rs = 0 ; rs < iRowSpan ; rs++ )
356                        {
357                                if ( !aMap[r + rs] )
358                                        aMap[r + rs] = new Array() ;
359
360                                for ( var cs = 0 ; cs < iColSpan ; cs++ )
361                                {
362                                        aMap[r + rs][c + cs] = aRows[i].cells[j] ;
363                                }
364                        }
365
366                        c += iColSpan - 1 ;
367                }
368        }
369        return aMap ;
370}
371
372FCKTableHandler.ClearRow = function( tr )
373{
374        // Get the array of row's cells.
375        var aCells = tr.cells ;
376
377        // Replace the contents of each cell with "nothing".
378        for ( var i = 0 ; i < aCells.length ; i++ )
379        {
380                if ( FCKBrowserInfo.IsGecko )
381                        aCells[i].innerHTML = GECKO_BOGUS ;
382                else
383                        aCells[i].innerHTML = '' ;
384        }
385}
Note: See TracBrowser for help on using the repository browser.