/**
* ContentFrameworkFactory
*    handles management of contentframework objects
*    attaches editor functionality
*    handles interface behaviours
*    handles full screen image viewing
*
*  isAdmin
*  doKeyPress
*  getContentFrameworkId
*  setEditorFunction
*  addEditor
*  registerModuleType
*  registerBehaviours
*  addContentModule
*  registerContentObject
*  viewImage
*  resizeFrame
*  zoomImage
*  closeImage
*  getWindowHeight
*  getScroll
*  getPosition
*
*
* ContentFrameworkClass
*
**/

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); };

function ContentFrameworkFactory()
{
	var self = this;
	
	// Array of Registered Content Framework Objects
	ContentFrameworkFactory.prototype.contentobjects = new Object();
	
	// Incremental for Tracking Content Framework Objects
	var contentobjects_counter = 0;
	
	// Switch, is the editor loaded?
	var editorloaded = false;
	
	// Container for the fullscreen image view.
	var overview = null;
	var photoframe = null;
	
	// A couple of holders for image information.
	var photoScale = 100;
	var photoDimensions = null;
		
	// Information about the registered modules.
	var moduletypes = new Array();
	var components = new Array();
	var frameworktypes = new Array();
	
	// Something to do with groups & group sizes.
	ContentFrameworkFactory.prototype.modulegroups = new Object();
	
	// Switch, is the user an administrator?
	ContentFrameworkFactory.prototype.admin = false;	
	
	ContentFrameworkFactory.prototype.isIE = diva.isIE;

	ContentFrameworkFactory.prototype.isSafari = false;	
	
	ContentFrameworkFactory.prototype.isNetscape = false;	
	
		var userAgent = navigator.userAgent;
		
		if (userAgent)
		{
			userAgent = userAgent.toLowerCase();
			
			if (userAgent.indexOf('safari') != -1)
			{
				this.isSafari = true;
			}
			
			if (userAgent.indexOf('netscape') != -1)
			{
				this.isNetscape = true;
			}
						
		}
	
	// Switch, is the browser ajax enabled?
	ContentFrameworkFactory.prototype.ajax = false;
	this.ajax = Ajax.getTransport();
	if( this.ajax )
		this.ajax = true;
		
//	this.ajax = false;
	
	// Behaviours
	var myrules = {		
		
		'.cof-module-onchange-text' : function(el)
		{
			el.onkeypress = function(e)
			{
				var theEvent;
				var keyCode;
				
				if (e)
				{
					theEvent = e;
					keyCode = e.which;
				}
				else
				{
					theEvent = event;
					keyCode = event.keyCode;
				}			

				if ( (theEvent.ctrlKey && keyCode == 118) || (theEvent.ctrlKey && keyCode == 120) || (!theEvent.ctrlKey && keyCode >= 32 && keyCode <= 126) || (el.type == 'textarea' && keyCode == 13) )
					ContentObjectFactory.onChange( el );
					
				if( el.type == 'text' && keyCode == 13 )
					return false;
				
				return true;
			},
			
			el.onkeydown = function(e)
			{
				var keyCode;
				
				if (e)
				{
					keyCode = e.which;
				}
				else
				{
					keyCode = event.keyCode;
				}					

				if ( keyCode == 46)
					ContentObjectFactory.onChange( el );
				
				return true;
			}
		},	
		
		
		'.cof-module-onchange-click' : function(el)
		{	
			el.onclick = function()
			{			
				ContentObjectFactory.onChange( el );
				return true;
			}
		},		
		
		
		'.cof-module-onchange-file' : function(el)
		{	// not called by ajax version, see keypress.js for that
			el.onchange = function()
			{
				ContentObjectFactory.onChange( el );
				return true;
			}
		},
		
	
		'.cof-module-form' : function(el)
		{
			el.onsubmit = function()
			{
				if( el.action == null || el.action == '' )
					return false;
				else
					return true;
			}
		},
		
		'.cof-photo-pre-control' : function(el)
		{
			el.onfocus = function()
			{
				document.getElementById( 'cof_photo_zoom_out' ).focus();
			}
		},
		
		'.cof-photo-post-control' : function(el)
		{
			el.onfocus = function()
			{
				document.getElementById( 'cof_photo_close' ).focus();
			}
		},						
		
		'.cof-addmodule' : function(el)
		{
			el.onclick = function()
			{
				var cof_index = el.id.slice( el.id.lastIndexOf('_') + 1 );
				var newStr = el.id.slice( 0, el.id.lastIndexOf('_') );
				var type = newStr.slice( newStr.lastIndexOf('_') + 1 );
				
				var framework = self.getFrameworkFromIndex(cof_index)
				framework.createModule(type);
				
				return false;
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},	
		
		'.cof-photo-zoom-in' : function(el)
		{
			el.onclick = function()
			{
				self.zoomImage(-10);
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},	
		
		'.cof-photo-zoom-out' : function(el)
		{
			el.onclick = function()
			{
				self.zoomImage(10);
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},							
		
		'.cof-photo-close' : function(el)
		{
			el.onclick = function()
			{
				self.closeImage();
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},	
		
		'.cof-photo-frame' : function(el)
		{
			el.onclick = function()
			{
				self.closeImage();
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},	
		
		'.cof-savebutton' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
				var the_index = the_framework.getModuleIndexFromElement( el );
				the_framework.goSave( the_index );	
				return false;	
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},
		
		'.cof-createbutton' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
				var the_index = the_framework.getModuleIndexFromElement( el );
				return the_framework.goCreate( the_index );	
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},		
		
		'.cof-cancelbutton' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId(el)];
				var the_index = the_framework.getModuleIndexFromElement(el);
				the_framework.goCancel(the_index);
				return false;	
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},		
		
		'.cof-inputtitle' : function(el)
		{
			el.onkeypress = function(e)
			{
				var keyCode;
				
				if (e)
				{
					keyCode = e.which;
				}
				else
				{
					keyCode = event.keyCode;
				}		

				if (keyCode == 13)
				{ 
					var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
					the_framework.goSaveTitle();		
					
					return false;
				}
				
				return true ;
			};
		},		
		
		'.cof-edittitle' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
				the_framework.goEditTitle();	
				return false;
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};
		},
		
		'.cof-savetitle' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
				the_framework.goSaveTitle();
				return false;
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};
		},				
		
		'.cof-upbutton' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
				var the_index = the_framework.getModuleIndexFromElement( el );
				the_framework.goUp( the_index );
				return false;	
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};			
		},
		
		'.cof-downbutton' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
				var the_index = the_framework.getModuleIndexFromElement( el );
				the_framework.goDown( the_index );
				return false;
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},

		
		'.cof-editbutton' : function(el)
		{
			el.onclick = function()
			{
				var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
				var the_index = the_framework.getModuleIndexFromElement( el );
				the_framework.goEdit( the_index );				
				return false;
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		},	
		
		'.cof-deletebutton' : function(el)
		{
			el.onclick = function()
			{
				if( confirm('Okay to delete this module?') )
				{
					var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
					var the_index = the_framework.getModuleIndexFromElement( el );
					the_framework.dropBlock( the_index );
					return false;
				}
				
				return false;
			},
			
			el.onkeypress = function(e)
			{
				return self.doKeyPress( el, e );
			};	
		}
	};
	
	
	/**
	* Sets the admin switch.
	**/
	ContentFrameworkFactory.prototype.isAdmin = function ()
	{
			this.admin = true;
	}	
	
	
	ContentFrameworkFactory.prototype.onChange = function (el)
	{
			var the_framework = self.contentobjects[self.getContentFrameworkId( el )];
			var the_index = the_framework.getModuleIndexFromElement( el );
			return the_framework.hasChanged( the_index );
	}		
	
	
	ContentFrameworkFactory.prototype.getModuleId = function (cof_index, the_index)
	{
		var contentObject = ContentObjectFactory.getFrameworkFromIndex(cof_index);
		return contentObject.modules[the_index]['module'];
	}	

	
	/**
	* Utility Function for Capturing 'Enter' as a 'click'.
	**/
	ContentFrameworkFactory.prototype.doKeyPress = function (el, e)
	{
		var keyCode;
		
		if (e)
		{
			keyCode = e.which;
		}
		else
		{
			keyCode = event.keyCode;
		}	

		if(keyCode == 13 || keyCode == 3)
		{ 
			el.onclick();
			return false;
		}
		
		return true ;
	}
	
	
	/**
	* Utility function for grabbing the content framework id of the child element.
	**/		
	ContentFrameworkFactory.prototype.getContentFrameworkId = function ( the_el )
	{
		while( the_el )
		{
			if( Element.hasClassName( the_el, 'cof-contentframework' ) )
				return the_el.id;
			
			the_el = the_el.parentNode;
		}
		
		return false;
	}			
	
	
	/**
	* Utility function for assigning the editor functions to the content framework objects.
	**/		
	ContentFrameworkFactory.prototype.setEditorFunction = function( the_name, the_function )
	{
		for (var i in this.contentobjects )
		{
			var the_object = this.contentobjects[i];
			the_object[the_name] = the_function;
		}
	}
	
	
	/**
	* Utility function for assigning the editor to the content framework objects.
	**/			
	ContentFrameworkFactory.prototype.addEditor = function()
	{
			for (var i in editorFuncs)
			  this.setEditorFunction( i, editorFuncs[i] );
	
			for (var i in this.contentobjects )
				this.contentobjects[i].createSortable();

			editorloaded = true;
	}
	
	
	ContentFrameworkFactory.prototype.createComponents = function ( type )
	{	
		if( window[type] && typeof window[type]['create'] == 'function' )
			window[type]['create']();		
			
		components[components.length] = type;
	}
	
	/**
	* Utility function for registering a module type with the content framework factory.
	**/		
	ContentFrameworkFactory.prototype.registerModuleType = function ( type, group )
	{
		moduletypes[moduletypes.length] = type;
		this.modulegroups[type] = group;
		
		if (!window[type]) window[type] = { };
	}
	
	
	/**
	* Utility function for registering custom module behaviours.
	**/			
	ContentFrameworkFactory.prototype.registerBehaviours = function ()
	{	
		for( var i = 0; i < components.length; i++ )
		{
			var moduleType = window[components[i]];
			
			if (typeof moduleType.getRules == 'function')
				this.addRules(moduleType.getRules());
		}
		
		var the_frameworks = new Array();
		
		while (frameworktypes.length > 0)
		{
			var ftype = frameworktypes.pop();

			if (the_frameworks[ftype])
				continue;
			else
			{
				var frameworkType = window[ftype];
				
				if (typeof frameworkType.getRules == 'function')
					this.addRules(frameworkType.getRules());
				
				the_frameworks[ftype] = true;
			}
		};
		
		Behaviour.register(myrules);
		Behaviour.apply();
	}
	
	
	/**
	*
	**/
	ContentFrameworkFactory.prototype.addRules = function (newrules)
	{	
		for (var ii in newrules)
			myrules[ii] = newrules[ii];
	}	
	

	/**
	* Calls the create module function of the parent content framework object.
	**/	
	ContentFrameworkFactory.prototype.addContentModule = function (el, type)
	{
		framework = this.contentobjects[this.getContentFrameworkId(el)];
		framework.createModule(type);
	}
	
	
	/**
	* Registers a Content Framework Object with the Content Framework Factory.
	**/	
	ContentFrameworkFactory.prototype.registerContentObject = function(c_id, c_type, c_title, c_div, c_url, c_rest )
	{
		var contentobject = new ContentFrameworkClass(contentobjects_counter, c_id, c_type, c_title, c_div, c_url, c_rest);
		
		this.contentobjects[c_div] = contentobject;
		
		frameworktypes.push(c_type);
		if (!window[c_type]) window[c_type] = new Object();
		
		contentobjects_counter++;
		
		return contentobject;
	}

	
	/**
	* Creates the fullscreen image viewer.
	**/	
	ContentFrameworkFactory.prototype.viewImage = function ( src, iheight, iwidth, icaption )
	{
		photoScale = 100;
		
		if( overview )
			self.closeImage();

		var the_body = document.getElementsByTagName( 'body' )[0];

		var el_pos = this.getPosition(the_body);
		var el_dim = Element.getDimensions(the_body);
		
		var top = this.getScroll() - el_pos.y;

		var marginis = 16;
		var borderis = 8;		

		if( this.getScroll() < el_pos.y )
			top = marginis;
		else
			top += marginis;
			
		if( iwidth > el_dim.width - marginis*2 - borderis*2 )
			el_dim.width = iwidth + marginis*2 + borderis*2;
		
		if( top + iheight > el_dim.height - marginis )
		{
			var diff = top + iheight - ( el_dim.height - marginis );
			if( top - diff >= marginis )
			{
				top = top - diff;
				el_dim.height += marginis*2;
			}
			else
			{
				// forget about it & resize our divs
				el_dim.height = iheight + marginis*2;
				top = marginis;
			}
		}
		else
		{
			var winHeight = this.getWindowHeight();
			if( winHeight )
				if( winHeight - marginis*2 > iheight )
				{
					if( this.getScroll() >= el_pos.y )
						top += ( winHeight - iheight - marginis ) / 2;
					else
					{
						var buf = el_pos.y - this.getScroll();
						if( (winHeight / 2) - buf >= (iheight / 2 + marginis ) )
						{
							top = (( winHeight - iheight) / 2) - buf;
						}
					}
				}
		}
		
		photoframe = Builder.node( 'div', { className:'cof-photo-frame', style:'float: left; z-index: 101; position: absolute; width:' + el_dim.width + 'px; height:' +  el_dim.height + 'px; top: 0px; left: 0px;' } );
		
		var content = Builder.node( 'div', { id:'cof_photo_content', className:'cof-photo-content', style:' z-index: 102; position: absolute; width: ' + iwidth + 'px; height: auto; top: ' + top + 'px; left:' + (el_dim.width - iwidth)/2 + 'px;' } );
		
		var image = Builder.node( 'img', { src: src, id:'cof_photo_image', className:'cof-photo-image' } );

		var controls = Builder.node( 'span', { id:'cof_photo_controls', className:'cof-photo-controls' } );
		
		var closer = Builder.node( 'button', { type: 'button', id:'cof_photo_close', className:'cof-photo-close cof-photo-button' } );
			closer.innerHTML = 'close';
			
		var saver = Builder.node( 'span', {type: 'button', className:'cof-photo-button'} );
			saver.innerHTML = '&nbsp;&nbsp;<a tabindex="1" class="cof-photo-save" href="' + src + '/download">save</a>';
			
		var zoomer = Builder.node( 'span', {className:'cof-photo-zoomer'} );
		
		var larger = Builder.node( 'button', {type: 'button', tabIndex: 1, className:'cof-photo-button cof-photo-button-zoom cof-photo-zoom-in' } );
			larger.innerHTML = 'zoomin';		
					
		var smaller = Builder.node( 'button', {type: 'button', tabIndex: 1, id:'cof_photo_zoom_out', className:'cof-photo-button cof-photo-button-zoom cof-photo-zoom-out' } );
			smaller.innerHTML = 'zoomout';

		
		zoomer.appendChild( larger );
		zoomer.appendChild( smaller );
		
		
		var prestub = Builder.node( 'button', {className:'cof-photo-hidden-control cof-photo-pre-control', tabIndex:1, style:'width: 1px;'} );
		var poststub = Builder.node( 'button', {className:'cof-photo-hidden-control cof-photo-post-control', tabIndex:1, style:'width: 1px;'} );
		
		controls.appendChild( prestub );
		
		controls.appendChild( closer );
		controls.appendChild( saver );
		controls.appendChild( zoomer );
		
		controls.appendChild( poststub );
		
		
		
		content.appendChild( controls );			
		content.appendChild( image );
		
		if( icaption != '' )
		{
			var caption = Builder.node( 'div', { style:'clear: both;' } );
			caption.innerHTML = unescape(icaption);
			content.appendChild( caption );	
		}
		else
		{
			var caption = Builder.node( 'div', { style:'clear:both;' } );
			content.appendChild( caption );	
		}
		
		overview = Builder.node( 'div', { style:'z-index: 100; overflow: visible; position: absolute; width:' + el_dim.width + 'px; height:' +  el_dim.height + 'px; top:' + el_pos.y +'px; left:' + el_pos.x +'px;' } );
		
		overview.appendChild( content );
		overview.appendChild( photoframe );
		
		
		var the_page = document.getElementById( 'pagebody' );
		the_page.appendChild( overview );
		
		Behaviour.apply();

		new Draggable(content,{ endeffect: null, starteffect: null, revert: ContentObjectFactory.resizeFrame, startEffect: null, stopEffect: null });
		
		this.resizeFrame();
		
		closer.tabIndex = 1;
		closer.focus();
	}
	
	
	/**
	* Updates the photo background.
	**/			
	
	ContentFrameworkFactory.prototype.resizeFrame = function ()
	{
		ContentObjectFactory.resizeFrameElement( photoframe );
	}
			
	ContentFrameworkFactory.prototype.resizeFrameElement = function ( the_el )
	{
		if( the_el.style )
		{
			var the_height = 0;
			var the_width = 0;
			
			
			if( ContentObjectFactory.isSafari )
			{
				the_height = document.body.scrollHeight;
				the_width = document.body.scrollWidth;
			}
			else if( window.innerHeight )
			{
				the_height = window.innerHeight;
				
				if( window.scrollMaxY )
					the_height += window.scrollMaxY;
					
				the_width = document.body.clientWidth;
				
				if( window.scrollMaxX )
					the_width += window.scrollMaxX;
				
			}
			else
			{
				var temp_el = null; 
				var the_parent = the_el.parentNode;
				
				for( var i = 0; i < the_parent.childNodes.length; i++ )
					if( the_parent.childNodes[i] != the_el )
					{
						temp_el = the_parent.childNodes[i];
						break;
					}
				
				var el_pos = ContentObjectFactory.getPosition( temp_el );
				var el_dims = Element.getDimensions( temp_el );
				
 				if( document.body.scrollHeight > document.body.offsetHeight )
 					the_height = document.body.scrollHeight;
 				else
 					the_height = document.body.offsetHeight;
 					
				if( document.body.scrollWidth > document.body.offsetWidth )
					the_width = document.body.scrollWidth;
				else
					the_width = document.body.offsetWidth; 					

 				if( el_pos.y + el_dims.height + 8 > the_height )
 					the_height = el_pos.y + el_dims.height + 8;
 					
 				if( el_pos.x + el_dims.width + 8 > the_width )
 					the_width = el_pos.x + el_dims.width + 8; 		
			}  

			Element.setStyle( the_el, { height: the_height + 'px' } );
			Element.setStyle( the_el, { width: the_width + 'px' } );
		}
	}
	
	
	/**
	* Handles the image zooming feature.
	**/		
	ContentFrameworkFactory.prototype.zoomImage = function ( magnification )
	{
		var controls_el = Element.getDimensions( 'cof_photo_controls' );
		var content_el = Element.getDimensions( 'cof_photo_content' );
		var image_el = Element.getDimensions( 'cof_photo_image' );		
		
		if( photoDimensions == null )
			photoDimensions = image_el;
		
		var newScale = photoScale - magnification;
		var newWidth = newScale / 100 * photoDimensions.width;
		var newHeight = newWidth * photoDimensions.height / photoDimensions.width;
		
		if( newWidth < controls_el.width )
			return;

		photoScale = newScale;

		Element.setStyle( 'cof_photo_content', { width: newWidth + 'px' } );
		Element.setStyle( 'cof_photo_image', { width: newWidth + 'px', height: newHeight + 'px' } );
		
		this.resizeFrame();
	}	
	
	
	/**
	* Closes the fullscreen image viewer.
	**/			
	ContentFrameworkFactory.prototype.closeImage = function ( el )
	{
		
		if( !overview )
			return;
			
		var the_parent = overview.parentNode;
		
		if( the_parent && overview )
			the_parent.removeChild( overview );
			
		photoDimensions = null;
		
		delete( overview );
		overview = null;
	}
	
	
	/**
	* Element Positioning Function for getting the window height.
	**/		
	ContentFrameworkFactory.prototype.getWindowHeight = function ()
	{
		var winH = window.innerHeight
							|| document.documentElement.clientHeight
							|| document.body.clientHeight
							|| 0;

		return winH;
	}  	
	
	ContentFrameworkFactory.prototype.getWindowWidth = function ()
	{
		var winW = window.innerWidth
							|| document.documentElement.clientWidth
							|| document.body.clientWidth
							|| 0;

		return winW;
	}

	/**
	* Element Positioning Function for getting the scroll position.
	**/		
	ContentFrameworkFactory.prototype.getScroll = function ()
	{
    var deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
                
    return deltaY;
	} 
	
	
	/**
	* Element Positioning Function for getting the element position.
	**/		
	ContentFrameworkFactory.prototype.getPosition = function (el)
	{
		var lx = 0;
		var ly = 0;
		
		while( el )
		{
			lx += el.offsetLeft;
			ly += el.offsetTop;
			
			el = el.offsetParent;
		}
		
		return {x:lx,y:ly};
	}	  	
	
	/**
	* 
	**/	
	ContentFrameworkFactory.prototype.jumpTo = function ( the_el )
	{
		document.getElementById( the_el ).focus();
		return false;
	}	
	
	ContentFrameworkFactory.prototype.getFrameworkFromId = function( the_id )
	{
		return this.contentobjects[ the_id ];
	}
	
	ContentFrameworkFactory.prototype.getFrameworkFromIndex = function( cof_index )
	{
		var result = false;
		
		for( var i in this.contentobjects )
		{
			if( this.contentobjects[i].getContentIndex && this.contentobjects[i].getContentIndex() == cof_index )
			{
				result = this.contentobjects[i];
				break;
			}
		}

		return result;
	}
	
	
	ContentFrameworkFactory.prototype.getViewportHeight = function()
	{
		if( window.innerHeight )
			return window.innerHeight;
		else
		{
//			alert( 'document.documentElement.scrollHeight: ' + document.documentElement.scrollHeight );
//			alert( 'document.body.offsetHeight: ' + document.body.offsetHeight );
//			alert( 'document.documentElement.offsetHeight: ' + document.documentElement.offsetHeight );
			return document.documentElement.offsetHeight;
			
//			Element.setStyle( document.body, { height: '100%' } );
//			var result = document.body.clientHeight;
//			Element.setStyle( document.body, { height: 'auto' } );
//			return result;
		}
	}	
	
	ContentFrameworkFactory.prototype.getViewportWidth = function()
	{
		if( window.innerWidth )
			return window.innerWidth;
		else
		{
		//	Element.setStyle( document.body, { height: '100%' } );
		//	var result = document.body.clientWidth;
		//	Element.setStyle( document.body, { height: 'auto' } );
		//	return result;
			return document.body.clientWidth;
		}			
	}		
}


function ContentFrameworkClass( c_index, c_id, c_type, c_title, c_div, c_url, c_rest )
{
	// Content Object Index
	this.url = c_url;
	
	// Rest Interface
	this.rest = c_rest;
		
	// Content Object Index
	this.content_object_index = c_index;
	
	// The Content Object Title
	this.content_object_title = c_title;	
	
	// The id of the Content Object being manipulated.
	this.content_object_id = c_id;
	
	// Framework Type
	this.framework_type = c_type;		
	
	// module_container: The containing DIV's id wherein the modules lie.
	this.module_container = c_div;
	
	// modules: Hash entries containing the module information.
	this.modules      = new Object();
	
	// module_order: Array of keys(modules) in the sorted order they appear.
	this.module_order = new Array();
	
	// module_counter: Incremental sequence for creating unique keys(modules)
	this.module_counter  = 0;

	// limits the size of groups
	this.groupSizeLimit = new Object();
	
	// list of draggable objects
	this.theDraggables = new Array();
	
	// if we are moving modules around
	this.isMoving = false;	
	
	// if we are moving modules around
	this.isResizing = false;	
	this.refireResize = false;		
	
	// keeps track of the modules that are currently being loaded
	this.currentlyLoading = 0;
	
	ContentFrameworkClass.prototype.getModuleIdFromIndex = function ( the_index )
	{	
		return this.modules[the_index]['module'];
	};	
	
	ContentFrameworkClass.prototype.getContentIndex = function ()
	{	
		return this.content_object_index;
	};
	
	ContentFrameworkClass.prototype.getRestInterface = function ()
	{	
		return this.rest;
	};	
	
	ContentFrameworkClass.prototype.getUrl = function ()
	{	
		return this.url;
	};		
	
	ContentFrameworkClass.prototype.registerModule = function ( mod_id, mod_type, the_index )
	{
		this.module_counter++;
		
 		this.modules[the_index] = new Object();
		this.modules[the_index]['module'] = mod_id;
		this.modules[the_index]['isEdit'] = false;
		this.modules[the_index]['hasChanged'] = false;
		this.modules[the_index]['type'] = mod_type;
		
		this.module_order.push(the_index);
	};
	
	ContentFrameworkClass.prototype.fixViewer = function(the_index)
	{
		var viewcontrols = document.getElementById( 'cof_module_header_view_box_' + this.content_object_index + '_' + the_index );		
		if( viewcontrols )
			this.fixDragButton(viewcontrols);
	}

	ContentFrameworkClass.prototype.activateViewers = function ()
	{
		var i = 1;
		while( this.modules[i] )
		{
			if( this.modules[i]['isEdit'] == false )
				this.invokeEvent(i, 'viewerLoaded');
			
			this.fixViewer( i );
				
			i++;
		}
		
		var self = this;
		Event.observe(window, 'resize', function() { self.resizeFramework(); } );
	};	
	
	ContentFrameworkClass.prototype.fixDragButton = function( controls )
	{
		var spans = controls.getElementsByTagName( 'span' );
		var dragspan = null;
		for( var i = 0; i < spans.length; i++ )
			if( Element.hasClassName( spans[i], 'cof-dragbutton' ) )
			{
				dragspan = spans[i];
				break;
			}

		if( dragspan )
		{
			var theButtons = controls.getElementsByTagName( 'button' );
			if( theButtons.length )
			{
				var buttondims = Element.getDimensions( theButtons[0] );
				Element.setStyle( dragspan, { height: (buttondims.height - 11) + 'px' } );
			}
		}
	}	
	
	ContentFrameworkClass.prototype.resizeFramework = function ()
	{
		if( !this.isResizing )
		{
			this.isResizing = true;
			var i = 1;
			while( this.modules[i] )
			{
				if( this.modules[i]['isEdit'] == false )
					this.invokeEvent(i, 'resizeViewer');
				else
				{
						var editcontrols = document.getElementById( 'cof_module_header_edit_controls_' + this.content_object_index + '_' + i );	
	
						if( editcontrols )
						{
							Element.setStyle( editcontrols.parentNode, { height: '1%' } );		
							Element.setStyle( editcontrols, { position: 'absolute' } );		
							this.fixEditControls( i );
						}
	
					this.invokeEvent(i, 'resizeEditor');
				}
					
				i++;
			}
			
			this.isResizing = false;
			
			if( this.refireResize )
			{
				this.refireResize = false;
				this.resizeFramework();
			}
		}
		else
			this.refireResize = true;
	};	
	
	ContentFrameworkClass.prototype.invokeEvent = function (moduleIndex, eventName)
	{
		var moduleResult = true, frameworkResult = true;
		
		if( moduleIndex != null )
		{
			var moduleType = window[this.modules[moduleIndex]['type']];
			
			if (typeof moduleType[eventName] == 'function')
			{
				var callResult = moduleType[eventName](this.content_object_index, moduleIndex);
				if (callResult != null) moduleResult = callResult;
			}
		}
		
		var frameworkType = window[this.framework_type];
		if (typeof frameworkType[eventName] == 'function')
		{
			var callResult = frameworkType[eventName](this.content_object_index, moduleIndex);
			if (callResult != null) frameworkResult = callResult;
		}
		
		var r = [moduleResult, frameworkResult];
		return r;
	};
}

// Create the obligatory Content Framework Factory Object
ContentObjectFactory = new ContentFrameworkFactory();


function ContentFrameworkUploadObject()
{
	ContentFrameworkUploadObject.prototype.onKeyPress = function (e)
	{
		var theEvent;
		var theTarget;
		var keyCode;
		
		if (e)
		{
			theEvent = e;
			keyCode = e.which;
		}
		else
		{
			theEvent = event;
			keyCode = event.keyCode;
		}	
		
		if (theEvent.target)
		{
			theTarget = theEvent.target;
		}
		else
		{
			theTarget = theEvent.srcElement;
		}		
		
		if ( (theEvent.ctrlKey && keyCode == 118) || (theEvent.ctrlKey && keyCode == 120) || (!theEvent.ctrlKey && keyCode >= 32 && keyCode <= 126) )
		{
			this.showChange( theTarget );
		}
			
		return true;
	}
	
	ContentFrameworkUploadObject.prototype.showChange = function (theTarget)
	{
			var the_string = theTarget.id;		
			
			var tindex = null;
			
			tindex = the_string.lastIndexOf('_');
			
			the_string = the_string.substr( 0, tindex );
			
			tindex = the_string.lastIndexOf('_');
			
			var the_index = the_string.substring(tindex+1,the_string.length);
			
			the_string = the_string.substr( 0, tindex );
			
			tindex = the_string.lastIndexOf('_');
			
			var cof_index = the_string.substring(tindex+1,the_string.length);
	
			var the_framework = ContentObjectFactory.getFrameworkFromIndex(cof_index);
			the_framework.hasChanged( the_index );
	}
	
	
	ContentFrameworkUploadObject.prototype.onFileChange = function (e)
	{
		var theEvent = null;
		var theTarget = null;

		if (e)
		{
			theEvent = e;
		}
		else
		{
			theEvent = event;
		}
		
		if (theEvent.target)
		{
			theTarget = theEvent.target;
		}
		else
		{
			theTarget = theEvent.srcElement;
		}		

		this.showChange( theTarget );
			
		return true;
	}
}

ContentFrameworkUpload = new ContentFrameworkUploadObject();


function getNextTabIndex( the_el, the_tabindex )
{
	var the_parent = the_el.parentNode;
	
	if( !the_parent )
		return false;
		
	var found = false;

	for( var i = 0; i < the_parent.childNodes.length; i++ )
	{
		if( !found )
		{
			if( the_parent.childNodes[i] == the_el )
				found = true;
		}
		else
		{
			var new_el = the_parent.childNodes[i];
			
			if( new_el.tabIndex && new_el.tabIndex == the_tabindex )
				return new_el;
			else if( new_el.childNodes && new_el.childNodes.length > 0 )
			{
				var result = checkChildrenForTabIndex( new_el, the_tabindex );
				
				if( result )
					return result;
			}
		}
	}

	// okay, didn't find anything in the parent element, so call this funcion on it's parent
	return getNextTabIndex( the_parent, the_tabindex );
}

function checkChildrenForTabIndex( the_el, the_tabindex )
{
	for( var i = 0; i < the_el.childNodes.length; i++ )
	{
		var new_el = the_el.childNodes[i];
		
		if( new_el.tabIndex && new_el.tabIndex == the_tabindex )
			return new_el;
		else if( new_el.childNodes && new_el.childNodes.length > 0 )
		{
			var result = checkChildrenForTabIndex( new_el, the_tabindex );
			
			if( result )
				return result;
		}
	}
	
	return false;
}

if( ContentObjectFactory.isNetscape )
{
	document.getElementsByClassName = function(className, parentElement) 
	{
		var the_parent = null;
		
		if(parentElement)
		{
			if( typeof(parentElement) == 'object' )
				the_parent = parentElement;
			else
				the_parent = $(parentElement);
		}
		else
		{
			the_parent = document.body;
		}
		
		var the_children = new Array();
		var the_results = new Array();

		if( Element.hasClassName( the_parent, 'flash-container' ) )
			return the_children;
		else	
		 	the_children = the_parent.childNodes;
	
		for( var i = 0; i < the_children.length; i++ )
		{
			var the_child = the_children[i];
			
			if( the_child.className )
		    if(the_child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
		      the_results.push(Element.extend(the_child));
	
	
			if( the_child.childNodes && the_child.childNodes.length > 0 )
			{	
				var child_results = document.getElementsByClassName( className, the_child );
	
				for( var ii = 0; ii < child_results.length; ii++ )
					the_results.push(child_results[ii]);
			}
		}
	
		return the_results;
	}
}

