/*
* @	WST - Web Standards Tools v 1.1
* @ http://wstframework.org
* @ Diego de Andrade Pereira - contact@wstframework.org
* @ Released on 13/10/2008 10:07
* @ See GPL LICENSE.txt for the license usage
*/


// testes tlkasej ldjflasd jflkads jl

(function(){
	/* ------------------------------------------------------------------------------------------------
													BASICS
	------------------------------------------------------------------------------------------------ */
	var wst = window.wst = function(expr)
	{
		// @wstFnID [wst.constructor]
		if(!wst.is.wst(this) && wst.ok(expr))
		{
			return (new wst).get(wst.create(expr));
		}
		else
		{
			// wst uid
			this.uid = wst.core.instances.length;
			wst.core.instances[this.uid] = this;
			
			/* ------------------------------------------------------------------------------------------
													PROTOTYPE OBJECTS
			------------------------------------------------------------------------------------------ */
			
			// wst dom object
			this.dom = new wst.proto.dom;
			
			// wst opacity object
			if(this.opacity)
			{
				this.opacity = new this.opacity();
				this.opacity.constructor = this;
			}
			
			// wst rollOver object
			if(this.rollOver)
			{
				this.rollOver = new this.rollOver();
				this.rollOver.constructor = this;
			}
		}
	};
	
	wst.proto = wst.prototype = {};
	
	wst.ok = wst.proto.ok = function(expr)
	{
		// @wstFnID [wst.ok]
		return (expr != null) && (expr != undefined) && (expr !== '') && (expr !== false);
	};
	
	wst.extend = wst.proto.extend = function(target, base)
	{
		// @wstFnID [wst.extend]
		if(wst.ok(target) && wst.ok(base))
		{
			var prop;
			
			if((target instanceof Array) && (typeof target.length == 'number'))
			{
				var i = -1;
				
				while(target[++i])
				{
					for(prop in base)
						target[i][prop] = base[prop];
				}
			}
			else
			{
				for(prop in base)
					target[prop] = base[prop];
			}
			
			return target;
		}
	};
	
	wst.object = {
		create : function(base)
		{
			// @wstFnID [wst.object.create]
			var object = {};
			base = base || false;
			
			if(base)
				wst.extend(object, base);
			
			return object;
		},
		createClass : function(className, isGlobal)
		{
			// @wstFnID [wst.object.createClass]
			return new wst.ClassBuilder(className, isGlobal);
		}
	};
	
	wst.ClassBuilder = (function(){
		/*
		* private members
		*/
		var _name = null;
		var _constructor = '';
		var _isGlobal = false;
		var _members = [];
		var _extends = '';
		var _privateMembersCount = 0;
		
		var _objectToString = function(obj)
		{
			// @wstFnID [wst.ClassBuilder._objectToString]
			var str = '{\n';
			
			for(var prop in obj)
			{
				if(wst.is(obj[prop]) == 'object')
				{
					str += '\t"' + prop + '" : ' + (
						wst.is.fn(obj[prop]) || wst.is.array(obj[prop]) ?
							obj[prop].toString()
							: wst.is.string(obj[prop]) ? '"' + obj[prop] + '"' : obj[prop]
					) + ',\n';
				}
				else if(wst.is.object(obj[prop]))
				{
					str += _objectToString(obj[prop]);
				}
			}
			
			str += '}';
			return str;
		};
		
		/*
		* constructor
		*/
		function ClassBuilder(className, isGlobal)
		{
			// @wstFnID [wst.ClassBuilder]
			_members = [];
			_extends = '';
			_privateMembersCount = 0;
			_isGlobal = !!isGlobal;
			
			if(wst.ok(className))
			{
				_name = className;
				_constructor = 'function ' + _name + '(){}';
			}
			else
			{
				_name = null;
				_constructor = null;
				throw wst.messages.ClassBuilder.missingClassName;
			}
		}
		
		/*
		* public members
		*/
		ClassBuilder.prototype.addConstructor = function(constructorFn)
		{
			// @wstFnID [wst.ClassBuilder.addConstructor]
			if(wst.is.fn(constructorFn))
			{
				var fnStr = constructorFn.toString();
				_constructor = fnStr.replace(fnStr.slice(0, fnStr.indexOf('(')), 'function ' + _name);
			}
			else
			{
				throw wst.messages.ClassBuilder.invalidConstructor;
			}
		};
		
		ClassBuilder.prototype.addMember = function(type, name, value)
		{
			// @wstFnID [wst.ClassBuilder.addMember]
			if(arguments.length == 3)
			{
				if(type == 'private')
					_privateMembersCount++;
					
				_members.push(({type : type, name : name, value : (!wst.is.undef(value) ? value : null)}));
			}
			else
			{
				throw wst.messages.ClassBuilder.wrongArgs;
			}
		};
		
		ClassBuilder.prototype.extend = function(base, propObj)
		{
			// @wstFnID [wst.ClassBuilder.extend]
			propObj = wst.ok(propObj) ? (propObj + '.') : '';
			
			for(var prop in base)
			{
				if(wst.is(base[prop]) == 'object')
				{
					_extends += '\t' + _name + '.prototype.' + propObj + prop + ' = ' + (
						wst.is.fn(base[prop]) || wst.is.array(base[prop]) ?
							base[prop].toString()
							: wst.is.string(base[prop]) ? '"' + base[prop] + '"' : base[prop]
					) + ';\n';
				}
				else if(wst.is.object(base[prop]))
				{
					this.extend(base[prop], prop);
				}
			}
		};
		
		ClassBuilder.prototype.build = function()
		{
			// @wstFnID [wst.ClassBuilder.build]
			var ret = null;
			
			if(wst.ok(_constructor))
			{
				var classBody = '';
				var i = -1;
				var current;
				var value;
				
				if(_privateMembersCount > 0)
				{
					classBody += '(function(){\n'
					+ '\tvar _private = {};\n'
					+ '\tvar instance;\n';

					_constructor = _constructor.replace('{', '{\n\tinstance = this;\n');
				}
				
				classBody += '\t' + _constructor + '\n';
				
				if(_isGlobal)
					classBody += '\n\twindow.' + _name + ' = ' + _name + ';';
				
				while((current = _members[++i]))
				{
					value = wst.is(current.value) == 'object' ? _objectToString(current.value) : wst.is.string(current.value) ? '"' + current.value + '"' : current.value;
					value = value === '' ? '""' : value;
					
					switch(current.type)
					{
						case 'public':
							classBody += '\t' + _name + '.prototype.' + current.name + ' = ' + value + ';\n';
							break;
						case 'private':
							classBody += '\t_private.' + current.name + ' = ' + value + ';\n';
							break;
						case 'static':
							classBody += '\t' + _name + '.' + current.name + ' = ' + value + ';\n';
							break;
						default:
							throw '"type" (' + current.type + ') not supported in ' + current.name;
							break;
					}
				}
				
				classBody += '\t' + _extends + '\n';
				
				if(_privateMembersCount > 0)
				{
					//+ '\n\t_private.source = arguments.callee.toString();\n'
					classBody += '\treturn ' + _name + ';\n'
					+ '})()';
				}
				else
				{
					classBody += '\t' + _name + ';';
				}
				
				try{
					ret = eval(classBody);
				}
				catch(err){
					wst.error(err);
				};
			}
			else
			{
				throw wst.messages.ClassBuilder.noConstructor;
			}
		
			return ret;
		};
		
		return ClassBuilder;
	})();
	
	/* ------------------------------------------------------------------------------------------------
													EXTEND
	------------------------------------------------------------------------------------------------ */
	wst.validObject = function(expr)
	{
		// @wstFnID [wst.validObject]
		expr = expr || this.E[0];
		expr = typeof expr == 'string' ? this.get(expr) : expr;
		return (expr != null && (typeof expr == 'object' || typeof expr == 'function') && ((typeof expr.nodeType != 'undefined' ? expr.nodeType != 8 : false) || expr == window || expr == document));
	};
	
	wst.error = function()
	{
		// @wstFnID [wst.error]
		var msg, args = arguments;
		var caller = wst.core._getCaller();
		var errFrom, errName, errNumber, errDescription, errMessage, errFromDefault, errType, errTitle, errUrl, errLine;
		
		if(wst.messages)
		{
			errFrom = wst.messages.functions.errorFrom;
			errName = wst.messages.functions.errorName;
			errNumber = wst.messages.functions.errorNumber;
			errDescription = wst.messages.functions.errorDescription;
			errMessage = wst.messages.functions.errorMessage;
			errFromDefault = wst.messages.functions.errorFromDefault;
			errType = wst.messages.functions.errorType;
			errTitle = wst.messages.functions.errorTitle;
			errUrl = wst.messages.functions.errorUrl;
			errLine = wst.messages.functions.errorLine;
		}
		else
		{
			errFrom = 'Origin';
			errName = 'Name';
			errNumber = 'Number';
			errDescription = 'Description';
			errMessage = 'Message';
			errFromDefault = '(Unknown)';
			errType = 'Type';
			errTitle = 'There was an execution error.';
			errUrl = 'Page URL';
			errLine = 'Code line';
		}
		
		switch(args.length)
		{
			case 1:
				if(typeof args[0] == 'string')
				{
					msg = args[0];
				}
				else
				{
					msg = errFrom + ': ' + (args[1] || caller || errFromDefault) + '\n'
						+ errName + ': ' + args[0].name + '\n'
						+ errNumber + ': ' + (args[0].number & 0xFFFF) + '\n'
						+ errDescription + ': ' + args[0].description + '\n'
						+ errMessage + ': ' + args[0].message;
				}
				break;
			case 2:
				msg = errFrom + ': ' + (args[1] || caller || errFromDefault) + '\n'
					+ errName + ': ' + args[0].name + '\n'
					+ errType + ': ' + args[0] + '\n'
					+ errNumber + ': ' + (args[0].number & 0xFFFF) + '\n'
					+ errDescription + ': ' + args[0].description + '\n'
					+ errMessage + ': ' + args[0].message;
				break;
			case 3:
				msg = errTitle + '\n'
					+ errFrom + ': ' + (caller || errFromDefault) + '\n'
					+ errMessage + ': ' + args[0] + '\n'
					+ errUrl + ': ' + args[1] + '\n'
					+ errLine + ': ' + (wst.browser.ie ? args[2] - 1 : args[2]);
				break;
		}
		
		if(wst.core.hasLog('errors'))
			wst.log.add('errors', caller, (typeof args[0].message != 'undefined' ? args[0].message : args[0]));
		
		if(this.alertErrors || wst.core.alertErrors)
			alert(msg);
	};
	
	/*****************
	* @ DOM OBJECT @ *
	*****************/
	var dom = function(){};
	
	var _comparsions = {
		'=' : function(curValue, value){ return value.indexOf('|') > 0 ? !!wst.regex(curValue, '^(' + value + ')$') : (curValue == value); },
		'!=' : function(curValue, value){ return value.indexOf('|') > 0 ? !wst.regex(curValue, '^(' + value + ')$') : (curValue != value); },
		'*=' : function(curValue, value){ return curValue.indexOf(value) > -1; },
		'~=' : function(curValue, value){ return !!wst.regex(curValue, '(?:^|\\s)(' + value + ')(?:\\s|$)'); },
		'%=' : function(curValue, value){ return curValue.indexOf(value) === -1; },
		'^=' : function(curValue, value){ return !!wst.regex(curValue, '^(' + value + ')'); },
		'$=' : function(curValue, value){ return !!wst.regex(curValue, '(' + value + ')$'); },
		'|=' : function(curValue, value){ return !!wst.regex(curValue, '^(' + value + '-)'); }
	};
	
	var _addNode = function(node, array, set)
	{
		// @wstFnID [_addNode]
		if(!set.temp[set.tag])
			set.temp[set.tag] = [];
		
		set.temp[set.tag].push(node);
		array.push(node);
		
		return array;
	};
	
	var _addedToTemp = function(node, set)
	{
		// @wstFnID [_addedToTemp]
		var found = false;
		
		if(set.temp[set.tag])
			found = wst.search(node, set.temp[set.tag], true) !== -1;
		
		return found;
	};
	
	var _dom = {
		getByAttr : function(attr, value, tagToFind, type, self, optTag, not, array, set)
		{
			// @wstFnID [wst.dom.getByAttr]
			var nodes = array ? array : [];
			var attrs = wst.html.attributes;
			attr = attrs[attr] || attr;
			tagToFind = tagToFind || '*';
			type = type || '=';
			optTag = optTag || '*';
			var es = self ? (wst.is.array(tagToFind) ? tagToFind : [tagToFind]) : (wst.is.dom(tagToFind) ? tagToFind.getElementsByTagName(optTag) : document.getElementsByTagName(tagToFind));
			var curE, curValue, addCur;
			var i = -1, len = es.length;
			
			while(++i < len)
			{
				curE = es[i];
				//curValue = curE[attr];
				curValue = attr == 'style' ? curE.style.cssText : curE.getAttribute(attr) || curE[attr];
				
				if(value !== null)
				{
					if(!_addedToTemp(curE, set))
						addCur = _comparsions[type](curValue, value);
					else
						addCur = false;
				}
				else
				{
					addCur = (curValue !== undefined);
				}
				
				if(not ^ addCur)
					_addNode(curE, nodes, set);
			}
			
			return nodes;
		},
		prev : function(set)
		{
			// @wstFnID [wst.dom.prev]
			var tag = set.tag;
			var context = set.context;
			var current, i = -1;
			var add = set.add;
			var array = [];
			
			while((current = context[++i]))
			{
				if(current.previousSibling)
				{
					var sib = current;
					
					while((sib = sib.previousSibling))
					{
						if(add)
						{
							if(_validateNode(sib, tag, set))
								_addNode(sib, array, set);
						}
						else
						{
							array.push(sib);
						}
					}
				}
			}
			
			if(add)
				set.context = array;
			
			return array;
		},
		next : function(set)
		{
			// @wstFnID [wst.dom.next]
			var tag = set.tag;
			var context = set.context;
			var current, i = -1;
			var add = set.add;
			var array = [];
			
			while((current = context[++i]))
			{
				if(current.nextSibling)
				{
					var sib = current;
					
					while((sib = sib.nextSibling))
					{
						if(add)
						{
							if(_validateNode(sib, tag, set))
								_addNode(sib, array, set);
						}
						else
						{
							array.push(sib);
						}
					}
				}
			}
			
			if(add)
				set.context = array;
			
			return array;
		},
		siblings : function(set)
		{
			// @wstFnID [wst.dom.siblings]
			var context = set.context;
			var current, i = -1;
			var add = set.add;
			var array = [];
			set.add = false;
			
			while((current = context[++i]))
			{
				if(current.previousSibling)
					array = array.concat(_dom.prev(set));
				
				if(current.nextSibling)
					array = array.concat(_dom.next(set));
			}
			
			if(add)
				set.context = array;
			
			set.add = add;
			
			return array;
		},
		parent : function(set)
		{
			// @wstFnID [wst.dom.parent]
			var context = set.context;
			var current, i = -1, parent;
			var add = set.add;
			var array = [];
			
			while((current = context[++i]))
			{
				if(add)
				{
					parent = !!current.parentNode ?
						current.parentNode
						: wst.is.doc(current) ?
							window
							: wst.is.win(current) && !!window.parent ?
								window.parent
								: null;
					
					if(parent && !_addedToTemp(parent, set))
						_addNode(parent, array, set);
				}
				else
				{
					array.push(parent);
				}
			}
			
			if(add)
				set.context = array;
			
			return array;
		},
		children : function(set)
		{
			// @wstFnID [wst.dom.children]
			var sel = set.self ? set.sel : set.go(1);
			var optimizeChild = set.self ? set.attr : set.next();
			var context = set.context;
			var current, i = -1;
			var array = [];
			var filter;
			
			if((sel == ':') && _children.test(optimizeChild))
			{
				filter = optimizeChild.match(_children)[1];
				set.go(1);
				
				if(_pseudoFn.test(optimizeChild) && !set.self)
					set.go(1);
			}
			else
			{
				filter = '_default';
				set.go(-1);
			}
			
			while((current = context[++i]))
				_selectChildren[filter](current, array, set);
			
			return array;
		},
		hasChildren : function(e)
		{
			// @wstFnID [wst.dom.hasChildren]
			return e ?
				e.hasChildNodes ?
					e.hasChildNodes()
					: (e.childNodes ? e.childNodes.length > 0 : false)
				: false;
		},
		family : function(root, type, n)
		{
			// @wstFnID [wst.dom.family]
			var returnObject = wst.core._duplicateWST(root);
			var set = _configSet('*', returnObject.E, root);
			var array;
			set.n = 1;
			set.last = ' ';
			
			if(typeof n == 'string')
			{
				set.expr[1] = set.tag = n;
				n = -1;
			}
			else
			{
				set.expr[1] = set.tag = '*';
				n = !wst.ok(n) ? -1 : n;
			}
			
			array = _dom[type](set);
			returnObject.total = (returnObject.E = (n == -1 ? array : [array[n]] || [])).length;
			returnObject.expr = set.expr.join('');
			
			return returnObject;
		},
		selectors : {
			' ' : function(set)
			{
				var tag = set.tag;
				var subSel = set.next();
				var next = set.expr[set.n + 2];
				var te, context = set.context;
				var current;
				var i = -1, j = -1;
				
				if(!set.not)
				{
					if((!_attrSelectors.test(subSel) && (subSel != ':')) || ((subSel == ':') && !_children.test(next) && (next != 'root')))
					{
						set.context = [];
						
						while((current = context[++i]))
						{
							te = current.getElementsByTagName(tag);
							j = -1;
							
							if(tag == '*')
							{
								// 'current' has only textNodes
								if((!set.root.dom.getTextNodes ? wst.dom.getTextNodes == true : true) && !wst.array.valid(te) && _dom.hasChildren(current))
									te = current.childNodes;
								
								if(!_addedToTemp(current, set))
								{
									while((current = te[++j]))
									{
										if(current.nodeType != 8)
											_addNode(current, set.context, set);
									}
								}
							}
							else
							{
								while((current = te[++j]))
								{
									if(!_addedToTemp(current, set))
										_addNode(current, set.context, set);
								}
							}
						}
					}
					else
					{
						if((subSel == ':') && _children.test(next))
							set.last = null;
							
						set.sel = set.go(1);
						_dom.selectors[set.sel](set);
						return;
					}
				}
				else
				{
					var cTag;
					set.context = [];
					
					while((current = context[++i]))
					{
						cTag = current.nodeName.toLowerCase();
						
						if((cTag != tag) && !_addedToTemp(current, set))
							_addNode(current, set.context, set);
					}
				}
				
				if(set.add)
					_get(set);
			},
			'#' : function(set)
			{
				var tag = set.tag;
				var id = set.go(1);
				var te = null;
				var context = set.context;
				set.context = [];
				
				if(!set.self)
				{
					var sameTag = false;
					te = document.getElementById(id);
					
					if(te)
						sameTag = (tag == '*') ? true : (tag == te.nodeName.toLowerCase());
					
					if(sameTag ^ set.not)
						_addNode(te, set.context, set);
					else
						return set.context = [];
				}
				else
				{
					var current;
					var i = -1;
					
					while((current = context[++i]))
						_dom.getByAttr('id', id, current, '=', set.self, tag, set.not, set.context, set);
				}
				
				_get(set);
			},
			'.' : function(set)
			{
				var tag = set.tag;
				var clss = set.go(1);
				var context = set.context;
				var current;
				var i = -1;
				set.context = [];
				
				while((current = context[++i]))
					_dom.getByAttr('class', clss, current, '=', set.self, tag, set.not, set.context, set);
				
				_get(set);
			},
			'[' : function(set)
			{
				var tag = set.tag;
				var attr = set.attr = set.go(1);
				var context = set.context;
				var attrParts, a, v, sep;
				var current;
				var i = -1;
				set.context = [];
				
				attrParts = set.root.dom.getAttrValue(attr);
				a = attrParts[0];
				v = attrParts[2];
				sep = attrParts[1];
				
				while((current = context[++i]))
					_dom.getByAttr(a, v, current, sep, set.self, tag, set.not, set.context, set);
				
				_get(set);
			},
			'>' : function(set)
			{
				set.context = _dom.children(set);
				_get(set);
			},
			'+' : function(set)
			{
				var tag = set.tag;
				var context = set.context;
				var next, current;
				var i = -1;
				set.context = [];
				
				while((current = context[++i]))
				{
					if(current.nextSibling)
					{
						next = current;
						
						while((next = next.nextSibling))
						{
							if(_validateNode(next, tag, set))
							{
								_addNode(next, set.context, set);
								break;
							}
						}
					}
				}
				
				_get(set);
			},
			'$' : function(set)
			{
				var tag = set.tag;
				var context = set.context;
				var prev, current;
				var i = -1;
				set.context = [];
				
				while((current = context[++i]))
				{
					if(current.previousSibling)
					{
						prev = current;
						
						while((prev = prev.previousSibling))
						{
							if(_validateNode(prev, tag, set))
							{
								_addNode(prev, set.context, set);
								break;
							}
						}
					}
				}
				
				_get(set);
			},
			'~' : function(set)
			{
				_dom.next(set);
				_get(set);
			},
			'%' : function(set)
			{
				_dom.prev(set);
				_get(set);
			},
			':' : function(set)
			{
				var pseudoAttr = set.go(1);
				var value = _pseudoFn.test(pseudoAttr) ? set.go(1) : '';
				var current, i = -1, addCur;
				var _set;
				var initFirst = set.last == null;
				
				if(value)
					value = value.slice(1, -1);
				
				if(initFirst)
				{
					_set = _configSet(set.tag, set.context, set.root);
					_set.temp = set.temp;
					_get(_set);
					set.context = _set.context;
					set.temp = {};
					set.self = true;
					
					if(_pseudoFn.test(pseudoAttr))
						set.go(-1);
				}
				
				var context = set.context;
				set.context = [];
				
				if(context.length > 0)
				{
					switch(pseudoAttr)
					{
						case 'first':			// additional: get the first element of the current selection
							if(set.not)
							{
								context.shift();
								
								while((current = context[++i]))
									_addNode(current, set.context, set);
							}
							else
							{
								_addNode(context[0], set.context, set);
							}
							break;
						case 'last':			// additional: get the last element of the current selection
							if(set.not)
							{
								context.pop();
								
								while((current = context[++i]))
									_addNode(current, set.context, set);
							}
							else
							{
								_addNode(context.slice(-1)[0], set.context, set);
							}
							break;
						case 'first-child':		// CSS 2 standard: get all elements of the current selection that are first children
						case 'last-child':		// additional: get all elemnts of the current selection that are last children
						case 'only-child':		// CSS 3: get elemnt if it is the only child of its parent
						case 'empty':			// CSS 3: get element if it has not child
						case 'nth-child':		// CSS 3: get element if is it the nth child of its parent
							set.context = context;
							set.attr = pseudoAttr;
							set.context = _dom.children(set);
							break;
						case 'root':			// CSS 3: get the root element of the document
							// http://www.w3.org/TR/css3-selectors/#structural-pseudos
							// "The :root pseudo-class represents an element that is the root of the document.
							// In HTML 4, this is always the HTML element."
							if(!set.not)
								set.context.push(document.documentElement);
							break;
						case 'not':				// CSS 3: get element if it doesn't match to the expression
							_set = _configSet(value, context, set.root);
							_set.not = true;
							_set.tag = set.tag;
							_set.sel = set.last;
							_set.temp = set.temp;
							_get(_set);
							set.context = _set.context;
							set.temp = _set.temp;
							break;	
						case 'enabled':			// CSS 3: get elements with enabled property set to true
							while((current = context[++i]))
							{
								addCur = !current.disabled;
								
								if(set.not ^ addCur)
									_addNode(current, set.context, set);
							}
							break;
						case 'disabled':		// CSS 3: get elements with enabled property set to false
							while((current = context[++i]))
							{
								addCur = !!current.disabled;
								
								if(set.not ^ addCur)
									_addNode(current, set.context, set);
							}
							break;
						case 'checked':			// CSS 3: get elements with checked property set to true
							while((current = context[++i]))
							{
								addCur = !!current.checked;
								
								if(set.not ^ addCur)
									_addNode(current, set.context, set);
							}
							break;
						case 'indeterminate':	// CSS 3: get elements with indeterminate property set to true
							while((current = context[++i]))
							{
								addCur = !!current.indeterminate;
								
								if(set.not ^ addCur)
									_addNode(current, set.context, set);
							}
							break;
						case 'target':			// CSS 3: get element that is the target of the URI
							var name = window.location.hash.slice(1);
							
							while((current = context[++i]))
							{
								addCur = current.id ? (current.id === name) : false;
								
								if(set.not ^ addCur)
									_addNode(current, set.context, set);
							}
							break;
						case 'hover':			// CSS 3: get elements in the hover state
							
							break;
						case 'focus':			// CSS 3: get elements in the focus state
							
							break;
						case 'active':			// CSS 3: get elements in the active state
							
							break;
						case 'contains':		// CSS 3: get elements that have the given text as a substring of its contents
							var text;
							
							while((current = context[++i]))
							{
								text = current.textContent || current.innerText || '';
								addCur = text.indexOf(value) > -1;
								
								if(set.not ^ addCur)
									_addNode(current, set.context, set);
							}
						case 'lang':			// CSS 2: get elements with the given lang attribute
							while((current = context[++i]))
							{
								addCur = current.getAttribute('lang') === value;
								
								if(set.not ^ addCur)
									_addNode(current, set.context, set);
							}
							break;
						default:
							break;
					}
				}
				
				if(set.sess)
					delete set.sess;

				if(!set.self || initFirst)
					_get(set);
			}
		}
	};
	
	// auxiliar function for sort DOM elements list
	var _sortDOM = function(a, b)
	{
		// @wstFnID [wst._sortDOM]
		if(a.compareDocumentPosition)
			return 3 - (a.compareDocumentPosition(b) & 6);
		else
			return a.sourceIndex - b.sourceIndex;
	};
	
	var _selectChildren = {
		first : function(current, array, set)
		{
			// @wstFnID [wst._selectChildren.first]
			var firstChild = set.self ? current.parentNode.firstChild : current.firstChild;
			
			if(firstChild ? !_validateNode(firstChild, set.tag, set, false) : false)
			{
				while(firstChild ? firstChild.nodeType != 1 : false)
					firstChild = firstChild.nextSibling;
			}
			
			if((set.self ? (current == firstChild) : !!firstChild) ^ set.not)
			{
				if(set.self)
					firstChild = current;
				
				if(set.add)
					_addNode(firstChild, array, set);
				else
					array.push(firstChild);
			}
		},
		last : function(current, array, set)
		{
			// @wstFnID [wst._selectChildren.last]
			var lastChild = set.self ? current.parentNode.lastChild : current.lastChild;
			
			if(lastChild ? !_validateNode(lastChild, set.tag, set, false) : false)
			{
				while(lastChild ? lastChild.nodeType != 1 : false)
					lastChild = lastChild.previousSibling;
			}
			
			if((set.self ? (current == lastChild) : !!lastChild) ^ set.not)
			{
				if(set.self)
					lastChild = current;
				
				if(set.add)
					_addNode(lastChild, array, set);
				else
					array.push(lastChild);
			}
		},
		only : function(current, array, set)
		{
			// @wstFnID [wst._selectChildren.only]
			var children = set.self ? current.parentNode.childNodes : current.childNodes;
			var child;
			var found = false;
			
			if(children.length == 1)
			{
				child = children[0];
				found = set.add && _validateNode(child, set.tag, set, false);
			}
			else if(children.length > 0)
			{
				if(!set.root.dom.getTextNodes && !wst.dom.getTextNodes)
				{
					var i = -1, count = 0;
					var next;
					
					while((next = children[++i]))
					{
						if(next.nodeType == 1)
						{
							count++;
							child = next;
						}
					}
					
					found = (count == 1) && _validateNode(child, set.tag, set, false);
				}
			}
			
			if(found ^ set.not)
			{
				if(set.self)
					child = current;
				
				if(set.add)
					_addNode(child, array, set);
				else
					array.push(child);
			}
		},
		nth : function(current, array, set)
		{
			// @wstFnID [wst._selectChildren.nth]
			var value = set.getCur().slice(1, -1);
			var matches;
			var step,	// a: step size
				offset;	// b: start offset
			var last = -1, node, index = -1, addCur = false, repeat, same, mod, i = -1, children = [];
			var oSelf = set.self, oTag = set.tag, oAdd = set.add;
			
			if(/^\d+$/.test(value))
			{
				step = 0;
				offset = parseInt(value);
			}
			else if(/^\D+$/.test(value))
			{
				step = Number(((value == 'even' || value == 'odd') && 2) || (value == 'n' && 1));
				offset = Number((value == 'even' && 2) || ((value == 'odd' || value == 'n') && 1));
			}
			else
			{
				matches = value.match(/^((?:-)?\d*)?(?:n)?((?:[+-]{1})?\d*)?$/);
				step = parseInt(wst.ok(matches[1]) && matches[1]) || ((String(matches[1]).indexOf('-') != -1) && -1) || 1;
				offset = parseInt(wst.ok(matches[2]) && matches[2]) || step;
			}
			
			if(offset < 0)
				offset = Math.abs(offset + step);
			
			repeat = step != 0;
			same = step === offset;
			
			set.tag = '*';
			set.self = false;
			set.add = false;

			if(set.sess && (set.sess.element.parentNode == current.parentNode))
			{
				children = set.sess.children;
				last = set.sess.last;
				
				if(last > -1)
					i = last - 1;
			}
			else
			{
				this._default((oSelf ? current.parentNode : current), children, set);
				
				set.sess = {
					children : children,
					last : -1
				};
			}

			set.sess.element = current;
			set.tag = oTag;
			set.self = oSelf;
			set.add = oAdd;

			if(repeat)
			{
				while((node = children[++i]))
				{
					if(oSelf ? (current === node) : true)
					{
						addCur = false;
						index = wst.search(node, children, true) + 1;

						if(_validateNode(node, set.tag, set))
						{
							if(step < 0)
							{
								addCur = index <= offset;
							}
							else
							{
								if(last == -1)
									mod = index % step, addCur = (index >= offset) && ((same && (mod === 0)) || (!same && (mod !== 0)) || (step === 1));
								else
									addCur = index >= (last + step);
							}
						}

						if(set.not ^ addCur)
						{
							set.sess.last = last = index;
							_addNode(node, array, set);
						}

						if(oSelf)
							break;
					}
				}
			}
			else
			{
				node = children[offset - 1];
				
				if(node ? _validateNode(node, set.tag, set) : false)
					addCur = true; 
				
				if((set.not ^ addCur) && (oSelf ? (current === node) : true))
					_addNode(node, array, set);
			}
		},
		empty : function(current, array, set)
		{
			// @wstFnID [wst._selectChildren.empty]
			if(!_dom.hasChildren(current) ^ set.not)
			{
				if(set.add)
					_addNode(current, array, set);
				else
					array.push(current);
			}
		},
		_default : function(current, array, set)
		{
			// @wstFnID [wst._selectChildren._default]
			var children = current.childNodes;
			var child;
			var i = -1;
			
			if(children ? children.length > 0 : false)
			{
				while((child = children[++i]))
				{
					if(_validateNode(child, set.tag, set))
					{
						if(set.add)
							_addNode(child, array, set);
						else
							array.push(child);
					}
				}
			}
		}
	};
	
	// creates an object from the given selector expression
	var _matchSelectors = function(expr, explode)
	{
		// @wstFnID [wst._matchSelectors]
		var newExpr = expr;
		newExpr = wst.trim(newExpr);
		//newExpr = (!_iniTagName.test(newExpr) ? '*' : '') + newExpr;
		newExpr = (newExpr.indexOf(' ') != 0) ? (_iniSelector.test(newExpr) ? newExpr : ' ' + newExpr) : newExpr;
		newExpr = newExpr
			.replace(_multiSpaces, ' ')
			.replace(_aloneSelector, '$1*$2')
			//.replace(_aloneSelector, function($1, $2){ return ($1 == ' ') ? (' *' + $2) : ('*' + $1) })
			.replace(_trimSelectors, '$1');
		
		if(explode)
			newExpr = newExpr.match(_matches);
		
		return newExpr;
	};
	
	var _configSet = function(expr, context, root)
	{
		// @wstFnID [wst._configSet]
		var set = {
			context : context,
			expr : _matchSelectors(expr, true),
			sel : null,
			tag : null,
			attr : null,
			n : -1,
			last : null,
			not : false,
			root : root,
			self : false,
			add : true,
			temp : {},
			next : function()
			{
				return this.expr[this.n + 1];
			},
			prev : function()
			{
				return this.expr[this.n - 1];
			},
			go : function(n)
			{
				this.n += n;
				return this.expr[this.n];
			},
			getSel : function()
			{
				var sel = this.go(1);
				return false || sel;
			},
			getTag : function()
			{
				var tag = this.go(1);
				
				//if(!_iniTagName.test(tag) ^ (_attrSelectors.test(this.sel) && (tag != '*')))
				//if(!this.self ? !_iniTagName.test(tag) : (this.sel == ':') && (_children.test(tag) || _pseudoFn.test(tag)))
				if(!this.self ? !_iniTagName.test(tag) : (this.sel == ':') && _pseudoSelectors.test(tag))
				{
					tag = this.tag;
					this.n--;
				}
				
				return false || tag;
			},
			getCur : function()
			{
				return this.expr[this.n];
			}
		};
		
		if(_invertedSelector.test(set.expr.slice(0, 3).join('')))
		{
			if(set.expr[0] == ' ')
				set.expr.shift();
			
			var a = set.expr[0];
			set.expr[0] = set.expr[1];
			set.expr[1] = a;
		}
		
		return set;
	};
	
	var _validateNode = function(node, tag, set, checkUID)
	{
		// @wstFnID [wst._validateNode]
		var valid = false;
		
		if(node)
		{
			var cTag = node.nodeName.toLowerCase();
			var sameTag = cTag == ((tag == '*') ? cTag : tag);
			var validNodeType = (node.nodeType == 1) ? true : (node.nodeType == 3) && (set.root.dom.getTextNodes || wst.dom.getTextNodes);
			checkUID = checkUID == undefined ? true : checkUID;
			valid = validNodeType && sameTag && (checkUID ? !_addedToTemp(node, set) : true);
		}
		
		return valid;
	};
	
	// do the loop looking for elements
	var _get = function(set)
	{
		// @wstFnID [wst._get]
		set.last	= set.sel;
		set.sel		= set.getSel();
		set.self	= !!set.last && _attrSelectors.test(set.sel);
		set.tag		= set.getTag();
		
		if(set.tag && set.sel && (set.context.length > 0))
		{
			if(_dom.selectors[set.sel])
				_dom.selectors[set.sel](set);
			else
				throw wst.format(wst.messages.functions.invalidSelector, {n1 : set.sel, n2 : set.expr.join('')});
		}
	};
	
	wst.extend(dom.prototype, {
		getAttrValue : function(attr)
		{
			// @wstFnID [wst.dom.getAttrValue]
			var attrs = wst.html.attributes;
			var array;
			var regex = /(\w*)([!*^$%|~]?=)(.*)/;
			
			attr = attr.replace(/\]|\[/g, '');
			attr = attrs[attr] || attr;
			array = regex.test(attr) ? attr.replace(/'|"/g, '').match(regex).slice(1) : [attr, '=', ''];
			
			if((attr.indexOf('=') == -1) && (array[2] == ''))
				array[2] = null;
			
			return array;
		},
		cssAttrName : function(attr, sintax)
		{
			// @wstFnID [wst.dom.cssAttrName]
			sintax = '' || sintax;
			
			if(((attr.indexOf('-') > -1) && !wst.browser.gecko) || sintax == 'js')
				attr = attr.replace(/-(\w{1})/g, function($0, $1){ return $1.toUpperCase() });
			else if(((attr.indexOf('-') == -1) && wst.browser.gecko) || sintax == 'css')
				attr = attr.replace(/([A-Z]{1})/g, '-$1').toLowerCase();
			
			return attr;
		},
		cssHexValue : function(str)
		{
			// @wstFnID [wst.dom.cssHexValue]
			var values = str.match(/(\d+)/g);
			var hex = '#';
			var i = -1, current;
			
			while((current = values[++i]) != null)
				hex += wst.hexEncode(current);
				
			return hex;
		},
		getStyle : function(style, e, dom)
		{
			// @wstFnID [wst.dom.getStyle]
			style = dom.cssAttrName(style);
			
			if(e.currentStyle)
			{
				style = e.currentStyle[style];
			}
			else if(window.getComputedStyle)
			{
				style = document.defaultView.getComputedStyle(e, null).getPropertyValue(style);
				style = style.indexOf('rgb') > -1 ? dom.cssHexValue(style) : style;
			}
			
			return style;
		},
		setStyle : function(styles, value, e, dom)
		{
			// @wstFnID [wst.dom.setStyle]
			var curE, i = -1;
			value = String(value).replace(/;/g, '');
			
			while((curE = e[++i]))
			{
				if(typeof styles == 'object')
				{
					for(var style in styles)
						curE.style[dom.cssAttrName(style, 'js')] = styles[style];
				}
				else
				{
					curE.style[dom.cssAttrName(styles, 'js')] = value;
				}
			}
		},
		makeXHTML : function(e, formatSource)
		{
			// @wstFnID [wst.dom.makeXHTML]
			formatSource = formatSource || false;
			var newLine = formatSource ? '\n' : '';
			//var tab = formatSource ? '\t' : '';
			//var nTab = 0;
			var xhtml = '';
			var HTMLChars;
			
			if(wst.modules.HTMLChars ? !wst.modules.HTMLChars.loaded : false)
			{
				if(wst.modules.load('HTMLChars') === false)
					return false;
			}
			
			HTMLChars = wst.html.chars;
			
			wst.loop(e, function(){
				var tag = this.nodeType == 1 ? (this.nodeName || this.tagName).toLowerCase() : '';
				var attrs = '';
				var children = '';
				//var i = 0;
				
				if(!!this.attributes ? this.attributes.length > 0 : false)
				{
					wst.loop(this.attributes, function(){
						attrs += wst.browser.ie ? 
							(this.nodeValue != null) && (this.nodeValue != '') && (this.nodeValue != 'inherit') ? ' ' + this.nodeName + '="' + this.nodeValue + '"' : ''
							: ' ' + this.nodeName + '="' + this.nodeValue + '"';
					});
				}
				
				if(_dom.hasChildren(this))
				{
					//nTab++;
					wst.loop(this.childNodes, function(){
						children += wst.dom.makeXHTML(this);
					});
					
					//while(i++ < nTab)
					//	tab += tab;
				}
				
				xhtml += tag != '' ? 
					'<' + tag + attrs + (children == '' ? '/>' : '>' + newLine + children + newLine + '</' + tag + '>') : 
					this.nodeType == 3 ? 
						!!HTMLChars ?
							this.nodeValue.replace(/[^\w\s\.!?,@#$%\(\)\[\]-]/g, function(c){ return !!HTMLChars[c] ? HTMLChars[c].name : c })
							: this.nodeValue
						: '';
			});
			
			return xhtml;
		},
		getTextNodes : false,
		cacheElements : false
	});
	
	wst.dom = new dom;
	wst.proto.dom = dom;
	
	wst.extend(wst, {
		get : function(expr, context)
		{
			if(!wst.is.wst(this))
				return (new wst).get(expr, context);
			
			try
			{
				// @wstFnID [wst.get]
				var r = [];
				
				if(typeof expr != 'undefined')
				{
					this.expr = expr;
					
					if(typeof expr == 'string')
					{
						// recover from cache
						if(wst.cache.enabled && this.dom.cacheElements ? wst.cache.get(this.expr) : false)
						{
							r = wst.cache.get(this.expr).dom;
						}
						else
						{
							context = (this.total > 0) && (context == undefined) ? this.E : (!wst.is.array(context) ? [context || document] : context);
							
							if(expr.indexOf(',') > -1)
							{
								var current, m, i = -1, oExpr = this.expr, arrayE = expr.replace(/\s*,\s+/g, ',').split(',');
								
								while((current = arrayE[++i]))
								{
									m = this.get(current, context).E;
									r = wst.array(m, r);
								}
								
								r = wst.array.unique(r);
								this.expr = oExpr;
							}
							else
							{
								var set = _configSet(expr, context, this);
								_get(set);
								r = set.context;
								
								// cache the result
								if(wst.cache.enabled && this.dom.cacheElements)
									wst.cache.add(this.expr, r, 'dom');
							}
						}
					}
					else
					{
						r = wst.is.wst(expr) ?
							expr.E :
							wst.ok(expr) ?
								(!wst.is.array(expr) ? wst.array.create(expr) : expr) :
								[];
					}
				}
				else
				{
					r = [];
				}
				
				// log
				if(wst.core.hasLog('dom'))
					wst.log.add('dom', wst.core._getCaller(), (r.length || 1));
				
				this.total = (this.E = r).length;
				
				return this;
			}
			catch(err)
			{
				if(this.alertErrors)
					wst.error(err);
				
				if(wst.core.hasLog('errors'))
					wst.log.add('errors', wst.core._getCaller(), (err.message || err));
				
				this.total = (this.E = []).length;
				
				return this;
			}
		},
		add : function(expr)
		{
			// @wstFnID [wst.add]
			if(wst.is.dom(expr))
			{
				this.E.push(expr);
				this.total += 1;
			}
			else if(wst.is.string(expr))
			{
				this.E = wst.array(this.E, this.get(expr).E);
				this.total = this.E.length;
			}
			
			return this;
		},
		rem : function(expr)
		{
			// @wstFnID [wst.rem]
			if(!wst.is.undef(expr))
			{
				if(wst.is.dom(expr))
				{
					wst.inArray(expr, this.E, 'delete');
				}
				else if(wst.is.string(expr))
				{
					var props = expr.split('=');
					
					this.filter(props[0], props[1]);
				}
				else if(wst.is.number(expr))
				{
					this.E = wst.array.remove(expr, this.E);
				}
			}
			else
			{
				this.E.pop();
			}
			
			this.total = this.E.length;
			
			return this;
		},
		parent : function(n)
		{
			// @wstFnID [wst.parent]
			return _dom.family(this, 'parent', n);
		},
		next : function(n)
		{
			// @wstFnID [wst.next]
			return _dom.family(this, 'next', n);
		},
		prev : function(n)
		{
			// @wstFnID [wst.prev]
			return _dom.family(this, 'prev', n);
		},
		siblings : function(n)
		{
			// @wstFnID [wst.siblings]
			return _dom.family(this, 'siblings', n);
		},
		children : function(n)
		{
			// @wstFnID [wst.children]
			return _dom.family(this, 'children', n);
		},
		hasChildren : function()
		{
			// @wstFnID [wst.hasChildren]
			return _dom.hasChildren(this.E[0]);
		},
		create : function(e)
		{
			// @wstFnID [wst.create]
			var elements = null;
			
			if(wst.html.regex.tag.test(e))
			{
				var xmlElements = wst.xml(e);
				var nodes = wst.ok(xmlElements) ?
					wst.is.doc(xmlElements) ?
						[xmlElements.documentElement]
						: xmlElements.length > 0 ?
							xmlElements
							: false
					: false;
				
				if(nodes)
				{
					elements = (function(nodes, parent){
						var i = -1, j = -1;
						var node = null;
						var correctAttrs = wst.html.attributes;
						var element, attr, attrs, correctAttr;
						var list = [];
						
						while((node = nodes[++i]))
						{
							switch(node.nodeType)
							{
								case 1:
									element = document.createElement(node.nodeName);
									attrs = node.attributes;
									
									// attributes
									if(attrs.length > 0)
									{
										j = -1;
										
										while((attr = attrs[++j]))
										{
											correctAttr = correctAttrs[attr.nodeName] || attr.nodeName;
											correctAttr == 'style' ? element[correctAttr].cssText = attr.nodeValue : element[correctAttr] = attr.nodeValue;
										}
									}
									
									// children
									if(node.childNodes ? node.childNodes.length > 0 : false)
										arguments.callee(node.childNodes, element);
									
									break;
								case 3:
									element = document.createTextNode(node.nodeValue);
									break;
								default:
									element = null;
									break;
							}
							
							if(element && parent)
								parent.appendChild(element);
							else
								list.push(element);
						}
						
						return list;
					})(nodes);
				}
				
				if(wst.is.doc(xmlElements))
					elements = elements[0];
			}
			else
			{
				elements = document.createTextNode(wst.html.replaceEntities(e));
			}
			
			return elements;
		},
		tag : function()
		{
			// @wstFnID [wst.dom.tag]
			var e = this.E[0];
			
			return e ? e.nodeName.toLowerCase() : '';
		},
		type : function()
		{
			// @wstFnID [wst.dom.type]
			var e = this.E[0];
			
			return e ? e.nodeType : '';
		},
		value : function(val)
		{
			// @wstFnID [wst.dom.value]
			var ret = null;
			
			if(this.total > 0)
			{
				if(!wst.is.undef(val))
				{
					this.loop(function(){
						if(!wst.is.undef(this.value))
							this.value = val;
					});
					
					ret = this;
				}
				else
				{
					ret = this.E[0].value;
				}
			}
			else
			{
				ret = this;
			}
			
			return ret;
		},
		text : function()
		{
			// @wstFnID [wst.dom.text]
			var txt = '';

			if(this.total > 0)
				txt = '' || this.E[0].textContent || this.E[0].text || this.E[0].innerText;

			return txt;
		},
		lookup : function(e)
		{
			// @wstFnID [wst.dom.lookup]
			var copy = wst.core._duplicateWST(this);
			var results = this.total > 0 ? copy.get(e) : copy;
			return results;
		},
		at : function(n, len)
		{
			// @wstFnID [wst.dom.at]
			var copy = wst.core._duplicateWST(this);
			
			if(this.total > 0)
			{
				if(!len)
					len = 1;
				
				var end = n + len;
				copy.E = copy.E.slice(n, end);
				copy.total = len;
			}
			
			return copy;
		},
		first : function()
		{
			// @wstFnID [wst.dom.first]
			var copy = wst.core._duplicateWST(this);
			copy.E = this.total > 0 ? copy.E.slice(0, 1) : copy;
			copy.total = 1;
			return copy;
		},
		last : function()
		{
			// @wstFnID [wst.dom.last]
			var copy = wst.core._duplicateWST(this);
			copy.E = this.total > 0 ? copy.E.slice(-1) : copy;
			copy.total = 1;
			return copy;
		},
		append : function(e)
		{
			// @wstFnID [wst.dom.append]
			if(this.total > 0)
			{
				if(wst.ok(e))
				{
					e = typeof e == 'string' ? [wst.create(e)] : typeof e.E != 'undefined' ? e.E : wst.is.array(e) ? e : [e];
					
					wst.loop(this.E, function(){
						wst.loop(e, function(parent){
							parent.appendChild(this);
						}, [this]);
					});
				}
			}
			
			return this;
		},
		appendTo : function(parent)
		{
			// @wstFnID [wst.dom.appendTo]
			if(this.total > 0)
			{
				parent = typeof parent == 'string' ? wst.get(parent).E[0] : typeof parent.E != 'undefined' ? parent.E[0] : parent;
				
				if(wst.ok(parent))
				{
					wst.loop(this.E, function(parent){
						parent.appendChild(this);
					}, [parent]);
				}
			}
			
			return this;
		},
		remove : function(e)
		{
			// @wstFnID [wst.dom.remove]
			
			if(this.total > 0)
			{
				e = typeof e == 'string' ? wst.get(e).E : wst.ok(e) ? typeof e.E != 'undefined' ? e.E : e : false;
				
				if(e)
				{
					wst.loop(this.E, function(){
						wst.loop(e, function(parent){
							parent.removeChild(this);
						}, [this]);
					});
				}
				else
				{
					wst.loop(this.E, function(){
						this.parentNode.removeChild(this);
					});
				}
			}
			
			return this;
		},
		after : function(contentToAppend)
		{
			// @wstFnID [wst.dom.after]
			if(this.total > 0)
			{
				if(wst.ok(contentToAppend))
				{
					var clone = typeof contentToAppend == 'string';
					var contents = clone ? wst.create(contentToAppend) : contentToAppend;
					
					wst.loop(this.E, function(){
						if(this.parentNode.insertBefore)
							this.parentNode.insertBefore(clone ? contents.cloneNode(true) : contents, this.nextSibling);
					});
				}
			}
			
			return this;
		},
		before : function(contentToAppend)
		{
			// @wstFnID [wst.dom.before]
			if(this.total > 0)
			{
				if(wst.ok(contentToAppend))
				{
					var clone = typeof contentToAppend == 'string';
					var contents = clone ? wst.create(contentToAppend) : contentToAppend;
					
					wst.loop(this.E, function(){
						if(this.parentNode.insertBefore)
							this.parentNode.insertBefore(clone ? contents.cloneNode(true) : contents, this);
					});
				}
			}
			
			return this;
		},
		replace : function(contentToReplace)
		{
			// @wstFnID [wst.dom.replace]
			if(this.total > 0)
			{
				var root = this;
				
				if(wst.ok(contentToReplace))
				{
					var toClone = typeof contentToReplace == 'string';
					var contents = toClone ? wst.create(contentToReplace) : contentToReplace;
					
					wst.loop(this.E, function(i){
						if(this.parentNode.replaceChild)
						{
							var clone = toClone ? contents.cloneNode(true) : contents;
							this.parentNode.replaceChild(clone, this);
							root.E[i] = clone;
						}
					});
				}
			}
			
			return this;
		},
		clone : function(cloneChildren)
		{
			// @wstFnID [wst.dom.clone]
			var clones = [];
			var wstClonedElements = wst.core._duplicateWST(this);
			cloneChildren = cloneChildren || true;
			
			wst.loop(this.E, function(){
				clones.push(this.cloneNode(cloneChildren));
			});
			
			wstClonedElements.total = (wstClonedElements.E = clones).length;
			
			return wstClonedElements;
		},
		content : function(contentToAppend)
		{
			// @wstFnID [wst.dom.content]
			var ret = this;
			
			if(this.total > 0)
			{
				var elements = this.E;
				var isString = typeof contentToAppend == 'string';
				
				if(wst.ok(contentToAppend) && (isString ? !/^\:\w+\:$/.test(contentToAppend) : true))
				{
					if(wst.core.mode == 'strict')
					{
						this
							.clear()
							.append(contentToAppend);
					}
					else if(wst.core.mode == 'quirk')
					{
						wst.loop(elements, function(){
							this.innerHTML = '';
							
							if(isString)
								this.innerHTML = contentToAppend;
							else
								this.appendChild(contentToAppend);
						});
					}
				}
				else
				{
					var contentMode = contentToAppend || ':innerHTML:';
					var contents;
					
					if(wst.core.mode == 'strict')
					{
						var WSTgetTextNodes = this.dom.getTextNodes;
						this.dom.getTextNodes = true;
						
						if(contentMode == ':innerHTML:')
							contents = this.dom.makeXHTML(this.children().E);
						else if(contentMode == ':outerHTML:')
							contents = this.dom.makeXHTML(elements);
						
						this.dom.getTextNodes = WSTgetTextNodes;
					}
					else if(wst.core.mode == 'quirk')
					{
						if(contentMode == ':innerHTML:')
							contents = elements[0].innerHTML;
						else if(contentMode == ':outerHTML:')
							contents = elements[0].outerHTML;
					}
					
					ret = contents;
				}
			}
			
			return ret;
		},
		clear : function(onlyWhiteSpace)
		{
			// @wstFnID [wst.dom.clear]
			
			// only clear if the selection has elements, otherwise the document would be used
			// as the parent node and all the elements on the document would be removed!
			if(this.total > 0)
			{
				if(wst.core.mode == 'strict')
				{
					var WSTgetTextNodes = this.dom.getTextNodes;
					this.dom.getTextNodes = true;
					var nodes = this.lookup('*').E;
					this.dom.getTextNodes = WSTgetTextNodes;
					onlyWhiteSpace = onlyWhiteSpace || false;
					
					wst.loop(nodes, function(){
						if(onlyWhiteSpace ? (this.nodeType == 3) && /^[\s\r\t\n]*$/.test(this.nodeValue) : true)
							this.parentNode.removeChild(this);
					});
				}
				else if(wst.core.mode == 'quirk')
				{
					wst.loop(this.E, function(){
						this.innerHTML = '';
					});
				}
			}
			
			return this;
		},
		css : function(style, value)
		{
			// @wstFnID [wst.dom.css]
			
			if(this.total > 0)
			{
				if(style || value)
				{
					if(value || (typeof style == 'object'))
					{
						this.dom.setStyle(style, value, this.E, this.dom);
						return this;
					}
					else
					{
						return this.dom.getStyle(style, this.E[0], this.dom);
					}
				}
				else
				{
					return '' || this.E[0].style.cssText;
				}
			}
		},
		attr : function(attr, value)
		{
			// @wstFnID [wst.dom.attr]
			
			if(this.total > 0)
			{
				var attrs;

				if(attr || value)
				{
					var obj = this.E;
					var updateValue = (value !== undefined) || (typeof attr == 'object');
					attrs = wst.html.attributes;
					var correctAttr = attrs[attr] || attr;
					var attrValue = null;
					
					if(updateValue)
					{
						wst.loop(obj, function(correctAttr, value){
							if(typeof correctAttr == 'object')
							{
								for(var prop in correctAttr)
									correctAttr[prop] == 'style' ? obj.style.cssText = correctAttr[prop] : this.setAttribute(prop, correctAttr[prop]) ? true : this[prop] = correctAttr[prop];
							}
							else
							{
								correctAttr == 'style' ? this.style.cssText = correctAttr : this.setAttribute(correctAttr, value) ? true : this[correctAttr] = value;
							}
						}, [correctAttr, value]);
					}
					else
					{
						obj = obj[0];
						attrValue = correctAttr == 'style' ? obj.style.cssText : obj.getAttribute(correctAttr) || (obj.attributes.getNamedItem(attr) ? obj.attributes.getNamedItem(attr).value : false) || obj[correctAttr];
						attrValue = (String(attrValue) === '0') ?
										attrValue
										: wst.ok(attrValue) ?
											attrValue
											: '';
					}
					
					if(attrValue !== null)
						return attrValue;
					else
						return this;
				}
				else
				{
					attrs = {};
					
					wst.loop(this.E[0].attributes, function(){
						if(wst.ok(this.nodeValue) && !/inherit|0/.test(this.nodeValue + ''))
							attrs[this.nodeName] = this.nodeValue;
					});
					
					return attrs;
				}
			}
		},
		clss : function(class1, class2)
		{
			// @wstFnID [wst.dom.clss]
			var elements = this.E;
			var returnValue = null;
			
			if(this.total > 0)
			{
				var clss, keyword, value;
				
				switch(arguments.length)
				{
					case 2:
						wst.loop(elements, function(class1, class2){
							clss = this.className;
							
							if(wst.regex(clss, '(?:^|\\s+)(' + class1 + ')(?:\\s+|$)'))
								clss = clss.replace(class1, class2);
							else if(!wst.regex(clss, '(?:^|\\s+)(' + class2 + ')(?:\\s+|$)'))
								clss = clss + (clss != '' ? ' ' : '') + class2;
							
							this.className = clss;
						}, [class1, class2]);
						
						returnValue = this;
						break;
					case 1:
						keyword = class1.match(/has|add|remove|toggle/);
						
						if(!keyword)
						{
							wst.loop(elements, function(){
								this.className = class1;
							});
							
							returnValue = this;
						}
						else
						{
							value = class1.match(/:(.+)$/);
							
							switch(keyword[0])
							{
								case 'has':
									clss = elements[0].className;
									returnValue = value ? (!!wst.regex(clss, '(?:^|\\s+)(' + value[1] + ')(?:\\s+|$)')) : false;
									break;
								case 'add':
									wst.loop(elements, function(value){
										clss = this.className;

										if(!wst.regex(clss, '(?:^|\\s+)(' + value[1] + ')(?:\\s+|$)'))
											clss = clss + (clss != '' ? ' ' : '') + value[1];
										
										this.className = clss;
									}, [value]);
									
									returnValue = this;
									break;
								case 'remove':
									if(value)
									{
										wst.loop(elements, function(value){
											clss = this.className;
											var needle = wst.regex(clss, '(?:^|\\s+|:)(' + value[1] + ')(?:\\s+|$)');
											clss = wst.trim(clss.replace((needle ? needle[1] : ''), ''));
											this.className = clss;
										}, [value]);
									}
									
									returnValue = this;
									break;
								case 'toggle':
									if(value)
									{
										wst.loop(elements, function(value){
											clss = this.className;
											var has = value ? (!!wst.regex(clss, '(?:^|\\s+)(' + value[1] + ')(?:\\s+|$)')) : false;
											var needle = wst.regex(clss, '(?:^|\\s+|:)(' + value[1] + ')(?:\\s+|$)');
											needle = needle ? needle[1] : '';
											
											if(has)
												clss = wst.trim(clss.replace(needle, ''));
											else
												clss = clss + (clss != '' ? ' ' : '') + value[1];
											
											this.className = clss;
										}, [value]);
									}
									
									returnValue = this;
									break;
							}
						}
						break;
					default:
						returnValue = elements[0].className;
						break;
				}
			}
			else
			{
				return this;
			}
			
			return returnValue;
		},
		filter : function(expr, value)
		{
			// @wstFnID [wst.dom.filter]
			var e = this.E;
			var r = [];
			
			if(wst.is.fn(expr))
			{
				r = wst.array.filter(e, expr);
			}
			else
			{
				var prop = expr;
				var actions = {
					'default' : function(){
						return this[prop] == value;
					},
					'has-children' : function(){
						return _dom.hasChildren(this);
					}
				};
				var specialAction = expr.charAt(0) == '@';
				var action = specialAction ? expr.slice(1) : expr;
				
				if(specialAction && actions[action])
					r = wst.array.filter(e, actions[action]);
				else
					r = wst.array.filter(e, actions['default']);
			}
			
			this.total = (this.E = r).length;
			return this;
		},
		index : function(expr)
		{
			// @wstFnID [wst.dom.index]
			var index = -1;
			expr = expr || this.E[0];
			
			if(expr)
			{
				var nodes = _dom.family(this.parent(), 'children', '*').E;
				index = wst.search(expr, nodes, true);
			}
			
			return index;
		},
		sort : function(elements)
		{
			// @wstFnID [wst.dom.sort]
			var returnValue;
			elements = elements ?
				elements
				: this.E ?
					this.E : [];
			
			if(elements.length > 0)
			{
				elements.sort(_sortDOM);
				returnValue = wst.is.wst(this) ? this : elements;
			}
			
			return returnValue;
		},
		equals : function(expr)
		{
			// @wstFnID [wst.dom.equals]
			var elements = this.E;
			var targets = wst.is.wst(expr) ? expr.E : wst.is.array(expr) ? expr : [expr];
			var theSame = false;
			
			if(elements ? (elements.length > 0 && (elements.length === targets.length)) : false)
			{
				if(elements.length == 1)
				{
					theSame = elements[0] === targets[0];
				}
				else
				{
					var i = -1;
					var len = elements.length;
					
					while(++i < len)
					{
						theSame = elements[i] === targets[i];
						
						if(!theSame)
							break;
					}
				}
			}
			
			return theSame;
		},
		show : function(type)
		{
			// @wstFnID [wst.show]
			type = type || 'block';
			this.css('display', type);
			
			return this;
		},
		hide : function(type)
		{
			// @wstFnID [wst.hide]
			type = type || 'none';
			this.css('display', type);
			
			return this;
		},
		focus : function()
		{
			// @wstFnID [wst.focus]
			if(this.total > 0)
			{
				this.loop(function(){
					this.focus && this.focus();
				});
			}
			
			return this;
		},
		blur : function()
		{
			// @wstFnID [wst.blur]
			if(this.total > 0)
			{
				this.loop(function(){
					this.blur && this.blur();
				});
			}
			
			return this;
		},
		enable : function(on)
		{
			// @wstFnID [wst.enable]
			if(this.total > 0)
			{
				on = !on;
				this.loop(function(){
					this.disabled = on;
				});
			}
			
			return this;
		},
		check : function(on)
		{
			// @wstFnID [wst.check]
			if(this.total > 0)
			{
				on = !!on;
				this.loop(function(){
					this.checked = on;
				});
			}
			
			return this;
		},
		isVisible : function()
		{
			// @wstFnID [wst.isVisible]
			if(this.total > 0)
				return (this.css('display') !== 'none') && (this.css('visibility') !== 'hidden');
			else
				return false;
		},
		pos : function()
		{
			// @wstFnID [wst.pos]
			var curleft = 0, curtop = 0;
			
			if(this.total > 0)
			{
				var e = this.E[0];
				
				if(e.getBoundingClientRect)
				{
					var rect = e.getBoundingClientRect();
					curleft = rect.left + _addMarginPadding(this, 'left');
					curtop = rect.top + _addMarginPadding(this, 'top');
				}
				else
				{
					if(e.offsetParent)
					{
						var _e = null;
						curleft = e.offsetLeft + _addMarginPadding(this, 'left');
						curtop = e.offsetTop + _addMarginPadding(this, 'top');
						
						while((e = e.offsetParent))
						{
							_e = wst.get(e);
							curleft += e.offsetLeft + _addMarginPadding(_e, 'left');
							curtop += e.offsetTop + _addMarginPadding(_e, 'top');
						}
					}
				}
			}
			
			return {left : curleft, top : curtop};
		},
		scrollView : function()
		{
			// @wstFnID [wst.scrollView]
			if(this.total > 0)
			{
				var args = arguments;
				var targets = this.E, pos, x, y;
				
				switch(args.length)
				{
					case 2:
						x = args[0];
						y = args[1];
						break;
					case 1:
						pos = wst.get(args[0]).pos();
						x = pos.left;
						y = pos.top;
						break;
				}
				
				targets.loop(function(){
					this.scrollLeft = x;
					this.scrollTop = y;
				});
			}
			
			return this;
		},
		encodeUrl : function(oStr)
		{
			// @wstFnID [wst.encodeUrl]
			var hex_chars = '0123456789ABCDEF';
			var str = new String(oStr);
			var n = -1, len = str.length;
			var strCode, hex1, hex2, strEncode = '';
			
			while(++n < len)
			{
				if(_noEncode.test(str.charAt(n)))
				{
					strEncode += str.charAt(n);
				}
				else
				{
					strCode = str.charCodeAt(n);
					hex1 = hex_chars.charAt(Math.floor(strCode / 16));
					hex2 = hex_chars.charAt(strCode % 16);
					strEncode += '%' + (hex1 + hex2);
				}
			}
			
			return strEncode;
		},
		decodeUrl : function(oStr)
		{
			// @wstFnID [wst.decodeUrl]
			var strCode, strDecode = '';
			var str = new String(oStr);
			var n = -1, len = str.length;
			
			while(++n < len)
			{
				if(str.charAt(n) == '%')
				{
					strCode = str.charAt(n + 1) + str.charAt(n + 2);
					strDecode += String.fromCharCode(parseInt(strCode, 16));
					n += 2;
				}
				else
				{
					strDecode += str.charAt(n);
				}
			}
			
			strDecode = strDecode.replace(/\+/g, ' ');
			return strDecode;
		},
		hexEncode : function(n)
		{
			// @wstFnID [wst.hexEncode]
			var chars = '0123456789ABCDEF'.split('');
			var div = Math.floor(n / 16);
			var mod = n % 16;
			var hex = String(chars[div] || '0') + String(chars[mod] || '0');
			
			return hex;
		},
		hexDecode : function(hex)
		{
			// @wstFnID [wst.hexDecode]
			var chars = {'A':10, 'B':11, 'C':12, 'D':13, 'E':14, 'F':15};
			var char1 = hex.charAt(0).toUpperCase(), char2 = hex.charAt(1).toUpperCase();
			var n = Number((chars[char1] || char1) * 16) + Number(chars[char2] || char2);
			
			return n;
		},
		/*******************
		* @ EVENT OBJECT @ *
		*******************/
		event : wst.extend(
			function(){
				// @wstFnID [wst.event]
				var evt = null;
				var args = arguments;
				var call = null;
				var i, k, len;
				
				if(window.event)
				{
					evt = window.event;
				}
				else
				{
					while(args != null)
					{
						if(args.length > 0)
						{
							for(k = 0, len = args.length; k < len; k++)
							{
								if(args[k] ? (args[k].type || args[k].target || args[k].srcElement || args[k].keyCode || args[k].which || args[k].charCode) : false)
								{
									evt = args[k];
									break;
								}
							}
						}
						
						if(evt)
							break;
						
						args = (call = args.callee.caller).arguments;
					}
				}
				
				return evt;
			
			}, {
				uid : 0,
				cancelDefault : function(evt)
				{
					// @wstFnID [wst.event.cancelDefault]
					evt = evt ? evt : wst.event(arguments);
					
					if(evt.preventDefault)
						evt.preventDefault();
					
					evt.returnValue = false;
					return false;
				},
				cancelPropagation : function(evt)
				{
					// @wstFnID [wst.event.cancelPropagation]
					evt = evt ? evt : wst.event(arguments);
					
					if(evt.stopPropagation)
						evt.stopPropagation();
					
					evt.cancelBubble = true;
				},
				keyCode : function(evt)
				{
					// @wstFnID [wst.event.keyCode]
					evt = evt ? evt : wst.event(arguments);
					
					return evt.keyCode || evt.which || evt.charCode || -1;
				},
				mouseButton : function(evt)
				{
					// @wstFnID [wst.event.mouseButton]
					evt = evt ? evt : wst.event(arguments);
					
					return evt.button || evt.which;
				},
				checkNumber : function(evt)
				{
					// @wstFnID [wst.event.checkNumber]
					var keycode = wst.event.keyCode(evt);
					
					return ((keycode >= 48 && keycode <= 57) || (keycode >= 96 && keycode <= 105));
				},
				checkLetter : function(evt)
				{
					// @wstFnID [wst.event.checkLetter]
					var keycode = wst.event.keyCode(evt);
					
					return (keycode >= 65 && keycode <= 90);
				},
				checkTab : function(evt)
				{
					// @wstFnID [wst.event.checkTab]
					var keycode = wst.event.keyCode(evt);
					
					return /^[89]{1}$|^1[36-9]{1}$|^20$|^3[3-9]{1}$|^4[06]{1}$|^9[1-3]{1}$|^14[45]{1}$/.test(keycode);
				},
				clone : function(evt)
				{
					// @wstFnID [wst.event.clone]
					var newEvent = wst.extend({}, evt);
					
					// fix the target element
					!wst.ok(newEvent.target) ? newEvent.target = evt.srcElement : null;
					// Safari bug
					wst.browser.sf && newEvent.target.nodeType == 3 ? newEvent.target = evt.target.parentNode : null;
					// create storPropagation for any browser
					newEvent.stopPropagation = function(){ wst.event.cancelPropagation(evt) };
					// create preventDefault for any browser
					newEvent.preventDefault = function(){ wst.event.cancelDefault(evt) };
					// create metaKey = ctrlKey if not present
					!wst.ok(newEvent.metaKey) && wst.ok(newEvent.ctrlKey) ? newEvent.metaKey = evt.ctrlKey : null;
					// standard keyCode
					newEvent.keyCode = evt.keyCode || evt.which || evt.charCode;
					// mouse button
					!wst.ok(evt.button) ? newEvent.button = evt.which : null;
					// verify if the key is a number
					newEvent.isNumber = wst.event.checkNumber(evt);
					// verify if the key is a letter
					newEvent.isLetter = wst.event.checkLetter(evt);
					
					return newEvent;
				},
				listen : function(evtType, handler)
				{
					// @wstFnID [wst.event.listen]
					
					if(this.total > 0)
					{
						if(wst.core.hasLog('events'))
							wst.log.add('events', wst.core._getCaller() + ' ' + wstFnID, es + '.on' + evtType + ' = ' + wst.core._getCaller(handler));
						
						this.loop(function(evtType, handler){
							var orig = handler;
							var thisElement = this;
							
							handler = function(evt){
								// create the event object
								var newEvent = wst.event.clone(evt);
								var args = [], arg;
								var i = 0;
								
								// arguments to be passed, with the event object as the first one
								while((arg = arguments[i++]))
									args.push(arg == evt ? newEvent : arg);
								
								// apply the arguments and the target element to the handler function
								return orig.apply(thisElement, args);
							};
							
							// cache the function
							var addEvent = false;
							var chachedObj = wst.cache.get(this) || {};
							var eventObj = null;
							var fnID = orig.name || (wst.ok(orig.uid) ? orig.uid : orig.uid = wst.event.uid++);
							var handlerObj = {
								target : this,
								type : evtType,
								fn : handler,
								orig : orig
							};
							
							if(!chachedObj.events)
							{
								addEvent = true;
								chachedObj.events = {
									indexes : {},
									handlers : {}
								};
								chachedObj.events.handlers[evtType] = {};
								chachedObj.events.handlers[evtType][fnID] = handlerObj;
								chachedObj.events.indexes[evtType] = [fnID];
							}
							else
							{
								eventObj = chachedObj.events;
								
								if(wst.is.array(eventObj.indexes[evtType]) ? wst.inArray(fnID, eventObj.indexes[evtType]) === false : true)
								{
									addEvent = true;
									
									if(!eventObj.handlers[evtType])
										eventObj.handlers[evtType] = {};
									
									eventObj.handlers[evtType][fnID] = handlerObj;
									
									if(eventObj.indexes[evtType])
										eventObj.indexes[evtType].push(fnID);
									else
										eventObj.indexes[evtType] = [fnID];
								}
							}
							
							//if(this === document)
								//alert(evtType + ' ' + addEvent + ' ' + orig + '\n\n' + eventObj.handlers[evtType][fnID].orig);
							
							if(addEvent)
							{
								wst.cache.add(this, chachedObj);
								
								if(this.addEventListener || this.attachEvent)
								{
									if(this.addEventListener && !this.attachEvent)
										this.addEventListener(evtType, handler, false);
									else if(this.attachEvent)
										this.attachEvent('on' + evtType, handler);
								}
								else if(wst.is.dom(this))
								{
									this['on' + evtType] = handler;
								}
							}
						}, [evtType, handler]);
					}
					
					return this;
				},
				unListen : function(evtType, handler)
				{
					// @wstFnID [wst.event.unListen]
					
					if(this.total > 0)
					{
						if(wst.core.hasLog('events'))
							wst.log.add('events', wst.core._getCaller() + ' ' + wstFnID, es + '.on' + evtType + ' = ' + wst.core._getCaller(handler));
						
						if(wst.ok(handler))
						{
							this.loop(function(evtType, handler){
								var cachedHandlers = wst.cache.get(this);
								var fnID = handler.name || handler.uid;
								var fnArray = null;
								var fnIndex = null;
								var list = null;
								
								if(
									cachedHandlers ?
										(cachedHandlers = cachedHandlers.events) ?
											cachedHandlers.indexes[evtType] ?
												((fnIndex = wst.inArray(fnID, (fnArray = cachedHandlers.indexes[evtType]))) !== false) && cachedHandlers.handlers[evtType]
											: false
										: false
									: false
								)
								{
									handler = cachedHandlers.handlers[evtType][fnArray[fnIndex]].fn;
									
									if(this.removeEventListener || this.detachEvent)
									{
										if(this.removeEventListener && !this.detachEvent)
											this.removeEventListener(evtType, handler, false);
										else if(this.detachEvent)
											this.detachEvent('on' + evtType, handler);
									}
									else if(typeof this == 'object' && this['on' + evtType])
									{
										this['on' + evtType] = null;
									}
									
									// update the cache
									delete cachedHandlers.handlers[evtType][fnArray[fnIndex]];
									delete fnArray[fnIndex];
									
									//if(/^,*[^,]+,*$/.test(fnArray.toString()))
									//	fnArray = null;
								}
							}, [evtType, handler]);
						}
						else
						{
							wst.loop(wst.event.handlers, function(es, evtType){
								if(this.target == es && this.type == evtType)
								{
									var savedHandler = this.fn;
									
									wst.event.handlers[savedHandler.uid] = null;
									delete wst.event.handlers[savedHandler.uid];
									
									if(this.removeEventListener && !this.detachEvent)
										this.removeEventListener(evtType, savedHandler, false);
									else if(this.detachEvent)
										this.detachEvent('on' + evtType, savedHandler);
									else if(typeof this['on' + evtType] != 'undefined')
										this['on' + evtType] = null;
								}
							}, [this.E, evtType]);
						}
					}
					
					return this;
				}
			}
		),
		loaded : function(fn, index, expr)
		{
			// @wstFnID [wst.loaded]
			
			expr = wst.ok(expr) ? expr : this.expr;
			index = wst.ok(index) ? index : 0;
			var elements = (this.total > 0 && !wst.ok(expr) ? this.E : wst.get(expr).E).slice(index);
			
			if((elements.length > 0) && (elements.length > index))
			{
				index = elements.length;
				
				elements.loop(function(i){
					wst.apply(fn, [i], this);
				});
			}
			
			if(!wst.documentLoaded)
				wst.timeout(this, 'loaded', 70, fn, index, expr);
			
			return this;
		},
		ready : function(fn)
		{
			// @wstFnID [wst.ready]
			var done = false;
			var checkModules = function(element, evt, fn, callback){
				// @wstFnID [wst.ready.checkModules]
				
				if(wst.modules.ready == wst.modules.loaded)
					wst.apply(callback, [element, evt, fn]);
				else
					wst.timeout(checkModules, 50, element, evt, fn, callback);
			};
			var onReadyState = function(evt){
				// @wstFnID [wst.ready.onReadyState]
				
				if(/complete|loaded/.test(this.readyState) && !done)
				{
					done = true;
					
					if(wst.browser.ie && wst.is.doc(this))
					{
						checkModules(this, evt, fn, function(element, evt, callback){
							var callbacks = wst.core.documentReadyCallbacks;
							var fn = null;
							var i = -1;
							
							while((fn = callbacks[++i]))
								fn.apply(element, [evt]);
						});
					}
					else
					{
						fn.apply(this, [evt]);
					}
				}
			};
			var onLoadGecko = function(evt){
				// @wstFnID [wst.ready.onLoadGecko]
				
				if(wst.is.doc(this))
				{
					checkModules(this, evt, fn, function(element, evt, callback){
						callback.apply(element, [evt]);
					});
				}
				else
				{
					fn.apply(this, [evt]);
				}
			};
			var onReadyWebkit = function(fn, element){
				// @wstFnID [wst.ready.onReadyWebkit]
				
				if(!done)
				{
					if(/complete|loaded/.test(element.readyState))
					{
						done = true;
						
						if(wst.is.doc(element))
						{
							checkModules(element, null, fn, function(element, evt, callback){
								callback.apply(element, [null]);
							});
						}
						else
						{
							fn.apply(element, [null]);
						}
					}
					else
					{
						wst.timeout(onReadyWebkit, 50, fn, element);
					}
				}
			};
			
			if(wst.browser.gecko)
			{
				this.listen('DOMContentLoaded', onLoadGecko);
			}
			else if(wst.browser.webkit)
			{
				this.loop(function(){
					wst.timeout(onReadyWebkit, 50, fn, this);
				});
			}
			else
			{
				// IE: add the document readyState listeners
				if(wst.browser.ie && (this.total == 1) && wst.is.doc(this.E[0]))
				{
					wst.core.documentReadyCallbacks.push(fn);
					
					if(wst.core.documentReadyCallbacks.length == 1)
						this.listen('readystatechange', onReadyState);
				}
				else
				{
					this.listen('readystatechange', onReadyState);
				}
			}
			
			return this;
		},
		blockKey : function(limit, fn)
		{
			// @wstFnID [wst.blockKey]
			limit = limit || 0;
			
			this
				.listen('keydown', function(evt){
					if(this.value.length >= limit)
					{
						if(!wst.event.checkTab(evt))
							return evt.preventDefault();
					}
				})
				.listen('paste', function(evt){
					var e = this;
					
					setTimeout(function(){
						var len = e.value.length;
						var diff = limit - len;
						
						if(e.value.length >= limit)
							e.value = e.value.slice(0, limit);
						
						if(diff >= 0)
							fn.call(e, diff);
					}, 1);
				});
			
			if(fn)
			{
				this.listen('keyup', function(){
					var len = this.value.length;
					var diff = limit - len;
					
					if(diff >= 0)
						fn.call(this, diff);
				});
			}
			
			return this;
		},
		onlyNumbers : function()
		{
			// @wstFnID [wst.onlyNumbers]
			var aceptOnlyNumbers = function(evt){
				if(!evt.isNumber)
				{
					if(!wst.event.checkTab(evt))
						evt.preventDefault();
				}
			};
			
			this.listen('keydown', aceptOnlyNumbers);
			
			return this;
		},
		disableRightClick : function(message)
		{
			// @wstFnID [wst.disableRightClick]
			var disableRightClick = function(evt){
				if((evt.button <= 0 && wst.browser.ie) || evt.button == 2 || evt.button == 3)
				{
					
					if(message)
						alert(message);
					else if(wst.browser.op)
						wst.error(message || wst.messages.functions.disableRightClick);
					
					evt.stopPropagation();
					return evt.preventDefault();
				}
			};
			message = message || '';
			
			this.listen('contextmenu', disableRightClick);
			
			if(wst.browser.op)
				this.listen('mousedown', disableRightClick);
			
			return this;
		},
		inArray : function(searchedValue, array, op, keyName)
		{
			// @wstFnID [wst.inArray]
			op = op || 'check';
			keyName = false || keyName;
			
			if(array.length != undefined)
			{
				if(array.length > 0)
				{
					var index = -1, size = array.length;
					
					while(++index < size)
					{
						if(keyName ? searchedValue == array[index][keyName] : searchedValue == array[index])
						{
							if(op == 'delete')
							{
								//delete array[index];
								array = wst.array.remove(index, array);
								return true;
							}
							else if(op == 'check')
							{
								return index;
							}
						}
					}
				}
				
				return false;
			}
			else
			{
				for(var key in array)
				{
					if(keyName ? searchedValue == array[key][keyName] : searchedValue == array[key])
					{
						if(op == 'delete')
						{
							delete array[key];
							return true;
						}
						else if(op == 'check')
						{
							return key;
						}
					}
				}
				
				return false;
			}
		},
		search : function(value, array, isDOM)
		{
			// @wstFnID [wst.search]
			var start = 0;
			var end = array.length - 1;
			var index = -1;
			
			if(isDOM === undefined)
				isDOM = wst.is.dom(value);
			
			// for faster search in some cases, we verify if the searched value is the first or last
			// element of the array, so we don't need to loop
			if(value === array[start])
			{
				index = start;
			}
			else if(value === array[end])
			{
				index = end;
			}
			else
			{
				// uses the Array.indexOf method if present (JavaScript 1.6)
				if(Array.indexOf)
				{
					index = array.indexOf(value);
				}
				else
				{
					// if the searched value was not found yet, we do the binary search
					var midValue, lowerValue, higherValue;
					var mid, up;
					var DOMSupport = !!value.compareDocumentPosition;
					
					while(start <= end)
					{
						mid = parseInt((start + end) / 2);
						lowerValue = array[mid - 1];
						midValue = array[mid];
						higherValue = array[mid + 1];
						
						if(isDOM)
							up = DOMSupport ? value.compareDocumentPosition(midValue) == 4 : midValue.sourceIndex > value.sourceIndex;
						else
							up = midValue > value;
						
						if(midValue === value)
						{
							index = mid;
							break;
						}
						else if(lowerValue === value)
						{
							index = mid - 1;
							break;
						}
						else if(higherValue === value)
						{
							index = mid + 1;
							break;
						}
						else if(up)
						{
							end = mid - 2;
						}
						else
						{
							start = mid + 2;
						}
					}
				}
			}
			
			return index;
		},
		regex : function(str, source)
		{
			// @wstFnID [wst.regex]
			switch(arguments.length)
			{
				case 2:
					if(typeof source == 'string')
						return str.match(source);
					else if(typeof source == 'object')
						return str.match(new RegExp(source.expr, ('' || source.flags)));
					break;
				case 1:
					if(typeof str == 'string')
						return new RegExp(str);
					else if(typeof str == 'object')
						return new RegExp(str.expr, ('' || str.flags));
					break;
				default:
					throw wst.messages.functions.wrongArgs;
					return false;
					break;
			}
		},
		/*regex : function(str, source)
		{
			// @wstFnID [wst.regex]
			var re = new wst.Regex();
			
			switch(arguments.length)
			{
				case 2:
					if(typeof arguments[1] == 'string')
						return re.run(arguments[0], arguments[1]);
					else if(typeof arguments[1] == 'object')
						return re.run(arguments[0], arguments[1].expr, (arguments[1].flags || ''));
					break;
				case 1:
					if(typeof arguments[0] == 'string')
						return re.create(arguments[0]);
					else if(typeof arguments[0] == 'object')
						return re.create((arguments[0].expr || ''), (arguments[0].flags || ''));
					break;
				default:
					return false;
					break;
			}
		},*/
		include : function()
		{
			// @wstFnID [wst.include]
			var list = arguments;
			
			if(list.length > 0)
			{
				var i = 0;
				var script;
				var type;
				var head = document.documentElement.firstChild;
				var include;
				
				while((script = list[i++]))
				{
					type = String(script).split('.').slice(-1)[0].toLowerCase().replace(/\?\d+$/, '');
										
					switch(type)
					{
						case 'js':
							include = wst('<script src="' + script + '" type="text/javascript"></script>');
							break;
						case 'css':
							include = wst('<link href="' + script + '" rel="stylesheet" type="text/css" media="all" />');
							break;
					}
					
					include.appendTo(head);
				}
				
				return include;
			}
		},
		loop : function(e, fn, args)
		{
			// @wstFnID [wst.loop]
			
			if(!fn || (wst.is.fn(e) && fn != undefined))
			{
				args = fn;
				fn = e;
				e = wst.is.wst(this) ? this.E : this;
			}
			
			if(e)
			{
				var i;
				
				if(e.length != undefined)
				{
					var len = e.length;
					i = -1;
					
					while(++i < len)
					{
						if(fn.apply(e[i], (args || [i, this])) === false)
							break;
					}
				}
				else
				{
					for(i in e)
					{
						if(fn.apply(e[i], (args || [i, this])) === false)
							break;
					}
				}
			}
			
			return this;
		},
		
		/*********************
		* @ TIMEOUT OBJECT @ *
		*********************/
		timeout : wst.extend(
			function(object, fn, time)
			{
				// @wstFnID [wst.timeout]
				var args, parent;
				var id = wst.timeout.timers.length;
				
				if(!wst.ok(time) || (typeof time != 'number' && arguments.length >= 3))
				{
					args = wst.array.create(arguments).slice(2) || [];
					time = fn;
					fn = object;
					object = null;
				}
				else
				{
					args = wst.array.create(arguments).slice(3);
				}
				
				parent = object || window;
				
				wst.timeout.timers[id] = setTimeout(function(){
					if(object)
						object[fn].apply(parent, args);
					else
						wst.apply(fn, args, parent);
					
					wst.timeout.clear(id);
				}, time);
				
				return id;
			}, {
				timers : [],
				update : function(id)
				{
					// @wstFnID [wst.timeout.update]
					
					return wst.timeout;
				},
				remove : function(id)
				{
					// @wstFnID [wst.timeout.remove]
					
					if(wst.ok(id))
					{
						wst.timeout.timers[id] = null;
						delete wst.timeout.timers[id];
					}
					
					return wst.timeout;
				},
				clear : function(id)
				{
					// @wstFnID [wst.timeout.clear]
					
					if(wst.ok(id))
						clearTimeout(wst.timeout.timers[id]);
					
					return wst.timeout;
				}
			}
		),
		
		/*******************
		* @ CACHE OBJECT @ *
		*******************/
		/*
			object syntax
			
			wst.cache = {
				contents : {
					IDExpression : {
						common : object,	// default
						event : object,
						shadow : object,
						...
					}
				},
				methods ...
			}

		*/
		cache : {
			enabled : true,
			contents : {},
			iterator : 0,
			id : function(expr, add)
			{
				// @wstFnID [wst.cache.id]
				var id = 'wst-cached' + (new Date).getTime() + (this.iterator++);
				add = wst.is.undef(add) ? true : add;
				
				if(wst.is.dom(expr) || wst.is.object(expr) || wst.is.array(expr) || wst.is.fn(expr))
				{
					if(!expr.id && add)
						expr.id = id;
					else
						id = expr.id;
				}
				else
				{
					id = expr;
				}
				
				return id;
			},
			add : function(expr, content, type)
			{
				// @wstFnID [wst.cache.add]
				var id = this.id(expr, true);
				//type = type || 'common';
				
				if(this.enabled)
				{
					if(type)
					{
						if(!this.contents[id])
							this.contents[id] = {};
						
						this.contents[id][type] = content;
					}
					else
					{
						this.contents[id] = content;
					}
				}
				
				return this;
			},
			get : function(expr)
			{
				// @wstFnID [wst.cache.get]
				
				return this.contents[this.id(expr, false)];
			},
			clear : function(expr, type, removeID)
			{
				// @wstFnID [wst.cache.clear]
				removeID = wst.is.undef(removeID) ? false : removeID;
				
				if(this.enabled)
				{
					if(expr)
					{
						if(type)
							delete this.contents[this.id(expr, false)][type];
						else
							delete this.contents[this.id(expr, false)];
						
						if(removeID)
						{
							if(wst.is.dom(expr))
								expr.id = '';
							else
								delete expr.id;
						}
					}
					else
					{
						this.contents = [];
					}
				}
				
				return this;
			}
		},
		
		/*******************
		* @ ARRAY OBJECT @ *
		*******************/
		array : wst.extend(
			function()
			{
				// @wstFnID [wst.array]
				var arr = [];
				var current = null;
				var i = -1;
				
				while((current = arguments[++i]))
					arr = arr.concat(!wst.is.array(current) ? wst.array.create(current) : current);
				
				return arr;
			}, {
				create : function(newArray)
				{
					// @wstFnID [wst.array.create]
					var array = [];
					
					if(wst.ok(newArray))
					{
						try{
							// Use Array.prototype.slice whenever possible
							array = Array.prototype.slice.call(newArray);
						}
						catch(err){
							//wst.error(err); // uncomment for debugging purposes
						};
						
						if(
							// IE is very limited about the use of Array.prototype.slice with objects.
							// So we create the array at the simplest way
							(array.length === 0) ||
							// Brwosers like FF in some cases (eg with DOM elements like "select") returns the newArray fulfilled with "undefined" values.
							// If this happen, we create a new array with the passed value.
							(/^,*$/.test(array.toString())) ||
							// IE has problems with the arguments object too. So we also must to verify it.
							(wst.ok(newArray.callee) && wst.browser.ie)
						)
						{
							if((!wst.is.dom(newArray) && !wst.is.win(newArray)) && (newArray.length > 0))
							{
								var i = -1, len = newArray.length;
								array = [];
								
								while(++i < len)
									array.push(newArray[i]);
							}
							else
							{
								array = [newArray];
							}
						}
					}
					
					return array;
				},
				filter : function(array, fn)
				{
					// @wstFnID [wst.array.filter]
					var resultArray = [];
					
					wst.loop(array, function(index){
						if(wst.apply(fn, [index, array], array[index]) === true)
							 resultArray.push(array[index]);
					});
					
					return  resultArray;
				},
				unique : function(array)
				{
					// @wstFnID [wst.array.unique]
					var resultArray = [];
					var i = -1, j, current, next, duplicate;
					
					while((current = array[++i]))
					{
						j = i;
						duplicate = false;
						
						while((next = array[++j]))
						{
							if(current === next)
								duplicate = true;
						}
						
						if(!duplicate)
							resultArray.push(current);
					}
					
					return resultArray;
				},
				values : function(obj)
				{
					// @wstFnID [wst.array.values]
					var key, resultArray = [];
					
					for(key in obj)
						resultArray.push(obj[key]);
					
					return resultArray;
				},
				keys : function(obj)
				{
					// @wstFnID [wst.array.keys]
					var key, resultArray = [];
					
					for(key in obj)
						resultArray.push(key);
					
					return resultArray;
				},
				valid : function(array)
				{
					// @wstFnID [wst.array.valid]
					return wst.is.array(array) ? array.length > 0 : false;
				},
				remove : function(index, array)
				{
					// @wstFnID [wst.array.remove]
					return array.slice(0, index).concat(array.slice(index + 1));
				}
			}
		),
		
		/****************
		* @ IS OBJECT @ *
		****************/
		is : wst.extend(
			function(expr)
			{
				// @wstFnID [wst.is]
				
				if(wst.ok(expr))
				{
					var exprConstructor;
					
					try{
						exprConstructor = expr.constructor.toString().match(/function\s+([^\(\s]+)\s*\(\)/)[1].toLowerCase();
					}
					catch(err){
						exprConstructor = Object.prototype.toString.call(expr).match(/\[(?:object\s+)?([\w\d]*)\]/)[1].toLowerCase();
					};
					
					exprConstructor = (exprConstructor == 'window') || (exprConstructor.search('html') > -1) ? 'object' : exprConstructor;
					exprConstructor = exprConstructor == 'object' && wst.is.dom(expr) ? 'DOMObject' : exprConstructor;
					
					return exprConstructor;
				}
				
				return expr + '';
			}, {
				string : function(expr)
				{
					// @wstFnID [wst.is.string]
					
					return wst.ok(expr) ? expr instanceof String || this(expr) == 'string' : false;
				},
				number : function(expr)
				{
					// @wstFnID [wst.is.number]
					
					return wst.ok(expr) ? expr instanceof Number || this(expr) == 'number' : false;
				},
				bool : function(expr)
				{
					// @wstFnID [wst.is.bool]
					
					return wst.ok(expr) ? expr instanceof Boolean || this(expr) == 'boolean' : false;
				},
				fn : function(expr)
				{
					// @wstFnID [wst.is.fn]
					
					return wst.ok(expr) ? (expr instanceof Function && !this.dom(expr)) : false;
				},
				object : function(expr)
				{
					// @wstFnID [wst.is.object]
					
					return wst.ok(expr) ? expr instanceof Object : false;
				},
				array : function(expr)
				{
					// @wstFnID [wst.is.array]
					
					return wst.ok(expr) ? (expr instanceof Array) && (expr.length !== undefined) : false;
				},
				date : function(expr)
				{
					// @wstFnID [wst.is.date]
					
					return wst.ok(expr) ? expr instanceof Date : false;
				},
				regexp : function(expr)
				{
					// @wstFnID [wst.is.regexp]
					
					return wst.ok(expr) ? expr instanceof RegExp : false;
				},
				error : function(expr)
				{
					// @wstFnID [wst.is.error]
					
					return wst.ok(expr) ? expr instanceof Error : false;
				},
				wst : function(expr)
				{
					// @wstFnID [wst.is.wst]
					
					return wst.ok(expr) ? expr instanceof wst : false;
				},
				dom : function(expr)
				{
					// @wstFnID [wst.is.dom]
					
					return wst.ok(expr) ? (typeof expr.nodeName != 'undefined' && (typeof expr.nodeType != 'undefined' ? expr.nodeType != 8 : false) && (expr !== window)) : false;
				},
				undef : function(expr)
				{
					// @wstFnID [wst.is.undef]
					
					return expr === undefined;
				},
				win : function(expr)
				{
					// @wstFnID [wst.is.win]
					
					return wst.ok(expr) ? !this.undef(expr.location) && (expr.document ? this.doc(expr.document) : false) : false;
				},
				doc : function(expr)
				{
					// @wstFnID [wst.is.doc]
					
					return wst.ok(expr) ? (expr.nodeType ? expr.nodeType === 9 : false) : false;
				}
			}
		),
		apply : function(fn, args, parent)
		{
			// @wstFnID [wst.apply]
			parent = parent || window;
			args = wst.ok(args) ? (wst.is.array(args) ? args : [args]) : [];
			
			if(fn.apply)
			{
				return fn.apply(parent, args);
			}
			else
			{
				try{
					// Simulate the call method in IE for functions that not allow
					// the method. E.g., we cannot do alert.call,
					// but we can do Function.prototype.call.apply(alert, [window, 'test to alert'])
					return Function.prototype.call.apply(fn, wst.array(parent, args));
				}
				catch(err){
					wst.error(err);
				};
			}
		},
		trim : function(str)
		{
			// @wstFnID [wst.trim]
			return str.replace(/^\s*|\s*$/g, '');
		},
		format : function()
		{
			// @wstFnID [wst.format]
			var args = this.array.create(arguments);
			var str = args[0];
			var replaces = args.slice(1);
			var strFormated = '';
			var numRegex = /[$#]\{\d\}/gm;
			var indexRegex = /\W/g;
			
			if(wst.is.object(replaces[0]) && replaces.length == 1)
			{
				replaces = replaces[0];
				strFormated = str;
				
				for(var key in replaces)
				{
					strFormated = strFormated.replace(wst.regex({expr:'[$#]\\{' + key + '\\}', flags:'gm'}), function(n){
						n = n.replace(indexRegex, '');
						return replaces[n];
					});
				}
			}
			else
			{
				strFormated = str.replace(numRegex, function(n){
					n = parseInt(n.replace(indexRegex, '')) - 1;
					return replaces[n];
				});
			}
			
			return strFormated;
		},
		/*****************
		* @ XML OBJECT @ *
		*****************/
		xml : wst.extend(function(expr){
				// @wstFnID [wst.xml]
				
				return !!wst.html.regex.tag.test(expr) ? this.xml.parse(expr) : this.xml.load(expr);
			}, {
				DOMSupport : (document.implementation ? !!document.implementation.createDocument : false),
				create : function(forLoad)
				{
					// @wstFnID [wst.xml.create]
					var xml = null;
					
					if(!wst.is.undef(forLoad))
					{
						try{
							if(this.DOMSupport)
								xml = forLoad ? document.implementation.createDocument('', '', null) : new DOMParser;
							else if(window.ActiveXObject)
								xml = new ActiveXObject('Microsoft.XMLDOM');
							else
								alert(wst.messages.functions.xmlLoadNotSupportedBrowser);
						}
						catch(err){
							wst.error(err);
						}
					}
					else
					{
						wst.error(wst.messages.functions.requiredArguments);
					}
					
					return xml;
				},
				parse : function(str)
				{
					// @wstFnID [wst.xml.parse]
					var xml = this.create(false);
					
					try{
						str = this.normalize(str);
						
						if(!wst.is.undef(xml.constructor))
						{
							xml = xml.parseFromString(str, 'text/xml');
						}
						else
						{
							xml.async = false;
							xml.loadXML(str);
						}
						
						xml = _checkError(xml);
					}
					catch(err){
						wst.error(err);
					}
					
					return xml;
				},
				load : function(url, callback)
				{
					// @wstFnID [wst.xml.load]
					var xml = this.create(true);
					var onLoad = function(){
						if(xml.readyState == 4)
							wst.apply(callback, xml);
					};
					
					if(callback)
					{
						if(wst.ok(xml.onreadystatechange))
							xml.onreadystatechange = onLoad;
						else
							xml.onload = onLoad;
					}
					
					try{
						xml.async = false;
						xml.load(url);
						
						xml = _checkError(xml);
					}
					catch(err){
						wst.error(err)
					}
					
					return xml;
				},
				normalize : function(str)
				{
					// @wstFnID [wst.xml.normalize]
					
					// remove new lines
					str = str.replace(/\n/g, '');
					
					// replace HTML entities
					if(wst.html.regex.entities.test(str))
						str = wst.html.replaceEntities(str);
					
					// replace invalid characters
					str = wst.html.replaceUnicode(str);
					
					return str;
				}
			}
		)
	});
	
	var _checkError = function(xml)
	{
		// @wstFnID [wst.xml._checkError]
		var result = xml;
		
		// DOM supported error
		if(xml.firstChild && (xml.firstChild.nodeName == 'parsererror'))
		{
			var error = xml.firstChild;
			result = null;
			wst.error(wst.messages.functions.xmlParserError + '\n\n' + error.firstChild.nodeValue + '\n\n' + error.lastChild.firstChild.nodeValue);
		}
		// IE error
		else if(xml.parseError && xml.parseError.reason)
		{
			result = null;
			wst.error(wst.messages.functions.xmlParserError + '\n\n' + xml.parseError.reason + '\n\n' + xml.parseError.srcText);
		}
		
		return result;
	};
	
	/********************
	* @ REGEXP OBJECT @ *
	********************/
	wst.Regex = wst.object.createClass('Regex');
	wst.Regex.addMember('public', 'source', false);
	wst.Regex.addMember('public', 'str', '');
	wst.Regex.addMember('public', 'matches', false);
	wst.Regex.addMember('public', 'test', false);
	wst.Regex.addMember('public', 'object', false);
	wst.Regex.addMember('public', 'flags', '');
	
	wst.Regex.addMember('public', 'create', function(source, flags)
	{
		// @wstFnID [wst.Regex.create]
		this.object = false;
		this.source = source || this.source;
		this.flags = flags || this.flags;
		
		if(this.source)
			this.object = new RegExp(this.source, this.flags);
		
		return this.object;
	});
	
	wst.Regex.addMember('public', 'run', function(str, source, flags)
	{
		// @wstFnID [wst.Regex.run]
		this.source = source || this.source;
		this.str = str || this.str;
		this.flags = flags || this.flags;
		
		if((!this.object && this.source && this.str) || this.object.source != this.source)
		{
			if(typeof this.source == 'string')
			{
				this.create();
			}
			else
			{
				this.object = this.source;
				this.source = this.object.source;
			}
		}
		
		if(this.object)
		{
			this.test = this.object.test(this.str);
			this.matches = this.object.exec(this.str);
		}
		else
		{
			this.test = false;
			this.matches = false;
		}
		
		return this.matches;
	});
	
	wst.Regex.addConstructor(function(source)
	{
		// @wstFnID [wst.Regex]
		this.source = source || false;
		
		if(this.source)
			this.create();
	});
	
	wst.Regex = wst.Regex.build();
	
	var _addMarginPadding = function(e, dir)
	{
		// @wstFnID [wst._addMarginPadding]
		var margin = e.css('margin-' + dir);
		var padding = e.css('padding-' + dir);
		
		return (!isNaN(parseInt(margin)) ? parseInt(margin) : 0) + (!isNaN(parseInt(padding)) ? parseInt(padding) : 0);
	};
	
	/*********************
	* @ BROWSER OBJECT @ *
	*********************/
	wst.browser = {
		// @wstFnID [wst.Browser]
		agent : navigator.userAgent,
		detect : function(agent)
		{
			// @wstFnID [wst.Browser.detect]
			var ids = {
				msie : 'ie',
				opera : 'op',
				firefox : 'ff',
				safari : 'sf',
				chrome : 'cm'
			};
			agent = (agent || this.agent).toLowerCase();
			
			this.name = null || (agent.match(/msie|firefox|opera|safari|chrome/)[0]);
			this.ie = this.name == 'msie';
			this.op = this.name == 'opera';
			this.ff = this.name == 'firefox';
			this.sf = this.name == 'safari';
			this.ch = this.name == 'chrome';
			
			this.version = null || wst.regex(agent, '(?:version|' + this.name + ')(?:\\s|\\/)?(\\d+(?:\\.\\d+)*)')[1];
			this.id = null || ids[this.name];
			this.gecko = /gecko\/\d+/.test(agent);
			this.webkit = /webkit/.test(agent);
			this.mobile = /mobile|midp|symbian|iphone/.test(agent);
			this.js = navigator.javaEnabled();
			this.os = agent.match(/windows|linux|mac|symbian|iphone/)[0];
			this.strict = (document.compatMode == 'CSS1Compat');
		}
	};
	
	wst.browser.detect();
	
	/* ------------------------------------------------------------------------------------------------
													CONFIG
	------------------------------------------------------------------------------------------------ */
	var _attrSelectors		= /[#:\.\[]/;
	var _trimSelectors		= /\s*([>+~%$])\s*/g;
	var _multiSpaces		= /\s{2,}/g;
	//var _matches			= /((?:[\w-_]+|\*)|(?:[#\.:+>~%$])|(?:(?:\[)(?=[^\]]*)(?:\]))|\s)|(?:\([^)]+\)\)?)/g;
	var _matches			= /(\([^\)]+\)|\[|[\w-_]+(?=.?=)[^\]]+(?=[\]])|(?:[\w-_]+|\*)|[#\.:+>~%$]|\s)/g;
	var _pseudoFn			= /lang|not|nth-child|contains/i;
	var _children			= /(?:\()?((?:first|last|only|nth)(?=-child)|empty|checked|selected)(?:\))?/i;
	var _iniSelector		= /^[#\.>+~%$]/;
	var _iniTagName			= /^(?:[\w-_]+|\*)/;
	var _aloneSelector		= /(\s+|^)([#\.:\[])/g;
	var _invertedSelector	= /^\s?(?:[\w-_]|\*)+[#:\.\[]{1}/;
	var _pseudoSelectors	= /lang|not|contains|empty|first|last|(?:first|last|only|nth)(?=-child)/i;
	var _noEncode			= /[\d\w\-\.\=]/;
	
	wst.extend(wst, {
		version : '1.1',
		E : [],
		total : 0, // we use total because length turns the object into an array, wich causes an error
		imagesLoaded : [],
		documentLoaded : false,
		onDocumentLoad : function()
		{
			// @wstFnID [wst.onDocumentLoad]
			
		},
		html : {
			attributes : {
				'class' : 'className',
				'colspan' : 'colSpan',
				'rowspan' : 'rowSpan',
				'for' : 'htmlFor'
			},
			regex : {
				'tag' : /<\/?\w+[^>]*>/,
				'tags' : /<\/?\w+[^>]*>/gim,
				'entities' : /&[^;]+;/gim,
				'unicode' : /[\x21\x23-\x25\x5E\x60\x7E\xA0-\xBF\xC0-\xFF]/g
			},
			replaceEntities : function(str)
			{
				// @wstFnID [wst.html.replaceEntities]
				return str.replace(this.regex.entities, function($1){ return (wst.html.entities[$1] ? wst.html.entities[$1] : $1) });
			},
			replaceUnicode : function(str)
			{
				// @wstFnID [wst.html.replaceUnicode]
				return str.replace(this.regex.unicode, function($1){ return '&#' + $1.charCodeAt(0) + ';' });
			},
			stripTags : function(str)
			{
				// @wstFnID [wst.html.stripTags]
				return str.replace(this.regex.tags, '');
			},
			toText : function(str)
			{
				// @wstFnID [wst.html.toText]
				return this.stripTags(this.replaceEntities(str));
			}
		},
		/*******************
		* @ CORE OBJECT @ *
		*******************/
		core : {
			alertErrors : true,
			exposeBaseDir : true,
			instances : [],
			documentReadyCallbacks : [],
			mode : 'strict', // available values: strict, quirk
			runningAt : (window.location.protocol == 'file:' ? 'localFileSystem' : 'server'),
			disableScriptCache : !!window.applicationCache || wst.browser.webkit /*(wst.browser.ff && (parseInt(wst.browser.version) > 2)) || wst.browser.webkit*/,
			_getWSTDir : function()
			{
				// @wstFnID [wst.core._getWSTDir]
				if(wst.core.exposeBaseDir)
				{
					var dir = '';
					
					wst.get('script[src]').loop(function(){
						var path = wst.get(this).attr('src');
						
						if(path.indexOf('wst.core') > -1)
						{
							dir = (path.split('wst.core'))[0];
							return false;
						}
					});
					
					return dir;
				}
				
				return '';
			},
			_getCaller : function()
			{
				// @wstFnID [wst.core._getCaller]
				var callerFn = arguments.callee.caller, anonymous = false, name = '', callerBody;
				var nameRegex = /\/{2}\s*@wstFnID\s*\[([^\]]+)\]/;
				var userFn = arguments[0];
				var i = 0;
				
				try{
					if(!userFn)
					{
						while((callerFn = callerFn.arguments.callee.caller) && (++i <= 50))
						{
							callerBody = callerFn.toString();
							
							if(callerBody.indexOf('wstFnID') > -1)
							{
								name = callerBody.match(nameRegex)[1] || '';
								break;
							}
							else
							{
								name = callerFn.name || '';
							}
							
							anonymous = true;
						}
					}
					else
					{
						callerBody = userFn.toString();
						
						if(callerBody.indexOf('wstFnID') > -1)
						{
							name = callerBody.match(nameRegex)[1] || '';
						}
						else
						{
							name = callerFn.name || '';
							anonymous = true;
						}
					}
				}
				catch(err){
					anonymous = true;
				};
				
				name = anonymous ? '(anonymous) ' + name : name;
				return name;
			},
			_duplicateWST : function(instance)
			{
				// @wstFnID [wst.core._duplicateWST]
				var newWST = new wst;
				instance = instance || wst.core.instances.slice(-1)[0];
				newWST.dom.getTextNodes = instance.dom.getTextNodes;
				newWST.dom.cacheElements = instance.dom.cacheElements;
				newWST.E = instance.E;
				newWST.total = instance.total;
				newWST.expr = instance.expr;
				newWST.alertErrors = instance.alertErrors;
				
				return newWST;
			},
			hasLog : function(logName)
			{
				// @wstFnID [wst.core.hasLog]
				return (wst.log ? wst.log.enabled && wst.log[logName].enabled : false);
			}
		},
		/*********************
		* @ MODULES OBJECT @ *
		*********************/
		modules : {
			ready : 0,
			loaded : 0,
			// By default the dynamic load is made with Ajax. In this case the wst.Ajax module
			// already must to be loaded. Otherwise, the load is made with the "standard" mode, with
			// a script element. The better choice is Ajax.
			load : function(module, ajaxLoad)
			{
				// @wstFnID [wst.modules.load]
				var customModule = module.split('/').slice(-1)[0].replace('.js', '');
				var qs = wst.core.disableScriptCache ? '?' + (new Date).getTime() : '';
				
				if(wst.ok(this[module]) ? !this[module].loaded : this[customModule] ? !this[customModule].loaded : true)
				{
					this.ready++;
					ajaxLoad = wst.is.undef(ajaxLoad) ? true : ajaxLoad;
					
					if(wst.core.hasLog('dom'))
					{
						var logDomEnabled = wst.log.dom.enabled;
						wst.log.dom.enabled = false;
					}
					
					var moduleSrc = this[module] ? wst.core.baseDir + this[module].src : module;
					var script;

					if(wst.ok(wst.load) && ajaxLoad)
					{
						var moduleContent = wst.load(moduleSrc + qs);
						var status = wst.ajax.stats.list.status.slice(-1)[0];
						
						if(/200|304/.test(status))
						{
							if(this[module])
								this[module].loaded = true;
							else
								this[customModule] = {loaded : true, src : moduleSrc};
							
							script = wst.create('<script type="text/javascript"></script>');
							
							script.text = moduleContent;
							wst.get('head').append(script);
						}
						else
						{
							var err = '';
							
							switch(status)
							{
								case 404:
									err = '404: ' + module + wst.messages.functions.modulesLoad404;
									break;
								case 500:
									err = '500: ' + wst.messages.functions.modulesLoad500 + module;
									break;
								default:
									err = (status || '-001') + ': ' + wst.messages.functions.modulesLoadDefault + module;
									break;
							}
							
							wst.error(err);
						}
						
						if(wst.core.hasLog('dom'))
							wst.log.dom.enabled = logDomEnabled;
						
						this.loaded++;
					}
					else
					{
						var wstFnCaller, wstArgsCaller, wstThisCaller;
						var scriptEvt = wst.browser.ie ? 'readystatechange' : 'load';
						script = wst.create('<script src="' + moduleSrc + qs + '" type="text/javascript"></script>');

						if(arguments.callee.caller && arguments.callee.caller.arguments)
						{
							wstFnCaller = arguments.callee.caller,
							wstArgsCaller = wstFnCaller.arguments,
							wstThisCaller = wstArgsCaller.callee.caller;
						}

						wst.get(script).listen(scriptEvt, function(){
							if(scriptEvt == 'readystatechange' ? this.readyState == 'complete' : true)
							{
								if(wst.modules[module])
									wst.modules[module].loaded = true;
								else
									wst.modules[module.split('/').slice(-1)[0]] = {loaded : true, src : moduleSrc};
								
								wst.modules.loaded++;

								if(wstFnCaller)
									wstFnCaller.apply(wstThisCaller, wstArgsCaller);
							}
						});
						
						wst.get('head').append(script);
						
						if(wst.core.hasLog('dom'))
							wst.log.dom.enabled = logDomEnabled;
						
						return false;
					}
				}
			},
			// Must to be called before the page load event
			loadAll : function()
			{
				// @wstFnID [wst.modules.loadAll]
				var root = this;
				var modules = wst.array.values(this).slice(4);
				var module = modules[0], i = 0;
				var qs = wst.core.disableScriptCache ? '?' + (new Date).getTime() : '';
				
				var loadMod = function(){
					if(module.autoLoad && !module.loaded)
					{
						var mod = module;
						root.ready++;
						
						if(!wst.documentLoaded)
						{
							var fn = function(){
								mod.loaded = true;
								root.loaded++;
							};
							
							if(wst.browser.gecko || wst.browser.webkit)
								wst.include(wst.core.baseDir + module.src + qs).on('load', fn);
							else
								wst.include(wst.core.baseDir + module.src + qs).ready(fn);
						}
						else
						{
							this.load(module.src.split('.')[1] + qs);
						}
					}
					
					//for(var j = 0; j < 5000; j++)
					//	continue;
					
					if((module = modules[++i]))
						loadMod();
				};
				
				loadMod();
			}
		}
	});
	
	/* ------------------------------------------------------------------------------------------------
													PROTOTYPE
	------------------------------------------------------------------------------------------------ */
	// Array
	Array.prototype.loop = wst.loop;
	
	// wst
	wst.extend(wst.proto, {
		version : wst.version,
		uid : 0,
		E : [],
		total : wst.total,
		expr : '',
		alertErrors : true,
		validObject : wst.validObject,
		get : wst.get,
		lookup : wst.lookup,
		at : wst.at,
		add : wst.add,
		rem : wst.rem,
		first : wst.first,
		last : wst.last,
		parent : wst.parent,
		next : wst.next,
		prev : wst.prev,
		siblings : wst.siblings,
		children : wst.children,
		hasChildren : wst.hasChildren,
		filter : wst.filter,
		index : wst.index,
		sort : wst.sort,
		equals : wst.equals,
		tag : wst.tag,
		type : wst.type,
		value : wst.value,
		text : wst.text,
		append : wst.append,
		appendTo : wst.appendTo,
		remove : wst.remove,
		after : wst.after,
		before : wst.before,
		replace : wst.replace,
		clone : wst.clone,
		content : wst.content,
		clear : wst.clear,
		attr : wst.attr,
		css : wst.css,
		clss : wst.clss,
		focus : wst.focus,
		blur : wst.blur,
		enable : wst.enable,
		check : wst.check,
		isVisible : wst.isVisible,
		pos : wst.pos,
		scrollView : wst.scrollView,
		show : wst.show,
		hide : wst.hide,
		listen : wst.event.listen,
		unListen : wst.event.unListen,
		loaded : wst.loaded,
		ready : wst.ready,
		blockKey : wst.blockKey,
		onlyNumbers : wst.onlyNumbers,
		disableRightClick : wst.disableRightClick,
		loop : wst.loop,
		on : function(evtType, opt)
		{
			// @wstFnID [wst.on]
			if(this.total > 0)
			{
				if(wst.is.fn(opt))
				{
					this.listen(evtType, opt);
				}
				else
				{
					if(wst.ajax.action)
						wst.ajax.action(this, evtType, (opt || {}));
				}
			}
			
			return this;
		},
		off : wst.event.unListen
	});
	
	wst.doc = wst.get(document);
	wst.core.baseDir = wst.core._getWSTDir();

	if(wst.browser.ie && (parseInt(wst.browser.verion) == 6))
		document.execCommand('BackgroundImageCache', false, true);
	
	/* ------------------------------------------------------------------------------------------------
											INTERNAL FUNCTIONS
	------------------------------------------------------------------------------------------------ */
	var wstOnDocumentReady = function(evt){
		// @wstFnID [wstOnDocumentReady]
		wst.documentLoaded = true;
		wst.apply(wst.onDocumentLoad, [evt], document);
	};
	
	var wstOnError = function(){
		var alertErrors = wst.core.alertErrors;
		wst.core.alertErrors = false;
		wst.error.apply(this, arguments);
		wst.core.alertErrors = alertErrors;
	};
	
	wst.doc.ready(wstOnDocumentReady);
	wst.get(window).on('error', wstOnError);
})();