(function() {
  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
     Matthias Miller, Dean Edwards and John Resig.
     NB: This has been modified to work with the s3core includer class.
     This section of code is also found in prototype.js and MUST be REMOVED! */

  var timer;

  function fireContentLoadedEvent() {
    if (document.loaded) return;
    if (timer) window.clearInterval(timer);
    document.fire("dom:loaded");
    document.loaded = true;
  }

  if (document.addEventListener) {
    if (Prototype.Browser.WebKit) {
//      timer = window.setInterval(function() {
//        if (/loaded|complete/.test(document.readyState))
//          fireContentLoadedEvent();
//      }, 0);

      Event.observe(window, "load", fireContentLoadedEvent);

    } else {
      document.addEventListener("DOMContentLoaded",
        fireContentLoadedEvent, false);
    }

  } else {
    document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
    $("__onDOMContentLoaded").onreadystatechange = function() {
      if (this.readyState == "complete") {
      	if (s3core.includeHandler!==false)
      	{
      		if (!s3core.includeHandler.working)
      		{
      			this.onreadystatechange = null;
       			fireContentLoadedEvent();
      		}
      	}
        else
        {
        	this.onreadystatechange = null;
       		fireContentLoadedEvent();
        }
      }
    };
  }
})();
Object.extend
(
	Array.prototype,
	{
		in_array: function(needle)
		{
			return (this.find
			(
				function(iteration)
				{
					return (needle==iteration)?true:false;
				}
			)!=undefined)?true:false;
		},
		ksort: function (sort_flags)
		{
			// function adopted from same-named @ http://kevin.vanzonneveld.net
			// +   modified by: Peter Mason, Timothy Chandler (http://www.petim.com.au)
			// *     example 1: data = {2: 'van', 3: 'Zonneveld', 1: 'Kevin'}; 
			// *     example 1: ksort(data);
			// *     results 1: data == {1: 'Kevin', 2: 'van', 3: 'Zonneveld'}
			// *     returns 1: true
			var that = [], keys = [], key_num = 0, key = '', value = '', i = 0, j = 0; 
			var sorter = false//, array = false;
			
			// For now only SORT_NUMERIC has a custom sorter
			// and SORT_REGULAR, SORT_STRING, and SORT_LOCALE_STRING
			// are all handled with the default sorter 
			if (sort_flags == 'SORT_NUMERIC') {
				sorter = function (a, b) {
					return(a - b);
				};
			}
			// Make a list of key names
			this.each
			(
				function(item)
				{
					if(item.key) keys[key_num++] = item.key;
					that[that.length]=Object.clone(item);
					return;
				}
			);
			// Sort key names
			if (sorter !== false) 
			{
				keys = keys.sort(sorter);
			} 
			else 
			{
				keys = keys.sort();
			}
			
			// Rebuild array with sorted keynames
			for (var i = 0; i < key_num; i++)
			{
				key = keys[i];
				value = '';
				for (var j = 0; j < key_num; j++)
				{
					if(that[j].key==key)
					{
						value=that[j].value;
						break;
					}
				}
				this[i].key=key;
				this[i].value=value;
			}
			that=null;
			return; // tmp_arr; 
		},
		getSelected: function()
		{
			var $return=[];
			if (this)
			{
				if(this.length==1)
				{
					if(this[0].tagName.toLowerCase()=='option')
					{
						if (this[0].selected) $return[0]=this[0];
					}
					else if(this[0].type=='checkbox' || this[0].type=='radio')
					{
						if(this[0].checked) $return[0]=this[0];
					}
				}
				else
				{
					$return=this.findAll
					(
						function(element)
						{
							if (element.tagName.toLowerCase()=='option')
							{
								if (element.selected)return true;
							}
							else
							{
								switch (element.type)
								{
									case 'checkbox':
									case 'radio':		if (element.checked)return true;	break;
								}
							}
							return false;
						}
					);
				}
			}
			return $return;
		},
		getSelectedValues: function()
		{
			var $return=[];
			if (this)
			{
				if(this.length==1)
				{
					if(this[0].tagName.toLowerCase()=='option')
					{
						if (this[0].selected) $return[0]=this[0].value;
					}
					else if(this[0].type=='checkbox' || this[0].type=='radio')
					{
						if(this[0].checked) $return[0]=this[0].value;
					}
				}
				else
				{
					this.each
					(
						function(element)
						{
							if (element.tagName.toLowerCase()=='option')
							{
								if (element.selected)return $return.unshift(element.value);
							}
							else
							{
								switch (element.type)
								{
									case 'checkbox':
									case 'radio':		if (element.checked)return $return.unshift(element.value);	break;
								}
							}
							return false;
						}
					);
				}
			}
			return $return;
		},
		getNumSelected: function()
		{
			return this.getSelected().length;
		},
		//Overwrite Prototype's without function so that it can accept an array.
		without: function()
		{
			if (Object.isArray(arguments[0]))
			{
				var values=$A(arguments[0]);
				return this.select
				(
					function(value)
					{
						return !values.include(value);
					}
				);
			}
			else
			{
				var values=$A(arguments);
				return this.select
				(
					function(value)
					{
						return !values.include(value);
					}
				);
			}
		}
	}
);
Form.Methods.getSelected=function(form,field)
{
	var $return=[];
	field=$$('#'+$(form).identify()+' *[[name="'+field+'"]') || false;
	if (field)
	{
		if (Object.isArray(field))
		{
			$return=field.findAll
			(
				function(element)
				{
					switch (element.type.toLowerCase())
					{
						case 'checkbox':
						case 'radio':		if (element.checked)return true;	break;
						case 'select':		if (element.selected)return true;	break;
					}
					return false;
				}
			);
		}
		else
		{
			switch (field.type.toLowerCase())
			{
				case 'checkbox':
				case 'radio':		if (field.checked)$return=field;	break;
				case 'select':		if (field.selected)$return=field;	break;
			}
		}
	}
	return $return;
}
Form.Methods.getNumSelected=function(form,field)
{
	return Form.Methods.getSelected(form,field).length;
}
Element.addMethods();
if (Prototype.Browser.IE)
{
	window.console=
	{
		log:	Prototype.emptyFunction(),
		debug:	Prototype.emptyFunction()
	}
}
var s3core=
{
	includeHandler:		false,
	include_once: function()
	{
		var args=[];
		for (var i=0,j=arguments.length; i<j; i++)args[i]=arguments[i];
		if (!this.includeHandler)this.includeHandler=new s3core._include();
		this.includeHandler.include_once(args);
		return this;
	},
	register_included: function()
	{
		var args=[];
		for (var i=0,j=arguments.length; i<j; i++)args[i]=arguments[i];
		if (!this.includeHandler)this.includeHandler=new s3core._include();
		this.includeHandler.register_inlcuded(args);
	},
	random: function(options)
	{
		var options=
		{
			min:	10,
			max:	20,
			chars:	$A($R(0,9)).concat($A($R('a','z')))
		}
		options=Object.extend(options,options);
		if (Object.isString(options.chars))
		{
			options.chars=$A(options.chars);
		}
		else if (Object.isNumber(options.chars))
		{
			eval('options.chars="'+options.chars+'"');
			options.chars=$A(options.chars);
		}
		var numChars=0;
		while (numChars<options.min)
		{
			numChars=Math.round(Math.random()*options.max);
		}
		var $return='';
		for (var i=0; i<numChars; i++)
		{
			$return+=options.chars[Math.round(Math.random()*options.chars.length)];
		}
		return $return;
	},
	template: function()
	{
		var args=[];
		for (var i=0; i<arguments.length; i++)args[i]=arguments[i];
		return new Template(args.join(''));
	},
	formatDisabledFieldLables: function()
	{
		$$('label input[disabled=disabled]').each
		(
			function(element)
			{
				element.up('label').addClassName('disabled');
				return true;
			}
		);
		return true;
	}
}
s3core._include=Class.create
(
	{
		included:		[],
		queue:			[],
		head:			$$('head')[0],
		working:		false,
		initialize:	function()
		{
			return;
		},
		include_once: function(args)
		{
			for (var i=0; i<args.length; i++)
			{
				if (Object.isArray(args[i]))
				{
					if (!this.included.in_array(args[i][0]))
					{
						this.queue[this.queue.length]=args[i];
						this.included[this.included.length]=args[i][0];
					}
				}
				else
				{
					if (!this.included.in_array(args[i]))
					{
						this.queue[this.queue.length]=args[i];
						this.included[this.included.length]=args[i];
					}
				}
			}
			if (!this.working)this.includeNext();
			return this;
		},
		register_inlcuded: function(args)
		{
			for (var i=0; i<args.length; i++)
			{
				if (!this.included.in_array(args[i]))
				{
					this.included[this.included.length]=args[i];
				}
			}
			return this;
		},
		includeNext: function()
		{
			if (this.queue.length)
			{
				this.working=true;
				var nextInclude=this.queue.shift();
				if (Object.isArray(nextInclude))
				{
					this._include(nextInclude[0],nextInclude[1]);
				}
				else
				{
					this._include(nextInclude);
				}
			}
			else
			{
				this.working=false;
			}
			return this;
		},
		_include: function(url,callback)
		{
			var id=s3core.random();
			//Opera and Safari require the callback method to be bound to the object before being appeneded to the page.
			if (Prototype.Browser.Opera || Prototype.Browser.WebKit)
			{
				var newScript=document.createElement('script');
				newScript.type='text/javascript';
				newScript.src=url;
				newScript.onload=function(url)
				{
					if (Object.isFunction(callback))callback();
					this.includeNext();
					return;
				}.bind(this,url);
				this.head.appendChild(newScript);
			}
			//IE is "special" and requires a specific kick up the arse to work.
			else if (Prototype.Browser.IE)
			{
				var newScript=document.createElement('script');
				newScript.type='text/javascript';
				newScript.src=url;
				this.head.appendChild(newScript);
				newScript.onreadystatechange=function(event)
				{
					if (event.srcElement.readyState=='complete')
			        {
			            if (Object.isFunction(callback))callback();
			            this.includeNext();
			        }
			        else if (event.srcElement.readyState=='loaded')
			        {
			        	if (Object.isFunction(callback))callback();
			        	this.includeNext();
			        }
				}.bindAsEventListener(this);
			}
			else
			{
				this.head.insert
				(
					new Element
					(
						'script',
						{
							id:		id,
							type:	'text/javascript',
							src:	url
						}
					)
				);
				$(id).observe
				(
					'load',
					function(event)
					{
						if (Object.isFunction(callback))callback();
						this.includeNext();
						return;
					}.bindAsEventListener(this)
				);
			}
			return;
		}
	}
);
