/** 
  *  Support for all javascript extensions.
  *  @author Ivars Veksins
  */


// -- GARBAGE COLLECTOR -- 

/** 
  * Implementation of garbage collector. Collects DOM 
  * references and releases it on before unload. 
  * 
  * @author Ivars Veksins (ivarsv@gmail.com) 
  */
  
function Garbage() 
{ 
}

/** 
  * Initialise garbage collections of data to be destroyed 
  */
Garbage.init = function() 
{
	if (!window._OBJECTS_)  {
		
		// create storage array 
		window._OBJECTS_ = []; 
		window._FUNCTIONS_ = []; 
		window._EVENTS_ = []; 
		window._CLASSES_ = []; 
	}
}

/** 
  * Called before unload. Goes through all reference 
  * arrays and releases DOM elements. 
  */
Garbage.release = function() 
{
	if (!window._OBJECTS_) 
		return false; 
	
	// release events first. 
	Garbage.release_events(); 
	
	// release objects 
	for (var index in window._OBJECTS_) {
		var element = window._OBJECTS_[index]; 
		
		if (typeof element == "function") 
			continue; 
		
		window._OBJECTS_[index] = null; 
	}
	
	window._OBJECTS_ = null; 
	
	// delete all functions as well 
	for (var index in window._FUNCTIONS_) { 
		var funct = window._FUNCTIONS_[index]; 
		
		funct = null; 
	} 
	
	window._FUNCTIONS_ = null
	
	// call unload 
	for (var index in window._CLASSES_) {
		var cls = window._CLASSES_[index]; 

		if (cls.dispose)
			cls.dispose(); 
			
		window._CLASSES_[index] = null; 
	}
	
	window._CLASSES_ = null; 
	
	return true; 
}

/** 
  * Detaches all events installed using event_install 
  * function. 
  */
Garbage.release_events = function () 
{
	var events = window._EVENTS_; 

	for (var i = 0; i < events.length; i++) { 
		var event = events[i]; 

		detach_event(event[0],event[1],event[2]); 
	}
	
	window._EVENTS_ = null; 
}

/** 
  * Picks up an event to be released on before unload 
  * @argument DOM element event has to be attached to 
  * @argument name of the event i.e. onclick etc.. 
  * @argumetn f function to action on event 
  */
Garbage.push_event = function(obj, event, f) 
{ 
	// init storage arrays 
	Garbage.init(); 

	var length = window._EVENTS_.length; 
	window._EVENTS_[length] = [obj,event,f]; 
}

/** 
  * Collect garbage information about a single object 
  * specified in arguments. 
  */
Garbage.collect = function(obj) {
	
	// initialise garbage 
	Garbage.init(); 
	
	var func = this; 
	
	// populate objects array 
	var object_id = obj._OBJID; 
	if (!object_id) {
		// object id is the last item in the objects array 
		object_id = obj_OBJID = window._OBJECTS_.length;
		window._OBJECTS_ [object_id] = obj; 
	}
	
	// do the same stuff for functions 
	var funct_id = func._FUNCID; 
	if (!funct_id) {
		funct_id = func._FUNCID = window._FUNCTIONS_.length; 
		window._FUNCTIONS_[funct_id] = obj._FUNCT = func; 
	}

	if (!obj._CLOSURES) 	
		obj._CLOSURES = []; 
	
	var closure = obj._CLOSURES[funct_id]; 
	if (closure) 
		return closure; 
		
	// release 
	obj = func = null; 
	
	// Create the closure, store in cache and return result.
	return window._OBJECTS_[object_id]._CLOSURES[funct_id] = function() {
		// page unloaded 
		if (!window._FUNCTIONS_) 
			return; 
			
		return window._FUNCTIONS_[funct_id].apply(window._OBJECTS_[object_id], arguments);
	};	
}


// assign closure function to garbage collector
Function.prototype.garbage = Garbage.collect;	

/** 
  * Function for attaching events to a
  * DOM element. 
  */
function event_install(obj,event_name,f){

	if (obj.addEventListener){	//W3C
		obj.addEventListener(event_name.substr(2), f.garbage(obj),false);
	}else if (obj.attachEvent){	 //IE 
		obj.attachEvent(event_name,f.garbage(obj));
	}
	
	Garbage.push_event(obj, event_name, f); 
}

/** 
  * Detach event from the DOM object 
  */
function detach_event(obj,event_name, f){

	if (obj.removeEventListener) { 
		obj.removeEventListener(event_name.substr(2), f,false);
	} else if (obj.detachEvent) { 
		obj.detachEvent(event_name, f.garbage(obj)); 

	}
}

/** 
  * Extension to custom classes which will implement dispose 
  * method. This allows classes clean their data from memory before page is unloaded
  * 
  * Note that calls will be static 
  * 
  * @argument name of the class
  */
function IMPLEMENT_GARBAGE(f) {
	Garbage.init(); 
	window._CLASSES_[ window._CLASSES_.length ] = f; 
}

event_install(window,"onunload",Garbage.release); 


function displayFlash()
{
	document.write('<h1>Our values...</h1>\n');
	document.write('<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="800" height="40" id="ourValues">\n');
	document.write('<a href="?a=4356">');
	document.write('<param name="movie" value="../live/images/refresh/ourValues.swf">\n');
	document.write('<param name="quality" value="high">\n');
	document.write('<param name="wmode" value="transparent">\n');
	document.write('<img src="../live/images/refresh/ourValues.gif" width="800" height="40" alt="We put the needs of patients at the centre of everything we do. We continuously seek to improve the service we deliver to patients. Staff will support, respect and value each other." />\n');
	document.write('<embed src="../live/images/refresh/ourValues.swf" quality="high" width="800" height="40" name="ourValues" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" wmode="transparent"></embed>\n');
	document.write('</a>\n');
	document.write('</object>');
}
