/*
 * Name:		DOM, Animations, Ajax and more Framework Library
 * Author:		Sandro Lain
 * Copyright:	Sandro Lain
 */

var Morphidae = {
	version: 0.5,
	updated: 20070824
};

var Types = {
	getFunction: function(f) {
		var t = typeof f;
		if(t == 'function') return f;
		if(f == 'string') return new Function(f);
		return null;
	},
	object: function(e, o) {
		var i;
		if(!e) e = {};
		if(!o) o = {};
		for(i in o) e[i] = o[i];
		return e;
	},
	// Function to convert an object list to an array
	toArray: function(a) {
		for(var r = [], i = a.length - 1; i >= 0; i--) r[i] = a[i];
		return r;
	},
	isNumeric: function(n) {
		return !isNaN(parseInt(n, 10));
	},
	isElement: function(o, n) {
		if(n) return (o.nodeName && o.nodeName.toLowerCase() == n.toLowerCase());
		return (o.nodeName && o.ownerDocument);
	},
	is: function(o) {
		return (o !== false && o !== undefined && o !== null);
	}
};

// Funzione per gli id
function I(o, d) {
	if(!d || !d.getElementById) d = document;
	if(!o) return d;
	if(typeof o == 'string') return d.getElementById(o);
	if(o.nodeName || d.getElementById) return o;
	return null;
}
function T(t, e) {
	return Types.toArray((I(e) || document).getElementsByTagName(t));
}

function C(c, o, t) {
	for(var a = T(t || '*', o), r = [], i = a.length - 1, j = 0; i >= 0 && (o = a[i]); i--) if(Dom.hasClass(o, c)) r[j++] = o;
	return r;
}

function A(c, o, t) {
	for(var a = T(t || '*', o), r = [], i = a.length - 1, j = 0; i >= 0 && (o = a[i]); i--) if(Dom.hasAttribute(o, c)) r[j++] = o;
	return r;
}

// Function to obtain a group of elements by a css-like path
function P(p, e) {
	p = p.replace('>', ' > ');
	p = p.replace(/(:[a-z][a-z0-9_-]*)/gi, ' $1 ');
	var s = [I(e)], t = p.split(/[\s]+/i), l = t.length, r, n, c, i, j, f, d, g,a = false;
	for(i = 0; i < l; i++) {
		d = t[i];
		if(!d) continue;
		g = s.length;
		if(d == '>') a = true;
		// Controllo primo figlio
		else if(d == ':first-child') {
			c = [];
			for(j = 0; j < g; j++) {
				f = Dom.first(s[j], true);
				if(f) c.push(f);
			}
			if(c.length === 0) return null;
			s = c;
		// Controllo prima lettera
		} else if(d == ':first-letter') {
			c = [];
			for(j = 0; j < g; j++) {
				f = Dom.firstLetter(s[j], true);
				if(f) c.push(f);
			}
			if(c.length === 0) return null;
			s = c;
		} else {
			r = null;

			// Controllo elemento
			m = d.match(/^(\*|[a-z][a-z0-9]*)/i);
			if(m) {
				n = m[1];
				if(n) {
					c = [];
					for(j = 0; j < g; j++) c = c.concat(T(n, s[j]));
					r = c;
					if(r.length === 0) return null;
				}
			}

			// Controllo id
			m = d.match(/#([a-z][a-z0-9_-]*)/i);
			if(m) {
				n = m[1];
				if(n) {
					c = [];
					for(j = 0; j < g; j++) {
						f = s[j].getElementById(n);
						if(f) { c = [f]; break; }
					}
					r = (r) ? r.intersect(c) : c;
					if(r.length === 0) return null;
				}
			}

			// Controllo Classe
			m = d.match(/(\.[a-z][a-z0-9_-]*)+/i);
			if(m) {
				n = m[0];
				if(n) {
					c = [];
					for(j = 0; j < g; j++) c = c.concat(C(n, s[j]));
					r = (r) ? r.intersect(c) : c;
					if(r.length === 0) return null;
				}
			}

			// Controllo attributi
			m = d.match(/\[([a-z]+)((~|\^|\$|\*)?=?([^\]]*))\]?/i);
			if(m) {
				n = m[0];
				if(n) {
					c = [];
					for(j = 0; j < g; j++) c = c.concat(A(n, s[j]));
					r = (r) ? r.intersect(c) : c;
					if(r.length === 0) return null;
				}
			}

			// Controllo figli
			if(a && r) {
				c = [];
				for(j = 0; j < g; j++) c = c.concat(Types.toArray(s[j].childNodes));
				r = (r) ? r.intersect(c) : c;
				if(r.length === 0) return null;
			}

			if(!r) return null;
			s = r;
		}
	}
	return s.unique();
}

function V(o, a) {
	o = I(o);
	var n = o.nodeName.toLowerCase(), v = null;
	if(n == 'input' || n == 'textarea' || n == 'select' || n == 'option') {
		v = o.value;
		if(a) o.value = a;
	} else {
		v = o.nodeValue;
		if(a) o.nodeValue = a;
	}
	return v;
}

if(!window.$) {
	$ = I;
}

var Dom = {
	// Metodo che ritorna il primo nodo all'interno di quello passato
	first: function(o, t) {
		o = I(o);
		var g = o.childNodes, i, c, l = g.length;
		if(!t && l > 0) return g[0];
		for(i = 0; i < l; i++) {
			c = g[i];
			if(c.nodeType == 1) return c;
		}
		return null;
	},
	// Metodo che ritorna l'ultimo nodo all'interno di quello passato
	last: function(o, t) {
		o = I(o);
		var g = o.childNodes, i, c, l = g.length;
		if(!t && l > 0) return g[l-1];
		for(i = 0; i < l; i++) {
			c = g[i];
			if(c.nodeType == 1) return c;
		}
		return null;
	},
	// Metodo che ritorna il nodo seguente a quello passato
	next: function(o, t) {
		o = I(o);
		o = o.nextSibling;
		if(!t && o) return o;
		while(o && (o = o.nextSibling)) if(o.nodeType == 1) return o;
		return null;
	},
	// Metodo che ritorna il nodo precedente a quello passato
	prev: function(o, t) {
		o = I(o);
		o = o.previousSibling;
		if(!t && o) return o;
		while(o && (o = o.previousSibling)) if(o.nodeType == 1) return o;
		return null;
	},
	// Metodo che ritorna la prima lettera all'interno del nodo passato
	firstLetter: function(o, t) {
		o = I(o);
		var g = o.childNodes, l = g.length, i, c, p;
		for(i = 0; i < l; i++) {
			c = g[i]; p = c.nodeType;
			if(p == 1) {
				p = Dom.firstLetter(c, t);
				if(p) return p;
			} else if(p == 3) {
				p = c.nodeValue;
				if(!p.match(/^[\s]*$/gm)) {
					if(t) {
						if(p.length == 1 && !c.previousSibling && !c.nextSibling && c.parentNode.nodeName.toLowerCase() == 'span') return c.parentNode;
						return Dom.spanSubtext(c, 0, 1);
					} else return p.substr(0, 1);
				}
			}
		}
		return null;
	},
	// Metodo che inserisce uno span ad una sottostringa di un elemento "nodo di testo" passato
	spanSubtext: function(o, s, f) {
		if(o.nodeType != 3) throw new TypeError();
		var v = o.nodeValue, b = v.substring(s, f), r = Dom.create(['span', b]), l = v.length, a = [o];
		if(s > 0) a.push(v.substring(0, s));
		a.push(r);
		if(f && f < l) a.push(v.substring(f, l));
		Dom.after.apply(null, a);
		Dom.remove(o);
		return r;
	},
	//### Class Name Functions
	// Function to check if an element has a class name
	hasClass: function(o, s) {
		o = I(o).className;
		s = s.split(/[\.\s]+/gi);
		for(var j = s.length - 1, e; j >= 0; j--) {
			if((e = s[j])) {
				e = new RegExp("(^|\\s)" + e + "(\\s|$)", 'g');
				if(!e.test(o)) return false;
			}
		}
		return true;
	},
	// Function to add one o more classnames to an element
	addClass: function(o, s) {
		o = I(o);
		Dom.removeClass(o, s);
		o.className += ' ' + s.split(/[\.\s]+/g).join(' ');
	},
	// Function to remove one or more classnames from an element
	removeClass: function(o, s) {
		o = I(o);
		s = new RegExp("(^|\\s+)(" + s.split(/[\.\s]+/gi).join('|') + ")(\\s+|$)", 'g');
		o.className = o.className.replace(s, ' ');
	},
	switchClass: function() {
		var a = arguments, o = I(a[0]), i, l = a.length, e;
		for(i = 1; i < l; i++) {
			e = a[i];
			if(Dom.hasClass(o, e)) {
				Dom.removeClass(o, e);
				e = (i == l - 1) ? a[1] : a[i + 1];
				Dom.addClass(o, e);
				return;
			}
		}
		Dom.addClass(o, a[1]);
	},
	booClass: function() {
		var a = arguments, o = I(a[0]), i, e;
		for(i = a.length - 1; i > 0; i--) {
			e = a[i];
			if(Dom.hasClass(o, e)) Dom.removeClass(o, e);
			else Dom.addClass(o, e);
		}
	},
	//### Class Name Functions
	// Function to remove elements
	remove: function() {
		for(var a = arguments, i = a.length - 1, o; i >= 0; i--) {
			o = I(a[i]);
			o.parentNode.removeChild(o);
		}
	},
	// Function to append multiple elements or insert html to a specified element
	append: function() {
		for(var a = arguments, l = a.length, o = I(a[0]), i = 1; i < l; i++) o.appendChild(Dom.create(a[i]));
	},
	prepend: function() {
		for(var a = arguments, i = a.length - 1, o = I(a[0]), f; i > 0; i++) {
			n = Dom.create(a[i]);
			f = o.firstChild;
			if(f) o.insertBefore(n, f); else o.appendChild(n);
		}
	},
	// Function to insert a child before another
	before: function() {
		for(var a = arguments, l = a.length, o = I(a[0]), i = 1; i < l; i++) o.parentNode.insertBefore(Dom.create(a[i]), o);
	},
	// Function to insert a child after another
	after: function() {
		for(var a = arguments, o = I(a[0]), p = o.parentNode, n, i = a.length - 1, c; i > 0; i--) {
			c = Dom.create(a[i]);
			n = o.nextSibling;
			if(n) p.insertBefore(c, n); else p.appendChild(c);
		}
	},
	copy: function(o, d) {
		o = I(o).cloneNode(true);
		I(d).appendChild(o);
		return o;
	},
	move: function(o, d) {
		d = Dom.copy(o, d);
		Dom.remove(o);
		return d;
	},
	childs: function() {
		for(var a = arguments, r = [], l = a.length, i = 0, y = 0, c, j, k; i < l; i++) {
			c = I(a[i]).childNodes;
			for(j = 0, k = c.length - 1; j < k; j++) r[y++] = c[j];
		}
		return r;
	},
	// Obsoleta (solo se si vuole ottenere anche i figli di tipo non element)
	descendants: function() {
		for(var a = arguments, r = [], i = 0, l = a.length, c, j, o, k; i < l; i++) {
			c = I(a[i]).childNodes;
			k = c.length;
			for(j = 0; j < k; j++) {
				o = c[j];
				if(o.nodeType == 1) r = r.concat(o, Dom.descendants(o));
			}
		}
		return r.unique();
	},
	// Function to delete all child nodes of an element
	removeChilds: function(o) {
		o = I(o);
		while(o.hasChildNodes()) o.removeChild(o.firstChild);
	},
	// Function to move all child nodes of an element to all other elements
	moveChilds: function(o, d) {
		var f;
		o = I(o); d = I(d);
		while(o.hasChildNodes()) {
			f = o.firstChild;
			d.appendChild(f.cloneNode(true));
			o.removeChild(f);
		}
	},
	replaceChilds: function() {
		var a = arguments;
		Dom.removeChilds(a[0]);
		Dom.append.apply(null, a);
	},
	// Function to copy all child nodes of an element to all other elements
	copyChilds: function() {
		var a = Types.toArray(arguments), c = I(a.shift()).cloneNode(true);
		Dom.moveChilds.apply(null, [c].concat(a));
	},
	getAttribute: function(o, a) {
		o = I(o);
		if(a == 'class' || a == 'className') return o.className;
		else return o.getAttribute(a);
	},
	getAttributes: function() {
		for(var a = arguments, o = I(a[0]), r = {}, i = a.length - 1, e; i > 0 && (e = a[i]); i--) r[e] = Dom.getAttribute(o, e);
		return r;
	},
	// Function to set multiple attributes to a specified element
	setAttributes: function(o, a) {
		o = I(o);
		var i, e;
		for(i in a) {
			e = a[i];
			if(typeof e == 'function') {
				Event.add(o, i, e);
				//o[i] = function() { e.apply(this, arguments); };
			}
			else if(i == 'class' || i == 'className') Dom.addClass(o, e);
			else if(i == 'style') Dom.setStyles(o, e);
			else o.setAttribute(i, e);
		}
	},
	hasAttribute: function(o, c) {
		o = I(o);var e, v;
		if(typeof c == 'string') {
			var m = c.match(/^\[?([a-z]+)(\~|\^|\$|\*)?(\=([^\]]+))?\]?$/i); e = '';
			if(m) {
				var a = m[1];
				//s.replace(/(\\|\.|\(|\)|\[|\]|\^|\$)/gmi, '\\' + '\\1');
				if(m[3]) {
					var t = m[2], s = m[4];
					if(t) {
						if(t == '~') e = '(^|\\s)' + s + '(\\s|$)';
						else if(t == '^') e = '^' + s;
						else if(t == '$') e = s + '$';
						else if(t == '*') e = s;
					} else e = '^' + s + '$';
				}
				v = Dom.getAttribute(o, a);
				//alert(v + " > " + a + " " + t + " = " + s + " > " + e)
				e = new RegExp(e);
				if(v && v.match(e)) return true;
			}
			return false;
		} else {
			for(var j in c) {
				e = c[j];
				if(typeof e == 'string') e = new RegExp("^" + (e.replace('*', '(.*)')) + "$", 'gm');
				else if(e.constructor != RegExp) continue;
				v = (j == 'class' || j == 'className') ? o.className : o.getAttribute(j);
				if(!e.test(v)) return false;
			}
		}
		return true;
	},
	// Function to set the CSS style attribute to an element
	setStyles: function(o, s) {
		o = I(o); var z = o.style, e = Agent.MSIE, i, c;
		if(typeof s == 'string') {
			if(e) z.cssText = s; else o.setAttribute("style", s);
		} else if(typeof s == 'object') {
			var f = (e) ? 'styleFloat' : 'cssFloat';
			for(i in s) {
				c = s[i];
				if(i == 'opacity') Dom.setOpacity(o, c);
				else if(i == 'backgroundAlphaImage') Dom.setAlphabackground(o, c);
				else if(i == 'float') z[f] = c;
				else z[i] = c;
			}
		}
	},
	getStyle: function(o, s) {
		o = I(o); s = s.camelCase();
		var z = o.style, c = o.currentStyle, k = document.defaultView;
		c = c ? c : (k ? k.getComputedStyle(o, '') : {});
		s = z[s] || c[s] || '';
		return s;
	},
	// Function to obtain the values of requested style properties
	getStyles: function() {
		var a = arguments, r = {}, o = I(a[0]), z = o.style, c = o.currentStyle, k = document.defaultView;
		c = c ? c : (k ? k.getComputedStyle(o, '') : {});
		for(var i = a.length - 1, e = null; i > 0 && (e = a[i].camelCase()); i--) r[e] = z[e] || c[e] || '';
		return r;
	},
	switchStyle: function() {
		var a = arguments, o = I(a[0]), n = a[1], s = Dom.getStyle(o, n);
		if(n.toLowerCase().indexOf('color') > -1) s = Color.css2hex(s);
		for(var l = a.length, i = 2, e; i < l; i++) {
			e = a[i];
			if(e == s) {
				e = (i == l - 1) ? a[2] : a[i+1];
				o.style[n] = e;
				return;
			}
		}
		Dom.addClass(o, a[2]);
	},
	setOpacity: function(i, o) {
		i = I(i); var s = i.style;
		o = parseFloat(o); o = (o < 0.01) ? 0 : ((o > 1) ? 1 : o);
		if(Agent.MSIE) s.filter = Dom.getStyle(i, 'filter').replace(/alpha\([^\)]*\)/gi,'') + 'alpha(opacity=' + Math.round(o * 100) + ')';
		else if(o === 1 && Agent.Gecko) s.opacity = 0.99;
		else s.opacity = o;
	},
	getOpacity: function(i) {
		i = I(i); var o = 1, s = Dom.getStyles(i, 'filter', 'opacity');
		if(Agent.MSIE) {
			var e = s.filter.match(/alpha\([\s]*opacity=([0-9]+)[\s]*\)/i);
			if(e && e[1]) o = parseInt(e[1], 10) / 100;
		} else o = s.opacity;
		if(o !== 0 && (!o || o == NaN)) o = 1;
		return parseFloat(o);
	},
	removeOpacity: function(i) {
		i = I(i); var s = i.style;
		if(Agent.MSIE) s.filter = Dom.getStyle(i, 'filter').replace(/alpha\([^\)]*\)/gi,'');
		else s.opacity = '';
	},
	setAlphaBackground: function(i, o, m) {
		i = I(i); var e = Agent.MSIE, s = i.style;
		if(e && e < 7) {
			if(m != 'crop' && m != 'image' && m != 'scale') m = 'crop';
			s.filter += 'progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,src=\'' + o + '\', sizingMethod=\'' + m + '\')';
		} else s.backgroundImage = 'url(\'' + o + '\')';
	},
	// Corretto il bug con IE6 e position:absolute
	realHeight : function(i, v) {
		var o = I(i).cloneNode(true), r = 0, s = o.style, g = Dom.getStyles(o, 'paddingTop', 'paddingBottom');
		s.visibility = 'hidden'; s.display = 'block'; s.height = 'auto';
		if(Agent.isMSIE(6.0)) s.position = 'absolute';
		if(v) s.width = v + 'px'; Dom.before (i, o);
		r = o.clientHeight - Tools.cleanSize(g.paddingTop) - Tools.cleanSize(g.paddingBottom);
		Dom.remove(o);
		return r;
	},
	// Function to obtain a clone of the passed elements
	clones: function() {
		for(var a = arguments, r = [], i = a.length - 1, o = null, j = 0; i >= 0 && (o = I(a[i])); i--) r[j++] = o.cloneNode(true);
		return r;
	},
	// Function to obtain a new Dom elements structure
	// Modification of graft() function by Sean M. Burke from interglacial.com
	// La funzione pił utile del Dom
	create: function(t, o) {
		var r;
		if(!t && t !== '') return null;
		if(t.constructor == Number) t = t.toString();
		if(t.constructor == String) r = document.createTextNode(t);
		else if(t.constructor == Array) {
			var l = t.length;
			for(var i = 0; i < l; i++) {
				var e = t[i];
				if(e === undefined) return null;
				else if(i === 0 && e.constructor == String) {
					var m = e.match(/^(\*|[a-z][a-z0-9]*)?(#([a-z][a-z0-9_-]*))?((\.[a-z][a-z0-9_-]*)+)?$/i);
					if(m) {
						r = document.createElement(m[1]);
						if(m[2]) r.setAttribute('id', m[3]);
						if(m[4]) r.className = m[4].replace('.', ' ').trim();
					} else return null;
				} else if(e.constructor == Number || e.constructor == String
					|| e.constructor == Array || e.nodeType) Dom.create(e, r);
				else if(e.constructor == Object) Dom.setAttributes(r, e);
				else return null;
			}
		} else r = t;
		if(o) I(o).appendChild(r);
		return r;
	},
	document: function(o) {
		o = I(o);
		if(!o) return document;
		var d = o.contentWindow || o.contentDocument || o.document, c;
		if(d) c = d.document;
		if(c) d = c;
		return d;
	},
	window: function(o) {
		if(!o) return window;
		o = I(o);
		var w = o.contentWindow || o;
		return w;
	},
	insertText: function(o, t) {
		o = I(o); var n = o.nodeName;
		if(n) {
			n = n.toLowerCase();
			if(n == "input" || n == "select" || n == "option" || n == "textarea") o.value = t;
			else o.appendChild(document.createTextNode(t));
		}
	},
	getId: function(o, a) {
		if(typeof o == 'string') return o;
		if(o.nodeType == 1) {
			var i = o.getAttribute('id'), r;
			if(i) return i;
			if(a) {
				r = 'xf_random_id_' + Tools.randomString();
				o.setAttribute('id', r);
				return r;
			}
		}
		return null;
	},
	body: function(d) {
		d = Dom.document(d);
		return T('body', d)[0];
	},
	head: function(d) {
		d = Dom.document(d);
		return T('head', d)[0];
	}
};

var Load = {
	image: function(o) {
		var g = new Image(), e = o.onerror, a = o.onabort;
		if(o.onload) g.onload = function() {
			if(arguments.callee.done) return false;
			arguments.callee.done = true;
			this.onload = null;
			return o.onload.call(this);
		};
		if(e) g.onerror = e;
		if(a) g.onabort = a;
		g.src = o.url;
		return g;
	},
	images: function(o) {
		var i = o.images, l = 0, j = 0, r = [], s = o.onstart, p = o.onprogress, c = o.oncomplete;
		i = (i instanceof Array) ? i : [i];
		s = (s) ? s : function(){};
		p = (p) ? p : function(){};
		c = (c) ? c : function(){};
		l = i.length;
		s(l);
		i.forEach(function(g) {
			if(typeof g == 'string') g = {url: g};
			var d = g.onload, e = g.onerror, a = g.onabort;
			d = (d) ? d : function(){};
			e = (e) ? e : function(){};
			a = (a) ? a : function(){};
			g.onload = function() {
				d.apply(this);
				j++;
				p.call(this, j, l);
				if(j == l) c(l);
			};
			g.onerror = function() {
				e.apply(this);
				j++;
				p.call(this, j, l);
				if(j == l) c(l);
			};
			g.onabort = function() {
				a.apply(this);
				j++;
				p.call(this, j, l);
				if(j == l) c(l);
			};
			r.push(Load.image(g));
		});
		return r;
	},
	css: function(o) {
		var a = {href: o.url, type: 'text/css'};
		a.rel = (o.rel) ? o.rel : 'stylesheet';
		a.media = (o.media) ? o.media : 'screen';
		var e = (o.append) ? Dom.head() : null;
		return Dom.create(['link', a], e);
	},
	javascript: function(o) {
		var a = {src: o.url, type: 'text/javascript'};
		if(o.id) a.id = o.id;
		var e = (o.append) ? Dom.head() : null;
		return Dom.create(['script', a], e);
	}
};

var Agent = {
	isMSIE: function(v) {
		if(!document.all) return false;
		var e = navigator.userAgent.match(/(MSIE) ([0-9\.]+)/i);
		if(e) {
			var w = parseFloat(e[2], 10);
			if(v) return (v == w) ? true : false;
			return w;
		}
		return false;
	},
	isGecko: function() {
		var u = navigator.userAgent;
		return (/Gecko/.test(u) && !(/Konqueror|Safari|KHTML/.test(u))) ? true : false;
	},
	isSafari: function() {
		return (/Safari/.test(navigator.userAgent)) ? true : false;
	},
	isKonqueror: function() {
		return (/Konqueror/.test(navigator.userAgent)) ? true : false;
	},
	isWebKit: function() {
		return (/WebKit/.test(navigator.userAgent)) ? true : false;
	},
	isNetscape: function(v) {
		if(!v) v = '';
		var e = new RegExp('(Netscape|NS)[0-9]*[ /]{0,1}' + v, 'g');
		if(e.test(navigator.userAgent)) return true;
		return false;
	},
	isFirefox: function(v) {
		var e = navigator.userAgent.match(/(Firefox|Minefield)\/([0-9\.]+)/i);
		if(e) {
			var w = parseFloat(e[2], 10);
			if(v) return (v == w) ? true : false;
			return w;
		}
		return false;
	},
	isOpera: function(v) {
		if(!window.opera) return false;
		var e = navigator.userAgent.match(/(Opera)[ \/]([0-9\.]+)/i);
		if(e) {
			var w = parseFloat(e[2], 10);
			if(v) return (v == w) ? true : false;
			return w;
		}
		return false;
	}
};
Agent.Firefox = Agent.isFirefox();
Agent.MSIE = Agent.isMSIE();
Agent.Opera = Agent.isOpera();
Agent.Gecko = Agent.isGecko();
Agent.Firefox = Agent.isFirefox();
Agent.Konqueror = Agent.isKonqueror();
Agent.WebKit = Agent.isWebKit();



var Tools = {
	forEach: function(o, f, t, p) {
		if(typeof f != "function") throw new TypeError();
		if(typeof o == 'object' && p) for(var i in o) f.call(t, o[i], i, o);
		else {
			if(f.construnctor != Array) o = [o];
			o.forEach(f, t);
		}
	},
	randomString: function(l) {
		var c = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz", g = c.length, r = '', i, n;
		if(!l) l = 8;
		for(i = l; i > 0; i--) {
			n = Math.floor(Math.random() * g);
			r += c.substring(n, n + 1);
		}
		return r;
	},
	cleanSize : function(s, a) {
		var v = 0, u = '', t = typeof s;
		if(t == 'number') v = s;
		else if(t == 'string') {
			var e = s.match(/(-?[0-9\.]*)(in|cm|mm|pt|pc|em|ex|px|%)?/i);
			if(e) {
				v = parseFloat(e[1], 10);
				u = e[2];
				if(!v) v = 0; if(!u) u = '';
			}
		}
		return (a) ? [v, u] : v;
	}
};



var Element = {
	positioned: function(o) {
		o = I(o);
		var p = Dom.getStyle(o, 'position'), s = o.style;
		if(p == 'static' || !p) {
			o._isPositioned = true;
			s.position = 'relative';
			if(Agent.Opera) s.top = s.left = 0;
		}
	},
	unPositioned: function(o) {
		o = $(o);
		if(o._isPositioned) {
			var s = o.style;
			o._isPositioned = false;
			s.position = s.top = s.left = s.bottom = s.right = '';
		}
	},
	clipping: function(o) {
		o = $(o);
		if(o._origOverflow) return;
		var w = Dom.getStyle(o, 'overflow'), s = o.style;
		o._origOverflow = w || 'auto';
		s.overflow = 'hidden';
	},
	unClipping: function(o) {
		o = $(o);
		if(!o._origOverflow) return;
		var g = element._origOverflow;
		o.style.overflow = g;
		element._origOverflow = null;
	},
	position: function(o, p) {
		o = I(o);
		var l = 0, t = 0, c, u = o;
		do {
			l += o.offsetLeft;
			t += o.offsetTop;
		} while((o = o.offsetParent));

		if(p) {
			c = p.alignment;
			p = p.element;
			if(p) {
				p = Element.position(p);
				l -= p[0];
				t -= p[1];
			}
			if(c) {
				var d = Element.size(u);
				// Allineamento orrizzontale
				if(c == 2 || c == 5 || c == 8) l += Math.round(d[0] / 2);
				else if(c == 3 || c == 6 || c == 9) l += d[0];
				// Allineamento verticale
				if(c >= 4 && c <= 6) t += Math.round(d[1] / 2);
				if(c >= 7 && c <= 9) t += d[1];
			}
		}
		return [l, t];
	},
	size: function(o) {
		o = I(o);
		return [o.offsetWidth, o.offsetHeight];
	},
	at: function(o, x, y) {
		var p = Element.position(o), s = Element.size(o), l = p[0], t = p[1], w = s[0], h = s[1];
		return (x >= l && x < (l + w) && y >= t && y < (t + h)) ? true : false;
	},
	into: function(o, t) {
		o = I(o); t = I(t);
		do { if(o === t) return true; } while((o = o.parentNode));
		return false;
	},
	unselectable: function(o) {
		o = I(o);
		Event.add(o, 'selectstart', function(e){
			Event.stop(e);
			return false;
		});
		o.unselectable = "on";
		var s = o.style;
		s.MozUserSelect = "none";
		s.cursor = "default";
	}
};


var Class = function(p) {
	var i, a = argouments, c = function() {
		if(this.initialize && a[0] != 'noinit') return this.initialize.apply(this, a);
		else return this;
	};
	for(i in this) c[i] = this[i];
	c.prototype = p;
	return c;
};
Class.prototype = {
	extend: function(p){
		var t = new this('noinit'), a, b, i,
		z = function(a, b){
			if(!a.apply || !b.apply) return false;
			return function(){
				this.parent = a;
				return b.apply(this, arguments);
			};
		};
		for(i in p){
			a = t[i]; b = p[i];
			if(a && a != b) b = z(a, b) || b;
			t[i] = b;
		}
		return new Class(t);
	},
	implement: function(p){
		for(var i in p) this.prototype[i] = p[i];
	}
};


(function() {
	var p = 'prototype', Op = Object[p], Sp = String[p], Ap = Array[p], Np = Number[p], Fp = Function[p], Mp = Math;
	Sp.trim = function() {
		return this.replace(/^\s+|\s+$/g,"");
	};
	Sp.clean = function() {
		return this.replace(/\s{2,}/g, ' ').trim();
	};
	Sp.empty = function(s) {
		return (this.length === 0 || (s && this.match(/^[\s]*$/gm))) ? true : false;
	};
	Sp.toInt = function(i) {
		return parseInt(this, i || 10);
	};
	Sp.toFloat = function(i) {
		return parseFloat(this, i || 10);
	};
	Sp.camelCase = function() {
		return this.replace(/-\D/g, function(m) { return m.charAt(1).toUpperCase(); });
	};
	Sp.hyphenate = function() {
		return this.replace(/\w[A-Z]/g, function(m){ return (m.charAt(0) + '-' + m.charAt(1).toLowerCase()); });
	};
	Sp.capitalize = function(){
		return this.toLowerCase().replace(/\b[a-z]/g, function(m) { return m.toUpperCase(); });
	};

	Sp.parseCss = function() {
		for(var s = this, p = s.split(';'), r = {}, i = p.length - 1, d, n; i >= 0; i--) {
			d = p[i].split(':');
			n = d[0].trim().camelize();
			if(n) r[n] = d[1].trim();
		}
		return r;
	};

	Sp.whiteSpaceChar = function(i) {
		if(!i) i = 0;
		return (this.charCodeAt(i) <= 32);
	};
	Sp.digitChar = function(i) {
		var c = this.charCodeAt(i);
		return (c >= 48  && c <= 57);
	};
	Sp.letterChar = function(i) {
		var c = this.charCodeAt(i);
		return ((c >= 65  && c <= 90) || (c >= 97 && c <= 122));
	};
	Sp.upperCaseChar = function(i) {
		var c = this.charCodeAt(i);
		return (c >= 65  && c <= 90);
	};
	Sp.lowerCaseChar = function(i) {
		var c = this.charCodeAt(i);
		return (c >= 97  && c <= 122);
	};

	// Implementazioni dello standard
	if(!Ap.indexOf) {
		Ap.indexOf = function(v, b) {
			for(var i =+ b || 0, l = this.length; i < l; i++) if(this[i] === v) return i;
			return -1;
		};
	}
	// Nota: tolti i controlli rispetto allo standard
	if(!Ap.filter) {
		Ap.filter = function(f, t) {
			if(typeof f != "function") throw new TypeError();
			for(var a = this, l = a.length, r = [], i = 0, j = 0, o; i < l; i++) {
				o = a[i]; if(f.call(t, o, i, a)) r[j++] = o;
			}
			return r;
		};
	}
	if(!Ap.forEach) {
		Ap.forEach = function(f, t) {
			if(typeof f != "function") throw new TypeError();
			for(var i = 0, a = this, l = a.length; i < l; i++) f.call(t, a[i], i, a);
		};
	}
	Ap.each = Ap.forEach;
	if(!Ap.every) {
		Ap.every = function(f, t){
			for(var i = 0, a = this, l = a.length; i < l; i++) if(!f.call(t, a[i], i, a)) return false;
			return true;
		};
	}
	if(!Ap.map) {
		Ap.map = function(f, t) {
			if(typeof f != "function") throw new TypeError();
			for(var a = this, l = a.length, r = [], i = 0; i < l; i++) r = r.concat(f.call(t, a[i], i, a));
			return r;
		};
	}
	if(!Ap.some) {
		Ap.some = function(f, t){
			for(var i = 0, a = this, l = a.length; i < l; i++) if(f.call(t, a[i], i, a)) return true;
			return false;
		};
	}
	// Implementazioni personalizzate
	Ap.unique = function(b) {
		var a = [], i, l = this.length;
		for(i = 0; i < l; i++) if(a.indexOf(this[i], 0, b) < 0) a.push(this[i]);
		return a;
	};
	Ap.replace = function(f, p) {
		for(var r = [], i = this.length - 1; i >= 0 ; i--) r[i] = (this[i] === f) ? p : this[i];
		return r;
	};
	Ap.intersect = function(a) {
		var r = [], b = this, k = b.length, i, j = 0, c;
		for(i = 0; i < k; i++) {
			c = b[i];
			if(a.indexOf(c) >= 0) r[j++] = c;
		}
		return r;
	};
	Ap.remove = function(a) {
		var i = 0;
		while(i < this.length) if(this[i] === a) this.splice(i, 1); else i++;
		return this;
	};
	Ap.copy = function(s, l) {
		var h = this.length, i, r = [];
		if(!s) s = 0;
		if(s < 0) s = h + s;
		if(!l) l = h - s;
		for(i = 0; i < l; i++) r[i] = this[s++];
		return r;
	};
	Ap.exists = function(i, s) {
		return this.indexOf(i, s) != -1;
	};
	Ap.clean = function() {
		for(var a = this, r =[], j = 0, i = 0, l = a.length, e; i < l; i++) {
			e = a[i];
			if(e || e === 0) r[j++] = e;
		}
		return r;
	};
	Ap.nearest = function(o) {
		if(typeof o != 'number') return null;
		for(var a = this, r = null, e, d = null, n, i = a.length - 1; i >= 0; i--) {
			e = a[i];
			n = Math.abs(e - o);
			if(d === null || n < d) {
				d = n;
				r = e;
			}
		}
		return d;
	};

	// ### Number prototypes
	Np.toInt = function(i) {
		return parseInt(this, i || 10);
	};
	Np.toFloat = function(i) {
		return parseFloat(this, i || 10);
	};
	Np.zeroFill = function(z, m) {
		var i, r = '', n = this, l;
		n = parseInt(n, 10) + '';
		l = n.length;
		if(m && l > z) return n.substr(l - z, z);
		l = z - l;
		for(i = 0; i < l; i++) r += '0';
		return r + '' + n;
	}

	// Function Prototypes
	Fp.interval = function(t, a) {
		var f = this, r = function() { f.apply(null, a || []); };
		return window.setInterval(r, t);
	};
	Fp.timeout = function(t, a) {
		var f = this, r = function() { f.apply(null, a || []); };
		return window.setTimeout(r, t);
	};

	// ### Math prototypes
	p = 1.61803398874989484820458683;
	Mp.rand = function(n, m) {
		return Math.floor(Math.random() * (m - n + 1) + n);
	};
	Mp.PHI = p;
	Mp.LOW_PHI = 1 / p;

	// eliminare il flickering su IE6
	if(Agent.isMSIE(6)) try { document.execCommand("BackgroundImageCache", false, true); } catch (e){}

})();
