// $ adds a # to the start of the string if its only alphanumeric, for backwards compatibility with old getElementById-based dollar functions
function $(a){ return document.querySelector((a.match(/[^A-z0-9_\-]/) ? '' : '#') + a); };
function $$(a){ return document.querySelectorAll(a); };

// addEvent manager - http://www.twinhelix.com/javascript/addevent/
if(typeof addEvent!='function'){var addEvent=function(o,t,f,l){var d='addEventListener',n='on'+t,rO=o,rT=t,rF=f,rL=l;if(o[d]&&!l)return o[d](t,f,false);if(!o._evts)o._evts={};if(!o._evts[t]){o._evts[t]=o[n]?{b:o[n]}:{};o[n]=new Function('e','var r=true,o=this,a=o._evts["'+t+'"],i;for(i in a){o._f=a[i];r=o._f(e||window.event)!=false&&r;o._f=null}return r');if(t!='unload')addEvent(window,'unload',function(){removeEvent(rO,rT,rF,rL)})}if(!f._i)f._i=addEvent._i++;o._evts[t][f._i]=f};addEvent._i=1;var removeEvent=function(o,t,f,l){var d='removeEventListener';if(o[d]&&!l)return o[d](t,f,false);if(o._evts&&o._evts[t]&&f._i)delete o._evts[t][f._i]}}


function object(o){
	var F = function(){};
	for (var i in o)
		F.prototype[i] = o[i];
	return new F();
};


// used to kill form submission via spec- rather than going _return false_ in your onsubmit handler, go _return killEvent(e)_
function killEvent(e){
 if (e && e.preventDefault)
    e.preventDefault(); // DOM style
  return false; // IE style
};


// fire event on element. Module is the createEvent module containing the event- defaults to HTMLEvents
function manualFireEvent(element, event, module){
	// all others not listed here are assumed to be in HtmlEvents
	var moduleMap = {
		'UIEevents' : 'DOMActivate,DOMFocusIn,DOMFocusOut,keydown,keypress,keyup',
		'MouseEvents' : 'click,mousedown,mousemove,mouseout,mouseover,mouseup',
		'MutationEvents' : ''
	};
	
	if (document.createEvent){ // ffx
		var evObj = document.createEvent(module || 'HTMLEvents');
		evObj.initEvent(event, true, false);
		element.dispatchEvent(evObj);
	}
	else if (document.createEventObject){ // IE
		element.fireEvent('on' + event);
	}
};
	
// clears a form's input fields
function clearForm(form){
	form.querySelectorAll('input,textarea,select').forEach(function(input){
		if (input.nodeName == 'SELECT')
			input.selectedIndex = 0;
		else if (input.nodeName == 'TEXTAREA')
			input.value = '';
		else if (input.getAttribute('type') == 'text' || input.getAttribute('type') == 'password' || input.getAttribute('type') == 'file')
			input.value = '';
		else if (input.getAttribute('type') == 'checkbox' || input.getAttribute('type') == 'radio')
			input.checked = 0;
	});
};


// Greg's cookie handler object
var cookies = {
  get: function (nameOfCookie){
    if (document.cookie.length > 0){
      begin = document.cookie.indexOf(nameOfCookie+"=");
      if (begin != -1){
        begin += nameOfCookie.length+1;
        end = document.cookie.indexOf(";", begin);
        if (end == -1) end = document.cookie.length;
          return unescape(document.cookie.substring(begin, end)); 
      }
    }
    return null;
  },
  set: function (nameOfCookie, value, expiredays, path){
    var ExpireDate = new Date ();
    ExpireDate.setTime(ExpireDate.getTime() + (expiredays * 24 * 3600 * 1000));
    document.cookie = nameOfCookie + "=" + escape(value) +
    ((expiredays == null) ? '' : '; expires=' + ExpireDate.toGMTString()) + '; path=' + (path || '/');
  },
  del: function (nameOfCookie){
    if (this.get(nameOfCookie))
      document.cookie = nameOfCookie + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/";
  }
};

var animate = {
	// smoothly moves an element to position pos
	slideTo : function(el, pos, inc, step){
		var that = this;
		if (!step || step < 0)
			step = 0;
		else if (step > 1)
			step = 1;
		
		// if increment isn't defined, figure it out on the fly based on how far the element needs to move (larger distance gives a smaller increment, so that the move takes longer for longer distances)
		if (!inc){
			//console.log(((pos.y !== false) ? Math.pow(parseInt(getComputedStyle(el, null).getPropertyValue('top')) - parseInt(pos.y), 2) : 0));
			var dist = Math.sqrt(((pos.x !== false) ? Math.pow(parseInt(domProperties.getStyle(el, 'left'),10) - parseInt(pos.x,10), 2) : 0) + ((pos.y !== false) ? Math.pow(parseInt(domProperties.getStyle(el, 'top'),10) - parseInt(pos.y,10), 2) : 0));
			inc = 1 / (0.0075 * dist + 2.5);
			//console.log(dist, inc);
		}
		
		if (pos.x !== false){
			a = parseInt(domProperties.getStyle(el, 'left'),10);
			a = a?a:0;
			el.style.left = Math.round((a - pos.x) * (1 - step * step) + pos.x) + 'px';
		}
		if (pos.y !== false){
			// Peter - fixed. was returning 'auto' which does not parseint as a number
			a = parseInt(domProperties.getStyle(el, 'top'),10);
			a = a?a:0;
			el.style.top = Math.round((a - pos.y) * (1 - step * step) + pos.y) + 'px';
		}
		if (step < 1){
			setTimeout(function(){
				that.slideTo(el, pos, inc, step + inc);
			}, 60);
		}
	},
	
	scrollTo : function(el, pos, inc, step){		
		// TODO - function to smoothly scroll to a position on the page

	}
};




// used by template fixers to get various dom properties
var domProperties = {
	viewportDim : function(){
		var r = {};
		if (self.innerHeight){ // all except Explorer
			r.x = self.innerWidth;
			r.y = self.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientHeight){ // Explorer 6 Strict Mode
			r.x = document.documentElement.clientWidth;
			r.y = document.documentElement.clientHeight;
		}
		else if (document.body){ // other Explorers
			r.x = document.body.clientWidth;
			r.y = document.body.clientHeight;
		}
		return r;
	},
	
	pageScroll : function(){
		var r = {};
		if (self.pageYOffset){ // all except Explorer
			r.x = self.pageXOffset;
			r.y = self.pageYOffset;
		}
		else if (document.documentElement && document.documentElement.scrollTop){
			// Explorer 6 Strict
			r.x = document.documentElement.scrollLeft;
			r.y = document.documentElement.scrollTop;
		}
		else if (document.body){ // all other Explorers
			r.x = document.body.scrollLeft;
			r.y = document.body.scrollTop;
		}
		return r;
	},
	
	elementDim : function(el){
		if (typeof el === 'string')
			el = $(el);
		
		return {'x' : el.offsetWidth, 'y' : el.offsetHeight};
	},
	
	elementPos : function(el){
		var curleft = curtop = 0;
		if (el.offsetParent){
			curleft = el.offsetLeft;
			curtop = el.offsetTop;
			while (el = el.offsetParent) {
				curleft += el.offsetLeft;
				curtop += el.offsetTop;
			}
		}
		return {'x' : curleft, 'y' : curtop};
	},
	
	getStyle : function(el,styleProp){
		if (el.currentStyle)
			return el.currentStyle[styleProp];
		else if (window.getComputedStyle)
			return document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
	}

};


/*
var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();
*/