/**
* Script Base.js
* Contains the base functions used by the rest of the NC scripts
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
*/
/**
* NC namespace
*/
if (NC == undefined) var NC = window.NC || {};

/**
* Namespace generation
* @argument string nc The namespace to create
*/
NC.namespace = function(ns) {
	if (!ns || ns.length == 0) {
		return null;
	}
	var n = ns.split('.');
	var nsobj = NC;
	for (var i =(n[0] == 'NC') ? 1 : 0; i < n.length; i ++) {
		if (nsobj[n[i]] == undefined) nsobj[n[i]] = nsobj[n[i]] || {}
		nsobj = nsobj[n[i]];
	}
	return nsobj
}


/**
* Find out what an object is
* @argument object obj The object to test
* @returns
*/
NC.type = function(obj) {
	if (!obj) return false;
	var result = false;
	if (obj.nodeType) {
		if (obj.nodeType == 1) result = 'elementNode';
		else if (obj.nodeType == 2) result = 'attributeNode';
		else if (obj.nodeType == 3 && !/\S/.test(obj.nodeValue)) result = 'textNode';
	}
	else if (obj instanceof Function) result = 'function';
	else if (obj instanceof Array) result = 'array';
	else if (typeof obj == "object") result = 'object';
	else if (typeof obj == "string") result = 'string';
	else if (typeof obj == "number" && isFinite(obj)) result = 'number';
	return result;
}
/*
Property: rgbToHex
Converts an RGB value to hexidecimal.

Arguments:
r - integer. the "r" value of "rgb"
g - integer. the "g" value of "rgb"
b - integer. the "b" value of "rgb"
a - integer. the "a" (alpha) value of rgba

Returns:
hex string or array. returns "transparent" if a is 0,
*/
NC.rgbToHex = function(r,g,b,a){
	if (a && a == 0) return 'transparent';
	r = r.toString(16); if (r.length == 1) r = '0' + r;
	g = g.toString(16); if (g.length == 1) g = '0' + g;
	b = b.toString(16); if (b.length == 1) b = '0' + b;
	return "#" + r + g + b;
}
/**
* Clears a timeout or interval
*/
NC.clearTimer = function(timer) {
	clearTimeout(timer);
	clearInterval(timer);
	return null;
}
/**
* Short function for getting an element
*/
NC.$ = function(el, env) {
	//The environment to search in. Defaults to document, but could be a dom element
	var env = env || document;
	var type = NC.type(el);
	if (type == 'string') {
		if (env.getElementById) el = env.getElementById(el);
		else if (env.all) el = env.all(el);
		else el = null;
	}
	if (NC.type(el) == 'elementNode') {
		if (!el.extend) {
			el.extend = Object.extend;
			el.extend(NC.Element.prototype);
		}
		return el;
	}
	else return false;

}
/**
* Short function for getting elements by class name
* Based on function by Dustin Diaz http://www.dustindiaz.com/top-ten-javascript/
*/
NC.$$ = function(className, env, tag) {
	var classElements = new Array();
	//The environment to search in. Defaults to document, but could be a dom element
	var env = env || document;
	//Specific tag to work with
	tag = tag || '*';
	var tagType = NC.type(tag);
	if (tagType == 'string') {
		var els = env.getElementsByTagName(tag);
	}
	else if (tagType == 'array') {
		els = new Array();
		for (var x = 0; x < tag.length; x ++) {
			els.push(env.getElememtsByTagName(tag[x]));
		}
	}
	var pattern = new RegExp('(^|\\s)' + className + '(\\s|$)');
	for (i = 0, j = 0; i < els.length; i++) {
		if (pattern.test(els[i].className)) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}
NC.getElementsByClassName = function(className, env, tag) {
	return NC.$$(className, env, tag);
}
/**
* Short function for the Array.copy() function
*/
NC.$AC = function(array) {
	return Array.prototype.copy.call(array);
}
/**
* Short function for getElementsByTagName()
*/
NC.$T = function(tag, env) {
	tag = tag || '*';
	env = env || document;
	var elements = null;
	if (document.getElementsByTagName) {
		elements = env.getElementsByTagName(tag);
		if (tag == '*' && (!elements || !elements.length)) elements = env.all; //IE 5 bug
	}
	return elements || new Array();
}
/**
* From http://cass-hacks.com/articles/discussion/js_url_encode_decode/
*/
NC.URLEncode = function (clearString) {
  var output = '';
  var x = 0;
  clearString = clearString.toString();
  var regex = /(^[a-zA-Z0-9_.\n\r]*)/; //Modified to add "\n\r" to not encode new line charactors
  while (x < clearString.length) {
    var match = regex.exec(clearString.substr(x));
    if (match != null && match.length > 1 && match[1] != '') {
    	output += match[1];
      x += match[1].length;
    } else {
      if (clearString[x] == ' ')
        output += '+';
      else {
        var charCode = clearString.charCodeAt(x);
        var hexVal = charCode.toString(16);
        output += '%' + hexVal.toUpperCase();
      }
      x++;
    }
  }
  return output;
}
/*
Function: $merge
	merges a number of objects recursively without referencing them or their sub-objects.

Arguments:
	any number of objects.

Example:
	>var mergedObj = $merge(obj1, obj2, obj3);
	>//obj1, obj2, and obj3 are unaltered
*/

NC.merge = function(){
	var mix = {};
	for (var i = 0; i < arguments.length; i++){
		for (var property in arguments[i]){
			var ap = arguments[i][property];
			var mp = mix[property];
			if (mp && NC.type(ap) == 'object' && NC.type(mp) == 'object') mix[property] = NC.merge(mp, ap);
			else mix[property] = ap;
		}
	}
	return mix;
};
/*
Function: $time
	Returns the current timestamp

Returns:
	a timestamp integer.
*/
NC.time = function() {
	return new Date().getTime();
};
/*
Function: $chk
	Returns true if the passed in value/object exists or is 0, otherwise returns false.
	Useful to accept zeroes.

Arguments:
	obj - object to inspect
*/
NC.chk = function(obj){
	return !!(obj || obj === 0);
};
/*
Function: $pick
	Returns the first object if defined, otherwise returns the second.

Arguments:
	obj - object to test
	picked - the default to return

Example:
	(start code)
		function say(msg){
			alert($pick(msg, 'no meessage supplied'));
		}
	(end)
*/

NC.pick = function(obj, picked){
	return NC.defined(obj) ? obj : picked;
};
/*
Function: $defined
	Returns true if the passed in value/object is defined, that means is not null or undefined.

Arguments:
	obj - object to inspect
*/
NC.defined = function(obj){
	return (obj != undefined);
};
/**
* Script Class.js
* Contains the class object and the Object.extend function
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js
*/
/*******************************************************
* Base object for creating new classes
* Allows class to be extended.
* Based on MooTools http://mootools.net/
********************************************************/
NC.Class = function(properties) {
	var thisClass = function() {
		if (arguments[0] !== 'noinit' && this.init) {
		    return this.init.apply(this, arguments);
		}
	};
	thisClass.prototype = properties;
	thisClass.implement = this.implement;
	thisClass.extend = this.extend;
	return thisClass;
}
/**
* Returns an empty class
*/
NC.Class.empty = function() {}

/**
* Same as new NC.Class
*/
NC.Class.create = function(properties) {
	return new NC.Class(properties);
}

NC.Class.prototype = {
	/**
	* Returns a copy of the class extended with the new properties
	*/
	extend: function(properties) {
		var newPrototype = new this('noinit');
		for (var property in properties) {
			//Get the property from the class being extended
			var previous = newPrototype[property];
			//Get the property from the new class
			var current = properties[property];
			if (previous && previous != current) {
			    var type = NC.type(current);
			    //If the type is not the same, current will automatically be used
			    if (type == NC.type(previous)) {
			        switch (type) {
			            case 'function': current = previous.parentize(current); break;
			            case 'object': current = NC.merge(previous, current); break;
			        }
			    }
			}
			newPrototype[property] = current;
		}
		return new NC.Class(newPrototype);
	},

	/**
	* Adds the properties to the object's prototype
	*/
	implement: function(properties) {
		for (var property in properties) {
			this.prototype[property] = properties[property];
		}
	}
};

/***********
* Object extension
************/
//Copies all of the properties from the second object to the first object
Object.extend = function() {
	var args;
	if (arguments[1]) {
		args = [arguments[0], arguments[1]];
	}
	else {
		args = [this, arguments[0]];
	}
	for (var property in args[1]) {
		//		alert(property + ' = ' + args[1][property]);
		args[0][property] = args[1][property] };
		return args;
}
Array.extend = NC.Class.prototype.implement;
Function.extend = NC.Class.prototype.implement;
String.extend = NC.Class.prototype.implement;
Number.extend = NC.Class.prototype.implement;
Function.extend({
	//Adds the this.parent property to the function.
	//this.parent points to the same function name in the previous
	//function being exteded
	parentize: function(current){
		var previous = this;
		return function(){
			this.parent = previous;
			return current.apply(this, arguments);
		};
	}

});

NC.Options = new NC.Class ({
   setOptions: function() {
       this.options = NC.merge.apply(null, [this.options].extend(arguments));
       return this;
   }
});
/**
* Script String.js
* Extends the String object
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js
*/
String.extend({
	test: function(regex, params) {
		return this.match(new RegExp(regex, params));
	},
	/**
	* Converts a hyphenated string to camelCase
	* this-string to thisString
	*/
	camelCase: function(){
		return this.replace(/-\D/gi, function(match){
			return match.charAt(match.length - 1).toUpperCase();
		});
	},
	/*
	Property: capitalize
	Converts the first letter in each word of a string to Uppercase.

	Example:
	>"i like cookies".capitalize(); //"I Like Cookies"

	Returns:
	the capitalized string
	*/
	capitalize: function(){
		return this.toLowerCase().replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},
	/**
	* Trims the leading and trailing spaces off a string.
	*/
	trim: function(){
		return this.replace(/^\s*|\s*$/g, '');
	},
	/**
	* trims a string AND removes all the double spaces in a string.
	*/
	clean: function(){
		return this.replace(/\s\s/g, ' ').trim();
	},
	/*
	Property: toInt
	parses a string to an integer.

	Returns:
	either an int or "NaN" if the string is not a number.

	Example:
	>var value = "10px".toInt(); // value is 10
	*/
	toInt: function(){
		return parseInt(this);
	},
	/**
	* Tests to see if a string is an integer
	*/
	isInt: function() {
		if (isNaN(this) || typeof(this) != 'number') return false;
		return true;
	},
	/*
	Property: rgbToHex
	Converts an RGB value to hexidecimal. The string must be in the format of "rgb(255, 255, 255)" or "rgba(255, 255, 255, 1)";

	Arguments:
	array - boolean value, defaults to false. Use true if you want the array ['FF', '33', '00'] as output instead of #FF3300

	Returns:
	hex string or array. returns transparent if the fourth value of rgba in input string is 0,

	Example:
	>"rgb(17,34,51)".rgbToHex(); //"#112233"
	>"rgba(17,34,51,0)".rgbToHex(); //"transparent"
	>"rgb(17,34,51)".rgbToHex(true); //[11,22,33]
	*/

	rgbToHex: function(array){
		var rgb = this.test('([\\d]{1,3})', 'g');
		if (rgb[3] == 0) return 'transparent';
		var hex = [];
		for (var i = 0; i < 3; i++){
			var bit = (rgb[i]-0).toString(16);
			hex.push(bit.length == 1 ? '0'+bit : bit);
		}
		var hexText = '#'+hex.join('');
		if (array) return hex;
		else return hexText;
	},

	/*
	Property: hexToRgb
	Converts a hexidecimal color value to RGB. Input string must be the hex color value (with or without the hash). Also accepts triplets ('333');

	Arguments:
	array - boolean value, defaults to false. Use true if you want the array ['255', '255', '255'] as output instead of "rgb(255,255,255)";

	Returns:
	rgb string or array.

	Example:
	>"#112233".hexToRgb(); //"rgb(17,34,51)"
	>"#112233".hexToRgb(true); //[17,34,51]
	*/

	hexToRgb: function(array){
		var hex = this.test('^[#]{0,1}([\\w]{1,2})([\\w]{1,2})([\\w]{1,2})$');
		var rgb = [];
		for (var i = 1; i < hex.length; i++){
			if (hex[i].length == 1) hex[i] += hex[i];
			rgb.push(parseInt(hex[i], 16));
		}
		var rgbText = 'rgb('+rgb.join(',')+')';
		if (array) return rgb;
		else return rgbText;
	}
});
/**
* Script Array.js
* Extends the Array object
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js
*/
//See http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
if (!Array.prototype.forEach) {
	Array.prototype.forEach = function(fn , thisOption) {
		if (typeof fn != "function") throw new TypeError();
		for (var i = 0; i < this.length; i++) {
			if (i in this) fn.call(thisOption || this, this[i], i, this);
		}
	};
}
Array.extend({
	each: Array.prototype.forEach,
	test: function(item) {
		for (var i = 0; i < this.length; i ++) {
			if (this[i] == item) return true;
		}
		return false;
	},
	copy: function(){
		var newArray = [];
		for (var i = 0; i < this.length; i++) newArray.push(this[i]);
		return newArray;
	},
	remove: function(item){
		for (var i = 0; i < this.length; i++){
			if (this[i] == item) this.splice(i, 1);
		}
		return this;
	},
	extend: function(newArray){
		for (var i = 0; i < newArray.length; i++) this.push(newArray[i]);
		return this;
	},
	first: function() {
		return this[0];
	},
	last: function() {
		return this[this.length - 1];
	}
});
/**
* Script Function.js
* Extends the Function object
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js
*/
Function.extend({
    /*
	Property: create
		Main function to create closures.

	Returns:
		a function.

	Arguments:
		options - An Options object.

	Options:
		bind - The object that the "this" of the function will refer to. Default is the current function.
		event - If set to true, the function will act as an event listener and receive an event as first argument.
				If set to a class name, the function will receive a new instance of this class (with the event passed as argument's constructor) as first argument.
				Default is false.
		arguments - A single argument or array of arguments that will be passed to the function when called.

					If both the event and arguments options are set, the event is passed as first argument and the arguments array will follow.

					Default is no custom arguments, the function will receive the standard arguments when called.

		delay - Numeric value: if set, the returned function will delay the actual execution by this amount of milliseconds and return a timer handle when called.
				Default is no delay.
		periodical - Numeric value: if set, the returned function will periodically perform the actual execution with this specified interval and return a timer handle when called.
				Default is no periodical execution.
		attempt - If set to true, the returned function will try to execute and return either the results or false on error. Default is false.
	*/

	create: function(options){
		var fn = this;
		options = NC.merge({
			'bind': fn,
			'event': false,
			'arguments': null,
			'delay': false,
			'interval': false,
			'attempt': false
		}, options);
		if (NC.chk(options.arguments) && NC.type(options.arguments) != 'array') options.arguments = [options.arguments];
		return function(event){
			var args;
			if (options.event){
				event = event || window.event;
				args = [(options.event === true) ? event : new options.event(event)];
				if (options.arguments) args.extend(options.arguments);
			}
			else args = options.arguments || arguments;
			var returns = function(){
				return fn.apply(NC.pick(options.bind, fn), args);
			};
			if (options.delay) return setTimeout(returns, options.delay);
			if (options.interval) return setInterval(returns, options.interval);
			if (options.attempt) try {return returns();} catch(err){return false;};
			return returns();
		};
	},

	/*
	Property: pass
		Shortcut to create closures with arguments and bind.

	Returns:
		a function.

	Arguments:
		args - the arguments passed. must be an array if arguments > 1
		bind - optional, the object that the "this" of the function will refer to.

	Example:
		>myFunction.pass([arg1, arg2], myElement);
	*/

	pass: function(args, bind){
		return this.create({'arguments': args, 'bind': bind});
	},

	/*
	Property: attempt
		Tries to execute the function, returns either the result of the function or false on error.

	Arguments:
		args - the arguments passed. must be an array if arguments > 1
		bind - optional, the object that the "this" of the function will refer to.

	Example:
		>myFunction.attempt([arg1, arg2], myElement);
	*/

	attempt: function(args, bind){
		return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
	},

	/*
	Property: bind
		method to easily create closures with "this" altered.

	Arguments:
		bind - optional, the object that the "this" of the function will refer to.
		args - optional, the arguments passed. must be an array if arguments > 1

	Returns:
		a function.

	Example:
		>function myFunction(){
		>	this.setStyle('color', 'red');
		>	// note that 'this' here refers to myFunction, not an element
		>	// we'll need to bind this function to the element we want to alter
		>};
		>var myBoundFunction = myFunction.bind(myElement);
		>myBoundFunction(); // this will make the element myElement red.
	*/

	bind: function(bind, args){
		return this.create({'bind': bind, 'arguments': args});
	},

	/*
	Property: bindAsEventListener
		cross browser method to pass event firer

	Arguments:
		bind - optional, the object that the "this" of the function will refer to.
		args - optional, the arguments passed. must be an array if arguments > 1

	Returns:
		a function with the parameter bind as its "this" and as a pre-passed argument event or window.event, depending on the browser.

	Example:
		>function myFunction(event){
		>	alert(event.clientx) //returns the coordinates of the mouse..
		>};
		>myElement.onclick = myFunction.bindAsEventListener(myElement);
	*/

	bindAsEventListener: function(bind, args){
		return this.create({'bind': bind, 'event': true, 'arguments': args});
	},

	/*
	Property: delay
		Delays the execution of a function by a specified duration.

	Arguments:
		delay - the duration to wait in milliseconds.
		bind - optional, the object that the "this" of the function will refer to.
		args - optional, the arguments passed. must be an array if arguments > 1

	Example:
		>myFunction.delay(50, myElement) //wait 50 milliseconds, then call myFunction and bind myElement to it
		>(function(){alert('one second later...')}).delay(1000); //wait a second and alert
	*/

	delay: function(delay, bind, args){
		return this.create({'delay': delay, 'bind': bind, 'arguments': args})();
	},

	interval: function(ms, bind, args){
		return this.create({'interval': ms, 'bind': bind, 'arguments': args})();
	}

});
/**
* Script String.js
* Extends the String object
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js
*/
Number.extend({

	/*
	Property: toInt
	Returns this number; useful because toInt must work on both Strings and Numbers.
	*/

	toInt: function(){
		return this;
	},

	/*
	Property: isInt
	Returns true; useful because isInt must work on both Strings and Numbers.
	*/
	isInt: function() {
		return true;
	}

});
/**
* Script Element.js
* Contains the Element object - methods for creating and manipulating DOM objects
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js, array.js
*/
NC.Element = new NC.Class({
	init: function() {
		return this.create.apply(this, arguments);
	},

	create: function(el, env) {
		env = env || document;
		var types = ("b|i|p|div|span|strong|em|img|table|tr|td|th|thead|tbody|tfoot|pre|code|h1|h2|h3|h4|h5|h6|ul|ol|li|form|input|textarea|legend|fieldset|select|option|blockquote|iframe|cite|br|hr|dd|dl|dt|address|a|button|abbr|acronym|script|link|style|bdo|ins|del|object|param|col|colgroup|optgroup|caption|label|dfn|kbd|samp|var").split("|");
		if (el && el.length > 0) {
			var i = 0;
			if (types.test(el)) {
				var e = env.createElement(el);
			}
			if (e == undefined) {
				var e = env.createTextNode(el);
				return e;
			}
			return NC.$(e);
		}
		else {
			return null;
		}
	},
	hasClass: function(className){
		return !!this.className.test("\\b"+className+"\\b");
	},
	addClass: function(className){
		if (!this.hasClass(className)) this.className = (this.className+' '+className.trim()).clean();
		return this;
	},
	removeClass: function(className){
		if (this.hasClass(className)) this.className = this.className.replace(className.trim(), '').clean();
		return this;
	},
	setStyle: function(property, value) {
		if (property == 'opacity') return this.setOpacity(parseFloat(value));
		if (property == 'display') return this.setDisplay(value, arguments[2] || '');
		this.style[property.camelCase()] = value;
		return this;
	},
	setStyles: function(styles){
		if (NC.type(styles) == 'object') {
			for (var property in styles) this.setStyle(property, styles[property]);
		}
		else if (NC.type(styles) == 'string') {
			if (window.ActiveXObject) this.cssText = styles;
			else this.setAttribute('style', styles);
		}
		return this;
	},
	/*
	Property: setOpacity
	Sets the opacity of the Element, and sets also visibility == "hidden" if opacity == 0, and visibility = "visible" if opacity == 1.

	Arguments:
	opacity - Accepts numbers from 0 to 1.

	Example:
	>$('myElement').setOpacity(0.5) //make it 50% transparent
	*/

	setOpacity: function(opacity){
		if (opacity == 0){
			if(this.style.visibility != "hidden") this.style.visibility = "hidden";
		} else {
			if(this.style.visibility != "visible") this.style.visibility = "visible";
		}
		if (window.ActiveXObject) this.style.filter = "alpha(opacity=" + opacity*100 + ")";
		this.style.opacity = opacity;
		return this;
	},
	/**
	* Sets the display for an element
	* @param    alt    The value to set the display to if the element display does not equal "value"
	*/
	setDisplay: function(value, alt) {
		if (value.substring(0, 5) == 'table' && window.ActiveXObject) value = 'block'; //IE doesn't like the table-... display values
		if (!this.style.display || this.style.display != value) this.style.display = value;
		else if (alt) {
			if (alt.substring(0, 5) == 'table' && window.ActiveXObject) alt = 'block'; //IE doesn't like the table-... display values
			this.style.display = alt;
		}
		return this;
	},
	setProperty: function(property, value) {
		switch(property){
			case 'style': this.setStyles(value); break;
			case 'class': this.className = value; break;
			default: this.setAttribute(property, value);
		}
		return this;
	},
	setProperties: function(properties) {
		for (var property in properties) this.setProperty(property, properties[property]);
		return this;
	},
	setHtml: function(html) {
		this.innerHTML = html;
		return this;
	},
	/*
	Property: getStyle
	Returns the style of the Element given the property passed in.

	Arguments:
	property - the css style property you want to retrieve

	Example:
	>$('myElement').getStyle('width'); //returns "400px"
	>//but you can also use
	>$('myElement').getStyle('width').toInt(); //returns "400"

	Returns:
	the style as a string
	*/

	getStyle: function(property){
		var proPerty = property.camelCase();
		var style = this.style[proPerty] || false;
		//		alert(property + ' = ' + String(style));
		if (!style) {
			if (document.defaultView) style = document.defaultView.getComputedStyle(this,null).getPropertyValue(property);
			else if (this.currentStyle) style = this.currentStyle[proPerty];
		}
		if (style && ['color', 'backgroundColor', 'borderColor'].test(proPerty) && style.test('rgb')) {
			style = style.rgbToHex();
		}
		return style;
	},
	getProperty: function(property) {
		return this.getAttribute(property);
	},
	getTag: function() {
		return this.tagName.toLowerCase();
	},
	getFirst: function() {
		var el = this.firstChild;
		while (NC.type(el) == 'textNode') el = el.nextSibling;
		return NC.$(el);
	},
	getLast: function() {
		var el = this.lastChild;
		while (NC.type == 'textNode') el = el.getSibling('previous');
		return NC.$(el);
	},
	getNext: function() {
		return this.getSibling('next');
	},
	getPrevious: function() {
		return this.getSibling('previous');
	},
	getSibling: function(type) {
		if (type != 'next' && type != 'previous') return;
		var el = this[type + 'Sibling'];
		while (NC.type(el) == 'textNode') el = el[type + 'Sibling'];
		return NC.$(el);
	},
	add: function(el, location) {
		el = NC.$(el) || new NC.Element(el);
		if (location == 'before') el.parentNode.insertBefore(this, el);
		else if (location == 'after') {
			if (!el.getNext()) el.parentNode.appendChild(this);
			else el.parentNode.insertBefore(this, el.getNext());
		}
		else if (location == 'inside') el.appendChild(this);
		else if (location == 'first') {
			var first = el.getFirst();
			if (first) el.insertBefore(this, first);
			else el.appendChild(this);
		}
		return this;
	},
	addBefore: function(el) {
		return this.add(el, 'before');
	},
	addAfter: function(el) {
		return this.add(el, 'after');
	},
	addInside: function(el) {
		return this.add(el, 'inside');
	},
	addto: function(el) {
		el = el || document.body;
		return this.add(el, 'inside');
	},
	addFirst: function(el) {
		return this.add(el, 'first');
	},
	addText: function(text, location) {
		if (text.nodeType == undefined) text = document.createTextNode(text);
		location = location || 'inside';
		if (location == 'inside') this.appendChild(text);
		else if (location == 'after') {
			if (!this.getNext()) this.parentNode.appendChild(text);
			else this.parentNode.insertBefore(text, this.getNext());
		}
		else if (location == 'before') this.parentNode.insertBefore(text, this);
		if (location == 'before') el.parentNode.insertBefore(this, el);
		else if (location == 'first') {
			var first = this.getFirst();
			if (first) this.insertBefore(text, first);
			else this.appendChild(text);
		}
		return this;
	},
	clone: function(deep) {
		return NC.$(this.cloneNode(deep || true));
	},
	//Adds the element as a child to this element
	adopt: function(element) {
	    NC.$(element).addto(this);
	    return this;
	},
	getOffset: function(what){
		what = what.capitalize();
		var el = this;
		var offset = 0;
		do {
			offset += el['offset'+what] || 0;
			el = el.offsetParent;
		} while (el);
		return offset;
	},

	/*
	Property: getTop
	Returns the distance from the top of the window to the Element.
	*/

	getTop: function(){
		return this.getOffset('top');
	},

	/*
	Property: getLeft
	Returns the distance from the left of the window to the Element.
	*/

	getLeft: function(){
		return this.getOffset('left');
	},

	/*
	Property: getPosition
	Returns an object with width, height, left, right, top, and bottom, representing the values of the Element

	Example:
	>var myValues = $('myElement').getPosition();
	>//myValues will be..
	>{
	>	width: 200,
	>	height: 300,
	>	left: 100,
	>	top: 50,
	>	right: 300,
	>	bottom: 350
	>}
	*/

	getPosition: function(){
		var obj = {};
		obj.width = this.offsetWidth;
		obj.height = this.offsetHeight;
		obj.cWidth = this.clientWidth;
		obj.cHeight = this.clientHeight;
		obj.left = this.getLeft();
		obj.top = this.getTop();
		obj.right = obj.left + obj.width;
		obj.bottom = obj.top + obj.height;
		return obj;
	},

	setHeight: function(value) {
		if (value.isInt()) value = value + 'px';
		this.setStyle('height', value);
		return this;
	},

	hide: function(type) {
		type = type || 'display';
		if (type == 'display') {
			this.setDisplay('none');
		}
		else if (type == 'visibility') {
			this.setStyle(type, 'hidden');
		}
		return this;
	},

	show: function(type, display) {
		type = type || 'display';
		if (type == 'display') {
			display = display || 'block';
			if (display == 'block') {
				var name = this.nodeName.toLowerCase();
				if (name == 'tr') display = 'table-row';
			}
			if (display.substring(0, 5) == 'table' && window.ActiveXObject) display = 'block'; //IE doesn't like the table-... display values
			this.setDisplay(display);
		}
		else if (type == 'visibility') {
			this.setStyle(type, 'visible');
		}
		return this;
	},

	toggle: function() {
		if (this.style.display != 'none' ) {
			this.style.display = 'none';
		}
		else {
			this.style.display = '';
		}
		return this;
	},

	setFocus: function(callback) {
		this.focus();
		if (callback) callback;
		return this;
	},
    /**
     * @depreciated
     * Use removeThis() method instead
     * This interfears with some built-in remove() methods of some Dom elements
     */
	remove: function() {
		this.removeThis();
	},
	removeThis: function() {
		this.parentNode.removeChild(this);
		return this;
	}
});
/**
* Script Window.js
* Contains the Window object, onload and onDomReady functions
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js
*/
NC.Window = {
	/*
	* Onload event written by Simon Willison (http://simon.incutio.com, http://simonwillison.net/2004/May/26/addLoadEvent/)
	* Sets a function to be executed when the page loads
	* @param    string    func    The function name to execute
	*/
	onLoad: function(func) {
		this.onload(func);
	},
	onload: function(func) {
		var oldonload = window.onload;
		if (typeof window.onload != 'function') {
			window.onload = func
		}
		else {
			window.onload = function() {
				if (oldonload) oldonload();
				func();
			}
		}
	},

	onDomReady: function(func){
		//NC.Window.__onDomReady is used by Gecko browsers only
		var oldOnDomReady = NC.Window.__onDomReady;
		if (typeof NC.Window.__onDomReady != 'function') {
			NC.Window.__onDomReady = func;
		}
		else {
			NC.Window.__onDomReady = function() {
				if (oldOnDomReady) oldOnDomReady();
				func();
			}
		}
		var state = document.readyState;
		if (state && document.childNodes && !document.all && !navigator.taintEnabled){ //khtml
		if (state.test(/loaded|complete/)) return  NC.Window.__onDomReady();
		else return NC.Window.onDomReady.pass(func).delay(100) ;
		}
		else if (state && window.ActiveXObject){ //ie
		var script = NC.$('_ie_ready_');
		if (!script) document.write("<script id='_ie_ready_' defer='true' src='://'></script>");
		NC.$('_ie_ready_').onreadystatechange = function(){
			if (this.readyState == 'complete') NC.Window.__onDomReady();
		}
		return;
		}
		else { //others
		if (document.addEventListener) {
			document.addEventListener("DOMContentLoaded", func, false);
		}
		else {
			NC.Window.onload(NC.Window.__onDomReady);
		}
		}
	},

	__onDomReady: "",
	/*
	Property: disableImageCache
	Disables background image chache for internex explorer, to prevent flickering.
	To be called if you have effects with background images, and they flicker.

	Example:
	Window.disableImageCache();
	*/

	disableImageCache: function(){
		if (window.ActiveXObject) document.execCommand("BackgroundImageCache", false, true);
	},

	extend: Object.extend,

	/*
	Property: getWidth
	Returns an integer representing the width of the browser.
	*/

	getWidth: function(){
		return window.innerWidth || document.documentElement.clientWidth || 0;
	},

	/*
	Property: getHeight
	Returns an integer representing the height of the browser.
	*/

	getHeight: function(){
		return window.innerHeight || document.documentElement.clientHeight || 0;
	},

	/*
	Property: getScrollHeight
	Returns an integer representing the scrollHeight of the window.

	See Also:
	<http://developer.mozilla.org/en/docs/DOM:element.scrollHeight>
	*/

	getScrollHeight: function(){
		return document.documentElement.scrollHeight;
	},

	/*
	Property: getScrollWidth
	Returns an integer representing the scrollWidth of the window.

	See Also:
	<http://developer.mozilla.org/en/docs/DOM:element.scrollWidth>
	*/

	getScrollWidth: function(){
		return document.documentElement.scrollWidth;
	},

	/*
	Property: getScrollTop
	Returns an integer representing the scrollTop of the window (the number of pixels the window has scrolled from the top).

	See Also:
	<http://developer.mozilla.org/en/docs/DOM:element.scrollTop>
	*/

	getScrollTop: function(){
		return document.documentElement.scrollTop || window.pageYOffset || 0;
	},

	/*
	Property: getScrollLeft
	Returns an integer representing the scrollLeft of the window (the number of pixels the window has scrolled from the left).

	See Also:
	<http://developer.mozilla.org/en/docs/DOM:element.scrollLeft>
	*/

	getScrollLeft: function(){
		return document.documentElement.scrollLeft || window.pageXOffset || 0;
	}
};
/**
* Script Fx.js
* Contains the base Fx object
* Version: 1.1
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js
*/
NC.namespace('NC.Fx');
/*
Class: NC.Fx
Base class for the effects library

Options:
onStart - the function to execute as the effect begins; nothing (<Class.empty>) by default.
onComplete - the function to execute after the effect has processed; nothing (<Class.empty>) by default.
duration - the duration of the effect in ms; 500 is the default.
fps - the frames per second for the transition; default is 30
*/
NC.Fx = new NC.Class({
    options: {
        onStart: NC.Class.empty,
        onComplete: NC.Class.empty,
        transition: function(p){
			return -(Math.cos(Math.PI * p) - 1) / 2;
		},
        duration: 500,
        fps: 30,
        unit: 'px'
    },
    init: function(options) {
        this.setOptions(options);
    },
    start: function(from, to) {
        if (this.timer) return this;
        this.from = from;
        this.to = to;
        this.time = NC.time();
        this.timer = this.step.interval(Math.round(1000 / this.options.fps), this);
        return this;
    },
    step: function() {
        var time = NC.time();
        if (time < this.time + this.options.duration) {
            this.delta = this.options.transition((time - this.time) / this.options.duration);
            this.setNow();
			this.increase();
        }
        else {
			this.stop();
			this.set(this.to);
		}
    },
    /*
	Property: set
		Immediately sets the value with no transition.

	Arguments:
		to - the point to jump to

	Example:
		>var myFx = new Fx.Style('myElement', 'opacity').set(0); //will make it immediately transparent
	*/

	set: function(to){
		this.now = to;
		this.increase();
		return this;
	},
	setNow: function(){
		this.now = this.compute(this.from, this.to);
	},

	compute: function(from, to){
		return (to - from) * this.delta + from;
	},
    /*
	Property: stop
		Stops the transition.
	*/

	stop: function(){
		if (!this.timer) return this;
		this.timer = NC.clearTimer(this.timer);
		return this;
	}

});
NC.Fx.implement(new NC.Options);
/**
* Script Slide.js
* Contains the Fx.Slide object
* Version: 1.0
* Credits - Based on MooTools - Mootools.net
* Depends on base.js, class.js, fx.js
*/
NC.Fx.Slide = NC.Fx.extend({
    options: {
        direction: 'vertical',
        wrapper: true
    },
    init: function(element, options) {
        this.element = NC.$(element);
        //this.element.setStyle('margin', 0);
        this.setOptions(options);
        this.parent(options);
        this.setupWrapper();
        this.now = [];
        this.setupElementSize();
    },
    setupWrapper: function() {
        if (this.options.wrapper) {
            this.wrapper = new NC.Element('div').setStyles({margin: this.element.getStyle('margin'),overflow: 'hidden'}).addAfter(this.element).adopt(this.element);
        }
        else {
            this.wrapper = this.element;
        }
    },
    setupElementSize: function() {
        this.offsetHeight = this.element.offsetHeight;
        this.elementHeight = this.element.getStyle('height').toInt();
        this.heightDiff = this.offsetHeight - this.elementHeight;
        this.offsetWidth = this.element.offsetWidth;
        this.elementWidth = this.element.getStyle('width').toInt();
        this.widthDiff = this.offsetWidth - this.elementWidth;
    },
    vertical: function() {
        this.margin = 'margin-top';
        this.layout = 'height';
//        this.offset = this.element.offsetHeight;
        this.offset = this.offsetHeight;
        this.size = this.elementHeight;
    },
    horizontal: function() {
        this.margin = 'margin-left';
        this.layout = 'width';
//        this.offset = this.element.offsetWidth;
        this.offset = this.offsetWidth;
        this.size = this.elementWidth
    },
    slideIn: function(direction) {
        this[direction || this.options.direction]();
        return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [0, this.options.wrapper ? this.offset : this.size]);
    },
    slideOut: function(direction) {
        this[direction || this.options.direction]();
        return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [-this.offset, 0]);
//        return this.start([this.element.getStyle(this.margin).toInt(), this.wrapper.getStyle(this.layout).toInt()], [-(this.wrapper ? this.offset : this.size), 0]);
    },
    setNow: function(){
        for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
    },
    increase: function() {
        if (this.options.wrapper) {
            this.element.setStyle(this.margin, this.now[0] + this.options.unit);
            this.wrapper.setStyle(this.layout, this.now[1] + this.options.unit);
        }
        else {
            this.wrapper.setStyle(this.layout, this.now[1] + this.options.unit);
        }
    }
});