/**
TagProcessor.js
Copyright (c)2004 Gabriel Harrison, Organic Inc
All Rights Reserved
**/

function TagProcessor()
{
	// This property contains all the registered tags to process as well as
	// their custom attributes and processing methods. The property is an
	// object with key's that represent arrays of custom attributes and methods
	// where the key name is equal to the tag name. For example:
	//		this.tags['a'][this.tags['a'].length] = {attr:...,method:...};
	this.tags = new Object();

	// This property contains all the registered ids to process as well as
	// their custom attributes and processing methods. The property is an
	// object with key's that represent arrays of custom attributes and methods
	// where the key name is equal to the tag name. For example:
	//		this.tags['a'][this.tags['a'].length] = {attr:...,method:...};
	this.ids = new Object();
	
	// This function takes a HTML tag name (a,span,div,etc...), a customized
	// attribute name that will be used in the HTML (<img swapOnClick="...")
	// and finally the processing method that is called on any tags found to
	// have the supplied attribute. This callback method should expect the
	// signature of:
	// 		function(tag,attribute)
	// 			- where tag is from a call to document.getElementsByTagName
	//			- and attribute is from tag.attributes[attributeName]
	this.register = function(tagName,attrName,callbackMethod)
	{
		if(!tagName.indexOf(','))
		{
			var items = tagName.split(',');
			for(var i = 0; i < items.length; i++)
				this.register(items[i],attrName,callbackMethod);
			return;
		}
		
		if(!this.tags[tagName]) 
			this.tags[tagName] = new Array();
	
		this.tags[tagName][this.tags[tagName].length] = 
			{attr:attrName,method:callbackMethod};
	}

	// This function takes a HTML tag name (a,span,div,etc...), a customized
	// attribute name that will be used in the HTML (<img swapOnClick="...")
	// and finally the processing method that is called on any tags found to
	// have the supplied attribute. This callback method should expect the
	// signature of:
	// 		function(tag,attribute)
	// 			- where tag is from a call to document.getElementsByTagName
	//			- and attribute is from tag.attributes[attributeName]
	this.registerId = function(idName,attrName,callbackMethod)
	{
		if(!idName.indexOf(','))
		{
			var items = idName.split(',');
			for(var i = 0; i < items.length; i++)
				this.registerId(items[i],attrName,callbackMethod);
			return;
		}
		
		if(!this.ids[idName]) 
			this.ids[idName] = new Array();
	
		this.ids[idName][this.ids[idName].length] = 
			{attr:attrName,method:callbackMethod};
	}
	
	// This function procedes to search through all available tags returned
	// by calling document.getElementsByTagName() for each of the registered
	// tag types and processing each custom attribute for each of the returned
	// tags.
	this.process = function()
	{
		var attr, attrName, elems, elem, id, key, method, failed=true, tagType;
		
		for(tagType in this.tags)
		{
			elems = document.getElementsByTagName(tagType);
			for(id = 0; id < elems.length; id++)
			{
				for(var i = 0; i < this.tags[tagType].length; i++)
				{
					attrName	= this.tags[tagType][i].attr;
					method		= this.tags[tagType][i].method;
					
					if(typeof elems[id].attributes[attrName] == 'undefined')
					{
						attrName = attrName.toLowerCase();
						for(var a = 0,len = elems[id].attributes.length; a < len; a++)
                        {
                            var attribute = elems[id].attributes[a]
							if(attribute && attribute.name && attribute.name.toLowerCase() == attrName)
								attr = elems[id].attributes[a];
                            else {failed = true; break;}
                        }
                        if(failed && elems[id].getAttribute)
                            attr = {value:elems[id].getAttribute(attrName)};
					}
					else attr = elems[id].attributes[attrName];
				
					if(elems[id].getAttribute(attrName))	
						method(elems[id], attr);
				}
			}					
		}				
	}
	
	// This function procedes to search through all available tags returned
	// by calling document.getElementById() for each of the registered
	// tag types and processing each custom attribute for each of the returned
	// tags.
	this.processIds = function()
	{
		var attr, attrName, elems, elem, id, key, method, id;
		
		for(id in this.ids)
		{
			elem = document.getElementById(id);
			
			if(elem) for(var i = 0; i < this.ids[id].length; i++)
			{
				attrName	= this.ids[id][i].attr;
				method		= this.ids[id][i].method;
				
				if(!elem.attributes[attrName])
				{
					attrName = attrName.toLowerCase();
					for(var a = 0; a < elem.attributes.length; a++)
						if(elem.attributes[a].name.toLowerCase() == attrName)
							attr = elem.attributes[a];
				}
				else attr = elem.attributes[attrName];
			
				if(elem.getAttribute(attrName))
					method(elem, attr);
			}
		}				
	}	
}
var tagProcessor = new TagProcessor();

function addEvent(object,event,method)
{
	// Create history of events object
	if(!object.attachedEvents)
		object.attachedEvents = new Array();
	
	// Store object reference to attached
	// events in the event that they are to
	// be later removed.
	object.attachedEvents[object.attachedEvents.length]
		= object.attachedEvents[event] = method;
	
	// Attach the event using whichever
	// browser supported method is available
	if(object.attachEvent)
		object.attachEvent('on'+event.toLowerCase(),method);
	else if(object.addEventListener)
		object.addEventListener(event.toLowerCase(),method,false);
}							

// Ensure the tags are processed once the page is loaded
addEvent(window,'load',function(){tagProcessor.process();tagProcessor.processIds();});
