// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //
//
//	NJS FRAMEWORK CORE 0.2.0
//
// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //

	String.prototype.trim = function()
	{
		var str = this.replace(/^\s\s*/, ''), ws = /\s/, i = str.length;
		while (ws.test(str.charAt(--i)));
		return str.slice(0, i + 1);
	};

	String.prototype.toNumeric = function()
	{

		var validChars = "0123456789.", isDouble = false, result = "";
		for (var i = 0; i < this.length; i++) 
		{
			if(validChars.indexOf(this.charAt(i)) >= 0 || (i == 0 && this.charAt(i) == "-"))
				result += this.charAt(i) + "";
			if(this.charAt(i) == ".")
				isDouble = true;
		}
		if(result == "")
			result = 0;
		if(isDouble)
			return parseFloat(result);
		else
			return parseInt(result);
	};

	Array.prototype.each = function(fun)
	{
		if (typeof fun != "function")
			return false;
		for(var i in this)
		{
			if(!(i in Array.prototype))
				fun.call(this, i, this[i]);
			
		}
	};

	Array.prototype.rebuildIndex = function()
	{
		var rebuilded = [];
		this.each(function(index,value)
		{
			rebuilded[rebuilded.length] = value;
		});
		return rebuilded;
	};

	Array.prototype.has = function(something)
	{
		var found = false;
		this.each(function(index,value)
		{
			if(value==something) found = true;
		});
		return found;
	};

	Array.prototype.hasOneOf = function(something)
	{
		var found = false;
		this.each(function(index,value)
		{
			if(something.has(value)) found = true;
		});
		return found;
	};

	Object.prototype.each = function(fun)
	{
		if (typeof fun != "function")
			return false;
		for(var i in this)
		{
			if(!(i in Object.prototype))
				fun.call(this, i, this[i]);
			
		}
	};

// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //
//
//	Njs Extensions:
//
// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //

	Njs		= {};

		Njs.browser	= {}
		
			Njs.browser.ff		= /firefox/i.test(navigator.userAgent);
			Njs.browser.opera	= /opera/i.test(navigator.userAgent);
			Njs.browser.ie		= /msie/i.test(navigator.userAgent);
			Njs.browser.safari	= /safari/i.test(navigator.userAgent) && !/firefox/i.test(navigator.userAgent);
			Njs.browser.ff2		= /firefox\/2\./i.test(navigator.userAgent);
			Njs.browser.ff3		= /firefox\/3\./i.test(navigator.userAgent);
			Njs.browser.ff31	= /firefox\/3\.1/i.test(navigator.userAgent);
			Njs.browser.opera9	= /opera/i.test(navigator.userAgent) && /9\./i.test(navigator.userAgent);
			Njs.browser.opera95	= /opera/i.test(navigator.userAgent) && /9\.5/i.test(navigator.userAgent);
			Njs.browser.ie55	= /msie 5\.5/i.test(navigator.userAgent);
			Njs.browser.ie6		= /msie 6\./i.test(navigator.userAgent);
			Njs.browser.ie7		= /msie 7\./i.test(navigator.userAgent);
			Njs.browser.safari3	= /safari/i.test(navigator.userAgent) && /n\/3\./i.test(navigator.userAgent) && !/firefox/i.test(navigator.userAgent);
			Njs.browser.safari31	= /safari/i.test(navigator.userAgent) && /n\/3\.1/i.test(navigator.userAgent) && !/firefox/i.test(navigator.userAgent);
			
		Njs.element	= {};

			Njs.element.addEvent = function(argEvent, argFunction)
			{
				this[argEvent] = (function(base)
				{
					return function(evt)
					{
						if(!evt) evt = window.event;
						if(base) base.call(this, evt);
						argFunction.call(this, evt);
					}
				})(this[argEvent]);
			};
			
			Njs.element.disableEvent = function(argEvent)
			{
				if(!this.disabledEvents)
					this.disabledEvents = [];
				this.disabledEvents[argEvent] = this[argEvent];
					this[argEvent] = null;
				return this;
			}
			
			Njs.element.enableEvent = function(argEvent)
			{
				if(this.disabledEvents[argEvent])
					this[argEvent] = this.disabledEvents[argEvent];
				delete this.disabledEvents[argEvent];
				return this;
			}
			
			Njs.element.disableSelection = function()
			{
				this.onselectstart = function(){return false;}
				this.onmousedown = function(){return false;}
				return this;
			}

			Njs.element.addClassName = function(argClassName)
			{
				var currentcn = this.className.split(" ");
				var found = false;
				for(var x=0;x<currentcn.length;x++)
					if(currentcn[x]==argClassName)
						found = true;
				if(!found)
					this.className += " " + argClassName;
			};
			
			Njs.element.hasClassName = function(argClassName)
			{
				var currentcn = this.className.split(" ");
				var found = false;
				for(var x=0;x<currentcn.length;x++)
					if(currentcn[x]==argClassName)
						found = true;
				return found;
			};

			Njs.element.removeClassName = function(argClassName)
			{
				var currentcn = this.className.split(" ");
				for(var x=0;x<currentcn.length;x++)
					if(currentcn[x]==argClassName)
						currentcn.splice(x,1);
				this.className = currentcn.join(" ");
			};

			Njs.element.getStyle = function(strCssRule)
			{
				var strValue = "";
				if(document.defaultView && document.defaultView.getComputedStyle)
					strValue = document.defaultView.getComputedStyle(this, "").getPropertyValue(strCssRule);
				else if(this.currentStyle)
				{
					strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){return p1.toUpperCase();});
					strValue = this.currentStyle[strCssRule];
					if(strCssRule == "width" && strValue == "auto")
						strValue = this.getWidth() + "px";
					if(strCssRule == "height" && strValue == "auto")
						strValue = this.getHeight() + "px";
				}

				if(strCssRule == "opacity")
				{
					if(!this.opacity)
						this.opacity = "100";
					strValue = this.opacity;
				}

				return strValue + "";
			};

			Njs.element.setStyle = function(name, value)
			{
				if(name == "opacity")
				{
					this.opacity = value;
					this.style.filter = "alpha(opacity=" + Math.round(this.opacity.toNumeric()) +")";
					this.style.opacity = this.opacity.toNumeric()/100;

				}
				else
					this.style.cssText += ";" + name + ":" + value;
				return this;
			};

			Njs.element.getWidth = function()
			{
				var a = [], minus = 0;
				a[a.length] = this.getStyle("padding-left").toNumeric();
				a[a.length] = this.getStyle("padding-right").toNumeric();
				a[a.length] = this.getStyle("border-left-width").toNumeric();
				a[a.length] = this.getStyle("border-right-width").toNumeric();
				for (var x = 0; x < a.length; x++)
					if(!isNaN(a[x]))
						minus += parseInt(a[x]);
				return(this.offsetWidth - minus);
			};

			Njs.element.getHeight = function()
			{
				var a = [], minus = 0;
				a[a.length] = this.getStyle("padding-top").replace("px","");
				a[a.length] = this.getStyle("padding-bottom").replace("px","");
				a[a.length] = this.getStyle("border-top-width").replace("px","");
				a[a.length] = this.getStyle("border-bottom-width").replace("px","");
				for (var x = 0; x < a.length; x++)
					if(!isNaN(a[x]))
						minus += parseInt(a[x]);
				return(this.offsetHeight - minus);
			};

			Njs.element.toggleDisplay = function()
			{
				if(!this.defaultDisplayValue)
					if(this.getStyle("display") != "none")
						this.defaultDisplayValue = this.getStyle("display");
					else
						if(arguments[0])
							this.defaultDisplayValue = arguments[0];
						else
							return false;

				if(this.getStyle("display") != "none")
					this.setStyle("display", "none");
				else
					this.setStyle("display", this.defaultDisplayValue);
				return this;
			}

			Njs.element.stopAnimation = function()
			{
				var element = this;
				if(element.animations)
				element.animations = [];
				return element;
				
			}
			
			Njs.element.animation = function(params, duration)
			{
				
				var element = this;
				if(!element.animations) element.animations = [];
				
				var animationid = element.animations.length;
				element.animations[animationid] = [];

				element.animations[animationid].properties = [];
				element.animations[animationid].values = [];
				element.animations[animationid].mspf = [];
				element.animations[animationid].increment = [];
				element.animations[animationid].steps=[];
				element.animations[animationid].currentStep = [];
				
				if(arguments[2]) var callback = arguments[2];
				
				params.each(function(cssName, cssValue)
				{
					if(
						cssValue.match(/^-?([0-9]+)(em|px|%|cm|in|pt|pc|ex|mm)$/) ||
						cssName == "line-height" && cssValue == "normal" ||
						cssName == "width" && cssValue == "auto" ||
						cssName == "height" && cssValue == "auto" ||
						cssName == "opacity" && cssValue.match(/^[0-9]+$/)
					)
					{
					
						element.animations.each(
						function(ga,bri)
						{
							element.animations[ga].properties.each(function(we,s)
							{
								if(s==cssName)
									delete element.animations[ga].properties[we];
							});
						}
						);
						
						element.animations[animationid].properties[element.animations[animationid].properties.length]			= cssName;
						element.animations[animationid].values[element.animations[animationid].values.length]					= cssValue;
						element.animations[animationid].steps[element.animations[animationid].steps.length]						= new Framerate(cssValue.toNumeric() - element.getStyle(cssName).toNumeric(), duration).steps2;
						element.animations[animationid].mspf[element.animations[animationid].mspf.length]						= new Framerate(cssValue.toNumeric() - element.getStyle(cssName).toNumeric(), duration).msPerFrame;
						element.animations[animationid].increment[element.animations[animationid].increment.length]				= new Framerate(cssValue.toNumeric() - element.getStyle(cssName).toNumeric(), duration).increment;
						element.animations[animationid].currentStep[element.animations[animationid].currentStep.length]			= 1;

					}
				});
				
				
				
				var ab = setInterval(function()
				{
					var end = true;
					if(element.animations[animationid]) element.animations[animationid].properties.each(function(id,val){end = false;});
					else{ end = true;callback=false};
					
					if(end)
					{
						
						clearInterval(ab);
						delete(ab);
						delete(element.animations[animationid]);
						if(callback)
							callback.call(element);
					}
					else
					{
						
						
						element.animations[animationid].properties.each(function(id, bah)
						{
						
							

							
							if(element.animations[animationid].currentStep[id]<=element.animations[animationid].steps[id])
							{
								var deletethis = false;
								
								var newvalue = element.getStyle(element.animations[animationid].properties[id]).toNumeric() + parseInt(element.animations[animationid].increment[id]);
		
								if(
								element.animations[animationid].currentStep[id]>=element.animations[animationid].steps[id]
								)
								{
									element.setStyle(element.animations[animationid].properties[id], element.animations[animationid].values[id].toNumeric() + "px");
									deletethis=true;
								}
								else
									if(element.animations[animationid].properties[id])
										element.setStyle(element.animations[animationid].properties[id], newvalue + "px");
								
								element.animations[animationid].currentStep[id]++;
								
								if(deletethis)
								{
									delete element.animations[animationid].properties[id];
								}
							}
						});
					}
					
				},25);

				function Framerate(targetDimension, duration)
				{
					var mspf = 25;
					if(targetDimension == 0)
					{
					this.steps2 = 1;
					this.msPerFrame = mspf;
					this.increment = 0;
					}
					else
					{
					
					
					var steps = Math.round(duration/mspf);
					var stepIncrement = targetDimension/steps;
					while(stepIncrement>=0 && stepIncrement<1)
					{
						mspf++;
						steps = Math.round(duration/mspf);
						stepIncrement = targetDimension/steps;
					}
					this.steps2 = steps;
					this.msPerFrame = Math.round(mspf);
					this.increment = Math.round(stepIncrement);
					}
					
				}

				return element;
			}









	// °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° //

	Njs.queue = function()
	{
		var list = [], queueIndex = -1, loop;
		
		if(arguments[0] && arguments[0] == true)
			loop = true
		else
			loop = false;

		this.add = function(callback)
		{
			list[list.length] = callback;
		}
			
		this.next = function()
		{
			if(list[++queueIndex])
				list[queueIndex].call(this);
			else
				if(loop)
				{
					queueIndex = -1;
					this.next();
				}
		}
		
		this.clear = function()
		{
			delete list;
			list = [];
			queueIndex = -1;
		}
	}

// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //


window.addEvent = function(argEvent, argFunction)
{
	window[argEvent] = (function(base)
	{
		return function(evt)
		{
			if(!evt) evt = window.event;
			if(base) base.call(window, evt);
			argFunction.call(window, evt);
		}
	})(window[argEvent]);
};



Njs.main = function(argFunction)
{
	window["onload"] = (function(base)
	{
		return function(evt)
		{
			if(!evt) evt = window.event;
			if(base) base.call(this, evt);
			argFunction.call(this, evt);
		}
	})(window["onload"]);
};








//ADD: * SELECTOR

Njs.get = function(argSelection)
{
	var foundarray = [document], selezioni = decodeSelectionTree(argSelection);
	for(var x=0;x<selezioni.length;x++)
	{
		var rules = decodeRules(selezioni[x]['string']), elementCollection, elementCollectionCleaned;
		for(var z=0;z<foundarray.length;z++)
		{
			elementCollection = getElementsOf(foundarray[z]);
			elementCollectionCleaned=elementCollection;
			elementCollection.each(function(hh, inutile)
			{
				if(
					((rules['class'] && rules['class'][0].length > 0 && rules['class'][0].hasOneOf(inutile.className.split(" "))) || (rules['class'] && rules['class'][1].length > 0 && !(rules['class'][1].hasOneOf(inutile.className.split(" "))))) ||
					((rules['id'] && rules['id'][0].length > 0 && rules['id'][0].has(inutile.id)) || (rules['id'] && rules['id'][1].length > 0 && !(rules['id'][1].has(inutile.id)))) ||
					((rules['tag'] && rules['tag'][0].length > 0 && rules['tag'][0].has(inutile.tagName.toLowerCase())) || (rules['tag'] && rules['tag'][1].length > 0 && !(rules['tag'][1].has(inutile.tagName.toLowerCase())))) ||
					(selezioni[x]['type'] == 1 && inutile.parentNode != foundarray[z])
				)
					delete elementCollectionCleaned[hh];
			});
			elementCollection = elementCollectionCleaned.rebuildIndex();
		}
		foundarray = elementCollection;
	}
	
	foundarray = foundarray.rebuildIndex();
	
	for(var y=0;y<foundarray.length;y++)
		for(lallo in Njs.element)
		{
		
		
			foundarray[y][lallo] = Njs.element[lallo];
			
		
		}
		
		return foundarray;
	

	// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //

	function getElementsOf(argElement)
	{
		var elementCollection = argElement.getElementsByTagName("*"), elementCollectionCleaned = [];
		for(var x in elementCollection)
			if(elementCollection[x])
				if(elementCollection[x].tagName)
					elementCollectionCleaned[x] = elementCollection[x];
		elementCollection = elementCollectionCleaned;
		elementCollection = elementCollection.rebuildIndex();
		return elementCollection;
	}

	// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //

	function decodeRules(argString)
	{
		var exploding, matches = [], matchesCleaned = [];
		
		exploding = argString.match(/(\$\^?[\w-\^\*\$]+)*(#\^?[\w-\^#]+)*(\.\^?[\w-\.\^]+)*/);
		if(exploding[1])
			matches['tag'] = exploding[1].match(/\$\^?[\w-\*]+/g);
		if(exploding[2])
			matches['id'] = exploding[2].match(/#\^?[\w-]+/g);
		if(exploding[3])
			matches['class'] = exploding[3].match(/\.\^?[\w-]+/g);

		matches.each(function(property, array)
		{
			matchesCleaned[property] = [];
			matchesCleaned[property][1] = [];
			matchesCleaned[property][0] = [];
			matches[property].each(function(yesno, array2)
			{
				if(!isNaN(yesno))
				{
					matches[property][yesno] = matches[property][yesno].replace(/[#.\$]/, "");
					if(matches[property][yesno].substring(0,1) == "^")
						if(property != "tag")
							matchesCleaned[property][0][matchesCleaned[property][0].length] = matches[property][yesno].substring(1);
						else
							matchesCleaned[property][0][matchesCleaned[property][0].length] = matches[property][yesno].substring(1).toLowerCase();
					else
						matchesCleaned[property][1][matchesCleaned[property][1].length] = matches[property][yesno].toLowerCase();
				}
			});
		});
		
		if(matchesCleaned['tag'])
			if(matchesCleaned['tag'][1])
				if(matchesCleaned['tag'][1].length > 0)
					matchesCleaned['tag'][0] = [];
		if(matchesCleaned['id'])
			if(matchesCleaned['id'][1])
				if(matchesCleaned['id'][1].length > 0)
					matchesCleaned['id'][0] = [];
		return matchesCleaned;
	}

	// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //

	function decodeSelectionTree(argSelection)
	{
		var selection = [], type;
		if(argSelection.trim().charAt(0) == ">")
		argSelection = argSelection.trim().substring(1);
		argSelection = " " + argSelection;
		argSelection = argSelection.match(/([>| ]{1}[\w-\^\*#\.\$]+)/g);
		argSelection.each(function(i,content)
		{
			if(!isNaN(i))
			{
				selection[i]=[];
				type=argSelection[i].charAt(0);
				if(type == " ")
					selection[i]['type']=0;
				else
					selection[i]['type']=1;
				selection[i]['string'] = content.substring(1);
			}
		}
		);
		return selection;
	}
};

// [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][] //
