/*
	jaxx : javascript asynchronous xml & xslt
	v0.89 beta (as in not yet feature complete)
	
	Copyright (c) 2006 WebEffekt.no
	Licensed under the MIT License:
	http://www.opensource.org/licenses/mit-license.php

	Inspired/based on the work of:
	prototype.conio.net		simon.incutio.com		jquery.com
	moofx.mad4milk.net		dean.edwards.name		erik.eae.ne
	
	Please send a mail to jaxx AT webeffekt . no if you find bugs
	or something that can be done in a smaller / faster way!
	
	More about jaxx on http://jaxx.WebEffekt.no
	
*/

if (!String.trim) String.prototype.trim = function(){
	//trimms left and right whitspace on strings
	return this.replace(/^\s+|\s+$/g,'');
};

if (!window.XMLHttpRequest && window.ActiveXObject) var XMLHttpRequest = function(){
	//XMLHttpRequest wrapper for ie browsers that do not support XMLHttpRequest nativly
	return new ActiveXObject(/MSIE 5/.test(navigator.userAgent) ? "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP");
};

if (!Function.bind) Function.prototype.bind = function(){
	//binds variables to a function callback
	var __m = this, args = $c(arguments), object = args.shift();
	return function(){ return __m.apply(object, args)}
};

if (!Function.bindE) Function.prototype.bindE = function(){
	//binds variables to a function callback, also includes variables when called (like event)
	var __m = this, args = $c(arguments), object = args.shift();
	return function(){ return __m.apply(object, $c(arguments).concat(args))}
};

if (!Array.indexOf) Array.prototype.indexOf = function(sE, sI){
	//javascript 1.6: finds the first index that is like sE, sI is optional start index
	for (var i=sI||0,l=this.length;i<l;i++) if (this[i]==sE) return i;
	return -1;
};

if (!Array.forEach) Array.prototype.forEach = function(cB, tO){
	//javascript 1.6: iterate thrue an array and calls cB on each iteration, t0 optionally overrides 'this'
	for (var i=0,l=this.length;i<l;i++) cB.call(tO,this[i],i,this);
};

if (!Array.filter) Array.prototype.filter = function(cB, tO){
	//javascript 1.6: filter return values of cB that evaluets to true, t0 optionally overrides 'this'
	for(var i=0,r=[],l=this.length;i<l;i++) cB.call(tO,this[i],i,this) && r.push(this[i]);
	return r;
};

if (!Array.map) Array.prototype.map = function(cB, tO){
	//javascript 1.6: maps the return value of a callback function, t0 optionally overrides 'this'
	for(var i=0,r=[],l=this.length;i<l;i++) r[i] = cB.call(tO,this[i],i,this);
	return r;
};


/* --------------- jaxx.Common --------------- */
function $ext(dest, props){
	//extends an dest object with object properties 
	for (prop in props || {}) dest[prop] = props[prop];
	return dest;
}

function $strippAnonymous(fc){
	//Stripps anonymous wrapper functions
	if (!fc) return null;
	var str = fc.toString();
	if (str.indexOf('anonymous') === -1) return fc;
	else return str.match(/function anonymous\(\)\n\{\n(.*)\n\}/gi) ?  RegExp.$1 : str;
}

function $c(arr,s){
	//Creates an array out of anything, also support splitting strings
	var r=[], el;
	if (typeof arr != 'object' && arr.constructor != Object) arr = [arr];
	for (var i=0;(el=arr[i]) !== undefined;i++){
		(s !== undefined && typeof el == 'string') ? r=r.concat(el.split(s)) : r.push(el);
	}
	return (r.length != 0 || arr.length == 0) ? r : [arr];
}

function $getStyle(el){
	//crossbrowser function to get calculated styles on element
	return (window.getComputedStyle) ? getComputedStyle(el, null) : el.currentStyle;
}

function $getPos(el){
	//gets the position on element
	var pT = pL = 0, t = -1, o = el;
	if ($getStyle(o).display == 'none') t = $show(o,t);
	do{	pT = pT + el.offsetTop || 0;
		pL = pL + el.offsetLeft || 0;
	} while (el = el.offsetParent);
	if (t != -1) $hide(o,t);
	return {pl: pL, pt: pT};
}

function $getSize(el){
	//gets the size on element
	if (!el) el = (document.body.clientWidth && !window.opera)? document.body : document.documentElement;
	var t = ($getStyle(el).display == 'none') ? $show(el,-1,1) : -1;
	var r = {ow:el.offsetWidth, oh:el.offsetHeight, sw:el.scrollWidth, sh:el.scrollHeight};
	if (t != -1) $hide(el,t,1);
	return r;
}

function $hide(el,s,r){
	//hides a display:none element after finding position and size
	var els = el.style, elp = el.parentNode.style;
	els.display = 'none';
	els.position = s.e;
	if (r) elp.position = s.p;
	els.visibility = 'visible';
}

function $show(el,s,r){
	//shows a display:none element so that position and size can be found
	var els = el.style, elp = el.parentNode.style, e = els.position, p = elp.position;
	if (r && p == '') elp.position = 'relative';
	els.visibility = 'hidden';
	els.position = 'absolute';
	els.display = '';
	return {e:e,p:p};
}

function $getScroll(){//todo: elemement support (overflow:scroll)
	//get document scroll
	var r = {sl:0,st:0}, d = document, w = window;
	if(d.documentElement.scrollTop)	r = {sl: d.documentElement.scrollLeft, st: d.documentElement.scrollTop};
	else if(typeof w.pageYOffset == 'number') r = {sl: w.pageXOffset, st: w.pageYOffset};
	else if(d.body.scrollTop) r = {sl: d.body.scrollLeft, st: d.body.scrollTop};
	return r;
}

//todo: setScroll

function $setCookie(n,v,d){
	//sets cookies value with name, value and days to expiration, if d is undefined the cookie will be deleted
	var date = new Date();
	date.setTime(date.getTime()+((d || -1)*86400));
	document.cookie = n+"="+v+"; expires="+date.toUTCString()+"; path=/";
}

function $getCookie(n){
	//get cookie value by name
	var r = ""; n = n + "=";
	document.cookie.split(';').forEach(function(c){
		c = c.trim();
		if (c.indexOf(n)==0) r = c.substring(n.length,c.length);									
	});
	return r;
}

var _handlers = [];
function $addEvent(el,t,h){
	//cross-browser method for setting element event
	if (el.addEventListener) el.addEventListener(t, h, false);
	else if (el.attachEvent) el.attachEvent('on' + t, h);
	else {
		var c = el['on' + t];
		if (typeof c != 'function')el['on' + t] = h;
		else el['on' + t] = function(){h();c()};
	}
	_handlers.push(arguments);
}

function $removeEvent(el,t,h){
	//cross-browser method for removing element event
	if (el.removeEventListener) el.removeEventListener(t, h, false);
	else if (el.detachEvent) try {el.detachEvent(t,h)} catch ($i){};
}

if (window.detachEvent && !window.opera) window.attachEvent('onunload',function(){
	//automaticly cleans up events in ie to avoid memory leaks
 	_handlers.forEach(function(el){el[0].detachEvent('on'+el[1], el[2])});
});




/* --------------- jaxx.Dom  ----------------- */

function $$(){
//css query function, returns a $jaxx extended array of elements 
var args = $c(arguments, ','), d = [document], r = [], atr, ati;
if (typeof args[args.length -1] == 'object') d = args.pop();
args.forEach(function(el){
	if (typeof el=='string'){
		var par = $c(d);
		(el.trim()).split(/\s+/).forEach(function(str){
			var temp = [], tag = (str.match(/^(\w+)([.#\[]?)\s?/)) ? RegExp.$1 : "*", id = false, cn = false, at = false;
			if (str.match(/([\#])([a-zA-Z0-9_\-]+)([.#\[]?)\s?/)) id = RegExp.$2;
			if (str.match(/([\.])([a-zA-Z0-9_\-]+)([.#\[]?)\s?/)) cn = ' ' + RegExp.$2 + ' ';
			if (str.match(/\[(\w+)([~\|\^\$\*]?)=?"?([^\]"]*)"?\]/)) at = [RegExp.$1 , RegExp.$2, RegExp.$3];
			par.forEach(function(doc){
				$c(doc.getElementsByTagName(tag)).forEach(function(i){
					if (i.length != undefined && i.action == undefined)	return;
					if (id && (!i.getAttribute("id") || i.getAttribute("id")!=id)) return;
					if (at){
					  if (atr = $strippAnonymous(i.getAttribute(at[0]))){
					    ati = atr.indexOf(at[2]);
						if (at[2]=='');
						else if (at[1] == '' && atr == at[2]);
						else if (at[1] == '*' && ati != -1);
						else if (at[1] == '~' && (' '+atr+' ').indexOf(' '+at[2]+' ') != -1);
						else if (at[1] == '^' && ati == 0);
						else if (at[1] == '$' && ati == (atr.length-at[2].length) && ati != -1);
						else return;
					  } else return;
					}
					if (cn && (' '+i.className+' ').indexOf(cn)==-1) return;
					temp.push(i); 
				});
			});
			par = temp;
		});
		r = r.concat(par);
	} else r.push(el);
}, this);
return $ext(r, new $jaxx()).init();
}

function $(a){
	//id query function, returns a $jaxx extended array of elements 
	var m = $c(arguments).map(function(el){return (typeof el=='string') ? document.getElementById(el) : el});
	return (a.jaxx) ? a.merge(m) : $ext(m, new $jaxx()).init();
}

var fx = {
	//inculded set of fx's to use with animations
	linear: function(p){return {h:p,w:p,o:p,pl:p,pt:p,t:p}},
	cubic: function(p){p = Math.pow(p,3); return {h:p,w:p,o:p,pl:p,pt:p,t:p}},
	circ: function(p){p = Math.sqrt(p); return {h:p,w:p,o:p,pl:p,pt:p,t:p}},
	sinoidal: function(p){p = ((-Math.cos(p*Math.PI)/2) + 0.5); return {h:p,w:p,o:p,pl:p,pt:p,t:p}}
};


/* --------------- jaxx       ------------- */
var __ext = [];
function $jaxx(){
	//init function for $jaxx, extends itself with all objects set in __ext
	__ext.forEach(function(o){$ext(this, o)},this);
}

$jaxx.prototype = {
jaxx: 0.85,
fI: 1, fs: 1, sI: -1, fT: 0, mT: 0,mH: 0, nArr: [],

add: function(str){
	//append content to all elements
	this.forEach(function(el){
		if (el.value !== undefined) el.value += str;
		else el.innerHTML += str;
	}); return this;
},

addClass: function(c,t,r){
	//add class, removes the class first from the whole array unless r is set
	this.removeClass(c, r);
	this.forEach(function(el, i){
		if (t === undefined || el === t || i === t)el.className = el.className + (el.className.length > 0 ? ' ' : '') + c;});
	return this;
},

addEvent: function(t,h,b,el){
	//add event to the whole element array unless el is set, b is optional 'this' override
	this.forEach(function(el2,i){
		if (el === undefined || el === el2 || el === i)
			$addEvent(el2,t,h.bindE(this, el2, i))
	}, b);
	return this;
},

check: function(s){
	//short cut for checking / unchecking  an array of checkboxes
	s = (s==undefined) ? ((this[0].checked) ? false : true) : ((s)? true : false);
	this.forEach(function(el){ if (el.type=="checkbox") el.checked = s; });
},

click: function(h,b,el){
	//shortcut for addEvent('click',h,b,el)
	return this.addEvent('click',h,b,el);
},

fx: function(o,t,sT){
	//init function for animations, can set options, target values and startTime for auto slideshow
	if (o && o.cookie) $c($getCookie(o.cookie).split(",")).forEach(function(el,i){if (el==1)o.defSlide=i;});
	if (o && o.defSlide != undefined) this.slide(o.defSlide);
	$ext(this.o, o || {});
	$ext(this.t, t || {});
	this.fI = this.fs = Math.round(this.o.duration/this.o.ft);
	if (this.p.length != this.length) this.setP();
	this.p = this.map(function(el,i){ return $ext($ext(this.p[i], $getSize(el)), $getPos(el))},this);
	if (sT) this.start(sT);
	return this;
},

fxprep: function(hide,item,noslide){
	//private preperation function for animations, have optional onStart event
	if (this.fT) clearInterval(this.fT);
	this.fI = this.fs - this.fI;
	if (this.p.length != this.length) this.setP();
	this.forEach(function(el, i){
		var p = this.p[i], t, r = (el===item || i===item || item === undefined) ? 1 : 0;
		if (hide !== undefined) t = (hide)?-1:1;
		else t = (p.a == 0) ? -p.d : -p.a;
		t = (r) ? t : -t;
		this.p[i].a = ((!r && noslide) || p.d == t && (p.a == 0 || p.a == t)) ? 0 : t;
	}, this);	
	this.fT = setInterval(this.fxStep.bind(this),this.o.ft);
	if (this.o.onStart) this.o.onStart(this);
	this.fxStep();
},

fxStep: function(){
	//private animation function, is started by fxprep, have optional onComplete/onHide/onShow events
	this.fI++;
	var ot = this.fI/this.fs, els, p, t = this.t, o = this.o, pos = o.transition(ot), iPos = o.transition(1-ot);
	if (this.fI == this.fs){
		clearInterval(this.fT);
		this.forEach(function(el,i){
			if (this.p[i].a == -1){
				el.style.display = o.display;
				this.p[i].d = -1;
				if (o.onHide) o.onHide(el, i, this);
			}
			}, this);
		if (o.onComplete) o.onComplete(this);
		if (o.cookie) $setCookie(o.cookie, this.p.map(function(p){return p.d}), (o.cookieDays || 10)); 
	}
	this.forEach(function(el,i){
	 if (this.p[i].a != 0){
		els = el.style;
		p = this.p[i];
		ot = (p.a == 1) ? pos : iPos;
		if (o.height) els.height = ((t.h-p.sh) * (1-ot.h) + p.sh) + "px";
		if (o.width) els.width = ((t.w-p.ow) * (1-ot.w) + p.ow) + "px";//convert to sw when Opera9 handels it
		if (o.text) els.fontSize = ((t.t-1) * (1-ot.t) + 1) * 100 + '%';
		if (o.position){
			els.top = ((t.pt-p.pt) * (1-ot.pt) + p.pt) + 'px';
			els.left = ((t.pl-p.pl) * (1-ot.pl) + p.pl) + 'px';
		}
		if (o.opacity){
			ot = (t.o-1) * (1-ot.o) + 1;
			if (els.opacity != undefined) els.opacity = (ot == 1) ? "" : ot;
			else if (els.filter != undefined) els.filter = (ot == 1) ? "" : "alpha(opacity=" + ot*100 + ")";
		}
		if (p.a == 1 && p.d == -1){
			els.display = '';
			this.p[i].d = 1;
			if (o.onShow) o.onShow(el, i, this);
		}
	 }
	}, this);	
},

hide: function(h){
	//hides the whole array unless h (element or index) is set
	this.fxprep(true,h,true);
},

init: function(r){
	//private init function to be called right after array is extended
	this.o = {duration:13, ft:13, display:'none', transition:fx.linear, defSlide:-1, selected:'selected'};
	this.t = {h:0,w:0,o:0,pl:0,pt:0,t:0};
	this.p = [];
	return this;
},

load: function(u,el){
	//shortcut to ajax functionality to target server response directly to element (index or element)
	if (el === undefined) el = this[0];
	else if (typeof el == 'number') el = this[el];
	if( !this.ajax ) this.ajax = new $ajax( this.o );
	if ( !this.o.update ) this.ajax.o.update = el;
	if ( this.o.preUpdate ) this.ajax.o.preUpdate = this.o.preUpdate.bindE( this , el );
	if ( this.o.onLoad ) this.ajax.o.onLoad = this.o.onLoad.bindE( this , el );
	this.ajax.load( u );
},

merge: function(a){
	//merge array with other array or element
	$c(a).forEach(function(el){
			if (el !== "" && this.indexOf(el) == -1) this.push(el);
	},this);
	return this;
},

mf: function(c){
	//private mouse on focus function
	clearInterval(this.mT);
	this.mH = 1;
	this.forEach(function(el, i){
		if (i == c && c != this.sI) this.slide(c);
	}, this);
	this.mT = setInterval(this.muf.bind(this), 2700);
},

muf: function(){
	//private mouse unfocus function
	if (this.mH == false){
		clearInterval(this.mT);
		this.slide(this.o.defSlide);
	}
},

nav: function(n,m){
	//set navigation options, n is navigation array and m us true/false value for mouse or click navigation
	if (m){
		if (n){
			n.addEvent("mouseover",function(e,el,i){this.mf(i)},this);
			n.addEvent("mouseout",function(){this.mH=0},this)
		}
		this.addEvent("mouseover",function(e,el,i){this.mf(i)},this);
		this.addEvent("mouseout",function(){this.mH=0},this);
	} else n.click(((n.length == 1) ? function(){this.toggle()} : function(e,el,i){this.slide(i)}),this);
	if (n) this.nArr = n.voidLink();
	return this;
},

remove: function(x){
	//removes all element or element(x) from document and array
	this.forEach(function(el,i){
		if (x === undefined || x === el || x === i){
			el.parentNode.removeChild(el);
			this[i] = 0;
		}
	},this);
	this.filter(function(el){return el});//need testing!
	return this;
},

removeClass: function(c,t){
	//removes className from all elements unless t is set (index or element)
	this.forEach(function(el){
	if (t === undefined || el === t || i === t)
	 el.className = el.className.split(' ').filter(function(cn, i){if (cn!=c) return cn;}).join(' ');
	});
	return this;
},

set: function(str){
	//overwrite content
	this.forEach(function(el){
		if (el.value !== undefined) el.value = str;
		else el.innerHTML = str;
	}); return this;
},

setP: function(){
	//private function to reseting element propertie cache (size / position....)
	this.p = this.map(function(el){return {a:0,d:((el.style.display == 'none') ? -1 : 1)}});
},

setStyle: function(s){
	//shortcut to set multiple styles by an object of name and value
	this.forEach(function(el){
		for (z in s) el.style[z] = s[z];
	}); return this;
},

show: function(s){
	//shows the whole array unless h (element or index) is set
	this.fxprep(false,s,true);
},

start: function(t){
	//start automatic slideshow, t is intervall time
	this.sT = setInterval(this.slide.bind(this),t);
	return this;
},

stop: function(){
	//stop automatic slideshow
	if (this.sT) clearInterval(this.sT);
	return this;
},

slide: function(s){
	//slides the the animation, slides to specific index if s is set (index or element)
	if (s != undefined) this.sI = ( typeof s == 'number' ) ? s : this.indexOf( s );
	else this.sI = ( this.sI > this.length-2 ) ? 0 : this.sI+1;
	this.addClass( this.o.selected, this.sI );
	if ( this.nArr.addClass ) this.nArr.addClass( this.o.selected, this.sI );
	this.fxprep( false, this.sI );
},

toggle: function(t){
	//toggles the whole array unless t (element or index) is set
	this.fxprep(undefined,t,true);
},

voidLink: function(){
	//substitutes href values for harmless void(0) calls (== do nothing)
	this.forEach(function(el){if (el.href) el.href="JavaScript:void(0)"});
	return this;
}
};


/* --------------- jaxx.Drag --------------- */
__ext.push({
//dragNdrop functionality as an extension
drag: -1,
dpi: -1,
odpi: -1,
drag: function(par){
	//init function to make elements elements dragable, optional parent containers as array
	//calls fx to preper aniamtion but sets display to '' to avoid hiding on drag
	this.fx({display:''}).forEach(function(el,i){
	  $addEvent(el,'mousedown',this.dragStart.bindE(this));
	},this);
	$addEvent(document,'mousemove', this.dragMove.bindE(this));
	$addEvent(document,'mouseup',this.dragStop.bindE(this));
	this.dp = (par) ? par.fx() : false;
	return this;
},

dragMove: function(e){
	//private window on mouse move function
	if (this.drag > -1){
		var i = this.dpi, s = $getScroll(), l = e.clientX + s.sl, t = e.clientY + s.st, x = this.drag;
		this[x].style.left = (l - this.p[x].pl - this.tpl - this.tps.sl) + 'px';
		this[x].style.top = (t - this.p[x].pt - this.tpt - this.tps.st) + 'px';
		if (this.dp) i = this.dp.parentPosition(l,t);
		if (this.dpi != i) this.dp.addClass(this.o.selected, this.dpi = i);
	}
	return false;
},

dragStart: function(e){
	//private on drag function, optional onDrag event, 'hides' element
	var el = e.target || e.srcElement, p = $getPos(el);
	this.drag = this.indexOf(el);
	this.tpl = e.clientX - p.pl;
	this.tpt = e.clientY - p.pt;
	this.tps = $getScroll();
	if (this.dp) this.dpi = this.odpi = this.dp.parentPosition(e.clientX + this.tps.sl, e.clientY + this.tps.st);
	if (this.dpi != -1) this.dp.addClass(this.o.selected, this.dpi);
	if (this.o.onDrag) this.o.onDrag(el);
	else this.hide(el);
},

dragStop: function(e){
	//private on drop function, optional onDrop event, 'shows' element
	if (this.drag != -1){
		e = this[this.drag];
		this.drag=-1;
		if (this.dp) this.dp.removeClass(this.o.selected);
		if (this.o.onDrop) this.o.onDrop(e);
		else this.show(e);
	}
},

parentIndex: function(c){
	//finding first element in array that is parent of c by index
	var i = -1;
	do{
		c = c.parentNode;
		i = this.indexOf(c);
	} while (c && i==-1);
	return i;
},

parentPosition: function(l,t){
	//finding first element in array that is parent of c by left and top position
	var i = -1, p;
	this.forEach(function(el,x){
		p = this.p[x];
		if (l >= p.pl && l <= p.pl + p.ow && t >= p.pt && t <= p.pt + p.oh) i = x;
	},this);
	return i;
}
});



/* --------------- jaxx.Ajax --------------- */
function $ajax(o,u){
	//init function for $ajax, if url is specified the call will be done imidently
	this.o = $ext({method: "GET"}, o || {});
	if (u)this.load(u, this.o.postBody || null);
};
$ajax.prototype = {
last: '',
load: function(u,pB){
	//function for re calling same ajax function with different url and postBody
	if (!this.req) this.req = new XMLHttpRequest();
	if ((u + pB) == this.last && !this.o.noCache) return this.done();
	this.last = (u + pB);
	if (0 < this.req.readyState && this.req.readyState < 4){
		this.req.onreadystatechange = function(){};
		this.req.abort();
	}
	this.req.open(this.o.method, u, true);
	this.req.onreadystatechange = function(){
		if (this.req.readyState==4){
		 if (this.req.status==200 || this.req.status==0) this.done();
		 else if (this.o.onError) this.o.onError(this.req.status, this.req.statusText);
	 	 this.req.onreadystatechange = function(){};
		}}.bind(this);
	if (this.o.method=='POST'){
		this.req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=iso-8859-1');
		if (this.req.overrideMimeType) this.req.setRequestHeader('Connection', 'close');
	}
	this.req.send(pB || null);
	return this;
},

done: function(){
	//private function called when ajax call is done. Optional update element, preUpdate and onLoad callBacks.
	var r=this.req, o=this.o;
	if (o.update) o.update.innerHTML = (o.preUpdate)? o.preUpdate(r): r.responseText;
	if (o.onLoad) o.onLoad(r);
}
};

function $xslt(xmlR,xslR,v){
	//cross browser function for clientside  xsl transformation
	var r = xmlR.responseText, xslP, tb;
	if(document.implementation && document.implementation.createDocument){
		xslP = new XSLTProcessor();
		xslP.importStylesheet(xslR.responseXML);
		if (xslP.setParameter && v) for (name in v) xslP.setParameter(null, name, v[name]);	
		tb = document.createElement("div");
		tb.appendChild(xslP.transformToFragment(xmlR.responseXML, document));
		r = tb.innerHTML;
	} else if(window.ActiveXObject){
		var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
		xslDoc.async = false;
		xslDoc.loadXML(xslR.responseText);
		var xslT = new ActiveXObject("Msxml2.XSLTemplate"), xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
		xslT.stylesheet = xslDoc;
		xslP = xslT.createProcessor();
		if (v) for (name in v) xslP.addParameter(name, v[name]);
		xmlDoc.async = false;
		xmlDoc.loadXML(xmlR.responseText);
		xslP.input = xmlDoc;
		xslP.transform();
		r = xslP.output;
	}
	return r;
}


function $json(str,oC){
	//json function, str handles both script url(optional onComplete callback) and script string
	var scr = document.createElement('script');
	scr.type = 'text/javascript';
	if (str.indexOf('.js') != -1){
		scr.src = str;
		if (oC) $addEvent(script, 'load', oC);
	} else scr.text = str;
	$$('head')[0].appendChild(scr);
}
