/*
	Script: evance_api.js
		Evance API creates the evance namespace and loads:
		evance.mootools.Core	- the MooTools library
								  <http://www.mootools.net>
		evance.core.Interface	- the Evance base Interface object,
								  which controls Event Listeners and Stage resizes
		Also, creates some handy loading tools.

	Copyright:
		copyright (c) 2007 Deveus, <http://www.deveus.com>
*/

$.extend({
	isset: function(obj){
		return (obj !== undefined);
	},
	
	isString: function(obj){
		return (typeof obj == 'string');
	},
	
	isNumber: function(obj){
		return (typeof obj == 'number');
	},
	
	isBoolean: function (obj){
		return (typeof obj == 'boolean');
	},
	
	isEmpty: function(obj){
		if(!$.isset(obj)) return true;
		if(obj === false || ($.isString(obj) && $.trim(obj) == '') || obj === 0 || obj === '0' || obj === null || ($.isArray(obj) && obj.length == 0)) return true;
		return false;
	}
});

var evance = {
	version: '1.0',
	path: '/js/',
	loaded: new Array(),
	pageLoaded: false,
	_autoId: 1,

	debug: function(obj, title){
		// debug using the firebug console.log if it exists
		if(typeof console != 'undefined' && $.isset(console.log)){
			if($.isset(title)) console.log(title + '(below):');
			console.log(obj);
		}
	},

	inArray: function(value, array){
		for(var i=0; i < array.length; i++){
			if(array[i] === value) return true;
		}
		return false;
	},
/*
	Function: evance.using(namespaceURI)
		a handy little function which makes life a bit easier to load Javascript files
		based on the namespace of the Object.
		All files must reside within the evance.path and must be in the same file structure
		as the namespace uri of the object. The last part of the uri must be the name of a
		.js file which can be loaded.

	Arguments:
		uri		- the javascript namespace of the object

	Example:
		evance.using(evance.core.Interface);

		or

		using(evance.core.Interface);

		is converted to evance.path/core/Interface.js
*/
	using: function(api){
		api = api.split('.');
		api = evance.path + api.join('/') + '.js';
		evance.load('script', api);
	},
/*
	Function: evance.isLoaded(src)
		Determines whether an attempt was made to load a file using the evance.load() function.

	Arguments:
		src		- the url of the file to load

	Retunrs:
		true	- an attempt has already been made to load the file
		false	- the file hasn't been loaded yet
*/
	isLoaded: function(src){
		return (evance.inArray(src, evance.loaded));
	},
/*
	Function: evance.load(type, src)
		Loads css or script files into the page.
		Before page load the scripts are written to the page
		After page load the scripts are called dynamically

	Arguments:
		type 	- type of file to load, either 'script' or 'css'
		src		- the url of the file to load

	Example:
		evance.load('script', 'path/filename.js');
*/
	load: function(type, src){
		var loadDynamically = evance.pageLoaded;
		if(!evance.isLoaded(src)){
			if(loadDynamically){
				var myScript = null;
				var head = document.getElementsByTagName('head')[0];
				if(type == 'css'){
					myScript=document.createElement("link");
					myScript.type="text/css";
					myScript.href=src;
					myScript.rel="stylesheet";
				} else if(type == 'script'){
					myScript = document.createElement('script');
					myScript.type = 'text/javascript';
					myScript.language = 'javascript';
					myScript.src = src;
				}
				if(myScript != null) head.appendChild(myScript);
			} else {
				if(type == 'css'){
					document.write('<link href="'+src+'" type="text/css" rel="stylesheet"></link>');
				} else if (type == 'script'){
					document.write('<script src="'+src+'" language="javascript" type="text/javascript"><\/script>');
				}
			}
			evance.loaded[evance.loaded.length] = src;
		}
	},

	// doesn't work on object functions
	// only works on classic function name()
	getFunctionName: function(f){
		if (/function (\w+)/.test(String(f))){
			var _name = RegExp.$1;
			return _name;
		} else {
			return "";
		}
	},

/*
 * Disable text selection for an element
 */
	disableSelect: function(el){
		el = $(el);
		if($.isset(el.onselectstart)){
			el.onselectstart = function(){return false;};
		} else if ($.isset(el.style.MozUserSelect)){
			el.style.MozUserSelect = 'none';
		}
		el.unselectable = "on";
		el.style.cursor = 'default';
	},
/*
 * Enable text selection for an element
 */
	enableSelect: function(el){
		el = $(el);
		if($.isset(el.onselectstart)){
			el.onselectstart = function(){return true;};
		} else if ($.isset(el.style.MozUserSelect)){
			el.style.MozUserSelect = '';
		}
		el.unselectable = "off";
		el.style.cursor = 'auto';
	},
	
	extend: function(){
		var args = arguments;
		if (!args[1]) args = [this, args[0]];
		for (var property in args[1]){
			args[0][property] = args[1][property];
		}
		return args[0];
	},
	
	evnative: function(){
		for (var i = 0, l = arguments.length; i < l; i++){
			arguments[i].extend = function(props){
				for (var prop in props){
					if (!this.prototype[prop]) this.prototype[prop] = props[prop];
					if (!this[prop]) this[prop] = evance.nativeGeneric(prop);
				}
			};
		}
	},
	
	nativeGeneric: function(prop){
		return function(bind){
			return this.prototype[prop].apply(bind, Array.prototype.slice.call(arguments, 1));
		};
	}
};

evance.evnative(Function, Array, String, Number);

/*
	Array Extension
*/
Array.extend({
	forEach: function(fn, bind){
		for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this);
	},
	filter: function(fn, bind){
		var results = [];
		for (var i = 0, j = this.length; i < j; i++){
			if (fn.call(bind, this[i], i, this)) results.push(this[i]);
		}
		return results;
	},
	map: function(fn, bind){
		var results = [];
		for (var i = 0, j = this.length; i < j; i++) results[i] = fn.call(bind, this[i], i, this);
		return results;
	},
	every: function(fn, bind){
		for (var i = 0, j = this.length; i < j; i++){
			if (!fn.call(bind, this[i], i, this)) return false;
		}
		return true;
	},
	some: function(fn, bind){
		for (var i = 0, j = this.length; i < j; i++){
			if (fn.call(bind, this[i], i, this)) return true;
		}
		return false;
	},
	indexOf: function(item, from){
		var len = this.length;
		for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
			if (this[i] === item) return i;
		}
		return -1;
	},
	copy: function(start, length){
		start = start || 0;
		if (start < 0) start = this.length + start;
		length = length || (this.length - start);
		var newArray = [];
		for (var i = 0; i < length; i++) newArray[i] = this[start++];
		return newArray;
	},
	remove: function(item){
		var i = 0;
		var len = this.length;
		while (i < len){
			if (this[i] === item){
				this.splice(i, 1);
				len--;
			} else {
				i++;
			}
		}
		return this;
	},
	contains: function(item, from){
		return this.indexOf(item, from) != -1;
	},
	associate: function(keys){
		var obj = {}, length = Math.min(this.length, keys.length);
		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
		return obj;
	},
	extend: function(array){
		for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
		return this;
	},
	merge: function(array){
		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
		return this;
	},
	include: function(item){
		if (!this.contains(item)) this.push(item);
		return this;
	},
	getRandom: function(){
		return this[$random(0, this.length - 1)] || null;
	},
	getLast: function(){
		return this[this.length - 1] || null;
	}			 
});


/*
Class: String
	A collection of The String Object prototype methods.
*/

String.extend({
	test: function(regex, params){
		return (($type(regex) == 'string') ? new RegExp(regex, params) : regex).test(this);
	},
	toInt: function(){
		return parseInt(this, 10);
	},
	toFloat: function(){
		return parseFloat(this);
	},
	camelCase: function(){
		return this.replace(/-\D/g, function(match){
			return match.charAt(1).toUpperCase();
		});
	},
	hyphenate: function(){
		return this.replace(/\w[A-Z]/g, function(match){
			return (match.charAt(0) + '-' + match.charAt(1).toLowerCase());
		});
	},
	capitalize: function(){
		return this.replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},
	trim: function(){
		return this.replace(/^\s+|\s+$/g, '');
	},
	clean: function(){
		return this.replace(/\s{2,}/g, ' ').trim();
	},
	contains: function(string, s){
		return (s) ? (s + this + s).indexOf(s + string + s) > -1 : this.indexOf(string) > -1;
	},
	escapeRegExp: function(){
		return this.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
	}
});

/*
 * 	Event Stuff
 */
	 evance.events = function() {
		var events = {};
		
		return {
			bind: function(name, fn) {
				events[name] = events[name] || [];
				events[name].push(fn);
			},
			trigger: function(name, obj) {
				if (!events[name]) return;
				jQuery.each(events[name], function(i, fn) { fn(obj || {}); });
			},
			unbind: function(name, fn) {
				if (!events[name]) return;
				events[name] = jQuery.grep(events[name], function(n) { return n != fn; });
			}
		};
	};
	evance.event = {};
	evance.event.fix = function(event){
		if (!event) event = window.event;
		if (event.target) {
			if (event.target.nodeType == 3) event.target = event.target.parentNode;
		} else if (event.srcElement) {
			event.target = event.srcElement;
		}
		return event;
	}
	evance.event.stopPropagation = function(e){
		if (e.stopPropagation) e.stopPropagation();
		else e.cancelBubble = true;
	}
	evance.event.preventDefault = function(e){
		if (e.preventDefault) e.preventDefault();
		else e.returnValue = false;
	}

/*
	Setup standard functions
*/
using = evance.using;

