// Chris Pyper 2006
// Core editor functions

// We are using IE if the document.all property exists
var ie = document.all;
var globalIframe = null;

// Turn of debugging window
var debugOn = false;

// Flag to track status of editor
var editorOn = false;

// Refernce to debugger window
var debugWindow = true;

// Some global vars
var isDrag = false;
var x,y,z = false;
var resizeMode = false;
var resizeWidth, resizeHeight, resizeType, resizeElementUpSkip = false;

// DOM reference to object currently being moved
var docObj = false;

// DOM reference of tabs for resize box
var docObjTab = false;

// DOM refernce to DIV that serves ar editor
var editor;

// Some vars for Mozilla specific functionality
var iframe = false;

// References of various DOM object, some functionality require swapping of DOM object so
// these vars hold the refernces to the original and cloned DOM nodes
var docSourceOrig  = false;
var docSourceClone = false;

// Refernece to resizing table
var editBoxRef = false;

// Reference to content of resize table
var resizeTableContentRef = false;

// Variable to hold highest known z-index
var maxZIndex = 2;
var startZIndex = maxZIndex;
var maxArtZIndex = 0;

var minArtZIndex = 2;
var minArtZIndexLimit = minArtZIndex;
var minZIndex = maxZIndex;


// Hold range and selection of highlighted object
var cachedRange		= null;
var cachedSelection = null;

// Hold text of highligted object
var cachedInnerText = null;

// Cached command array used to cache commands for comparison on each change, this way we minimize 
// signaling to outside editor only when there is change
var cachedCommandArray = null;

// Flag to hold whether or not document has been edited
var documentChanged = false;

// Grid layout element id
var GRIDLAYOUT_ELEMENTID = "layoutGrid";

// How long to delay before showing the grid on a mousedown
var GRIDLAYOUT_DELAY = 100;  // ms

// set current grid for art|text
var CURR_GRID_TYPE = "text";// text | art

// set href container for links
var LINK_HREF_ATTR = "go_href";

// Switch design mode on the referenced DOM node
var currEditedDiv = false;

// set preview mode off designOn
var previewMode = false;

// set master template mode off designOn
var masterMode = false;
MASTER_EL_ATTR = "master_element";

var globalMoveTextTFI = 0; // global recurcive iterator index

// set last element
lastSelectedElement = null;
lastSelectedElementZIndex = "";

rightMouseBtnClicked = false;

// shift key status for resize aspect ratio - movemouse
isPressShiftKey = false;
//
isDesignModeOn = false;
var groupObj;
var selectionObj;


function designModeOnEditable(docSource)
{
	debug("designModeOnEditable(): Selected = " + docSource.tagName, 'info');

	// Turn off design mode to switch off and save any node being edited
	designModeOffEditable();

	// Gecko based browsers let you define a height for an element that is less then the actual displayed height
	// when you fetch this height in the switch to editing mode you get the height that is less then the content.
	// Since this height is the one used for the iframe it gives the appearance of cropping the content.  This issue
	// only effects height, as width is constrained and height is used for overflow.  The fix is to grab the display
	// height in gecko and set the actual height to that.  Added to work with IE as well to clean up any overly long
	// text areas.

	lastSelectedElementZIndex = docSource.style.zIndex;
	raiseToTop(docSource);


	if(docSource.tagName != 'IMG' && docSource.className.indexOf(TABLECONTENT_CLASS) == -1 )
	{
		docSource.style.height = 'auto';
		var tempHeight = docSource.offsetHeight + EDITMODEOFFSET;
		setStyle(docSource, 'height', tempHeight, true);
	}

	// Initalize global DOM references
	docSourceOrig  	= docSource;
	docSourceClone 	= false;
	editBoxRef 	= false;
	iframe 		= false;


	// Make sure we can edit this field, check if class is correct
	if(docSource.className.search(/editable/gi) < 0 )
	{
		debug('designModeOnEditable(): Element does not have editable style, cannot edit', 'warn'); 
		return false;
	}

	// Clone node
	var clone = docSource.cloneNode(true);
	setStyle(clone, 'left', 0, true);
	setStyle(clone, 'top', 0, true);
	setStyle(clone, 'position', 'relative');

	// With Mozilla things are a little diffrent.  There is no contentEditable property.  There is a concept known
	// as design mode where only an entire page, frame, or iframe can have it's content edited.  Once it is turned
	// on only content can be read/written to the frame and only some scattered DOM functionality is supported.
	// Javascript will not function properly with in the frame, and the frame itself will not support events, so
	// in order to mimic the functionality found in IE a new iframe is spawned and the content of the node editable
	// node it written, this iframe is then given the same size and moved to the location of the editable node, the
	// node is then made invisible so the iframe give the appearance of taking over the node

	// If using mozilla we have to edit text diffrently, as explained above
	if(!ie && docSourceOrig.tagName != 'IMG' )
	{

		// Clear out the iframe
		iframe = false;

		// Build the new iframe and add to the document, set it invisilbe and turn on editing
		// A new iframe must be generated each time, building one into the html document and then
		// manipulating it casues issues with referencing for some reason

		var width  = getStyle(docSource, 'width', true);
		var height = getStyle(docSource, 'height', true);
		iframe              = document.createElement("iframe");
		iframe.id           = 'iframeEditor';
		iframe.scrolling    = 'no';
		iframe.marginheight = '0';
		iframe.marginwidth  = '0';
		setStyle(iframe, 'width', width, true);
		setStyle(iframe, 'height', height, true);
		setStyle(iframe, 'border', 0, true);
		// Highlight frame
		addClass(iframe, 'editBorder');

		var resizeBox = buildResizeBox(iframe, clone);
		debug('designModeOnEditable(): Using iframe in resize box', 'info');
	}
	// Images can be manipluated the same way in all browsers
	else
	{
		var resizeBox = buildResizeBox(clone, clone);
		debug('designModeOnEditable(): Using cloned element in resize box', 'info');	
	}

	// Position the resize box
	setStyle(resizeBox, 'position', 'absolute');

	// Maintain the zIndex
	setStyle(resizeBox, 'zIndex', getStyle(docSource, 'zIndex'));

	// Left, minus offset to prevent nudge of content
	var leftPos = getStyle(docSource, 'left', true);
	var leftOffset = 0;
	if(iframe)
		leftOffset = RESIZETABLEIFRAMEOFFSET;
	else if(ie)
		leftOffset = RESIZETABLEOFFSETIE;
	else
		leftOffset = RESIZETABLEOFFSETMOZ;
	leftPos = leftPos - leftOffset;
	debug('designModeOnEditable(): leftPos: ' + leftPos, 'info');
	setStyle(resizeBox, 'left', leftPos, true); 

	// Top, minus offset to prevent nudge of content
	var topPos = getStyle(docSource, 'top', true);
	var topOffset = 0;
	if(iframe)
		topOffset = RESIZETABLEIFRAMEOFFSET;
	else if(ie)
		topOffset = RESIZETABLEOFFSETIE;
	else
		topOffset = RESIZETABLEOFFSETMOZ;
	topPos = topPos - topOffset;
	debug('designModeOnEditable(): topPos: ' + topPos, 'info');
	setStyle(resizeBox, 'top', topPos, true);

	setStyle(resizeBox, 'visibility', 'hidden');
	resizeBox.id = 'nodeEditEditable';

	// The rezise box is positioned and ready, now add content
	if(!ie && docSourceOrig.tagName != 'IMG')
	{
		currEditedDiv = clone.cloneNode(true);// get another one copy of original div

		// Add to docuemnt and get reference back, the one that is 'returned' by the DOM functions
		// is buggy, I found it is best to use getElementById to go out and get it
		document.getElementById(MIDDLEEDITORID).appendChild(resizeBox);
		iframe = document.getElementById('iframeEditor');
		iframe.contentWindow.document.designMode = "on";

		// ***IMPORTANT*** This must be done AFTER the iframe is rendered or else it won't work.
		// The iframe was rendered when the is was apppened to the document above.
		// Turn on design mode and add a html document stub
		iframe.contentWindow.document.open('text/html; charset="UTF-8"');
		html = "<html><head></head><body class='editor'></body></html>";
		iframe.contentWindow.document.write(html);
		iframe.contentWindow.document.close();

		// Add style sheets to retain look
		for ( i = document.styleSheets.length - 1; i>=0; i-- )
		{   
			var	newLink = iframe.contentDocument.createElement("LINK");
			newLink.rel  = "stylesheet";
			newLink.type = "text/css";
			newLink.href = document.styleSheets[i].href;
			var iframeHead = iframe.contentDocument.getElementsByTagName('head')[0];
			if(iframeHead)
				iframeHead.appendChild(newLink);
		}   

		// The iframe with it's designMode set to on will support limited DOM functionality, here I use to add the conetent
		docSourceClone = iframe.contentWindow.document.body.appendChild(clone);

		// Adding selection caching for context sensitivity of highlighting and typing
		iframe.contentWindow.document.addEventListener('mouseup', cacheSelection, true);
		iframe.contentWindow.document.addEventListener('keypress', cacheSelection, true);
		iframe.contentWindow.document.addEventListener('click', checkClick, true);
		if(!ie && docSourceOrig.tagName != 'TABLE')
		{
			iframe.contentWindow.document.addEventListener('keyup', checkDelete, true);
			iframe.contentWindow.document.addEventListener('keydown', checkPressedKey, true);

		}


		// Here I turn on editing
		debug('designModeOnEditable(): Design Mode On', 'info');
		// Wait till the last step to change visibility, this makes for a smoother transition
		setStyle(docSourceOrig, 'visibility', 'hidden');

		var startPar = iframe.contentWindow.document.getElementsByTagName("div").item(0);//[the span node];
		if (startPar)
		{
			var sel = window.getSelection().selectAllChildren(startPar);
		}


	}
	else
	{
		// Swap node, use getElementById() to fetch reference and get around appendChild() not correctly
		// returning reference to appended node
		docSourceClone = clone;
		docSourceOrig.parentNode.replaceChild(resizeBox, docSourceOrig);

		// Add highligthing
		addClass(docSourceClone, 'editBorder');

		// We have to make sure we unregister this or content editable will not function
		document.onmousemove = null;

		// Imagees can be manipulated the same way in all browsers
		if(docSourceOrig.tagName != 'IMG')
		{
			// This is the magic line which makes content editable for a element

			//docSourceClone.unselectable = "off"
			docSourceClone.contentEditable = true;

			// Layer in a event to trap any selected content for context sensitivity of highlighting and typing
			docSourceClone.onmouseup  = cacheSelection;
			docSourceClone.onkeypress = cacheSelection;
			docSourceClone.onclick	  =	checkClick;

			debug('designModeOnEditable(): Content Editable True', 'info');

		}
	}

	// Start off initial caching of selection for future comparison ofr context sensitivity
	if(docSourceOrig.tagName != 'IMG')
		cacheSelection();



	// Grab a reference to the resize table and make it visible
	editBoxRef = document.getElementById("nodeEditEditable");
	setStyle(editBoxRef, 'visibility', 'visible');

	// Inform editor wrapper in case for context sensitivity
	var callBacks = fetchInterface();
	if(docSourceOrig.tagName == 'IMG')
		callBacks.triggerCallBack('imageElementSelected');
	else
		callBacks.triggerCallBack('textElementSelected');

	if(ie && docSourceOrig.tagName != 'IMG') // for IE move cursor to first char
	{

		var rng = document.selection.createRange();
		rng.select();
		rng.collapse(true);


		// if table move cursor to first TD
		if ( docSourceClone.tagName == "DIV" && docSourceClone.firstChild )
		{
			if ( docSourceClone.firstChild.tagName == "TABLE" )
			{
				var table = docSourceClone.firstChild;
				var td1 = table.getElementsByTagName("td").item(0);
				var td_content = td1.firstChild;

				var range_all = document.body.createTextRange();
				range_all.moveToElementText(td1);
				range_all.move('character', 0);
				range_all.select();
				range_all.collapse(false);
			}
		}



	}
	else if(!ie && docSourceOrig.tagName != 'IMG')
	{
		globalIframe = iframe.contentWindow;
		setTimeout('setFocusToObject()', 10);
	}

	// Turn on context menu
	document.body.oncontextmenu = function(){return true;}
	document.onmousedown = null;


	return true;
}

function setFocusToObject()
{
	try {
		globalIframe.focus();

		globalIframe.getSelection().collapseToStart();
	} catch(e){}

	if (globalIframe.document.getElementsByTagName("div").item(0).hasChildNodes())
	{
		var sel = globalIframe.document.getElementsByTagName("div").item(0).firstChild;

		if ( sel.tagName == "TABLE" )
		{
			var td1 = sel.getElementsByTagName("td").item(0);
			sel = td1;   
		}

		if (sel.nodeType != 1)
		{
			while (undefined != (sel = sel.nextSibling))
			{
				if (sel.nodeType == 1)
				{
					break;
				}
			}
		}
		try {

			window.getSelection().selectAllChildren(sel);
			window.getSelection().collapseToStart();
		}catch(e){}
	}
	globalIframe = null;
}

// Turn off design mode on the node that is currently on
function designModeOffEditable(docSource)
{
	if(!docSource)
		debug("designModeOffEditable()", 'info');
	else
		debug("designModeOffEditable(): Selected = " + docSource.tagName, 'info');

	// You can't turn off something that is not on
	if(!editBoxRef)
		return false;

	// If the user clicks on something that is already on this means they are moving the cursor not turning the
	// design mode off for the element
	if(docSource == docSourceClone)
		return false;

	// Clean up spell check if it is on
	removeSpellCheckHighlighting();
	document.getElementById('spellCheck').innerHTML = '';

	// If it's anything but mozilla and a text based element
	if(ie || docSourceOrig.tagName == 'IMG')
	{
		// Turn off content editing for the node
		if(ie && docSourceOrig.tagName != 'IMG')
		{
			// Unregister the event registered to capture any highlighting
			docSourceClone.onmouseup  = null;
			docSourceClone.onkeypress = null;
			docSourceClone.onclick	  = null;

			// Do a little housekeeping just in case
			cachedRange = null;

			// Turn off the content Editable feature
			docSourceClone.contentEditable = false;
			debug("designModeOffEditable() Content Editable false", 'info');
		}

		// Remove border highlighting
		removeClass(docSourceClone, 'editBorder');

		// Looks like javascript has  trouble fetching position in IE, gotta do it the old fashioned way instead.
		docSourceClone.style.position = docSourceOrig.style.position;

		// Swap out the newly edited node with the original
		editBoxRef.parentNode.replaceChild(docSourceClone, editBoxRef);

		// Fetch the offset
		var offSet = 0;
		if(ie)
			offSet = RESIZETABLEOFFSETIE; 
		else
			offSet = RESIZETABLEOFFSETMOZ;

		// The repositioning has to come after the replaceChild call above so it looks smooth in IE
		setStyle(docSourceClone, 'left', getStyle(editBoxRef, 'left', true) + offSet, true);
		setStyle(docSourceClone, 'top', getStyle(editBoxRef, 'top', true) + offSet, true);
	}
	else
	{
		// *** WARNING *** turning off designMode throw error if the editor is wrapped
		// in a iframe, we do not need to turn it off anyways becuase we destroy the iframe

		// Hide frame
		if(iframe)
		{
			// Shut off design mode, this doesn't actually affect anything becuase of the flaky support
			// but good practice for future compatibility
			//iframe.contentWindow.document.designMode = "off";
			setStyle(iframe, 'visibility', 'hidden');
			setStyle(iframe, 'width', 0, true);
			setStyle(iframe, 'height', 0, true);
			removeClass(iframe, 'editBorder');
		}

		// Replace edited node with edited content from frame, make frame visible
		if(docSourceOrig)
		{
			if(iframe && docSourceClone)
			{
				//Reset to original positioning
				setStyle(docSourceClone, 'left', getStyle(editBoxRef, 'left', true) + RESIZETABLEIFRAMEOFFSET, true);
				setStyle(docSourceClone, 'top',  getStyle(editBoxRef, 'top', true) + RESIZETABLEIFRAMEOFFSET, true); 
				// This line won't work in IE, will never get executed in IE, but will never work nevertheless
				setStyle(docSourceClone, 'position', getStyle(docSourceOrig, 'position'));

				// Replace the original with the edited clone
				if (docSourceOrig.parentNode)
					docSourceOrig.parentNode.replaceChild(docSourceClone, docSourceOrig);
				else
				{

					editor.appendChild(docSourceClone);
				}

			}
			setStyle(docSourceOrig, 'visibility', 'visible');
		}

		editBoxRef.parentNode.removeChild(editBoxRef);
	}

	// Inform editor wrapper in case for context sensitivity
	var callBacks = fetchInterface();
	if(docSourceOrig.tagName == 'IMG')
		callBacks.triggerCallBack('imageElementUnSelected');
	else
		callBacks.triggerCallBack('textElementUnSelected');		


	// Clear global node references 
	docSourceOrig  = false;
	docSourceClone = false;
	editBoxRef     = false;
	iframe         = false;

	// Clear selection cache
	cachedSelection = null;
	cachedRange     = null;
	cachedInnerText = null;

	return true;
}

// Turn on design mode for draggable elements, similar to editable elements but toned down
function designModeOnDraggable(docSource)
{

	debug("designModeOnDraggable()", 'info');

	// Initalize global DOM references
	docSourceOrig  = docSource;
	docSourceClone = false;

	lastSelectedElementZIndex = docSource.style.zIndex;
	raiseToTop(docSource);


	// Clone node
	var clone = docSource.cloneNode(true);
	docSourceClone = clone;
	setStyle(clone, 'left', 0, true);
	setStyle(clone, 'top', 0, true);
	setStyle(clone, 'position', 'relative');

	var highlightBox = buildHighlightBox(clone);
	highlightBox.id = 'nodeEditDraggable';

	setStyle(highlightBox, 'position', 'absolute');
	setStyle(highlightBox, 'left', getStyle(docSource, 'left', true), true);
	setStyle(highlightBox, 'top', getStyle(docSource, 'top', true), true);
	// Maintain the zIndex
	setStyle(highlightBox, 'zIndex', getStyle(docSource, 'zIndex'));

	docSource.parentNode.replaceChild(highlightBox, docSource);
	editBoxRef = document.getElementById("nodeEditDraggable");

	return true;
}

// Turn off design mode for draggable element
function designModeOffDraggable()
{
	debug("designModeOffDraggable()", 'info');

	editBoxRef.parentNode.replaceChild(docSourceOrig, editBoxRef);

	// Clear global node references
	docSourceOrig  = false;
	docSourceClone = false;
	editBoxRef     = false;

	return true;
}

// Turn on desgin mode for selected object depending on type
function designModeOn(docSource)
{
	debug("designModeOn(): Selected = " + docSource.tagName, 'info');

	if (docSource.id == "ESWuserMenuPosition" )
		return false;		

	stopDragCopy();
	//	document.onkeydown  = ""; // clear delete element feature on delete key
	isDesignModeOn = true;
	document.onkeydown  = checkPressedKey;

	if(docSource.className.search(/editable/gi) >= 0 )
		return designModeOnEditable(docSource);
	else if(docSource.className.search(/draggable/gi) >= 0)
		return designModeOnDraggable(docSource);

	debug("designModeOn(): Cannot find matching element class", 'error');
	return false;
}

// Turn off design mode for a particular object depending on type
function designModeOff(docSource)
{
	debug("designModeOff()", 'info');

	var docSourceCurrId = docSourceOrig.id;
	// Check for type using orig doc ref, pass along clicked on node for comparison check in off functions
	if(docSourceOrig && docSourceOrig.className.search(/editable/gi) >= 0)
		var res = designModeOffEditable(docSource);
	else if(docSourceOrig && docSourceOrig.className.search(/draggable/gi) >= 0)
		var res = designModeOffDraggable(docSource);

	if ( lastSelectedElementZIndex > 0 )
	{
		var sObj = getEl(docSourceCurrId);
		if (sObj !== null)
			sObj.style.zIndex = lastSelectedElementZIndex;
	}
	lastSelectedElementZIndex = -1;
	
	if(res)
	{
		isDesignModeOn = false;
		startDragCopy();
		delete docSourceCurr;
		return res;
	}

	debug("designModeOff(): Cannot find matching element class", 'error');
	return false;
}

// Function to content to mouse position
function movemouse(e)
{
	// Flag to tell function to stop moving content
	if(!isDrag)
		return false;

	toggleContextPanel(false);	
	// Grab event based on browser
	var eventObject = getEventObject(e);

	// If not resize mode calulate new mouse position
	if(!resizeMode && docObj)
	{
		// Check if element locked
		var lObj = new LockStatus(docObj);
		if ( lObj.isLocked())
		{
			delete lObj;
			return false;
		}
		delete lObj;

		
		// Calculate new mouse position


		if(docObj.style.position == 'absolute')
		{


			var newX = tx + eventObject.clientX - x;
			var newY = ty + eventObject.clientY - y;

			/*
			   if (!ie)
			   {
			   var newX = tx + eventObject.clientX - x;
			   var newY = ty + eventObject.clientY - y;
			   }
			   else if (eventObject.clientX || eventObject.clientY)
			   {
			   var newX = eventObject.clientX + document.body.scrollLeft;
			   var newY = eventObject.clientY + document.body.scrollTop;
			//				var newX = eventObject.clientX;
			//				var newY = eventObject.clientY;
			}
			else if(eventObject.pageX && eventObject.pageY)
			{
			var newX = tx + eventObject.pageX - x;
			var newY = ty + eventObject.pageY - y;
			}
			 */
		}
		else
		{
			var newX = tx + eventObject.clientX - x;
			var newY = ty + eventObject.clientY - y;
		}




		setStyle(docObj, 'left', newX);
		setStyle(docObj, 'top', newY);
		var xDiff =  newX - tx;
		var yDiff =  newY - ty;

		// move group!!!!
		/*
		if ( false !== groupObj.isGrouped(docObj) )
		{
			var gElements = groupObj.getGroupedElXY(docObj);
	        	for (var i in gElements)
	        	{
				// Calculate and initiate movement
				gtx = gElements[i].x;//getStyle(getEl(gElements[i]), 'left', true) + 0;
				gty = gElements[i].y;//getStyle(getEl(gElements[i]), 'top', true) + 0;

				var gnewX = gtx + xDiff;
				var gnewY = gty + yDiff;
				var gEl =  getEl(gElements[i].id);
				setStyle(gEl, 'left', gnewX);
				setStyle(gEl, 'top', gnewY);
	        	}
		}
		*/

	}
	// How to handle calculations for resize table
	else	
	{
		// Reset flags
		var vertical   = false;
		var horizontal = false;
		var lockRight  = false;
		var lockBottom = false;

		showLayoutGrid();

		// Define how each tab should react
		switch(docObjTab.className)
		{
			case "northWest":
				vertical   = true;
			horizontal = true;
			lockRight  = true;
			lockBottom = true;
			break;

			case "north":
				vertical   = true;
			lockBottom = true;
			break;

			case "northEast":
				vertical   = true;
			horizontal = true;
			lockBottom = true
				break;

			case "east":
				horizontal = true;
			break;

			case "southEast":
				vertical   = true;
			horizontal = true;
			break;

			case "south":
				vertical = true;
			break;

			case "southWest":
				vertical   = true;
			horizontal = true;
			lockRight  = true
				break;

			case "west":
				horizontal = true;
			lockRight  = true;
			break;
		}

		// Depending on which way user is pulling tab other side of table will stay static
		// so it is calculated opposite
		if(!lockRight)
			var width = resizeWidth + (eventObject.clientX - x);
		else
			var width = resizeWidth - (eventObject.clientX - x);

		debug('movemouse(): width =' + width, 'info');

		// Depending on which way user is pulling tab other side of table will stay static
		// so it is calclated opposite
		if(!lockBottom)
			var height = resizeHeight + (eventObject.clientY - y);
		else
			var height = resizeHeight - (eventObject.clientY - y);

		debug('movemouse(): height =' + height, 'info');

		if (isPressShiftKey)
		{
			var ratio;
			if( resizeWidth > width )
			{
				ratio   = ( resizeWidth/width );					
				height = Math.floor( resizeHeight/ratio );
			}
			else 
			{
				ratio   = ( width/resizeWidth );
				height = Math.floor( resizeHeight*ratio );
			}

		}

		// Make the resize
		if(width > 0 && horizontal)
		{
			// Calculate the diffrence in case there is a need to resposition
			var diffrence = getStyle(docSourceClone, 'width', true) - width;

			setStyle(docSourceClone, 'width', width, true);

			// Reposition if we are positioning the right side statically
			if(lockRight)
			{
				var resizeLeft = getStyle(editBoxRef, 'left', true) + diffrence;
				setStyle(editBoxRef, 'left',  resizeLeft, true);
			}

			if (isPressShiftKey)
			{
				setStyle(docSourceClone, 'height', height, true);
			}

		}

		// Make the resize
		if(height > 0 && vertical)
		{
			// Calculate the diffrence in case there is a need to resposition
			var diffrence = getStyle(docSourceClone, 'height', true) - height;

			setStyle(docSourceClone, 'height', height, true);

			// Reposition if we are positioning the bottom statically
			if(lockBottom)
			{
				var resizeTop = getStyle(editBoxRef, 'top', true) + diffrence;
				setStyle(editBoxRef, 'top', resizeTop, true);
			}
			if (isPressShiftKey)
			{
				setStyle(docSourceClone, 'width', width, true);

			}

		}
	}

	// ***WARNING EXTREMELY IMPORTANT*** - It seems you have to return false at the end of this function or else it
	// will not function correctly.  I beleive that if a function is registered to the onmousemove event if you return
	// true the function does continue to work correctly in IE.
	return false;
}

// Function to select and initiate appropriate action based on clicked on content clicked on
function selectElement(e, edit, resize) 
{

	// This flag tracks whether the docuemnt has changed, it is best to set it here becasue nearly all
	// editing actions are routed through this function
	//documentChanged = true;
	//if (resizeMode == 'off')
	//{
	//document.onclick = null;

	//}
	var eventObject = getEventObject(e);
	var topelement  = getTopElement();
	docSource       = getDOMfromEventObject(eventObject);

	if (docSource && docSource.className.indexOf("ESWuserButton") ==  -1)
		documentChanged = true;

	// A little hook to bring up debugger, have to piggy back it on to another event handler or else
	// there is issues with editor events being intercepted
	if(eventObject.altKey && eventObject.ctrlKey)
	{
		if(!debugOn)
		{
			debugOn = true;
			debug('START DEBUGGER', 'info');
		}
		else
		{
			debugOn = false;
			debug('STOP DEBUGGER', 'info');
		}
		return true;
	}

	// Print a recursive trace of all events, for debugging purposes, debugger must be on
	if(debugOn && eventObject.ctrlKey)
	{
		printAllEvents(document);	
		return true;
	}

	resizeMode = false;
	if(resize)
	{
		resizeMode = true;
		// Grab initial size for calculations on first select of resize tab
		if(!editBoxRef)
		{
			resizeWidth  = getStyle(docSourceOrig, 'width', true);
			resizeHeight = getStyle(docSourceOrig, 'height', true);
		}
		// Used clone for up to date size on reselect of resize tab
		else
		{
			resizeWidth  = getStyle(docSourceClone, 'width', true);
			resizeHeight = getStyle(docSourceClone, 'height', true);
		}

		if(!resizeWidth)
		{
			resizeWidth = docSourceClone.offsetWidth;
			setStyle(docSourceClone, 'width', resizeWidth, true);
		}
		if(!resizeHeight)
		{
			resizeHeight = docSourceClone.offsetHeight;
			setStyle(docSourceClone, 'height', resizeHeight, true);
		}

		debug('selectElement(): resizeWidth = ' + resizeWidth, 'info');
		debug('selectElement(): resizeHeight = ' + resizeHeight, 'info');
	}

	// Climb DOM tree till the node has a class of the specified type
	while (docSource.tagName != topelement && (
				docSource.className.search(/draggable/gi) < 0 && 
				docSource.className.search(/editable/gi) < 0 &&
				docSource.className.search(/ESWuserForm/gi) < 0))
	{
		if(ie)
			docSource = docSource.parentElement;
		else
			docSource = docSource.parentNode;
	}
	if (edit == 'on' || (lastSelectedElement != null && lastSelectedElement.id != docSource.id) )	
		toggleContextPanel(false);

	if(edit == 'on' && docSource.className.search(/ESWuserForm/gi) >= 0)
	{
		var callBacks = fetchInterface();
		callBacks.triggerCallBack('editForm', docSource);
		return false;
	}
	if ( previewMode)
		return false;
	// Turn on editing for selected node, triggered on double click
	if(edit == 'on' && (docSource.className.search(/editable/gi) >= 0 || docSource.className.search(/draggable/gi) >= 0) )
		return designModeOn(docSource);
	else if(edit == 'off')
		return designModeOff(docSource);

	// If it's a node with a class of draggagle and not double clicked then take appropriate action
	if ((docSource.className.search(/draggable/gi) >= 0 || resizeMode) && edit != 'on') 
	{
		isDrag = true;

		// Save referece of node to move
		docObj = docSource;

		// Is this a plugin?
		if ( docSource.className.search(/editorPlugin/gi) >= 0 )
		{
			// hide the plugin IFRAME to prevent it from grabbing the events
			docSource.lastChild.style.visibility = "hidden";  
			docSource.style.borderStyle = "dashed";
		}

		// Calculate and initiate movement
		tx = getStyle(docObj, 'left', true) + 0;
		ty = getStyle(docObj, 'top', true) + 0;
		// z = getStyle(docObj, 'z-index', true) + 0;
		x  = eventObject.clientX;
		y  = eventObject.clientY;
		document.onmousemove = movemouse;
		document.onclick = stopDraggable;

		//if ( isNaN(z) )
		//	z = 0;
		debug('selectElement(): tx=' + tx + ' ty=' + ty + ' x=' + x + ' y=' + y, 'info');

		if(resizeMode)
			undoRedoSnapShot(getDocObjFromClone(), 'resize');
		else
		{
			undoRedoSnapShot(docObj, 'move');
			// Raise element to top after taking snapshot, gives it a nice feel, and will give undo/redo
			// functionality for bringing elements forward

//			if ( !rightMouseBtnClicked )
//				raiseToTop(docSource);

			// setup type of current element for the grid
			if ( docSource.className.indexOf('art') > -1 )
				CURR_GRID_TYPE = "art";
			else
				CURR_GRID_TYPE = "text";

			lastSelectedElement = docSource;
			// leave a bit of a delay to ensure that we don't show the grid
// unneccessarily
			setTimeout(showLayoutGrid,GRIDLAYOUT_DELAY);

		}

//		if (isPressShiftKey)
//		{
//			if (!groupObj.isGrouped(docSource))
//				selectionObj.add(docSource.id);
//			else
//				groupObj.selectGroup(docSource.id)
//		}
//		else if(!rightMouseBtnClicked)
//			selectionObj.clear();



		return true;
	}

	// ***EXTREMELY IMPORTANT*** - You must always return something at the end on funcitons registered to events
	// or else you cannot properly unregister them, so if you layering events you will really mess up your results.
	// Currently this seems to be a IE issue mainly
	return false;
}


// displays a "layout grid" over the page to assist the user when aligning content blocks
function showLayoutGrid()
{
	if (!isDrag) {
		hideLayoutGrid();
		return false;
	}

//	if ( CURR_GRID_TYPE == "art" )
//	{
//		debug('showing grid: ' + (maxArtZIndex - 1), 'info');
//		document.getElementById(GRIDLAYOUT_ELEMENTID).style.zIndex = (maxArtZIndex - 1);
//	}
//	else
//	{
//		debug('showing grid: ' + (maxZIndex - 1), 'info');
//		document.getElementById(GRIDLAYOUT_ELEMENTID).style.zIndex = (maxZIndex - 1);
		document.getElementById(GRIDLAYOUT_ELEMENTID).style.zIndex = lastSelectedElement.style.zIndex -1;
//	}
	document.getElementById(GRIDLAYOUT_ELEMENTID).style.width = getWindowWidth() + "px";
	if ( !ie )
		document.getElementById(GRIDLAYOUT_ELEMENTID).style.height = getWindowHeight() + this.scrollMaxY + "px";
	else
	{
		var grid_h = 0;
		if ( getWindowHeight() > document.body.scrollHeight )
			grid_h = getWindowHeight() - 20;
		else
			grid_h = document.body.scrollHeight;

		document.getElementById(GRIDLAYOUT_ELEMENTID).style.height = grid_h + "px";
	}
	document.getElementById(GRIDLAYOUT_ELEMENTID).style.display = "block";
	//document.getElementById(GRIDLAYOUT_ELEMENTID).onmouseup = stopDraggable;
	document.getElementById(GRIDLAYOUT_ELEMENTID).onmouseup = function(){hideLayoutGrid();}
	document.getElementById(GRIDLAYOUT_ELEMENTID).onclick = function(){hideLayoutGrid();}

}

function hideLayoutGrid()
{
	document.getElementById(GRIDLAYOUT_ELEMENTID).style.display = "none";
}

// Fetch event object from triggered event
function getEventObject(e)
{
	//debug("getEventObject()", 'info');

	if (ie)
		return event;
	else
		return e;
}

// Get DOM reference of object associated with event
function getDOMfromEventObject(eventObject)
{
	debug("getDOMfromEventObject()", 'info');

	if (ie)
		return eventObject.srcElement;
	else
		return eventObject.target;
}

// If we need to take a undo snapshot of a element that currently has some styles applied to it for editing purposes
// then make sure to remove some of those styles before the snapshot is taken
function getDocObjFromClone()
{
	debug('getDocObjFromClone()', 'info');

	if(!docSourceClone)
		return false;

	var snapShot = docSourceClone.cloneNode(true);

	snapShot.style.position = docSourceOrig.style.position;
	removeClass(snapShot, 'editBorder');

	// Fetch the offset
	var offSet = 0;
	if(ie)
		offSet = RESIZETABLEOFFSETIE;
	else
		offSet = RESIZETABLEOFFSETMOZ;

	setStyle(snapShot, 'left', getStyle(editBoxRef, 'left', true) + offSet, true);
	setStyle(snapShot, 'top', getStyle(editBoxRef, 'top', true) + offSet, true);

	return snapShot;
}

// Fetch what is considered the top dom element depeding on the browser
function getTopElement()
{
	debug("getTopElement()", 'info');

	if (ie)
		return "BODY";
	else
		return "HTML";
}

function parceLinks(docRef)
{


	debug("parceLinks", 'info');

	if (!docRef)
		return;

	if (docRef.nodeType == 1 /*Node.ELEMENT_NODE*/)  // Check if n is an Element
	{

		var links = docRef.getElementsByTagName("a");
		for (var i=0;i<links.length;i++)
		{
			try{
				if ( links[i].href.length > 1 &&  links[i].href != "#" && links[i].href.charAt(links[i].href.length - 1)!='#')
				{
					//links[i].href = links[i].setAttribute;
					links[i].setAttribute(LINK_HREF_ATTR, links[i].href);
				}
				links[i].href = "#";
				links[i].onclick = function(){return false}
			}
			catch (e){}
		}
	}
}




// This function will recurse all the elements of a DOM node and find the highest z-index
// it is used to find the highest index so we can propogate clicked on elements to the top of the document
function getMaxZIndex(docRef, type)
{
	if (!type)
		type = "text"

			debug("getMaxZindex()"+type, 'info');

	var tempZIndex = 0;
	var tempArtZIndex = 0;

	if (docRef.nodeType == 1 /*Node.ELEMENT_NODE*/)  // Check if n is an Element
	{
		tempZIndex = parseInt(getStyle(docRef, 'zIndex', true));
		if (docRef.className && docRef.className.indexOf('art') > -1)
		{
			if(tempZIndex && tempZIndex > maxArtZIndex)
				maxArtZIndex = tempZIndex;
		}
		else
		{
			if(tempZIndex && tempZIndex > maxZIndex)
				maxZIndex = tempZIndex;
		}
	}

	// Now get all children of docref	
	var children = docRef.childNodes;

	// Loop through the children and recurse the children
	for(var i = 0; i < children.length - 1; i++)
		getMaxZIndex(children[i]);

	debug("getMaxZIndex(): maxZIndex = " + maxZIndex, 'info');
}



// When a event is registered a reference to the element clicked on is passed to the registered function as a parameter.
// However, only one paramter can be passed, wrapping the function in another allows us to pass a flag to it.
function editElementOn(e)
{
	debug("editElementOn()", 'info');

	return selectElement(e, 'on');
}

// When a event is registered a reference to the element clicked on is passed to the registered function as a parameter.
// However, only one paramter can be passed, wrapping the function in another allows us to pass a flag to it.
function editElementOff(e)
{
	debug("editElementOff()", 'info');
	return selectElement(e, 'off');
}

// Turn off dragging of a element, set a flag to signal element moving function
function stopDraggable(e)
{
	debug("stopDraggable()", 'info');
	document.onmousemove = null;
	isDrag = false;
//	groupObj.reloadCoordinates();

	/* attempt to restore the element's original z-index
	 * debug("restoring  z-index: " + z, "info");
	 * if ( !isNaN(z) )
	 *	setStyle(docObj, 'zIndex', z);
	 */

	// Is this a plugin?
	if ( docObj && docObj.className.search(/editorPlugin/gi) >= 0 )
	{
		// hide the plugin IFRAME to prevent it from grabbing the events
		docObj.lastChild.style.visibility = "visible";  
		docObj.style.borderStyle = "solid";
	}

	hideLayoutGrid();

	document.onkeydown  = checkPressedKey;
	document.onkeyup  = checkReleasedKey;

	document.click = checkPressedKey;
	//	document.getElementById(INNEREDITORID).onmouseup = function(){toggleContextPanel(false);}
	//	document.onmouseup = function(){toggleContextPanel(false);editElementOff();}
	//	document.body.onmouseup = function(){toggleContextPanel(false);}
	document.body.oncontextmenu = function(){return false;}




	return true;
}

// ***EXTREMELY IMPORTANT*** - One of the most painful parts of the development of this application
// is the proper layering of events, browsers behave very diffrently then they should so it is very important
// that you be as careful as possible when changing anything to do with events.

// Register and layer functions for movable content
function startDragCopy()
{
	debug("startDragCopy()", 'info');

	document.onmousemove = null;
	editor.onmousemove   = null; // Original above
	editor.onmousedown   = selectElement;
	editor.onmouseup     = stopDraggable; // Original above
	editor.ondblclick    = editElementOn;
	document.onclick     = null;
	document.onmousedown = checkPressedKey;

}

// Unregister functions for movable content
function stopDragCopy()
{
	debug("stopDragCopy()", 'info');
	document.onclick   = editElementOff;
	editor.onmousedown = null;
	editor.onmouseup   = null;
	editor.onmousemove = null;
	editor.ondblclick  = null;
	//	document.onmousedown = null;

	//	document.onKeyPress  = alert("!!!");


	stopDraggable();
}

// Start editor
function startEditor()
{
	debug("startEditor()", 'info');

	if(editorOn)
		return false;

	editor = document.getElementById(INNEREDITORID);
	moveTextToForeground(editor);
	movePageMenuToTop(editor);
	parceLinks(editor);

	getMaxZIndex(editor);
	getMinZIndex(editor);
	registryStart();
	startDragCopy();
	editorOn = true;

	//	document.onKeyDown  = checkDownKey;
	//	editor.onKeyPress  = alert("!!!");
	addContextMenuActions();
	addContextMenu(editor) ;
	//groupObj = new GroupControl();
	//selectionObj = new SelectionControl();

	return true;
}

// Stop Editor
function stopEditor()
{
	debug("stopEditor()", 'info');

	if(!editorOn)
		return false;

	if(docSourceClone)
		designModeOff();
	stopDragCopy();
	document.onclick = null;

	editorOn = false;

	return true;
}

// Set the language code for the editor
function setLanguage(lang)
{
	debug("setLanguage("+lang+")", 'info');
	if ( lang && lang != "" )
	{
		EDITORUSERLANGUAGE = lang;
	}
}

// Event handler for when resize table tab is pressed
function resizeElementDown(e)
{
	debug("resizeElementDown()", 'info');

	// Get DOM reference of tab selected 
	docObjTab = getDOMfromEventObject(getEventObject(e));

	// Hide frame, show element to be resized, highlight
	if(iframe)
	{
		addClass(resizeTableContentRef, 'editBorder');
		setStyle(iframe, 'visibility', 'hidden');
		setStyle(iframe, 'width', 0, true);
		setStyle(iframe, 'height', 0, true);
		resizeTableContentRef.appendChild(docSourceClone);
	}

	// Layer in events to handle when user releases tab
	document.onclick    = null;
	document.onmouseup  = resizeElementUp;
	resizeElementUpSkip = true;
	selectElement(e, false, true);

	return true;
}

// Event handler for when a resize table tab is released
function resizeElementUp(e)
{
	debug("resizeElementUp()", 'info');

	// show frame again with new resized element placed in it
	if(iframe)
	{
		removeClass(resizeTableContentRef, 'editBorder');
		iframe.contentWindow.document.body.appendChild(docSourceClone);
		setStyle(iframe, 'width', getStyle(docSourceClone, 'width'));
		setStyle(iframe, 'height', getStyle(docSourceClone, 'height'));
		setStyle(iframe, 'visibility',  'visible');
	}

	if(resizeElementUpSkip)
		resizeElementUpSkip = false;
	else
		document.onclick = editElementOff;

	// Clean up events to smooth out content editable
	document.onmousemove = null;

	resizeMode = false;

	return true;
}

// Wrap execCommand
function execCommand(command, iface, variant)
{
	debug("execCommand(): commmand = " + command, 'info');

	if(!editorOn)
		return false;

	var undoRedo = fetchUndoRedo();
	var finalSnapShotTaken = false; // Flag to hold if a final undo snapshot was taken to capture last minute change

	// If user activated undo and we are at top of undo stack(i.e. no redos performed) and a object is being edited
	// grab a last minute snaphost of this object to capture any final changes and set flag to indicate this 
	if(command == 'undo' && undoRedo.atTopOfUndoStack() && docSourceClone) 
	{
		finalSnapShotTaken = true;
		undoRedoSnapShot(getDocObjFromClone(), 'edit');
	}
	// Otherwise alwasy take snapshot if the user has activated a command other then undo and redo, such as bold, etc...
	else if(command != 'undo' && command != 'redo' && docSourceClone)
		undoRedoSnapShot(getDocObjFromClone(), 'edit');

	// If the user wants to undo or redo something lets grab it from the undo/redo stack and swap it in
	if(command == 'undo' || command == 'redo')
	{
		// The undo/redo stack contains snapshots of changed dom nodes and a string describing the change.
		// Both are conainted in simple container object
		var container;

		if(command == 'undo')
		{
			// Grab next snapshot, return false if none left
			container = undoRedo.undo();
			// Drop down one more level to skip over the last minute snapshot if one was taken
			if(finalSnapShotTaken)
				container = undoRedo.undo();
		}
		else if(command == 'redo')
		{
			// Move forward one snapshot, return false if none left
			container = undoRedo.redo();
		}

		// If we have a valid container remove the cloned node from it and swap it with existing
		if(container)
		{
			var turnBackOn = false;	// Flag to hold if it is currently being edited
			// Check if it is editable right now
			if(docSourceClone && getId(docSourceClone) == getId(container.clone))
			{
				turnBackOn = true; // Set flag if it is
				designModeOff();   // Turn it off
			}

			// Find it and swap it
			if(container.type == 'edit' || container.type == 'resize' || container.type == 'move')
			{
				var undoDocRef = getElementByESWId(getId(container.clone));
				if(undoDocRef)
				{
					// If it's a edit of some sort we have to swap with exisiting in case we make 
					// various back and forth passes through the undo/redo stack, we will retian
					// modern changes.
					var currentDoc = undoDocRef.cloneNode(true);
					undoDocRef.parentNode.replaceChild(container.clone, undoDocRef);
					container.clone = currentDoc;
					undoRedo.replaceSnapShot(container);
				}
			}
			// Use existing functions to perform undo/redo of entire elements, swithc depending on direction
			else if((container.type == 'delete' && command == 'undo') ||
					(container.type == 'add' && command == 'redo'))
				addElement(container.clone, false, false, true);
			else if((container.type == 'add' && command == 'undo') ||
					(container.type == 'delete' && command == 'redo'))
				deleteElement(container.clone, true);

			// Turn it back on if it was on 
			if(turnBackOn && getElementByESWId(getId(container.clone)))
				designModeOn(getElementByESWId(getId(container.clone.id)));
		}
		return true;
	}

	if(ie || (!ie && command == 'receiveLink'))
	{
		// Highlight cached selection
		highlightSelection();
	}

	// Exec commands works smoother in Mozilla then IE, all we do is directoy exec
	if(iframe)
	{
		if(command == 'cut' || command == 'copy' || command == 'paste')
			debug('execCommand(): Command not supported = ' + command, 'error');
		else
		{
			iframe.contentWindow.focus();
			iframe.contentWindow.document.execCommand(command, iface, variant);
		}
	}
	// Otherwise we have to exec the command and reselect to maintain highlighting
	else
		document.execCommand(command, iface, variant);

	// Test if command state has changed by exec'd command and send appropriate signal if it has
	checkCommandState();

	return true;
}

// Handle user clicking on editable area
function checkClick()
{
	var clickedTag = getParentElement();

	//clickedTag.contentEditable = true;
	// If the user clicked on a spell check span
	if(clickedTag && clickedTag.className && clickedTag.className.search(/spellCheck/gi) >= 0)
	{
		showSuggestions(clickedTag);
		return true;
	}

	// If the user clicked on 
	if(clickedTag && /^a$/i.test(clickedTag.tagName))
	{
		createLink();
		return true;
	}

	// If user clicked elsewhere hide spell check box
	document.getElementById('spellCheck').innerHTML = '';
}

// Return flag indicating whether or not document has been edited
function hasDocumentChanged()
{
	return documentChanged;
}

// Reset the "document changed" flag... (ie. after a Save operation)
function resetDocumentChangedFlag()
{
	documentChanged = false;
}

function checkDelete(e)
{
	var Key = null;
	var type = "";

	if (!ie)
	{
		Key = e.which;
		type = e.type;
	}
	else
	{
		Key = window.event.keyCode;
		type = window.event.type;
	}

	if (Key == 16 && type == "keydown")
	{
		isPressShiftKey = true;
		//xdebug("shift down from checkDelete");
		//		alert("shift out");
	}
	if (Key == 16 && type == "keyup")
	{
		isPressShiftKey = false;
		//		alert("shift out");
		//xdebug("shift up from checkDelete");
	}

	if (iframe.contentWindow.document.body.getElementsByTagName("*").length == 1 && iframe.contentWindow.document.body.firstChild.tagName == "BR" && iframe.contentWindow.document.body.firstChild.tagName != "TABLE" )
	{
		debug('checkDelete(): add empty div for correct insertion');
		var id = currEditedDiv.id;
		while(currEditedDiv.hasChildNodes())
		{
			currEditedDiv.removeChild(currEditedDiv.firstChild);
		}
		var p = document.createElement("p");

		var text = document.createTextNode(" ");
		p.appendChild(text);
		currEditedDiv.appendChild(p);
		iframe.contentWindow.document.body.removeChild(iframe.contentWindow.document.body.firstChild);

		docSourceClone =	iframe.contentWindow.document.body.appendChild(currEditedDiv);

		var startPar = iframe.contentWindow.document.getElementsByTagName("p").item(0);//[the span node];
		window.getSelection().selectAllChildren(startPar);
	}
	if (iframe.contentWindow.document.body.firstChild.tagName !== "DIV")
	{
		while(currEditedDiv.hasChildNodes())
		{
			currEditedDiv.removeChild(currEditedDiv.firstChild);
		}


		var content = iframe.contentWindow.document.body.innerHTML;
		iframe.contentWindow.document.body.innerHTML = "";

		var p = document.createElement("p");
		var text = document.createTextNode(" ");
		p.innerHTML = content;		
		currEditedDiv.appendChild(p);
		docSourceClone = iframe.contentWindow.document.body.appendChild(currEditedDiv);


		var startPar = iframe.contentWindow.document.getElementsByTagName("p").item(0);//[the span node];
		window.getSelection().selectAllChildren(startPar);
		window.getSelection().collapseToEnd();
	}

}
function setPreviewMode()
{
	if ( !previewMode )
		previewMode = true;
	else
		previewMode = false;
}
function setMasterMode()
{
	if ( !masterMode )
		masterMode = true;
	else
		masterMode = false;


// !!!! parce all for master	
	var allLayersObj = new layersList(editor);

	for(var i=0; i<allLayersObj.allLayers.length; i++)
	{
		allLayersObj.allLayers[i].obj.setAttribute(MASTER_EL_ATTR, "true");
		generateId(allLayersObj.allLayers[i].obj);
	}
			
	allLayersObj.allLayers
}
function checkReleasedKey(e)
{

	var Key = 0;
	var button = null;
	var type = "";
	rightMouseBtnClicked = false;
	if (!ie)
	{
		Key = e.which;
		button = Key;
		type = e.type;
	}
	else
	{
		Key = window.event.keyCode;
		button = window.event.button;
		type = window.event.type;
	}

	if (Key == 16 && type == "keyup")
	{
		isPressShiftKey = false;
		//		hideLayoutGrid();
		//alert('shift up');
		//xdebug("shift up from checkReleasedKey(e)");
	}

	if (Key == 16 && type == "keydown")
	{
		isPressShiftKey = true;
		//alert('shift up');
		//xdebug("shift down from checkReleasedKey(e)");
	}

}

function checkPressedKey(e)
{

	var Key = 0;
	var button = null;
	var type = "";

	rightMouseBtnClicked = false;
	if (!ie)
	{
		Key = e.which;
		button = Key;
		type = e.type;
	}
	else
	{
		Key = window.event.keyCode;
		button = window.event.button;
		type = window.event.type;
	}

	// check shift key down
	if (Key == 16 && type == "keydown") 
	{
		//xdebug("shift down from checkPressedKey(e)");
		isPressShiftKey = true;

	}

	var eventObject = getEventObject(e);
	docSource       = getDOMfromEventObject(eventObject);
	var topelement  = getTopElement();

	if (docSource.tagName == "HTML" || docSource.tagName == "BODY")
	{
		toggleContextPanel(false);
	}


	// delete kast selected element on Del btn
	if (Key == 46)
	{
		//        	alert("Delete: " + lastSelectedElement.id);
		if ( !isDesignModeOn  && (lastSelectedElement.id != "ESWuserMenuPosition" )) // delete only if design mode off!!
			deleteElement(lastSelectedElement);
	}


	// show context menu on left click
	if( (ie && button == 2) || (!ie && button == 3) )
	{
		// context menu
		if (previewMode)
			return;
		var eventObject = getEventObject(e);
		docSource       = getDOMfromEventObject(eventObject);
		var topelement  = getTopElement();

		// Climb DOM tree till the node has a class of the specified type
		while (docSource.tagName != topelement && (
					docSource.className.search(/draggable/gi) < 0 && 
					docSource.className.search(/editable/gi) < 0 &&
					docSource.className.search(/ESWuserForm/gi) < 0 &&
					( docSource.className.search(/ESWuserTable/gi) < 0 ) ))
		{
			if(ie)
				docSource = docSource.parentElement;
			else
				docSource = docSource.parentNode;
		}
		lastSelectedElement = docSource;
		rightMouseBtnClicked = true;
		if (	   docSource.className.search(/draggable/gi) >= 0   ||
				docSource.className.search(/editable/gi) >= 0    ||
				docSource.className.search(/ESWuserForm/gi) >= 0 ||
				docSource.className.search(/ESWuserTable/gi) >= 0)
		{
			//			alert(docSource.id);
			//			document.getElementById('pluginPanel').style.display = "block";
			stopDraggable(e);

//			if ( !selectionObj.isSelected(docSource.id))
//			{
//				selectionObj.clear();
				flashElement(docSource);
				showContextMenu(e);
				toggleContextPanel(true);
//			}
//			else
//			{
//				showContextMenu(e);
//				toggleGroupContextPanel(true);
//			}
		}
	}
	//else
	////	toggleContextPanel(false);


	return true;
}


function addContextMenu(docRef, type) 
{
	if (!type)
		type = "text"

			debug("getMaxZindex()"+type, 'info');

	var tempZIndex = 0;
	var tempArtZIndex = 0;

	if (docRef.nodeType == 1 /*Node.ELEMENT_NODE*/)  // Check if n is an Element
	{

		if (	docRef.className.search(/draggable/gi) >= 0   ||
				docRef.className.search(/editable/gi) >= 0    ||
				docRef.className.search(/art/gi) >= 0    ||
				docRef.className.search(/ESWuserForm/gi) >= 0 ||
				docRef.className.search(/ESWuserTable/gi) >= 0)
		{
			docRef.onmousedown = checkPressedKey;

		}
	}

	// Now get all children of docref	
	var children = docRef.childNodes;

	// Loop through the children and recurse the children
	for(var i = 0; i < children.length - 1; i++)
		addContextMenu(children[i]);

	debug("addContextMenu()", 'info');
}


