Click here to Skip to main content
15,886,710 members
Articles / Web Development / HTML

FCKEditor SharePoint Integration

Rate me:
Please Sign up or sign in to vote.
4.64/5 (7 votes)
15 Nov 2008CPOL6 min read 69.2K   1.1K   33  
How to integrate FCKEditor with SharePoint.
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,
	"_TableMap" : null,
	"_doc" : document,
	"_IsInsideNode" : function( w, domNode, pos )
	{
		var myCoords = FCKTools.GetWindowPosition( w, domNode ) ;
		var xMin = myCoords.x ;
		var yMin = myCoords.y ;
		var xMax = parseInt( xMin, 10 ) + parseInt( domNode.offsetWidth, 10 ) ;
		var yMax = parseInt( yMin, 10 ) + parseInt( domNode.offsetHeight, 10 ) ;
		if ( pos.x >= xMin && pos.x <= xMax && pos.y >= yMin && pos.y <= yMax )
			return true;
		return false;
	},
	"_GetBorderCells" : function( w, tableNode, tableMap, 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 = FCKTools.GetWindowPosition( w, cells[i] ) ;
			var rightX = pos.x + parseInt( cells[i].clientWidth, 10 ) ;
			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 ) ;
		*/
		var rowIdx = rbCell.parentNode.rowIndex ;
		var colIdx = FCKTableHandler._GetCellIndexSpan( tableMap, rowIdx, rbCell ) ;
		var colSpan = isNaN( rbCell.colSpan ) ? 1 : rbCell.colSpan ;
		lbCell = tableMap[rowIdx][colIdx + colSpan] ;

		if ( ! lbCell )
			return null ;

		// Abort if too far from the border.
		lxDist = mouse.x - FCKTools.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._RightCell, "tr" ) ;
		return FCKTableHandler._GetCellIndexSpan( this._TableMap, row.rowIndex, this._RightCell ) ;
	},
	"_ResizeBarMouseDownListener" : function( evt )
	{
		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._GetIframeOffset();
		var table = FCKTools.GetElementAscensor( FCKDragTableHandler._LeftCell, "table" );
		var minX = null ;
		var maxX = null ;
		for ( var r = 0 ; r < FCKDragTableHandler._TableMap.length ; r++ )
		{
			var leftCell = FCKDragTableHandler._TableMap[r][borderIndex - 1] ;
			var rightCell = FCKDragTableHandler._TableMap[r][borderIndex] ;
			var leftPosition = FCKTools.GetWindowPosition( FCK.EditorWindow, leftCell ) ;
			var rightPosition = FCKTools.GetWindowPosition( FCK.EditorWindow, rightCell ) ;
			var leftPadding = FCKDragTableHandler._GetCellPadding( table, leftCell ) ;
			var rightPadding = FCKDragTableHandler._GetCellPadding( table, rightCell ) ;
			if ( minX == null || leftPosition.x + leftPadding > minX )
				minX = leftPosition.x + leftPadding ;
			if ( maxX == null || rightPosition.x + rightCell.clientWidth - rightPadding < maxX )
				maxX = rightPosition.x + rightCell.clientWidth - rightPadding ;
		}

		FCKDragTableHandler._MinimumX = minX + offset.x ;
		FCKDragTableHandler._MaximumX = maxX + offset.x ;
		FCKDragTableHandler._LastX = null ;

		if (evt.preventDefault)
			evt.preventDefault();
		else
			evt.returnValue = false;
	},
	"_ResizeBarMouseUpListener" : function( evt )
	{
		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 = [] ;
		var tableMap = FCKDragTableHandler._TableMap ;
		for ( var i = 0 ; i < tableMap.length ; i++ )
		{
			for ( var j = 0 ; j < tableMap[i].length ; j++ )
			{
				var cell = tableMap[i][j] ;
				var width = FCKDragTableHandler._GetCellWidth( table, cell ) ;
				var colSpan = isNaN( cell.colSpan) ? 1 : cell.colSpan ;
				if ( colArray.length <= j )
					colArray.push( { width : width / colSpan, colSpan : colSpan } ) ;
				else
				{
					var guessItem = colArray[j] ;
					if ( guessItem.colSpan > colSpan )
					{
						guessItem.width = width / colSpan ;
						guessItem.colSpan = 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 <col> 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.
		var processedCells = [] ;
		for ( var i = 0 ; i < tableMap.length ; i++ )
		{
			for ( var j = 0 ; j < tableMap[i].length ; j++ )
			{
				var cell = tableMap[i][j] ;
				if ( cell._Processed )
					continue ;
				if ( tableMap[i][j-1] != cell )
					cell.width = colArray[j].width ;
				else
					cell.width = parseInt( cell.width, 10 ) + parseInt( colArray[j].width, 10 ) ;
				if ( tableMap[i][j+1] != cell )
				{
					processedCells.push( cell ) ;
					cell._Processed = true ;
				}
			}
		}
		for ( var i = 0 ; i < processedCells.length ; i++ )
		{
			if ( FCKBrowserInfo.IsIE )
				processedCells[i].removeAttribute( '_Processed' ) ;
			else
				delete processedCells[i]._Processed ;
		}

		FCKDragTableHandler._LastX = null ;
	},
	"_ResizeBarMouseMoveListener" : function( evt )
	{
		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, 10 ) * 2 ;
		var cssGuess = null ;
		if ( typeof( window.getComputedStyle ) == "function" )
		{
			var styleObj = window.getComputedStyle( cell, null ) ;
			cssGuess = parseInt( styleObj.getPropertyValue( "padding-left" ), 10 ) +
				parseInt( styleObj.getPropertyValue( "padding-right" ), 10 ) ;
		}
		else
			cssGuess = parseInt( cell.currentStyle.paddingLeft, 10 ) + parseInt (cell.currentStyle.paddingRight, 10 ) ;

		var cssRuntime = cell.style.padding ;
		if ( isFinite( cssRuntime ) )
			cssGuess = parseInt( cssRuntime, 10 ) * 2 ;
		else
		{
			cssRuntime = cell.style.paddingLeft ;
			if ( isFinite( cssRuntime ) )
				cssGuess = parseInt( cssRuntime, 10 ) ;
			cssRuntime = cell.style.paddingRight ;
			if ( isFinite( cssRuntime ) )
				cssGuess += parseInt( cssRuntime, 10 ) ;
		}

		attrGuess = parseInt( attrGuess, 10 ) ;
		cssGuess = parseInt( cssGuess, 10 ) ;
		if ( isNaN( attrGuess ) )
			attrGuess = 0 ;
		if ( isNaN( 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 = cell.clientWidth ;
		if ( isNaN( clientWidth ) )
			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 )
	{
		if ( FCK.MouseDownFlag )
			return ;
		var node = evt.srcElement || evt.target ;
		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 ( FCKTools.GetElementDocument( node ) == document )
		{
			var offset = this._GetIframeOffset() ;
			mouseX -= offset.x ;
			mouseY -= offset.y ;
		}


		if ( this._ResizeBar && this._LeftCell )
		{
			var leftPos = FCKTools.GetWindowPosition( FCK.EditorWindow, this._LeftCell ) ;
			var rightPos = FCKTools.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 = this._TableMap = null ;
			this._HideResizeBar() ;
			return ;
		}
		node = FCKTools.GetElementAscensor( node, "table" ) ;
		var tableMap = FCKTableHandler._CreateTableMap( node ) ;
		var cellTuple = this._GetBorderCells( FCK.EditorWindow, node, tableMap, { "x" : mouseX, "y" : mouseY } ) ;

		if ( cellTuple == null )
		{
			if ( this._LeftCell )
				this._LeftCell = this._RightCell = this._TableMap = null ;
			this._HideResizeBar() ;
		}
		else
		{
			this._LeftCell = cellTuple["leftCell"] ;
			this._RightCell = cellTuple["rightCell"] ;
			this._TableMap = tableMap ;
			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.target ;
		if ( FCKTools.GetElementDocument( node ) == FCK.EditorDocument )
		{
			var offset = this._GetIframeOffset() ;
			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 + FCKTools.GetScrollPosition( window ).X ;
		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 = this._doc.createElement( "div" ) ;
			var paddingBar = this._ResizeBar ;
			var paddingStyles = { 'position' : 'absolute', 'cursor' : 'e-resize' } ;
			if ( FCKBrowserInfo.IsIE )
				paddingStyles.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=10,enabled=true)" ;
			else
				paddingStyles.opacity = 0.10 ;
			FCKDomTools.SetElementStyles( paddingBar, paddingStyles ) ;
			this._avoidStyles( paddingBar );
			paddingBar.setAttribute('_fcktemp', true);
			this._doc.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 = this._doc.createElement( "img" ) ;
			filler.setAttribute('_fcktemp', true);
			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.preventDefault )
					evt.preventDefault() ;
				else
					evt.returnValue = false ;
			}
			FCKTools.AddEventListener( filler, "dragstart", disabledListener ) ;
			FCKTools.AddEventListener( filler, "selectstart", disabledListener ) ;
		}

		var paddingBar = this._ResizeBar ;
		var offset = this._GetIframeOffset() ;
		var tablePos = this._GetTablePosition( 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 ;
		}
		var bw = parseInt( table.border, 10 ) ;
		if ( isNaN( bw ) )
			bw = 0 ;
		var cs = parseInt( table.cellSpacing, 10 ) ;
		if ( isNaN( cs ) )
			cs = 0 ;
		var barWidth = Math.max( bw+100, cs+100 ) ;
		var paddingStyles =
		{
			'top'		: barTop + 'px',
			'height'	: barHeight + 'px',
			'width'		: barWidth + 'px',
			'left'		: ( offset.x + mouse.x + FCKTools.GetScrollPosition( w ).X - barWidth / 2 ) + 'px'
		} ;
		if ( FCKBrowserInfo.IsIE )
			paddingBar.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 10 ;
		else
			paddingStyles.opacity = 0.1 ;

		FCKDomTools.SetElementStyles( paddingBar, paddingStyles ) ;
		var filler = paddingBar.getElementsByTagName( "img" )[0] ;

		FCKDomTools.SetElementStyles( filler,
			{
				width	: paddingBar.offsetWidth + 'px',
				height	: barHeight + 'px'
			} ) ;

		barWidth = Math.max( bw, cs, 3 ) ;
		var visibleBar = null ;
		if ( paddingBar.getElementsByTagName( "div" ).length < 1 )
		{
			visibleBar = this._doc.createElement( "div" ) ;
			this._avoidStyles( visibleBar );
			visibleBar.setAttribute('_fcktemp', true);
			paddingBar.appendChild( visibleBar ) ;
		}
		else
			visibleBar = paddingBar.getElementsByTagName( "div" )[0] ;

		FCKDomTools.SetElementStyles( visibleBar,
			{
				position		: 'absolute',
				backgroundColor	: 'blue',
				width			: barWidth + 'px',
				height			: barHeight + 'px',
				left			: '50px',
				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.
			FCKDomTools.SetElementStyles( this._ResizeBar,
				{
					top		: '-100000px',
					left	: '-100000px'
				} ) ;
	},
	"_GetIframeOffset" : function ()
	{
		return FCKTools.GetDocumentPosition( window, FCK.EditingArea.IFrame ) ;
	},
	"_GetTablePosition" : function ( w, table )
	{
		return FCKTools.GetWindowPosition( w, table ) ;
	},
	"_avoidStyles" : function( element )
	{
		FCKDomTools.SetElementStyles( element,
			{
				padding		: '0',
				backgroundImage	: 'none',
				border		: '0'
			} ) ;
	}

};

FCK.Events.AttachEvent( "OnMouseMove", FCKDragTableHandler.MouseMoveListener ) ;

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer CPU
Serbia Serbia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions