Index: /FCKeditor/trunk/editor/_source/classes/fckspecialcombo.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckspecialcombo.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/classes/fckspecialcombo.js (revision 480)
@@ -139,4 +139,5 @@
for ( var i in this.Items )
{
+ if ( !this.Items[i] ) continue;
this.Items[i].className = this.Items[i].originalClass = 'SC_Item' ;
this.Items[i].Selected = false ;
Index: /FCKeditor/trunk/editor/_source/commandclasses/fck_othercommands.js
===================================================================
--- /FCKeditor/trunk/editor/_source/commandclasses/fck_othercommands.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/commandclasses/fck_othercommands.js (revision 480)
@@ -99,8 +99,21 @@
if ( typeof( fontSize ) == 'string' ) fontSize = parseInt(fontSize, 10) ;
- if ( fontSize == null || fontSize == '' )
- {
- // TODO: Remove font size attribute (Now it works with size 3. Will it work forever?)
- FCK.ExecuteNamedCommand( 'FontSize', 3 ) ;
+ // If user wants the font size cleared, we have to find
+ // where the font size tag is and go clear it (if there's one)
+ if ( !fontSize || fontSize == null || fontSize == '' )
+ {
+ var oFont = FCK.Selection.MoveToAncestorNode('FONT');
+ if ( oFont && oFont.getAttribute("size") )
+ {
+ //if the only thing here is SIZE, collapse the whole tag
+ if (oFont.attributes.length == 1 ||
+ (oFont.outerHTML && oFont.outerHTML.search(//i)))
+ {
+ FCKTools.RemoveOuterTags(oFont);
+ }
+ else
+ oFont.removeAttribute("size");
+ }
+
}
else
Index: /FCKeditor/trunk/editor/_source/internals/fck_gecko.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fck_gecko.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/internals/fck_gecko.js (revision 480)
@@ -39,4 +39,19 @@
}
+ //allow the table handler to handle mouse messages for dynamic table sizing
+ this._ExecMouseDown = function(e)
+ {
+ FCK.Events.FireEvent( "OnMouseDown",e ) ;
+ }
+
+ this._ExecMouseMove = function(e)
+ {
+ FCK.Events.FireEvent( "OnMouseMove",e ) ;
+ }
+
+ this._ExecMouseUp = function(e)
+ {
+ FCK.Events.FireEvent( "OnMouseUp",e ) ;
+ }
this.ExecOnSelectionChangeTimer = function()
{
@@ -62,4 +77,10 @@
// Record changes for the undo system when there are key down events.
this.EditorDocument.addEventListener( 'keydown', this._KeyDownListener, false ) ;
+
+
+ //Hooks for table sizing
+ this.EditorDocument.addEventListener( 'mousedown', this._ExecMouseDown, true ) ;
+ this.EditorDocument.addEventListener( 'mouseup', this._ExecMouseUp, true ) ;
+ this.EditorDocument.addEventListener( 'mousemove', this._ExecMouseMove, true ) ;
// Reset the context menu.
@@ -99,4 +120,5 @@
Print : true,
Paste : true,
+
Cut : true,
Copy : true
Index: /FCKeditor/trunk/editor/_source/internals/fck_ie.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fck_ie.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/internals/fck_ie.js (revision 480)
@@ -70,4 +70,15 @@
FCK.EditorWindow.event.returnValue = false ;
}
+ FCK.Events.FireEvent( "OnMouseUp",FCK.EditorWindow.event) ;
+}
+
+function Doc_OnMouseDown()
+{
+ FCK.Events.FireEvent( "OnMouseDown",FCK.EditorWindow.event ) ;
+}
+
+function Doc_OnMouseMove()
+{
+ FCK.Events.FireEvent( "OnMouseMove",FCK.EditorWindow.event) ;
}
@@ -103,4 +114,8 @@
this.EditorDocument.attachEvent("ondblclick", Doc_OnDblClick ) ;
+
+ //additions for table sizing
+ this.EditorDocument.attachEvent( 'onmousedown', Doc_OnMouseDown ) ;
+ this.EditorDocument.attachEvent( 'onmousemove', Doc_OnMouseMove ) ;
// Catch cursor selection changes.
Index: /FCKeditor/trunk/editor/_source/internals/fckcommands.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fckcommands.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/internals/fckcommands.js (revision 480)
Index: /FCKeditor/trunk/editor/_source/internals/fckselection.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fckselection.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/internals/fckselection.js (revision 480)
@@ -23,2 +23,3 @@
var FCKSelection = FCK.Selection = new Object() ;
+
Index: /FCKeditor/trunk/editor/_source/internals/fckselection_gecko.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fckselection_gecko.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/internals/fckselection_gecko.js (revision 480)
@@ -150,2 +150,48 @@
return oSel ;
}
+
+// If FCKSelection is inside a table, return
's so we can work on each
+// one as a separate element
+FCKSelection.TableNodes = function()
+{
+ var oSel = FCK.EditorWindow.getSelection();
+ var aNodes = new Array();
+ if (this.HasAncestorNode("TABLE"))
+ {
+ var oTable = this.MoveToAncestorNode("TABLE");
+ for (var r = 0; r < oTable.rows.length; r++)
+ {
+ for (var c = 0; c < oTable.rows[r].cells.length; c++)
+ {
+ if (oSel.containsNode(oTable.rows[r].cells[c],true))
+ {
+ aNodes[aNodes.length] = oTable.rows[r].cells[c];
+ }
+ }
+ }
+ }
+ return aNodes;
+}
+
+FCKSelection.SelectedHTML = function()
+{
+ var oSel = FCK.EditorWindow.getSelection();
+ var strHTML = "";
+ //convert to a text range and walk the elements
+ for ( var i = 0 ; i < oSel.rangeCount ; i++ )
+ {
+ var df = oSel.getRangeAt(i).cloneContents();
+
+ for (var j = 0; j < df.childNodes.length; j++)
+ {
+ if (df.childNodes[j].nodeName == "#text")
+ {if (df.childNodes[j].textContent) strHTML += df.childNodes[j].textContent;}
+ else
+ strHTML += '<' + df.childNodes[j].nodeName + '>'
+ + df.childNodes[j].innerHTML
+ + '' + df.childNodes[j].nodeName + '>';
+ }
+ }
+ return strHTML;
+}
+
Index: /FCKeditor/trunk/editor/_source/internals/fckselection_ie.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fckselection_ie.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/internals/fckselection_ie.js (revision 480)
@@ -47,4 +47,5 @@
{
case 'Control' :
+ if (!FCKSelection.GetSelectedElement()) return;
return FCKSelection.GetSelectedElement().parentElement ;
case 'None' :
@@ -110,4 +111,25 @@
return false ;
} ;
+// If FCKSelection is inside a table, return | 's so we can work on each
+// one as a separate element
+FCKSelection.TableNodes = function()
+{
+ var oRange = FCK.EditorDocument.selection.createRange() ;
+ if (!oRange.htmlText.search(/ | = 0; i-- )
+ {
+ if ( aRowsToDelete[i] )
+ FCKTableHandler.DeleteRows( aRowsToDelete[i] );
+ }
+ return ;
+ }
// Get the row's table.
@@ -77,5 +93,11 @@
FCKSelection.SelectNode( table ) ;
FCKSelection.Collapse();
- table.parentNode.removeChild( table ) ;
+
+ // if the table is wrapped with a singleton ( or something similar ), remove
+ // the surrounding tag -- which likely won't show after deletion anyway
+ if ( table.parentNode.childNodes.length == 1 )
+ table.parentNode.parentNode.removeChild( table.parentNode );
+ else
+ table.parentNode.removeChild( table ) ;
}
@@ -83,21 +105,10 @@
{
// Get the cell where the selection is placed in.
- var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ;
-
- if ( !oCell )
- {
- // oCell not fouund could be due to multiple selection ranges on tables in Gecko.
- // We have another function to find the table cell for this special case.
- if ( ! FCKBrowserInfo.IsIE )
- {
- var node = this._GetSelectedCellFromGecko( true ) ;
- if ( node )
- oCell = node ;
- else
- return null ;
- }
- else
- return null ;
- }
+ var oCell = null ;
+ var nodes = this.GetSelectedCells() ;
+ if ( nodes && nodes.length )
+ oCell = nodes[ insertBefore ? 0 : ( nodes.length - 1 ) ] ;
+ if ( ! oCell )
+ return null ;
// Get the cell's table.
@@ -133,8 +144,18 @@
}
-FCKTableHandler.DeleteColumns = function()
-{
- // Get the cell where the selection is placed in.
- var oCell = FCKSelection.MoveToAncestorNode('TD') || FCKSelection.MoveToAncestorNode('TH') ;
+FCKTableHandler.DeleteColumns = function( oCell )
+{
+ // if user selected multiple cols ( by selecting multiple cells ), walk
+ // the selected cell list and delete the rows containing the selected cells
+ if ( !oCell )
+ {
+ var aColsToDelete = FCKTableHandler.GetSelectedCells();
+ for ( var i = aColsToDelete.length; i >= 0; i-- )
+ {
+ if ( aColsToDelete[i] )
+ FCKTableHandler.DeleteColumns( aColsToDelete[i] );
+ }
+ return;
+ }
if ( !oCell ) return ;
@@ -170,20 +191,10 @@
{
// Get the cell where the selection is placed in.
- var oCell = cell ? cell : FCKSelection.MoveToAncestorNode( 'TD' ) ;
- if ( !oCell )
- {
- // oCell not fouund could be due to multiple selection ranges on tables in Gecko.
- // We have another function to find the table cell for this special case.
- if ( ! FCKBrowserInfo.IsIE )
- {
- var node = this._GetSelectedCellFromGecko( true ) ;
- if ( node )
- oCell = node ;
- else
- return null ;
- }
- else
- return null ;
- }
+ var oCell = null ;
+ var nodes = this.GetSelectedCells() ;
+ if ( nodes && nodes.length )
+ oCell = nodes[ insertBefore ? 0 : ( nodes.length - 1 ) ] ;
+ if ( ! oCell )
+ return null ;
// Create the new cell element to be added.
@@ -191,5 +202,5 @@
if ( FCKBrowserInfo.IsGecko )
oNewCell.innerHTML = GECKO_BOGUS ;
-// oNewCell.innerHTML = " " ;
+ // oNewCell.innerHTML = " " ;
if ( !insertBefore && oCell.cellIndex == oCell.parentNode.cells.length - 1 )
@@ -256,5 +267,5 @@
continue ;
- oCellsContents.insertBefore( eChild, oCellsContents.firstChild ) ;
+ oCellsContents.insertBefore( eChild, oCellsContents.firstChild ) ;
}
@@ -288,5 +299,5 @@
var iCellIndex = FCKTableHandler._GetCellIndexSpan( aMap, aCells[0].parentNode.rowIndex , aCells[0] ) ;
- var aCollCells = this._GetCollumnCells( aMap, iCellIndex ) ;
+ var aCollCells = this._GetColumnCells( aMap, iCellIndex ) ;
for ( var i = 0 ; i < aCollCells.length ; i++ )
@@ -325,6 +336,19 @@
}
-// Get the cells available in a collumn of a TableMap.
-FCKTableHandler._GetCollumnCells = function( tableMap, collumnIndex )
+// Get the cell location from a TableMap. Returns an array with an [x,y] location
+FCKTableHandler._GetCellLocation = function( tableMap, cell )
+{
+ for ( var i = 0 ; i < tableMap.length; i++ )
+ {
+ for ( var c = 0 ; c < tableMap[i].length ; c++ )
+ {
+ if ( tableMap[i][c] == cell ) return [i,c];
+ }
+ }
+ return null ;
+}
+
+// Get the cells available in a column of a TableMap.
+FCKTableHandler._GetColumnCells = function( tableMap, columnIndex )
{
var aCollCells = new Array() ;
@@ -332,5 +356,5 @@
for ( var r = 0 ; r < tableMap.length ; r++ )
{
- var oCell = tableMap[r][collumnIndex] ;
+ var oCell = tableMap[r][columnIndex] ;
if ( oCell && ( aCollCells.length == 0 || aCollCells[ aCollCells.length - 1 ] != oCell ) )
aCollCells[ aCollCells.length ] = oCell ;
@@ -405,39 +429,2 @@
}
}
-
-FCKTableHandler._GetSelectedCellFromGecko = function( getLastCell )
-{
- var sel = FCK.EditorWindow.getSelection() ;
- if ( sel.rangeCount < 1 )
- return null ;
- var range = getLastCell ? sel.getRangeAt( sel.rangeCount - 1 ) : sel.getRangeAt( 0 ) ;
- var node = getLastCell ? range.endContainer : range.startContainer ;
-
- // Gecko returns a | as startContainer and endContainer when cells are selected.
- // We need to find back the final that's being selected.
- if ( node.nodeType == 1 && node.tagName.toLowerCase() == 'tr' )
- {
- for ( var i = range.startOffset ; i <= range.endOffset ; i++ )
- {
- var candidate = node.childNodes[i] ;
- var tag = candidate.tagName.toLowerCase() ;
- if ( candidate.nodeType == 1 && ( tag == 'td' || tag == 'th' ) )
- {
- node = node.childNodes[i] ;
- break ;
- }
- }
- }
- // For safety, we have to be ready for the 'usual' case as well.
- else
- {
- while ( node && node.tagName.toLowerCase() != 'td' && node.tagName.toLowerCase() != 'th' )
- node = node.parentNode ;
- }
-
- // Have we found the | node we wanted, finally? If yes, return the found node. If not, abort.
- if ( node.tagName.toLowerCase() != 'td' && node.tagName.toLowerCase() != 'th' )
- return null ;
- else
- return node ;
-}
Index: /FCKeditor/trunk/editor/_source/internals/fcktools.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fcktools.js (revision 479)
+++ /FCKeditor/trunk/editor/_source/internals/fcktools.js (revision 480)
@@ -94,9 +94,4 @@
return '' ;
- text = text.replace( /&/g, '&' ) ;
- text = text.replace( //g, '>' ) ;
-
- return text ;
}
Index: /FCKeditor/trunk/editor/plugins/dragresizetable/fckplugin.js
===================================================================
--- /FCKeditor/trunk/editor/plugins/dragresizetable/fckplugin.js (revision 480)
+++ /FCKeditor/trunk/editor/plugins/dragresizetable/fckplugin.js (revision 480)
@@ -0,0 +1,542 @@
+var FCKDragTableHandler =
+{
+ "_DragState" : 0,
+ "_LeftCell" : null,
+ "_RightCell" : null,
+ "_MouseMoveMode" : 0, // 0 - find candidate cells for resizing, 1 - drag to resize
+ "_ResizeBar" : null,
+ "_OriginalX" : null,
+ "_MinimumX" : null,
+ "_MaximumX" : null,
+ "_LastX" : null,
+ "_GetWindowScrollX" : function( w )
+ {
+ var scrollX = 0 ;
+ if ( w.document.documentElement && w.document.documentElement.scrollLeft )
+ scrollX = w.document.documentElement.scrollLeft ;
+ else if ( w.document.body && w.document.body.scrollLeft )
+ scrollX = w.document.body.scrollLeft ;
+ else if ( w.scrollX )
+ scrollX = w.scrollX ;
+ return scrollX ;
+ },
+ "_GetWindowScrollY" : function( w )
+ {
+ var scrollY = 0 ;
+ if ( w.document.documentElement && w.document.documentElement.scrollTop )
+ scrollY = w.document.documentElement.scrollTop ;
+ else if ( w.document.body && w.document.body.scrollTop )
+ scrollY = w.document.body.scrollTop ;
+ else if ( w.scrollY )
+ scrollY = w.scrollY ;
+ return scrollY ;
+ },
+ "_GetDocumentPosition" : function( w, node )
+ {
+ var x = 0 ;
+ var y = 0 ;
+ var curNode = node ;
+ while ( curNode && curNode != w.document.body )
+ {
+ x += curNode.offsetLeft - curNode.scrollLeft ;
+ y += curNode.offsetTop - curNode.scrollTop ;
+ curNode = curNode.offsetParent ;
+ }
+ return { "x" : x, "y" : y } ;
+ },
+ "_GetWindowPosition" : function( w, node )
+ {
+ var pos = this._GetDocumentPosition( w, node ) ;
+ pos.x -= this._GetWindowScrollX( w ) ;
+ pos.y -= this._GetWindowScrollY( w ) ;
+ return pos ;
+ },
+ "_IsInsideNode" : function( w, domNode, pos )
+ {
+ var myCoords = this._GetWindowPosition( w, domNode ) ;
+ var xMin = myCoords.x ;
+ var yMin = myCoords.y ;
+ var xMax = parseInt( xMin ) + parseInt( domNode.offsetWidth ) ;
+ var yMax = parseInt( yMin ) + parseInt( domNode.offsetHeight ) ;
+ if ( pos.x >= xMin && pos.x <= xMax && pos.y >= yMin && pos.y <= yMax )
+ return true;
+ return false;
+ },
+ "_GetBorderCells" : function( w, tableNode, mouse )
+ {
+ // Enumerate all the cells in the table.
+ var cells = [] ;
+ for ( var i = 0 ; i < tableNode.rows.length ; i++ )
+ {
+ var r = tableNode.rows[i] ;
+ for ( var j = 0 ; j < r.cells.length ; j++ )
+ cells.push( r.cells[j] ) ;
+ }
+
+ if ( cells.length < 1 )
+ return null ;
+
+ // Get the cells whose right or left border is nearest to the mouse cursor's x coordinate.
+ var minRxDist = null ;
+ var lxDist = null ;
+ var minYDist = null ;
+ var rbCell = null ;
+ var lbCell = null ;
+ for ( var i = 0 ; i < cells.length ; i++ )
+ {
+ var pos = this._GetWindowPosition( w, cells[i] ) ;
+ var rightX = pos.x + parseInt( cells[i].clientWidth ) ;
+ var rxDist = mouse.x - rightX ;
+ var yDist = mouse.y - ( pos.y + ( cells[i].clientHeight / 2 ) ) ;
+ if ( minRxDist == null ||
+ ( Math.abs( rxDist ) <= Math.abs( minRxDist ) &&
+ ( minYDist == null || Math.abs( yDist ) <= Math.abs( minYDist ) ) ) )
+ {
+ minRxDist = rxDist ;
+ minYDist = yDist ;
+ rbCell = cells[i] ;
+ }
+ }
+ var rowNode = FCKTools.GetElementAscensor( rbCell, "tr" ) ;
+ var cellIndex = rbCell.cellIndex + 1 ;
+ if ( cellIndex >= rowNode.cells.length )
+ return null ;
+ lbCell = rowNode.cells.item( cellIndex ) ;
+
+ // Abort if too far from the border.
+ lxDist = mouse.x - this._GetWindowPosition( w, lbCell ).x ;
+ if ( lxDist < 0 && minRxDist < 0 && minRxDist < -2 )
+ return null ;
+ if ( lxDist > 0 && minRxDist > 0 && lxDist > 3 )
+ return null ;
+
+ return { "leftCell" : rbCell, "rightCell" : lbCell } ;
+ },
+ "_GetResizeBarPosition" : function()
+ {
+ var row = FCKTools.GetElementAscensor( this._LeftCell, "tr" ) ;
+ var colIndex = 0 ;
+ for ( var i = 0 ; i <= this._LeftCell.cellIndex ; i++ )
+ {
+ var colSpan = parseInt( row.cells.item( i ).colSpan ) ;
+ if ( colSpan != colSpan )
+ colSpan = 1 ;
+ colIndex += colSpan ;
+ }
+ return colIndex ;
+ },
+ "_ResizeBarMouseDownListener" : function( evt )
+ {
+ if ( ! evt )
+ evt = window.event ;
+ if ( FCKDragTableHandler._LeftCell )
+ FCKDragTableHandler._MouseMoveMode = 1 ;
+ if ( FCKBrowserInfo.IsIE )
+ FCKDragTableHandler._ResizeBar.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 50 ;
+ else
+ FCKDragTableHandler._ResizeBar.style.opacity = 0.5 ;
+ FCKDragTableHandler._OriginalX = evt.clientX ;
+
+ // Calculate maximum and minimum x-coordinate delta.
+ var borderIndex = FCKDragTableHandler._GetResizeBarPosition() ;
+ var offset = FCKDragTableHandler._GetDocumentPosition( window, FCK.EditingArea.IFrame ) ;
+ var table = FCKTools.GetElementAscensor( FCKDragTableHandler._LeftCell, "table" );
+ var minX = null ;
+ var maxX = null ;
+ for ( var r = 0 ; r < table.rows.length ; r++ )
+ {
+ var row = table.rows.item( r ) ;
+ var colIndex = 0 ;
+ for ( var c = 0 ; c < row.cells.length ; c++ )
+ {
+ var cell = row.cells.item( c ) ;
+ var cellPosition = FCKDragTableHandler._GetWindowPosition( FCK.EditorWindow, cell ) ;
+ var cellPadding = FCKDragTableHandler._GetCellPadding( table, cell ) ;
+ var cellMinX = cellPosition.x + cellPadding ;
+ var cellMaxX = cellPosition.x + cell.clientWidth - cellPadding ;
+ if ( colIndex < borderIndex )
+ {
+ if ( minX == null || cellMinX > minX )
+ minX = cellMinX ;
+ }
+ else
+ {
+ if ( maxX == null || cellMaxX < maxX )
+ maxX = cellMaxX ;
+ }
+ colIndex += cell.colSpan ;
+ }
+ }
+ FCKDragTableHandler._MinimumX = minX + offset.x ;
+ FCKDragTableHandler._MaximumX = maxX + offset.x ;
+ FCKDragTableHandler._LastX = null ;
+ },
+ "_ResizeBarMouseUpListener" : function( evt )
+ {
+ if ( ! evt )
+ evt = window.event ;
+ FCKDragTableHandler._MouseMoveMode = 0 ;
+ FCKDragTableHandler._HideResizeBar() ;
+
+ if ( FCKDragTableHandler._LastX == null )
+ return ;
+
+ // Calculate the delta value.
+ var deltaX = FCKDragTableHandler._LastX - FCKDragTableHandler._OriginalX ;
+
+ // Then, build an array of current column width values.
+ // This algorithm can be very slow if the cells have insane colSpan values. (e.g. colSpan=1000).
+ var table = FCKTools.GetElementAscensor( FCKDragTableHandler._LeftCell, "table" ) ;
+ var colArray = [] ;
+ for ( var r = 0 ; r < table.rows.length ; r++ )
+ {
+ var colIndex = 0 ;
+ var row = table.rows.item( r ) ;
+ for ( var c = 0 ; c < row.cells.length ; c++ )
+ {
+ var cell = row.cells.item( c ) ;
+ var width = FCKDragTableHandler._GetCellWidth( table, cell ) ;
+ var colSpan = parseInt( cell.colSpan ) ;
+ if ( colSpan != colSpan )
+ colSpan = 1 ;
+ if ( colArray.length < colIndex + colSpan )
+ {
+ for ( var i = 0 ; i < colSpan ; i++ )
+ colArray.push( { "width" : width / colSpan, "colSpan" : colSpan } ) ;
+ }
+ else
+ {
+ for ( var i = colIndex ; i < colIndex + colSpan ; i++ )
+ {
+ var guessItem = colArray[i] ;
+ if ( guessItem.colSpan > colSpan )
+ {
+ guessItem.width = width / colSpan ;
+ guessItem.colSpan = colSpan ;
+ }
+ }
+ }
+ colIndex += colSpan ;
+ }
+ }
+
+ // Find out the equivalent column index of the two cells selected for resizing.
+ colIndex = FCKDragTableHandler._GetResizeBarPosition() ;
+
+ // Note that colIndex must be at least 1 here, so it's safe to subtract 1 from it.
+ colIndex-- ;
+
+ // Modify the widths in the colArray according to the mouse coordinate delta value.
+ colArray[colIndex].width += deltaX ;
+ colArray[colIndex + 1].width -= deltaX ;
+
+ // Clear all cell widths, delete all elements from the table.
+ for ( var r = 0 ; r < table.rows.length ; r++ )
+ {
+ var row = table.rows.item( r ) ;
+ for ( var c = 0 ; c < row.cells.length ; c++ )
+ {
+ var cell = row.cells.item( c ) ;
+ cell.width = "" ;
+ cell.style.width = "" ;
+ }
+ }
+ var colElements = table.getElementsByTagName( "col" ) ;
+ for ( var i = colElements.length - 1 ; i >= 0 ; i-- )
+ colElements[i].parentNode.removeChild( colElements[i] ) ;
+
+ // Set new cell widths.
+ for ( var r = 0 ; r < table.rows.length ; r++ )
+ {
+ var row = table.rows.item( r ) ;
+ var colIndex = 0 ;
+ for ( var c = 0 ; c < row.cells.length ; c++ )
+ {
+ var cell = row.cells.item( c ) ;
+ var colSpan = parseInt( cell.colSpan ) ;
+ if ( colSpan != colSpan )
+ colSpan = 1 ;
+ var cellWidth = 0 ;
+ for ( var i = colIndex ; i < colIndex + colSpan ; i++ )
+ cellWidth += colArray[i].width ;
+ try
+ {
+ cell.width = cellWidth ;
+ }
+ catch(e)
+ {
+ }
+ colIndex += colSpan ;
+ }
+ }
+
+ FCKDragTableHandler._LastX = null ;
+ },
+ "_ResizeBarMouseMoveListener" : function( evt )
+ {
+ if ( ! evt )
+ evt = window.event ;
+ if ( FCKDragTableHandler._MouseMoveMode == 0 )
+ return FCKDragTableHandler._MouseFindHandler( FCK, evt ) ;
+ else
+ return FCKDragTableHandler._MouseDragHandler( FCK, evt ) ;
+ },
+ // Calculate the padding of a table cell.
+ // It returns the value of paddingLeft + paddingRight of a table cell.
+ // This function is used, in part, to calculate the width parameter that should be used for setting cell widths.
+ // The equation in question is clientWidth = paddingLeft + paddingRight + width.
+ // So that width = clientWidth - paddingLeft - paddingRight.
+ // The return value of this function must be pixel accurate acorss all supported browsers, so be careful if you need to modify it.
+ "_GetCellPadding" : function( table, cell )
+ {
+ var attrGuess = parseInt( table.cellPadding ) * 2 ;
+ var cssGuess = null ;
+ if ( typeof( window.getComputedStyle ) == "function" )
+ {
+ var styleObj = window.getComputedStyle( cell, null ) ;
+ cssGuess = parseInt( styleObj.getPropertyValue( "padding-left" ) ) +
+ parseInt( styleObj.getPropertyValue( "padding-right" ) ) ;
+ }
+ else
+ cssGuess = parseInt( cell.currentStyle.paddingLeft ) + parseInt (cell.currentStyle.paddingRight ) ;
+
+ var cssRuntime = cell.style.padding ;
+ if ( parseInt( cssRuntime ) == parseInt( cssRuntime ) )
+ cssGuess = parseInt( cssRuntime ) * 2 ;
+ else
+ {
+ cssRuntime = cell.style.paddingLeft ;
+ if ( parseInt( cssRuntime ) == parseInt( cssRuntime ) )
+ cssGuess = parseInt( cssRuntime ) ;
+ cssRuntime = cell.style.paddingRight ;
+ if ( parseInt( cssRuntime ) == parseInt( cssRuntime ) )
+ cssGuess += parseInt( cssRuntime ) ;
+ }
+
+ attrGuess = parseInt( attrGuess ) ;
+ cssGuess = parseInt( cssGuess ) ;
+ if ( attrGuess != attrGuess )
+ attrGuess = 0 ;
+ if ( cssGuess != cssGuess )
+ cssGuess = 0 ;
+ return Math.max( attrGuess, cssGuess ) ;
+ },
+ // Calculate the real width of the table cell.
+ // 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
+ // that, the table cell should be of exactly the same width as before.
+ // The real width of a table cell can be calculated as:
+ // width = clientWidth - paddingLeft - paddingRight.
+ "_GetCellWidth" : function( table, cell )
+ {
+ var clientWidth = parseInt( cell.clientWidth ) ;
+ if ( clientWidth != clientWidth ) // NaN possible? lets just be safe...
+ clientWidth = 0 ;
+ return clientWidth - this._GetCellPadding( table, cell ) ;
+ },
+ "MouseMoveListener" : function( FCK, evt )
+ {
+ if ( FCKDragTableHandler._MouseMoveMode == 0 )
+ return FCKDragTableHandler._MouseFindHandler( FCK, evt ) ;
+ else
+ return FCKDragTableHandler._MouseDragHandler( FCK, evt ) ;
+ },
+ "_MouseFindHandler" : function( FCK, evt )
+ {
+ var node = evt.srcElement || evt.originalTarget ;
+ try
+ {
+ if ( ! node || node.nodeType != 1 )
+ {
+ this._HideResizeBar() ;
+ return ;
+ }
+ }
+ catch ( e )
+ {
+ this._HideResizeBar() ;
+ return ;
+ }
+
+ // Since this function might be called from the editing area iframe or the outer fckeditor iframe,
+ // the mouse point coordinates from evt.clientX/Y can have different reference points.
+ // We need to resolve the mouse pointer position relative to the editing area iframe.
+ var mouseX = evt.clientX ;
+ var mouseY = evt.clientY ;
+ if ( node.ownerDocument == document )
+ {
+ var offset = this._GetDocumentPosition( window, FCK.EditingArea.IFrame ) ;
+ mouseX -= offset.x ;
+ mouseY -= offset.y ;
+ }
+
+
+ if ( this._ResizeBar && this._LeftCell )
+ {
+ var leftPos = this._GetWindowPosition( FCK.EditorWindow, this._LeftCell ) ;
+ var rightPos = this._GetWindowPosition( FCK.EditorWindow, this._RightCell ) ;
+ var rxDist = mouseX - ( leftPos.x + this._LeftCell.clientWidth ) ;
+ var lxDist = mouseX - rightPos.x ;
+ var inRangeFlag = false ;
+ if ( lxDist >= 0 && rxDist <= 0 )
+ inRangeFlag = true ;
+ else if ( rxDist > 0 && lxDist <= 3 )
+ inRangeFlag = true ;
+ else if ( lxDist < 0 && rxDist >= -2 )
+ inRangeFlag = true ;
+ if ( inRangeFlag )
+ {
+ this._ShowResizeBar( FCK.EditorWindow,
+ FCKTools.GetElementAscensor( this._LeftCell, "table" ),
+ { "x" : mouseX, "y" : mouseY } ) ;
+ return ;
+ }
+ }
+
+ var tagName = node.tagName.toLowerCase() ;
+ if ( tagName != "table" && tagName != "td" && tagName != "th" )
+ {
+ if ( this._LeftCell )
+ this._LeftCell = this._RightCell = null ;
+ this._HideResizeBar() ;
+ return ;
+ }
+ node = FCKTools.GetElementAscensor( node, "table" ) ;
+ var cellTuple = this._GetBorderCells( FCK.EditorWindow, node, { "x" : mouseX, "y" : mouseY } ) ;
+
+ if ( cellTuple == null )
+ {
+ if ( this._LeftCell )
+ this._LeftCell = this._RightCell = null ;
+ this._HideResizeBar() ;
+ }
+ else
+ {
+ this._LeftCell = cellTuple["leftCell"] ;
+ this._RightCell = cellTuple["rightCell"] ;
+ this._ShowResizeBar( FCK.EditorWindow,
+ FCKTools.GetElementAscensor( this._LeftCell, "table" ),
+ { "x" : mouseX, "y" : mouseY } ) ;
+ }
+ },
+ "_MouseDragHandler" : function( FCK, evt )
+ {
+ var mouse = { "x" : evt.clientX, "y" : evt.clientY } ;
+
+ // Convert mouse coordinates in reference to the outer iframe.
+ var node = evt.srcElement || evt.originalTarget ;
+ if ( node.ownerDocument == FCK.EditorDocument )
+ {
+ var offset = this._GetDocumentPosition( window, FCK.EditingArea.IFrame ) ;
+ mouse.x += offset.x ;
+ mouse.y += offset.y ;
+ }
+
+ // Calculate the mouse position delta and see if we've gone out of range.
+ if ( mouse.x >= this._MaximumX - 5 )
+ mouse.x = this._MaximumX - 5 ;
+ if ( mouse.x <= this._MinimumX + 5 )
+ mouse.x = this._MinimumX + 5 ;
+
+ var docX = mouse.x + this._GetWindowScrollX( window ) ;
+ this._ResizeBar.style.left = ( docX - this._ResizeBar.offsetWidth / 2 ) + "px" ;
+ this._LastX = mouse.x ;
+ },
+ "_ShowResizeBar" : function( w, table, mouse )
+ {
+ if ( this._ResizeBar == null )
+ {
+ this._ResizeBar = document.createElement( "div" ) ;
+ var paddingBar = this._ResizeBar ;
+ paddingBar.style.position = "absolute" ;
+ paddingBar.style.cursor = "e-resize" ;
+ if ( FCKBrowserInfo.IsIE )
+ paddingBar.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=10,enabled=true)" ;
+ else
+ paddingBar.style.opacity = 0.10 ;
+ document.body.appendChild( paddingBar ) ;
+ FCKTools.AddEventListener( paddingBar, "mousemove", this._ResizeBarMouseMoveListener ) ;
+ FCKTools.AddEventListener( paddingBar, "mousedown", this._ResizeBarMouseDownListener ) ;
+ FCKTools.AddEventListener( document, "mouseup", this._ResizeBarMouseUpListener ) ;
+ FCKTools.AddEventListener( FCK.EditorDocument, "mouseup", this._ResizeBarMouseUpListener ) ;
+
+ // IE doesn't let the tranparent part of the padding block to receive mouse events unless there's something inside.
+ // So we need to create a spacer image to fill the block up.
+ var filler = document.createElement( "img" ) ;
+ filler.border = 0 ;
+ filler.src = FCKConfig.BasePath + "images/spacer.gif" ;
+ filler.style.position = "absolute" ;
+ paddingBar.appendChild( filler ) ;
+
+ // Disable drag and drop, and selection for the filler image.
+ var disabledListener = function( evt )
+ {
+ if ( ! evt )
+ evt = window.event ;
+ if ( evt.preventDefault )
+ evt.preventDefault() ;
+ else
+ evt.returnValue = false ;
+ }
+ FCKTools.AddEventListener( filler, "dragstart", disabledListener ) ;
+ FCKTools.AddEventListener( filler, "selectstart", disabledListener ) ;
+ }
+
+ var paddingBar = this._ResizeBar ;
+ if ( FCKBrowserInfo.IsIE )
+ paddingBar.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 10 ;
+ else
+ paddingBar.style.opacity = 0.1 ;
+ var offset = this._GetDocumentPosition( window, FCK.EditingArea.IFrame ) ;
+ var tablePos = this._GetWindowPosition( w, table ) ;
+ var barHeight = table.offsetHeight ;
+ var barTop = offset.y + tablePos.y ;
+ // Do not let the resize bar intrude into the toolbar area.
+ if ( tablePos.y < 0 )
+ {
+ barHeight += tablePos.y ;
+ barTop -= tablePos.y ;
+ }
+ paddingBar.style.top = barTop + "px" ;
+ paddingBar.style.height = barHeight + "px" ;
+ var bw = parseInt( table.border ) ;
+ if ( bw != bw )
+ bw = 0 ;
+ var cs = parseInt( table.cellSpacing ) ;
+ if ( cs != cs )
+ cs = 0 ;
+ var barWidth = Math.max( bw+100, cs+100 ) ;
+ paddingBar.style.width = barWidth + "px" ;
+ paddingBar.style.left = ( offset.x + mouse.x + this._GetWindowScrollX( w ) - barWidth / 2 ) + "px" ;
+ var filler = paddingBar.getElementsByTagName( "img" )[0] ;
+ filler.style.width = paddingBar.offsetWidth + "px" ;
+ filler.style.height = barHeight + "px" ;
+
+ barWidth = Math.max( bw, cs, 3 ) ;
+ var visibleBar = null ;
+ if ( paddingBar.getElementsByTagName( "div" ).length < 1 )
+ {
+ visibleBar = document.createElement( "div" ) ;
+ paddingBar.appendChild( visibleBar ) ;
+ }
+ else
+ visibleBar = paddingBar.getElementsByTagName( "div" )[0] ;
+ visibleBar.style.position = "absolute" ;
+ visibleBar.style.backgroundColor = "blue" ;
+ visibleBar.style.width = barWidth + "px" ;
+ visibleBar.style.height = barHeight + "px" ;
+ visibleBar.style.left = "50px" ;
+ visibleBar.style.top = "0px" ;
+ },
+ "_HideResizeBar" : function()
+ {
+ if ( this._ResizeBar )
+ {
+ // IE bug: display : none does not hide the resize bar for some reason.
+ // so set the position to somewhere invisible.
+ this._ResizeBar.style.top = "-100000px" ;
+ this._ResizeBar.style.left = "-100000px" ;
+ }
+ }
+};
+
+FCK.Events.AttachEvent( "OnMouseMove", FCKDragTableHandler.MouseMoveListener ) ;
Index: /FCKeditor/trunk/fckconfig.js
===================================================================
--- /FCKeditor/trunk/fckconfig.js (revision 479)
+++ /FCKeditor/trunk/fckconfig.js (revision 480)
@@ -49,4 +49,5 @@
// FCKConfig.Plugins.Add( 'autogrow' ) ;
+// FCKConfig.Plugins.Add( 'dragresizetable' );
FCKConfig.AutoGrowMax = 400 ;
|