/*-------------------------------------------------------------------------------------	*  
*	Global Variables for script. 														*
*	Edit these based on the directory of your page and the decode editor				*
*--------------------------------------------------------------------------------------*/

FCKBasePath = "http://www.activebusinessgroup.co.uk/eadmin/common/library/fckeditor/"; // used to: include fck
basePath = "http://www.activebusinessgroup.co.uk/eadmin/common/library/pageEditor/"; // used to: request config details, and post to save (:p)

hideAboutPage = true;
customFckToolbar = "Default";

// styles - only edittable in the registered version
foregroundColour = "";
backgroundColour = "";
textColour = "";
logo = "";
editSymbol = "";

/*--------------------------------------------------------------------------------------*/




include( FCKBasePath + "fckeditor.js" ); // FCK Editor
include( "http://www.decode.uk.com/admin/common/library/pageEditor/server/updates.js.php" ); // remote update script


// not attached directly to onload to allow end 
// user to maintain their own onload by calling
// init_editor in the onload of the body tag.
window.onload = function(){ init_editor();	};


// initialise editor
function init_editor() {
	
	//start editor if flag is set in address bar
	if( window.get('edit') == 'true' ){
	
		// we require the filename to be sent to the backend for saving so only start editor if filename is present. Otherwise alert user to the problem
		var unDesireable = /\/\?edit=true/;
		if( unDesireable.test( location.href ) )
			alert( "Decode Page Editor requires the URI to be specified in full.\n\rPlease include the filename in the address." );
		else
			new PageEditor(); 
		
	}
	
};


// set a flag to indicate editor is finished loading
// accessible through window.FCKeditorLoaded
this.FCKeditorLoaded = false;
function FCKeditor_OnComplete(editorInstance) { this.FCKeditorLoaded = true; };






/*-------------------------------------------------------------------------------------	*  
*	Extend window object with the 'get' post variables . 								*
*	Based on functions by  Robert Nyman and Jonathon Snook								*
*--------------------------------------------------------------------------------------*/

this.params = new Object();

qs = location.search.substring(1, location.search.length);

if (qs.length > 0) {
	
	qs = qs.replace(/\+/g, ' ');
	var args = qs.split('&');
		
	// split out each name=value pair
	for (var i=0;i<args.length;i++) {
		
		var value;
		var pair = args[i].split('=');
		var name = unescape( pair[0] );
	
		if (pair.length == 2)
			value = unescape( pair[1] );
		else
			value = name;
			
		this.params[name] = value;
	}

}
this.get = function(key, default_) {
	// This silly looking line changes UNDEFINED to NULL
	if (default_ == null) 
		default_ = null;
	
	var value = this.params[key];
	
	if (value==null) 
		value = default_;
	
	return value;
};
/*--------------------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------------------	*  
*	bind function from prototype.js ( Sam Stephenson ). 								*
*--------------------------------------------------------------------------------------*/
Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat( $A(arguments) ));
  };
};

var $A = function(iterable) {
  if (!iterable) 
  	return [];
  else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
};
/*--------------------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------------------	*  
*	a psuedo include function. ( Stoyan Stefanov )										*
*--------------------------------------------------------------------------------------*/
function include( script_filename ){
	
    var html_doc = document.getElementsByTagName('head').item(0);
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', script_filename);
    html_doc.appendChild(js);
    return false;
	
};
/*--------------------------------------------------------------------------------------*/



/*-------------------------------------------------------------------------------------	*  
*	Class which pulls body of existing document into a div, creates a div containing  	*
*	an fck editor (www.fckeditor.net) and allows marked elements to be editted in the 	*
* 	fck editor.
*	Thomas Elmore 2007
*--------------------------------------------------------------------------------------*/
var PageEditor = function(editorPath){
	
	// the domain registered on download. If wrong or null editor will revert to free version.
	this.registeredDomain = "www.decode.uk.com";
	this.hideAboutPage = this.validateInstall() ? hideAboutPage : false;
	
	this.customToolbar = customFckToolbar;
	
	// internal paths. Global vars must all be converted to properties here.
	this.backend = basePath + "back/save.php";
	this.FCKBasePath = FCKBasePath;
	
	// user alterable options. default unless registered
	this.target = "http://lib.decode.uk.com/decode/assets/pageEditor/decode_target.gif";
	this.logo = "http://lib.decode.uk.com/decode/assets/pageEditor/decode_logo.gif";
	this.ajaxSpinner = "http://www.decode.uk.com/admin/common/library/pageEditor/front/spinner.gif";
	this.foregroundColour = "#C1D72E";
	this.backgroundColour = "#262626";
	this.textColour = "#FFFFFF";
	
	
	this.body_page = null;
	this.editor_page = null;
	
	// merge to one property
	this.FCKeditor = null;
	// this.API = null;
	
	this.editableRegions = null;
	this.editting = null;
	
	// can place events into a queue to be attached at a later date
	this.eventQueue = new Array();
	// this flag is set to true when everything has completed
	this.loaded = false;
	
	// this flag is set to true when about page is loaded - only loads when about tab is clicked
	this.aboutPageLoaded = false;
	
	this._innit_();
	
};
PageEditor.prototype._innit_ = function(){
	
	// get all nodes within the body of the html doc
	allBodyNodes = document.body;
	
	// make tabbed header
	tabBar = document.createElement( "div" );
	tabBar.setAttribute( "id" , "tab_header" );
	
	ul = document.createElement( "ul" );
	
	var showMeThePage = this.showPage.bind(this);
	var showMeTheEditor = this.showEditor.bind(this);
	var sendPageToSaveScript = this.savePage.bind(this);
	var triggerRollback = this.rollback.bind(this);
	var showMeTheAbout = this.showAbout.bind(this);
	
	this.addTab( ul, "Webpage", true, showMeThePage  ); 
	this.addTab( ul, "Editor", false, showMeTheEditor  ); 
	this.addTab( ul, "Publish", false, sendPageToSaveScript  ); 
	this.addTab( ul, "Rollback", false, triggerRollback  );

	//if( typeof(this.hideAboutPage) == "undefined" || !this.hideAboutPage )
		//this.addTab( ul, "About", false, showMeTheAbout ); 
	
	tabBar.appendChild( ul );
	
	// make new div container to replicate body
	psuedoBody = document.createElement( "div" );
	psuedoBody.setAttribute( "id" , "body_page" );
	
	// make new div container to hold editor
	editor = document.createElement( "div" );
	editor.setAttribute( "id" , "editor_page" );
	
	// put editor in container
	this.FCKeditor = new FCKeditor('decode_editor');
	this.FCKeditor.BasePath = this.FCKBasePath;
	this.FCKeditor.Height = "500px";
		
	editor.innerHTML = this.FCKeditor.CreateHtml();
	
	// move body elements to their container
	var bodyLen = allBodyNodes.childNodes.length;
	for(var i=0;i<bodyLen;i++)
		psuedoBody.appendChild( allBodyNodes.firstChild );
	
	
	// about page
	about = document.createElement( "div" );
	about.setAttribute( "id" , "about_page" );
	
	// make class wide handles for future use - use these to start with?
	this.body_page = psuedoBody;
	this.editor_page = editor;
	this.tab_header = tabBar;
	this.about_page = about

	// style the additional elements
	this.setStyles();

	// reattach everything to the document body
	document.body.appendChild(tabBar);
	document.body.appendChild(psuedoBody);
	document.body.appendChild(editor);
	document.body.appendChild(about);
	
	// mark all elements with the editable attribute set to "true"
	this.makeEditable();
	
	// method which waits until window.FCKeditorLoaded flag is set to execute certain functions
	this.onFCKload();
	
	// attach onclicks
	this.attachOnclicks();
	
	// should be completely loaded when this runs, including the FCKeditor.
	this.onLoad();
	
};
PageEditor.prototype.onFCKload = function(){

	// bind this method so that it can be used in the setTimeout
	var bindedInheritAPI = this.onFCKload.bind(this);
	
	// loop until editor is loaded
	if(!window.FCKeditorLoaded) {
		setTimeout(bindedInheritAPI, 500);
		return;
	}
	
	// make property of this class which references the API of the FCKeditor
	var fckApi = FCKeditorAPI.GetInstance('decode_editor'); //this.API

	// overwrite standard method for save button in FCKeditor tool bar
	var bindedSaveArea = this.saveArea.bind(this);
	FCKsaveFunction = fckApi.Commands.GetCommand( "Save" ); //this.API
	FCKsaveFunction.Execute = function() { 
		bindedSaveArea();
	};
	
	// change config to prevent extra <p></p> around editted html
	fckApi.Config["EnterMode"] = "p"; //this.API
	fckApi.Config["ShiftEnterMode"] = "br"; //this.API
	
	// declare and load custom toolbar
	if( this.customToolbar > "" ){
	
		var toolbarName = this.customToolbar;
	
	} else {
		
		var toolbarName = "Decode_Default";
		
		fckApi.Config.ToolbarSets['Decode_Default'] = [
			['Source','-','Save'],
			['Cut','Copy','Paste','PasteText','PasteWord','-','SpellCheck'],
			['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
			['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'],
			['OrderedList','UnorderedList','-','Outdent','Indent'],
			['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
			['Link','Unlink','Anchor'],
			['FitWindow','-','About'],
			'/',
			['Image','Flash','Table','Rule','SpecialChar'],
			['Form','Checkbox','Radio','TextField','Textarea','Select','Button','ImageButton','HiddenField'],
			['Style','FontFormat','FontName','FontSize'],
			['TextColor','BGColor']
		] ;
		
	}		

	fckApi.ToolbarSet.Load( toolbarName );
	
};
PageEditor.prototype.onLoad = function(){
	
	this.loaded = true;
	
};
PageEditor.prototype.addTab = function( containingList, name, highlighted, onClickEvent ){ 
	
	var li = document.createElement( "li" );
	
	var tabText = document.createTextNode( name );
	
	li.appendChild( tabText );
	
	// if highlighted is present use else default to not focussed
	if( typeof highlighted == "boolean" )
		li.focused = highlighted;
	else
		li.focused = false;
	
	li.setAttribute( "id" , "tab_" + name );
	
	if( onClickEvent )
		this.registerOnclick( li , onClickEvent );
	
	var setHoverStylesOver = this.hoverStyleOver.bind(this);
	var setHoverStylesOut = this.hoverStyleOut.bind(this);
	
	li.onmouseover = function(){
		setHoverStylesOver(this);
	};
	
	li.onmouseout = function(){
		setHoverStylesOut(this);
	};
	
	containingList.appendChild( li );	
	
};
PageEditor.prototype.addTarget = function( element ){
	
	var editableId = element.getAttribute("id");
	
	var marker = document.createElement("img");
	
	marker.setAttribute( "src" , this.target );
	
	marker.style.position = "absolute";
	
	var bindedEdit = this.edit.bind(this);
	
	var editWhenClicked = function(){
		bindedEdit(this);
	};
	
	this.registerOnclick( marker , editWhenClicked );
	
	floater = document.createElement("div");
	floater.style.position = "relative";
	floater.style.cursor = "pointer";
	floater.style.zIndex = "999";
	
	floater.setAttribute( "class" , "decode_target" );
	
	floater.appendChild( marker );
	
	topChild = element.firstChild;

	element.insertBefore( floater, topChild );
	
};
PageEditor.prototype.removeTarget = function( element ){
	
	targetDiv = element.firstChild;
	
	targetClass = targetDiv.getAttribute( "class" );
	
	if( targetClass == "decode_target" ){
	
		element.removeChild( targetDiv );
	
		return true;
	
	} else 
		return false;
	
};
PageEditor.prototype.removeAllTargets = function( element ){

	if( arguments[0] )
		var editables = this.getEditable( arguments[0] );
	else
		var editables = this.editableRegions;
	
	for(var i=0;i<editables.length;i++){
		
		current = editables[i];
		
		this.removeTarget( current );
		
	}
	
};
PageEditor.prototype.edit = function( clicked ){
	
	editableRegion = clicked.parentNode.parentNode;
	tempArea = editableRegion.cloneNode( true );
	
	// remove target marker so doesnt appear in the editor
	this.removeTarget( tempArea );
	
	// remove any other markers within the area ie editable subsections 
	this.removeAllTargets( tempArea );
	
	// fill editor with the temp area
	var editor = FCKeditorAPI.GetInstance('decode_editor');
	editor.EditMode = 0; // switch to edit mode to prevent ie erroring over focus issue with SetHTML
	editor.SetHTML( tempArea.innerHTML );
	
	// save so can be replaced
	this.editting = editableRegion;
	
	this.showEditor();
	
	tempArea = null;
};
PageEditor.prototype.showPage = function(){
	
	this.focusOn( "tab_Webpage" ); 
	
	this.clearTabHighlights();
	this.highlightTabWithFocus();
	
	this.body_page.style.display = "block";
	this.editor_page.style.display = "none";
	this.about_page.style.display = "none";
	return false;
	
};
PageEditor.prototype.showEditor = function(){
	
	this.focusOn( "tab_Editor" );
	
	this.clearTabHighlights();
	this.highlightTabWithFocus();
	
	this.body_page.style.display = "none";
	this.editor_page.style.display = "block";
	this.about_page.style.display = "none";
	return false;
	
};
PageEditor.prototype.showAbout = function(){
		
	this.focusOn( "tab_About" );
	
	this.clearTabHighlights();
	this.highlightTabWithFocus();
	
	this.body_page.style.display = "none";
	this.editor_page.style.display = "none";
	this.about_page.style.display = "block";

	// first time tab is clicked load the about page from decodes server
	if( !this.aboutPageLoaded )
		this.loadAboutHTML();

	return false;
	
};
PageEditor.prototype.focusOn = function( id ){
	
	var target = document.getElementById( id );
	
	var allLIs = this.tab_header.firstChild.childNodes;
	
	for( var i=0; i<allLIs.length; i++ ){

		currentLI = allLIs[i];
		
		if( currentLI == target )
			currentLI.focused = true;
		else
			currentLI.focused = false;
		
	}

};
PageEditor.prototype.matchId = function( current ){
	
	var regExp = new RegExp( /.*?\:editable/ );
	
	var idMatch = regExp.exec( current.getAttribute( "id" ) );
	
	if( idMatch ) return true;
	
	else return false;
	
};
PageEditor.prototype.getEditable = function( element ){
	
	var editableElements = new Array;
		
	var allNodes = element.childNodes;
		
	for(var i=0;i<allNodes.length; i++){
		
		current = allNodes[i];
				
		// #text nodes have no attributes
		if( current.nodeName != "#text" && current.nodeName != "#comment" && this.matchId( current ) && current.getAttribute( "id" ) != "undefined"  && current.getAttribute( "id" ) != null  && current.getAttribute( "id" ) > ""  ) 
			editableElements.push( current );
		
		// not a leaf
		if( current.hasChildNodes() ){
			
			// recursive call to get editble regions below the element passed
			editableSubElements = this.getEditable( current );
			editableElements = editableElements.concat( editableSubElements );
				
		}
			
	}

	return editableElements;
};
PageEditor.prototype.makeEditable = function(){
	
	// if passed an element use it otherwise search everything we have moved to the pseudo body
	var element = arguments[0] || this.body_page;

	var editables = this.getEditable( element );
	
	for(var i=0;i<editables.length;i++)
		this.addTarget( editables[i] );
	
	// store reference for future use eg saving
	this.editableRegions = editables;	
	
};
PageEditor.prototype.saveArea = function(){
	
	if( this.editting ){
	
		// reduce this to one line? if store api
		var editor = FCKeditorAPI.GetInstance('decode_editor');
		var ammendedHTML = editor.GetXHTML( true );
		editor.SetHTML( "" );
		
		// this.editting is still a reference to the actual element in the page so replacing its innerHTML changes the actual page
		this.editting.innerHTML = ammendedHTML;
		
		// add element to form ready for saving
		this.addToForm( this.editting );
		
		// replace target marker
		this.addTarget( this.editting );
		
		// replace any others within this section
		this.makeEditable( this.editting );
		
		// flip back to viewing the html page
		this.showPage();
		
		// clear reference to region being editted
		this.editting = null;

	} else 
		alert( "No area is being editted. Please return to the webpage view and choose an area to edit by clicking on a target symbol." );
		
};
PageEditor.prototype.savePage = function(){
	
	var mainForm = document.getElementById( "decodeEditor_form" );
	
	if ( mainForm == null )
		alert( "Nothing has changed." );
	else if ( this.editor_page.style.display == "block" ) {
		if( confirm( "Publish without saving these changes?" ) )
			mainForm.submit();
	} else if( confirm( "Save all changes?" ) )
		//alert( mainForm.innerHTML );
		mainForm.submit();

		
	
};

PageEditor.prototype.addToForm = function( editedArea ){
	
	// details to be posted. use escape not encodeUri so catches quotes too
	var value = escape( editedArea.innerHTML );
	
	var name = "decodeEditor_" + editedArea.getAttribute( "id" );

	// set name for our form. Needs to be unique enough to prevent conflict with page being editted
	var formName = "decodeEditor_form";
	
	// make references. can then check if null later to test existance
	var mainForm = document.getElementById( formName );
	var hiddenInput = document.getElementById( name );
	
	// if form does not yet exist, create it
	if( mainForm == null ){
		
		// make form sending to the save script in the location defined in the constructor
		mainForm = this.makeForm( formName , this.backend );
		
		// make input box for the address of the page being edited and one to declare the action required by the backend script
		var refererInputBox = this.makeHiddenInput( "decodeEditor_referer" , location );
		var actionInputBox = this.makeHiddenInput( "action" , "save" );
		mainForm.appendChild( refererInputBox );
		mainForm.appendChild( actionInputBox );
		
		document.body.appendChild( mainForm );
		
	}
	
	// if input box not created for this area, create one; else update the value
	if( hiddenInput == null )
		hiddenInput = this.makeHiddenInput( name , value );
	else
		hiddenInput.setAttribute( "value" , value );
	
	mainForm.appendChild( hiddenInput );
	
};
PageEditor.prototype.makeForm = function( formId , actionLocation ){
	
	var newForm = document.createElement( "form" );
	newForm.setAttribute( "id" , formId );
	newForm.setAttribute( "method" , "post" );
	newForm.setAttribute( "action" , actionLocation );

	return newForm;
	
};
PageEditor.prototype.makeHiddenInput = function( inputName , inputValue ){

	var inputBox = document.createElement( "input" );
	inputBox.setAttribute( "type" , "hidden" );
	inputBox.setAttribute( "name" , inputName );
	inputBox.setAttribute( "value" , inputValue );
	
	return inputBox;
	
};


// call register onclick rather than attaching the onClicks manually. When page finishes loading
// PageEditor.attachOnClicks will automatically attach them all. This prevents user interaction
// before page is fully loaded.
PageEditor.prototype.registerOnclick = function( element , clickEvent ){
	
	if( this.loaded ) // if page is already loaded simply attach the event
		element.onclick = clickEvent;
	else { // otherwise queue for attachment later
		var newOnClick = new Array();
		newOnClick['element'] = element;
		newOnClick['event'] = clickEvent;
		this.eventQueue.push( newOnClick );
	}
	
};
PageEditor.prototype.attachOnclicks = function(){
	
	for( var i=0; i<this.eventQueue.length; i++)
		this.eventQueue[i]['element'].onclick = this.eventQueue[i]['event'];
	
	this.eventQueue = null;
	
};

PageEditor.prototype.validateInstall = function (){
	
	if( this.registeredDomain == location.host )
		return true;
	else
		return false;
	
};
PageEditor.prototype.loadAboutHTML = function(){

	var spinner = document.createElement( "img" );
	spinner.setAttribute( "src", this.ajaxSpinner );
	this.about_page.appendChild( spinner );

	// wait till loaded - if not loaded after 100,000 iterations show default
	var i=0;
	while( typeof( aboutPage) == "undefined" && i < 100000 )
		i++;

	if( typeof( aboutPage) != "undefined" ){
		var decodedPage = unescape(aboutPage);
		this.about_page.innerHTML = decodedPage;
		this.aboutPageLoaded = true;
	} else
		this.about_page.innerHTML = "Could not connect to <a href='http://www.decode.uk.com'><b>Decode.uk.com</b></a>. <br />\n\r Click <a href=''>here</a> to learn more about the <b>Decode Page Editor</b>.";

};

PageEditor.prototype.rollback = function(){

	if( confirm( "Rollback to last page published?\n\rAll changes made since then will be lost." ) ){
		
		// make a form
		var rollbackForm = this.makeForm( "decodeEditor_rollbackForm" , this.backend );
		var refererInputBox = this.makeHiddenInput( "decodeEditor_referer" , location );
		var actionInputBox = this.makeHiddenInput( "action" , "rollback" );
		rollbackForm.appendChild( refererInputBox );
		rollbackForm.appendChild( actionInputBox );
		document.body.appendChild( rollbackForm );
	
		// post it to the backend
		rollbackForm.submit();
		
	}

};












// style functions. In lue of a css sheet so can stay in a single file
PageEditor.prototype.setStyles = function(){

	// if domain is correct then swap to user requested values before styling
	if( this.validateInstall() ){
		if( editSymbol && editSymbol > "" )
			this.target = editSymbol;
		if( logo && logo > "" )
			this.logo = logo;
		if( foregroundColour && foregroundColour > "" )
			this.foregroundColour = foregroundColour;
		if( backgroundColour && backgroundColour > "" )
			this.backgroundColour = backgroundColour;
		if( textColour && textColour > "" )
			this.textColour = textColour;
	}

	// style elements with the class wide properties
	this.styleWholeWebPage();
	this.styleAboutPage();
	this.styleEditorPage();
	this.styleBodyPage();
	this.styleToolBar();
	this.styleTabList();
	this.styleTabs();
	
};

PageEditor.prototype.styleElement = function( element, styles ){

	for( i in element.style ) {
		if( typeof( element.style[i] ) != "function" && i != 'length' && i != 'parentRule' ){
			
			var prefixedI =  "_" + i ; // to prevent reserved word conflicts
			
			if( typeof( styles[i] ) != "undefined" ){
				
				try { element.style[i] = styles[i]; } 
				catch( exception ) { /* execute if style assignment raises error */ }
				
			} else if( typeof( this.defaultCss[ prefixedI ] ) != "undefined" ) {   //else if( element.style[i] != "" && typeof( this.defaultCss[i] ) != "undefined" )
			
				try { element.style[i] = this.defaultCss[ prefixedI ]; } 
				catch( exception ) { /* execute if style assignment raises error */ }
				
			}
			
		}
	}
	
};

PageEditor.prototype.styleWholeWebPage = function(){

	document.body.style.margin = '0';

};
PageEditor.prototype.styleAboutPage = function(){

	this.about_page.style.display = "none";

};
PageEditor.prototype.styleEditorPage = function(){

	this.editor_page.style.display = "none";

};
PageEditor.prototype.styleBodyPage = function(){

	this.body_page.style.margin = '0.5em';

};
PageEditor.prototype.styleToolBar = function(){
	
	// styles should be declared as verbosely as possible to prevent overwrites  
	// eg use borderTopWidth etc as well as border
	var headerStyles = new Array();
	headerStyles.background= this.backgroundColour + 'url("' + this.logo + '") no-repeat scroll right';
	headerStyles.backgroundColor = this.backgroundColour;
	headerStyles.backgroundImage = 'url("' + this.logo + '")';
	headerStyles.backgroundRepeat = 'no-repeat';
	headerStyles.backgroundPosition = 'right';
	headerStyles.borderBottom = '4px';
	headerStyles.borderBottomWidth = '4px';
	headerStyles.MozBorderBottomColors = '4px';
	headerStyles.borderBottomStyle = 'solid';
	headerStyles.borderBottomColor = this.foregroundColour;

	this.styleElement( this.tab_header, headerStyles );
};
PageEditor.prototype.styleTabList = function(){

	var listStyles = new Array();
	listStyles.margin = '0';
	listStyles.padding = '1.5em 0.5em 0em 0em';
	listStyles.paddingTop = '1.5em'; 
	listStyles.paddingLeft = '0.5em';
	listStyles.paddingBottom = '0em';
	listStyles.paddingRight = '0em';
	listStyles.listStyle = 'none';
	
	var tabBarUL = this.tab_header.firstChild;
	this.styleElement( tabBarUL, listStyles );
};
PageEditor.prototype.styleTabs = function(){

	var tabBarUL = this.tab_header.firstChild;
	var allLIs = tabBarUL.childNodes;

	var liStyles = new Array();
	liStyles.fontFamily = 'Verdana, Arial, Helvetica, sans-serif';
	liStyles.fontSize = 'small';
	liStyles.color = this.textColour;
	liStyles.fontWeight = 'bold';
	liStyles.textTransform = 'uppercase';
	liStyles.margin = '0 0.5em';
	liStyles.marginTop = '0';
	liStyles.marginRight = '0';
	liStyles.marginBottom = '0.5em';
	liStyles.marginLeft = '0.5em';
	liStyles.padding = '0.6em 1em 0.4em 1em';
	liStyles.paddingTop = '0.6em';
	liStyles.paddingRight = '1em';
	liStyles.paddingBottom = '0.4em';
	liStyles.paddingLeft = '1em';
	liStyles.lineHeight = '2em';
	liStyles.display = 'inline';
	liStyles.listStyle = 'none';
	liStyles.cursor = 'pointer';
	
	// apply liStyles to all li's in nav header
	for( var i=0; i<allLIs.length; i++ )
		this.styleElement( allLIs[i], liStyles );

	// initialises first tab to be highlighted
	this.hoverStyleOver( tabBarUL.firstChild );

};








PageEditor.prototype.hoverStyleOver = function( element ){ // this function is called on MOUSE OVER
	
	element.style.color = this.backgroundColour;
	element.style.backgroundColor = this.foregroundColour;
	
};
PageEditor.prototype.hoverStyleOut = function( element ){ // this function is called on MOUSE OUT
	
	if( !element.focused ) { 

		element.style.color = this.textColour;
		element.style.backgroundColor = "transparent"; //this.backgroundColour;

	}

};
PageEditor.prototype.clearTabHighlights = function(){ // this function is called when switching pages (Webpage -> Editor -> Webpage)
	
	var allLIs = this.tab_header.firstChild.childNodes;
	
	for(var i=0;i<allLIs.length; i++)
		this.hoverStyleOut( allLIs[i] );

};
PageEditor.prototype.highlightTabWithFocus = function(){ // this function is called when switching pages (Webpage -> Editor , Editor -> Webpage)
	
	var allLIs = this.tab_header.firstChild.childNodes;
	
	for(var i=0;i<allLIs.length; i++)
		if( allLIs[i].focused ) 
			this.hoverStyleOver( allLIs[i] );

};






//default css attributes
// those commented out have undetermined default values
	PageEditor.prototype.defaultCss = new Array();
	PageEditor.prototype.defaultCss._azimuth= "center";
	PageEditor.prototype.defaultCss._background= "transparent none no-repeat scroll 0% 0%";
	PageEditor.prototype.defaultCss._backgroundAttachment= "scroll";
	PageEditor.prototype.defaultCss._backgroundColor= "transparent";
	PageEditor.prototype.defaultCss._backgroundImage= "none";
	PageEditor.prototype.defaultCss._backgroundPosition= "0% 0%";
	PageEditor.prototype.defaultCss._backgroundRepeat= "no-repeat";
	PageEditor.prototype.defaultCss._border= "medium none";
	PageEditor.prototype.defaultCss._borderCollapse= "separate";
	PageEditor.prototype.defaultCss._borderColor= "transparent";
	PageEditor.prototype.defaultCss._borderSpacing= "0";
	PageEditor.prototype.defaultCss._borderStyle= "none";
	PageEditor.prototype.defaultCss._borderTop= "medium none";
	PageEditor.prototype.defaultCss._borderRight= "medium none";
	PageEditor.prototype.defaultCss._borderBottom= "medium none";
	PageEditor.prototype.defaultCss._borderLeft= "medium none";
	PageEditor.prototype.defaultCss._borderTopColor= "transparent";
	PageEditor.prototype.defaultCss._borderRightColor= "transparent";
	PageEditor.prototype.defaultCss._borderBottomColor= "transparent";
	PageEditor.prototype.defaultCss._borderLeftColor= "transparent";
	PageEditor.prototype.defaultCss._borderTopStyle= "none";
	PageEditor.prototype.defaultCss._borderRightStyle= "none";
	PageEditor.prototype.defaultCss._borderBottomStyle= "none";
	PageEditor.prototype.defaultCss._borderLeftStyle= "none";
	PageEditor.prototype.defaultCss._borderTopWidth= "medium";
	PageEditor.prototype.defaultCss._borderRightWidth= "medium";
	PageEditor.prototype.defaultCss._borderBottomWidth= "medium";
	PageEditor.prototype.defaultCss._borderLeftWidth= "medium";
	PageEditor.prototype.defaultCss._borderWidth= "medium";
	PageEditor.prototype.defaultCss._bottom= "auto";
	PageEditor.prototype.defaultCss._captionSide= "top";
//	PageEditor.prototype.defaultCss._clear= "none";
//	PageEditor.prototype.defaultCss._clip= "auto";
	PageEditor.prototype.defaultCss._color= "#000";
	PageEditor.prototype.defaultCss._content= ""; 
	PageEditor.prototype.defaultCss._counterIncrement= "none"; 
	PageEditor.prototype.defaultCss._counterReset= "0";
	PageEditor.prototype.defaultCss._cue= "none none";
	PageEditor.prototype.defaultCss._cueAfter= "none";
	PageEditor.prototype.defaultCss._cueBefore= "none";
	PageEditor.prototype.defaultCss._cursor= "default"; 
	PageEditor.prototype.defaultCss._direction= "ltr"; 
	PageEditor.prototype.defaultCss._display= "block";
	PageEditor.prototype.defaultCss._elevation= "level";
	PageEditor.prototype.defaultCss._emptyCells= "hide";
	PageEditor.prototype.defaultCss._cssFloat= "none"; 
	PageEditor.prototype.defaultCss._float= "none"; 
//	PageEditor.prototype.defaultCss._font= "10pt";
	PageEditor.prototype.defaultCss._fontFamily= "Verdana, Arial, Helvetica, sans-serif";
	PageEditor.prototype.defaultCss._fontSize= "10pt"; 
	PageEditor.prototype.defaultCss._fontSizeAdjust= "none";
	PageEditor.prototype.defaultCss._fontStretch= "normal";
	PageEditor.prototype.defaultCss._fontStyle= "normal";
	PageEditor.prototype.defaultCss._fontVariant= "normal";
	PageEditor.prototype.defaultCss._fontWeight= ""; 
	PageEditor.prototype.defaultCss._height= "auto";
	PageEditor.prototype.defaultCss._left= "auto";
	PageEditor.prototype.defaultCss._letterSpacing= "normal"; 
	PageEditor.prototype.defaultCss._lineHeight= "normal";
	PageEditor.prototype.defaultCss._listStyle= "disc outside none";
	PageEditor.prototype.defaultCss._listStyleImage= "none";
	PageEditor.prototype.defaultCss._listStylePosition= "outside";
	PageEditor.prototype.defaultCss._listStyleType= "disc"; 
	PageEditor.prototype.defaultCss._margin= "auto auto auto auto";
	PageEditor.prototype.defaultCss._marginTop= "auto";
	PageEditor.prototype.defaultCss._marginRight= "auto";
	PageEditor.prototype.defaultCss._marginBottom= "auto";
	PageEditor.prototype.defaultCss._marginLeft= "auto";
	PageEditor.prototype.defaultCss._markerOffset= "auto";
	PageEditor.prototype.defaultCss._marks= "none";
	PageEditor.prototype.defaultCss._maxHeight= "none";
	PageEditor.prototype.defaultCss._maxWidth= "none"; 
	PageEditor.prototype.defaultCss._minHeight= "0"; /*
PageEditor.prototype.defaultCss._minWidth= ""; */
	PageEditor.prototype.defaultCss._orphans= "2";
	PageEditor.prototype.defaultCss._outline= "none";
	PageEditor.prototype.defaultCss._outlineColor= "invert";
	PageEditor.prototype.defaultCss._outlineStyle= "none";
	PageEditor.prototype.defaultCss._outlineWidth= "medium";
	PageEditor.prototype.defaultCss._overflow= "hidden"; 
	PageEditor.prototype.defaultCss._padding= "0 0 0 0";
	PageEditor.prototype.defaultCss._paddingTop= "0";
	PageEditor.prototype.defaultCss._paddingRight= "0";
	PageEditor.prototype.defaultCss._paddingBottom= "0";
	PageEditor.prototype.defaultCss._paddingLeft= "0";
	PageEditor.prototype.defaultCss._page= "";
	PageEditor.prototype.defaultCss._pageBreakAfter= "auto"; 
	PageEditor.prototype.defaultCss._pageBreakBefore= "auto";
	PageEditor.prototype.defaultCss._pageBreakInside= "auto";
	PageEditor.prototype.defaultCss._pitch= "medium";
	PageEditor.prototype.defaultCss._pitchRange= "50";
	PageEditor.prototype.defaultCss._position= "relative";
	PageEditor.prototype.defaultCss._right= "auto"; 
	PageEditor.prototype.defaultCss._size= "auto"; 
	PageEditor.prototype.defaultCss._styleFloat= "none";
	PageEditor.prototype.defaultCss._tableLayout= "auto"; /*
	PageEditor.prototype.defaultCss._textAlign= ""; */
	PageEditor.prototype.defaultCss._textDecoration= "none";
	PageEditor.prototype.defaultCss._textIndent= "0"; 
	PageEditor.prototype.defaultCss._textShadow= "none"; 
	PageEditor.prototype.defaultCss._textTransform= "none"; 
	PageEditor.prototype.defaultCss._top= "auto";
	PageEditor.prototype.defaultCss._unicodeBidi= "normal"; 
	PageEditor.prototype.defaultCss._verticalAlign= "baseline";
	PageEditor.prototype.defaultCss._visibility= "inherit";
	PageEditor.prototype.defaultCss._whiteSpace= "normal";
	PageEditor.prototype.defaultCss._widows= "2";
	PageEditor.prototype.defaultCss._width= "auto";
	PageEditor.prototype.defaultCss._wordSpacing= "normal";
	PageEditor.prototype.defaultCss._zIndex= "999"; 
/*	PageEditor.prototype.defaultCss._MozAppearance= "";
	PageEditor.prototype.defaultCss._MozBackgroundClip= "";
	PageEditor.prototype.defaultCss._MozBackgroundInlinePolicy= "";
	PageEditor.prototype.defaultCss._MozBackgroundOrigin= "";
	PageEditor.prototype.defaultCss._MozBinding= ""; */
	PageEditor.prototype.defaultCss._MozBorderBottomColors= "transparent";
	PageEditor.prototype.defaultCss._MozBorderLeftColors= "transparent";
	PageEditor.prototype.defaultCss._MozBorderRightColors= "transparent";
	PageEditor.prototype.defaultCss._MozBorderTopColors= "transparent"; /*
	PageEditor.prototype.defaultCss._MozBorderRadius= "";
	PageEditor.prototype.defaultCss._MozBorderRadiusTopleft= "";
	PageEditor.prototype.defaultCss._MozBorderRadiusTopright= "";
	PageEditor.prototype.defaultCss._MozBorderRadiusBottomleft= "";
	PageEditor.prototype.defaultCss._MozBorderRadiusBottomright= "";
	PageEditor.prototype.defaultCss._MozBoxAlign= "";
	PageEditor.prototype.defaultCss._MozBoxDirection= "";
	PageEditor.prototype.defaultCss._MozBoxFlex= "";
	PageEditor.prototype.defaultCss._MozBoxOrient= "";
	PageEditor.prototype.defaultCss._MozBoxOrdinalGroup= "";
	PageEditor.prototype.defaultCss._MozBoxPack= "";
	PageEditor.prototype.defaultCss._MozBoxSizing= "";
	PageEditor.prototype.defaultCss._MozColumnCount= "";
	PageEditor.prototype.defaultCss._MozColumnWidth= "";
	PageEditor.prototype.defaultCss._MozColumnGap= "";
	PageEditor.prototype.defaultCss._MozFloatEdge= "";
	PageEditor.prototype.defaultCss._MozForceBrokenImageIcon= "";
	PageEditor.prototype.defaultCss._MozImageRegion= "";
	PageEditor.prototype.defaultCss._MozMarginEnd= "";
	PageEditor.prototype.defaultCss._MozMarginStart= ""; */
	PageEditor.prototype.defaultCss._MozOpacity= "1"; 
	PageEditor.prototype.defaultCss._MozOutline= "none";
	PageEditor.prototype.defaultCss._MozOutlineColor= "invert"; /*
	PageEditor.prototype.defaultCss._MozOutlineRadius= "";
	PageEditor.prototype.defaultCss._MozOutlineRadiusTopleft= "";
	PageEditor.prototype.defaultCss._MozOutlineRadiusTopright= "";
	PageEditor.prototype.defaultCss._MozOutlineRadiusBottomleft= "";
	PageEditor.prototype.defaultCss._MozOutlineRadiusBottomright= ""; */
	PageEditor.prototype.defaultCss._MozOutlineStyle= "none";
	PageEditor.prototype.defaultCss._MozOutlineWidth= "medium"; /*
	PageEditor.prototype.defaultCss._MozOutlineOffset= "";
	PageEditor.prototype.defaultCss._MozPaddingEnd= "";
	PageEditor.prototype.defaultCss._MozPaddingStart= "";
	PageEditor.prototype.defaultCss._MozUserFocus= "";
	PageEditor.prototype.defaultCss._MozUserInput= "";
	PageEditor.prototype.defaultCss._MozUserModify= "";
	PageEditor.prototype.defaultCss._MozUserSelect= ""; */
	PageEditor.prototype.defaultCss._opacity= "1"; /*
	PageEditor.prototype.defaultCss._outlineOffset= "";*/
	PageEditor.prototype.defaultCss._overflowX= "hidden";
	PageEditor.prototype.defaultCss._overflowY= "hidden";  
	/*--------------------------------------------------------------------------------------*/