source: sandbox/filemanager/tp/fckeditor/editor/plugins/dragresizetable/fckplugin.js @ 1575

Revision 1575, 17.9 KB checked in by amuller, 14 years ago (diff)

Ticket #597 - Implentação, melhorias do modulo gerenciador de arquivos

  • Property svn:executable set to *
Line 
1var FCKDragTableHandler =
2{
3        "_DragState" : 0,
4        "_LeftCell" : null,
5        "_RightCell" : null,
6        "_MouseMoveMode" : 0,   // 0 - find candidate cells for resizing, 1 - drag to resize
7        "_ResizeBar" : null,
8        "_OriginalX" : null,
9        "_MinimumX" : null,
10        "_MaximumX" : null,
11        "_LastX" : null,
12        "_TableMap" : null,
13        "_doc" : document,
14        "_IsInsideNode" : function( w, domNode, pos )
15        {
16                var myCoords = FCKTools.GetWindowPosition( w, domNode ) ;
17                var xMin = myCoords.x ;
18                var yMin = myCoords.y ;
19                var xMax = parseInt( xMin, 10 ) + parseInt( domNode.offsetWidth, 10 ) ;
20                var yMax = parseInt( yMin, 10 ) + parseInt( domNode.offsetHeight, 10 ) ;
21                if ( pos.x >= xMin && pos.x <= xMax && pos.y >= yMin && pos.y <= yMax )
22                        return true;
23                return false;
24        },
25        "_GetBorderCells" : function( w, tableNode, tableMap, mouse )
26        {
27                // Enumerate all the cells in the table.
28                var cells = [] ;
29                for ( var i = 0 ; i < tableNode.rows.length ; i++ )
30                {
31                        var r = tableNode.rows[i] ;
32                        for ( var j = 0 ; j < r.cells.length ; j++ )
33                                cells.push( r.cells[j] ) ;
34                }
35
36                if ( cells.length < 1 )
37                        return null ;
38
39                // Get the cells whose right or left border is nearest to the mouse cursor's x coordinate.
40                var minRxDist = null ;
41                var lxDist = null ;
42                var minYDist = null ;
43                var rbCell = null ;
44                var lbCell = null ;
45                for ( var i = 0 ; i < cells.length ; i++ )
46                {
47                        var pos = FCKTools.GetWindowPosition( w, cells[i] ) ;
48                        var rightX = pos.x + parseInt( cells[i].clientWidth, 10 ) ;
49                        var rxDist = mouse.x - rightX ;
50                        var yDist = mouse.y - ( pos.y + ( cells[i].clientHeight / 2 ) ) ;
51                        if ( minRxDist == null ||
52                                        ( Math.abs( rxDist ) <= Math.abs( minRxDist ) &&
53                                          ( minYDist == null || Math.abs( yDist ) <= Math.abs( minYDist ) ) ) )
54                        {
55                                minRxDist = rxDist ;
56                                minYDist = yDist ;
57                                rbCell = cells[i] ;
58                        }
59                }
60                /*
61                var rowNode = FCKTools.GetElementAscensor( rbCell, "tr" ) ;
62                var cellIndex = rbCell.cellIndex + 1 ;
63                if ( cellIndex >= rowNode.cells.length )
64                        return null ;
65                lbCell = rowNode.cells.item( cellIndex ) ;
66                */
67                var rowIdx = rbCell.parentNode.rowIndex ;
68                var colIdx = FCKTableHandler._GetCellIndexSpan( tableMap, rowIdx, rbCell ) ;
69                var colSpan = isNaN( rbCell.colSpan ) ? 1 : rbCell.colSpan ;
70                lbCell = tableMap[rowIdx][colIdx + colSpan] ;
71
72                if ( ! lbCell )
73                        return null ;
74
75                // Abort if too far from the border.
76                lxDist = mouse.x - FCKTools.GetWindowPosition( w, lbCell ).x ;
77                if ( lxDist < 0 && minRxDist < 0 && minRxDist < -2 )
78                        return null ;
79                if ( lxDist > 0 && minRxDist > 0 && lxDist > 3 )
80                        return null ;
81
82                return { "leftCell" : rbCell, "rightCell" : lbCell } ;
83        },
84        "_GetResizeBarPosition" : function()
85        {
86                var row = FCKTools.GetElementAscensor( this._RightCell, "tr" ) ;
87                return FCKTableHandler._GetCellIndexSpan( this._TableMap, row.rowIndex, this._RightCell ) ;
88        },
89        "_ResizeBarMouseDownListener" : function( evt )
90        {
91                if ( FCKDragTableHandler._LeftCell )
92                        FCKDragTableHandler._MouseMoveMode = 1 ;
93                if ( FCKBrowserInfo.IsIE )
94                        FCKDragTableHandler._ResizeBar.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 50 ;
95                else
96                        FCKDragTableHandler._ResizeBar.style.opacity = 0.5 ;
97                FCKDragTableHandler._OriginalX = evt.clientX ;
98
99                // Calculate maximum and minimum x-coordinate delta.
100                var borderIndex = FCKDragTableHandler._GetResizeBarPosition() ;
101                var offset = FCKDragTableHandler._GetIframeOffset();
102                var table = FCKTools.GetElementAscensor( FCKDragTableHandler._LeftCell, "table" );
103                var minX = null ;
104                var maxX = null ;
105                for ( var r = 0 ; r < FCKDragTableHandler._TableMap.length ; r++ )
106                {
107                        var leftCell = FCKDragTableHandler._TableMap[r][borderIndex - 1] ;
108                        var rightCell = FCKDragTableHandler._TableMap[r][borderIndex] ;
109                        var leftPosition = FCKTools.GetWindowPosition( FCK.EditorWindow, leftCell ) ;
110                        var rightPosition = FCKTools.GetWindowPosition( FCK.EditorWindow, rightCell ) ;
111                        var leftPadding = FCKDragTableHandler._GetCellPadding( table, leftCell ) ;
112                        var rightPadding = FCKDragTableHandler._GetCellPadding( table, rightCell ) ;
113                        if ( minX == null || leftPosition.x + leftPadding > minX )
114                                minX = leftPosition.x + leftPadding ;
115                        if ( maxX == null || rightPosition.x + rightCell.clientWidth - rightPadding < maxX )
116                                maxX = rightPosition.x + rightCell.clientWidth - rightPadding ;
117                }
118
119                FCKDragTableHandler._MinimumX = minX + offset.x ;
120                FCKDragTableHandler._MaximumX = maxX + offset.x ;
121                FCKDragTableHandler._LastX = null ;
122
123                if (evt.preventDefault)
124                        evt.preventDefault();
125                else
126                        evt.returnValue = false;
127        },
128        "_ResizeBarMouseUpListener" : function( evt )
129        {
130                FCKDragTableHandler._MouseMoveMode = 0 ;
131                FCKDragTableHandler._HideResizeBar() ;
132
133                if ( FCKDragTableHandler._LastX == null )
134                        return ;
135
136                // Calculate the delta value.
137                var deltaX = FCKDragTableHandler._LastX - FCKDragTableHandler._OriginalX ;
138
139                // Then, build an array of current column width values.
140                // This algorithm can be very slow if the cells have insane colSpan values. (e.g. colSpan=1000).
141                var table = FCKTools.GetElementAscensor( FCKDragTableHandler._LeftCell, "table" ) ;
142                var colArray = [] ;
143                var tableMap = FCKDragTableHandler._TableMap ;
144                for ( var i = 0 ; i < tableMap.length ; i++ )
145                {
146                        for ( var j = 0 ; j < tableMap[i].length ; j++ )
147                        {
148                                var cell = tableMap[i][j] ;
149                                var width = FCKDragTableHandler._GetCellWidth( table, cell ) ;
150                                var colSpan = isNaN( cell.colSpan) ? 1 : cell.colSpan ;
151                                if ( colArray.length <= j )
152                                        colArray.push( { width : width / colSpan, colSpan : colSpan } ) ;
153                                else
154                                {
155                                        var guessItem = colArray[j] ;
156                                        if ( guessItem.colSpan > colSpan )
157                                        {
158                                                guessItem.width = width / colSpan ;
159                                                guessItem.colSpan = colSpan ;
160                                        }
161                                }
162                        }
163                }
164
165                // Find out the equivalent column index of the two cells selected for resizing.
166                colIndex = FCKDragTableHandler._GetResizeBarPosition() ;
167
168                // Note that colIndex must be at least 1 here, so it's safe to subtract 1 from it.
169                colIndex-- ;
170
171                // Modify the widths in the colArray according to the mouse coordinate delta value.
172                colArray[colIndex].width += deltaX ;
173                colArray[colIndex + 1].width -= deltaX ;
174
175                // Clear all cell widths, delete all <col> elements from the table.
176                for ( var r = 0 ; r < table.rows.length ; r++ )
177                {
178                        var row = table.rows.item( r ) ;
179                        for ( var c = 0 ; c < row.cells.length ; c++ )
180                        {
181                                var cell = row.cells.item( c ) ;
182                                cell.width = "" ;
183                                cell.style.width = "" ;
184                        }
185                }
186                var colElements = table.getElementsByTagName( "col" ) ;
187                for ( var i = colElements.length - 1 ; i >= 0 ; i-- )
188                        colElements[i].parentNode.removeChild( colElements[i] ) ;
189
190                // Set new cell widths.
191                var processedCells = [] ;
192                for ( var i = 0 ; i < tableMap.length ; i++ )
193                {
194                        for ( var j = 0 ; j < tableMap[i].length ; j++ )
195                        {
196                                var cell = tableMap[i][j] ;
197                                if ( cell._Processed )
198                                        continue ;
199                                if ( tableMap[i][j-1] != cell )
200                                        cell.width = colArray[j].width ;
201                                else
202                                        cell.width = parseInt( cell.width, 10 ) + parseInt( colArray[j].width, 10 ) ;
203                                if ( tableMap[i][j+1] != cell )
204                                {
205                                        processedCells.push( cell ) ;
206                                        cell._Processed = true ;
207                                }
208                        }
209                }
210                for ( var i = 0 ; i < processedCells.length ; i++ )
211                {
212                        if ( FCKBrowserInfo.IsIE )
213                                processedCells[i].removeAttribute( '_Processed' ) ;
214                        else
215                                delete processedCells[i]._Processed ;
216                }
217
218                FCKDragTableHandler._LastX = null ;
219        },
220        "_ResizeBarMouseMoveListener" : function( evt )
221        {
222                if ( FCKDragTableHandler._MouseMoveMode == 0 )
223                        return FCKDragTableHandler._MouseFindHandler( FCK, evt ) ;
224                else
225                        return FCKDragTableHandler._MouseDragHandler( FCK, evt ) ;
226        },
227        // Calculate the padding of a table cell.
228        // It returns the value of paddingLeft + paddingRight of a table cell.
229        // This function is used, in part, to calculate the width parameter that should be used for setting cell widths.
230        // The equation in question is clientWidth = paddingLeft + paddingRight + width.
231        // So that width = clientWidth - paddingLeft - paddingRight.
232        // The return value of this function must be pixel accurate acorss all supported browsers, so be careful if you need to modify it.
233        "_GetCellPadding" : function( table, cell )
234        {
235                var attrGuess = parseInt( table.cellPadding, 10 ) * 2 ;
236                var cssGuess = null ;
237                if ( typeof( window.getComputedStyle ) == "function" )
238                {
239                        var styleObj = window.getComputedStyle( cell, null ) ;
240                        cssGuess = parseInt( styleObj.getPropertyValue( "padding-left" ), 10 ) +
241                                parseInt( styleObj.getPropertyValue( "padding-right" ), 10 ) ;
242                }
243                else
244                        cssGuess = parseInt( cell.currentStyle.paddingLeft, 10 ) + parseInt (cell.currentStyle.paddingRight, 10 ) ;
245
246                var cssRuntime = cell.style.padding ;
247                if ( isFinite( cssRuntime ) )
248                        cssGuess = parseInt( cssRuntime, 10 ) * 2 ;
249                else
250                {
251                        cssRuntime = cell.style.paddingLeft ;
252                        if ( isFinite( cssRuntime ) )
253                                cssGuess = parseInt( cssRuntime, 10 ) ;
254                        cssRuntime = cell.style.paddingRight ;
255                        if ( isFinite( cssRuntime ) )
256                                cssGuess += parseInt( cssRuntime, 10 ) ;
257                }
258
259                attrGuess = parseInt( attrGuess, 10 ) ;
260                cssGuess = parseInt( cssGuess, 10 ) ;
261                if ( isNaN( attrGuess ) )
262                        attrGuess = 0 ;
263                if ( isNaN( cssGuess ) )
264                        cssGuess = 0 ;
265                return Math.max( attrGuess, cssGuess ) ;
266        },
267        // Calculate the real width of the table cell.
268        // The real width of the table cell is the pixel width that you can set to the width attribute of the table cell and after
269        // that, the table cell should be of exactly the same width as before.
270        // The real width of a table cell can be calculated as:
271        // width = clientWidth - paddingLeft - paddingRight.
272        "_GetCellWidth" : function( table, cell )
273        {
274                var clientWidth = cell.clientWidth ;
275                if ( isNaN( clientWidth ) )
276                        clientWidth = 0 ;
277                return clientWidth - this._GetCellPadding( table, cell ) ;
278        },
279        "MouseMoveListener" : function( FCK, evt )
280        {
281                if ( FCKDragTableHandler._MouseMoveMode == 0 )
282                        return FCKDragTableHandler._MouseFindHandler( FCK, evt ) ;
283                else
284                        return FCKDragTableHandler._MouseDragHandler( FCK, evt ) ;
285        },
286        "_MouseFindHandler" : function( FCK, evt )
287        {
288                if ( FCK.MouseDownFlag )
289                        return ;
290                var node = evt.srcElement || evt.target ;
291                try
292                {
293                        if ( ! node || node.nodeType != 1 )
294                        {
295                                this._HideResizeBar() ;
296                                return ;
297                        }
298                }
299                catch ( e )
300                {
301                        this._HideResizeBar() ;
302                        return ;
303                }
304
305                // Since this function might be called from the editing area iframe or the outer fckeditor iframe,
306                // the mouse point coordinates from evt.clientX/Y can have different reference points.
307                // We need to resolve the mouse pointer position relative to the editing area iframe.
308                var mouseX = evt.clientX ;
309                var mouseY = evt.clientY ;
310                if ( FCKTools.GetElementDocument( node ) == document )
311                {
312                        var offset = this._GetIframeOffset() ;
313                        mouseX -= offset.x ;
314                        mouseY -= offset.y ;
315                }
316
317
318                if ( this._ResizeBar && this._LeftCell )
319                {
320                        var leftPos = FCKTools.GetWindowPosition( FCK.EditorWindow, this._LeftCell ) ;
321                        var rightPos = FCKTools.GetWindowPosition( FCK.EditorWindow, this._RightCell ) ;
322                        var rxDist = mouseX - ( leftPos.x + this._LeftCell.clientWidth ) ;
323                        var lxDist = mouseX - rightPos.x ;
324                        var inRangeFlag = false ;
325                        if ( lxDist >= 0 && rxDist <= 0 )
326                                inRangeFlag = true ;
327                        else if ( rxDist > 0 && lxDist <= 3 )
328                                inRangeFlag = true ;
329                        else if ( lxDist < 0 && rxDist >= -2 )
330                                inRangeFlag = true ;
331                        if ( inRangeFlag )
332                        {
333                                this._ShowResizeBar( FCK.EditorWindow,
334                                        FCKTools.GetElementAscensor( this._LeftCell, "table" ),
335                                        { "x" : mouseX, "y" : mouseY } ) ;
336                                return ;
337                        }
338                }
339
340                var tagName = node.tagName.toLowerCase() ;
341                if ( tagName != "table" && tagName != "td" && tagName != "th" )
342                {
343                        if ( this._LeftCell )
344                                this._LeftCell = this._RightCell = this._TableMap = null ;
345                        this._HideResizeBar() ;
346                        return ;
347                }
348                node = FCKTools.GetElementAscensor( node, "table" ) ;
349                var tableMap = FCKTableHandler._CreateTableMap( node ) ;
350                var cellTuple = this._GetBorderCells( FCK.EditorWindow, node, tableMap, { "x" : mouseX, "y" : mouseY } ) ;
351
352                if ( cellTuple == null )
353                {
354                        if ( this._LeftCell )
355                                this._LeftCell = this._RightCell = this._TableMap = null ;
356                        this._HideResizeBar() ;
357                }
358                else
359                {
360                        this._LeftCell = cellTuple["leftCell"] ;
361                        this._RightCell = cellTuple["rightCell"] ;
362                        this._TableMap = tableMap ;
363                        this._ShowResizeBar( FCK.EditorWindow,
364                                        FCKTools.GetElementAscensor( this._LeftCell, "table" ),
365                                        { "x" : mouseX, "y" : mouseY } ) ;
366                }
367        },
368        "_MouseDragHandler" : function( FCK, evt )
369        {
370                var mouse = { "x" : evt.clientX, "y" : evt.clientY } ;
371
372                // Convert mouse coordinates in reference to the outer iframe.
373                var node = evt.srcElement || evt.target ;
374                if ( FCKTools.GetElementDocument( node ) == FCK.EditorDocument )
375                {
376                        var offset = this._GetIframeOffset() ;
377                        mouse.x += offset.x ;
378                        mouse.y += offset.y ;
379                }
380
381                // Calculate the mouse position delta and see if we've gone out of range.
382                if ( mouse.x >= this._MaximumX - 5 )
383                        mouse.x = this._MaximumX - 5 ;
384                if ( mouse.x <= this._MinimumX + 5 )
385                        mouse.x = this._MinimumX + 5 ;
386
387                var docX = mouse.x + FCKTools.GetScrollPosition( window ).X ;
388                this._ResizeBar.style.left = ( docX - this._ResizeBar.offsetWidth / 2 ) + "px" ;
389                this._LastX = mouse.x ;
390        },
391        "_ShowResizeBar" : function( w, table, mouse )
392        {
393                if ( this._ResizeBar == null )
394                {
395                        this._ResizeBar = this._doc.createElement( "div" ) ;
396                        var paddingBar = this._ResizeBar ;
397                        var paddingStyles = { 'position' : 'absolute', 'cursor' : 'e-resize' } ;
398                        if ( FCKBrowserInfo.IsIE )
399                                paddingStyles.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=10,enabled=true)" ;
400                        else
401                                paddingStyles.opacity = 0.10 ;
402                        FCKDomTools.SetElementStyles( paddingBar, paddingStyles ) ;
403                        this._avoidStyles( paddingBar );
404                        paddingBar.setAttribute('_fcktemp', true);
405                        this._doc.body.appendChild( paddingBar ) ;
406                        FCKTools.AddEventListener( paddingBar, "mousemove", this._ResizeBarMouseMoveListener ) ;
407                        FCKTools.AddEventListener( paddingBar, "mousedown", this._ResizeBarMouseDownListener ) ;
408                        FCKTools.AddEventListener( document, "mouseup", this._ResizeBarMouseUpListener ) ;
409                        FCKTools.AddEventListener( FCK.EditorDocument, "mouseup", this._ResizeBarMouseUpListener ) ;
410
411                        // IE doesn't let the tranparent part of the padding block to receive mouse events unless there's something inside.
412                        // So we need to create a spacer image to fill the block up.
413                        var filler = this._doc.createElement( "img" ) ;
414                        filler.setAttribute('_fcktemp', true);
415                        filler.border = 0 ;
416                        filler.src = FCKConfig.BasePath + "images/spacer.gif" ;
417                        filler.style.position = "absolute" ;
418                        paddingBar.appendChild( filler ) ;
419
420                        // Disable drag and drop, and selection for the filler image.
421                        var disabledListener = function( evt )
422                        {
423                                if ( evt.preventDefault )
424                                        evt.preventDefault() ;
425                                else
426                                        evt.returnValue = false ;
427                        }
428                        FCKTools.AddEventListener( filler, "dragstart", disabledListener ) ;
429                        FCKTools.AddEventListener( filler, "selectstart", disabledListener ) ;
430                }
431
432                var paddingBar = this._ResizeBar ;
433                var offset = this._GetIframeOffset() ;
434                var tablePos = this._GetTablePosition( w, table ) ;
435                var barHeight = table.offsetHeight ;
436                var barTop = offset.y + tablePos.y ;
437                // Do not let the resize bar intrude into the toolbar area.
438                if ( tablePos.y < 0 )
439                {
440                        barHeight += tablePos.y ;
441                        barTop -= tablePos.y ;
442                }
443                var bw = parseInt( table.border, 10 ) ;
444                if ( isNaN( bw ) )
445                        bw = 0 ;
446                var cs = parseInt( table.cellSpacing, 10 ) ;
447                if ( isNaN( cs ) )
448                        cs = 0 ;
449                var barWidth = Math.max( bw+100, cs+100 ) ;
450                var paddingStyles =
451                {
452                        'top'           : barTop + 'px',
453                        'height'        : barHeight + 'px',
454                        'width'         : barWidth + 'px',
455                        'left'          : ( offset.x + mouse.x + FCKTools.GetScrollPosition( w ).X - barWidth / 2 ) + 'px'
456                } ;
457                if ( FCKBrowserInfo.IsIE )
458                        paddingBar.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 10 ;
459                else
460                        paddingStyles.opacity = 0.1 ;
461
462                FCKDomTools.SetElementStyles( paddingBar, paddingStyles ) ;
463                var filler = paddingBar.getElementsByTagName( "img" )[0] ;
464
465                FCKDomTools.SetElementStyles( filler,
466                        {
467                                width   : paddingBar.offsetWidth + 'px',
468                                height  : barHeight + 'px'
469                        } ) ;
470
471                barWidth = Math.max( bw, cs, 3 ) ;
472                var visibleBar = null ;
473                if ( paddingBar.getElementsByTagName( "div" ).length < 1 )
474                {
475                        visibleBar = this._doc.createElement( "div" ) ;
476                        this._avoidStyles( visibleBar );
477                        visibleBar.setAttribute('_fcktemp', true);
478                        paddingBar.appendChild( visibleBar ) ;
479                }
480                else
481                        visibleBar = paddingBar.getElementsByTagName( "div" )[0] ;
482
483                FCKDomTools.SetElementStyles( visibleBar,
484                        {
485                                position                : 'absolute',
486                                backgroundColor : 'blue',
487                                width                   : barWidth + 'px',
488                                height                  : barHeight + 'px',
489                                left                    : '50px',
490                                top                             : '0px'
491                        } ) ;
492        },
493        "_HideResizeBar" : function()
494        {
495                if ( this._ResizeBar )
496                        // IE bug: display : none does not hide the resize bar for some reason.
497                        // so set the position to somewhere invisible.
498                        FCKDomTools.SetElementStyles( this._ResizeBar,
499                                {
500                                        top             : '-100000px',
501                                        left    : '-100000px'
502                                } ) ;
503        },
504        "_GetIframeOffset" : function ()
505        {
506                return FCKTools.GetDocumentPosition( window, FCK.EditingArea.IFrame ) ;
507        },
508        "_GetTablePosition" : function ( w, table )
509        {
510                return FCKTools.GetWindowPosition( w, table ) ;
511        },
512        "_avoidStyles" : function( element )
513        {
514                FCKDomTools.SetElementStyles( element,
515                        {
516                                padding         : '0',
517                                backgroundImage : 'none',
518                                border          : '0'
519                        } ) ;
520        },
521        "Reset" : function()
522        {
523                FCKDragTableHandler._LeftCell = FCKDragTableHandler._RightCell = FCKDragTableHandler._TableMap = null ;
524        }
525
526};
527
528FCK.Events.AttachEvent( "OnMouseMove", FCKDragTableHandler.MouseMoveListener ) ;
529FCK.Events.AttachEvent( "OnAfterSetHTML", FCKDragTableHandler.Reset ) ;
Note: See TracBrowser for help on using the repository browser.