(function(){

this.Skelax = new Class({

	Implements: [Events],
	_applications: $empty,
	_components: $empty,
	_debug: false,
	_vars: {},
	initialize: function(lang) {
		this._applications=new Hash;
		this._components=new Hash;
		this._vars = new Hash();
		Skelax.History.init();
		MooTools.lang.setLanguage(lang.replace('_','-') || 'en-US');
	},
	switchLang: function(lang) {
		var params = Skelax.HTML.Location.parse(top.document.location.hash);
		if (params.lang != lang) {
			MooTools.lang.setLanguage(lang.replace('_', '-'));
			var params = Skelax.HTML.Location.parse(top.document.location.hash);
			params.action = 'switchlang';
			params.lang = lang;
			var sl = new Skelax.JSON.Query({remoteUrl: 'remoting.php', update: 'content', onComplete: function(request) { 
					Skelax.HTML.batch(request.htmlElements);
					if ($type(params.func)) params.func = params.func.replace('remote','');
					Skelax.HTML.Location.write(params);
					$exec(request.js);
			}});
			sl.doRequest(params);
		}
	},
	callApplication: function(appName, funcName, appArgs) { 
		if (!$type(appName)) {Skelax.Console().log("Trying to load an undefined application","",true); return false }
		if (($type(this._applications) && (!this._applications.get(appName)))) {
			new Skelax.Loader({
				files: ['applications/'+appName+'/'+appName+'_main.js'],
				onComplete: function() {
					var oneshot = eval('var os = new '+appName+'_main();');
					skelax._getAllApplications().set(appName, os);
					if ($type(funcName)) {
						eval('var so = os.'+funcName+'(appArgs);');
					}
				}
			},this);
		} else if ($type(funcName)) {
			eval('var os = this._getAllApplications().get(appName).'+funcName+'(appArgs)');
		}
		return true;
	},
	callComponent: function(compName, funcName, appArgs) { 
		if (!$type(compName)) {Skelax.Console().log("Trying to load an undefined component","",true); return false }
		if (($type(this._components) && (!this._components.get(compName)))) {
			new Skelax.Loader({
				files: ['components/'+compName+'/'+compName+'_main.js'],
				onComplete: function() {
					var oneshot = eval('var os = new '+compName+'_main();');
					skelax._getAllComponents().set(compName, os);
					if ($type(funcName)) {
						eval('var so = os.'+funcName+'(appArgs);');
					}
				}
			},this);
		} else if ($type(funcName)) {
			eval('var os = this._getAllComponents().get(compName).'+funcName+'(appArgs)');
		}
		return true;
	},
	_getAllComponents: function() {
		return this._components;
	},
	getComponentByName: function(compName) {
		return this._components.get(compName);
	},
	_getAllApplications: function() {
		return this._applications;
	},
	getApplicationByName: function(appName) {
		return this._applications.get(appName);
	},
	registerVar: function(name, value) {
		if (!name.test(/[A-Za-z0-9_-]/)) return false;
		this._vars.set(name, value);
		return true;
	},
	getVar: function(name) {
		if (!name.test(/[A-Za-z0-9_-]/)) return false;
		return this._vars.get(name) || null;
	},
	deleteVar: function(name) {
		if (!name.test(/[A-Za-z0-9_-]/)) return false;
		if ($defined(this._vars.get(name))) {
			this._vars.erase(name);
			return true;
		}
		return false;
	}
});

String.implement({
	href2object: function() {
		var txt = this.toString();
		s = txt.split('&');
		var funcParams = {};
		var res = {};
		var rgxp = /funcParams\[(.*)\]/
		for (i = 0; i < s.length; i++) {
			var f = s[i].split('=');
			var fup = rgxp.exec(f[0]);
			if ($type(fup)) {
				funcParams[fup[1]] = f[1];
				var process = true;
			} else {
				res[f[0]]=f[1];
			}
		}
		if (process) res['funcParams'] = funcParams;
		return res;
	}
});

Skelax.History = new Hash;
Skelax.History.extend({
	init: function() {
		// Parse Url and load page if needed
		if (top.document.location.hash.replace('#','') != '') {
			var params = Skelax.HTML.Location.parse(top.document.location.hash);
			var sl = new Skelax.JSON.Query({update: 'content', onComplete: function(jsonResult) { 
				if ( (!$type(jsonResult)) || (Skelax.Exception.isError(jsonResult)) ) return false;
				if ($type(jsonResult.loadApplication)) this.callApplication(jsonResult.loadApplication, jsonResult);
			}});
			sl.doRequest(params);
		}
		// Init history engine
		this.historyKey = '0';
		this.instance = new History.Route({
			onMatch: function(values, defaults) {
				if (!values || values[0] == '') return false;
				var params = Skelax.HTML.Location.parse(values[0]);
				if (!params) params = {'tpl': 'home_content'}
					var sl = new Skelax.JSON.Query({update: 'content', onComplete: function(jsonResult) { 
						if ( (!$type(jsonResult)) || (Skelax.Exception.isError(jsonResult)) ) return false;
						$exec(jsonResult.js);
					}});
					sl.doRequest(params);

			}.bind(this)
		});
		History.start();
	},
	getInstance: function() {
		return this.instance;
	}
});

Skelax.JSON = new Hash;
Skelax.JSON.extend({
	params: {},
	addParam: function(name, value) {
		this.params[name] = value;
	},
	getParam: function(name) {
		return this.params[name];
	},
	addObjParam: function(obj) {
		if ($type(obj) == "object") {
			var os = new Hash;
			os.extend(obj);
			os.each(function(id,val) {
				this.addParam(val,id);
			}.bind(this));
		}
	},
	send: function(obj) {
		if ($type(obj) == "object") {
			this.addObjParam(obj);
		}
		var sl = new Skelax.JSON.Query({onComplete: function(jsonResult) { 
			if (($type(this.getParam("update"))) && (!jsonResult.error)) {
				if ($type(this.getParam("clear"))) this.getParam("update").set("html","").setProperty("disabled", false);
				Skelax.HTML.update(this.getParam("update"),jsonResult);
			}
			this.reset();
		}.bind(this)});
		sl.doRequest(this.params);
		// Return false to stop the event
		return false;
	},
	reset: function() {
		this.params = {};
	}
});

Skelax.JSON.Query = new Class({
	Implements: [Events, Options],

	options: {
		remoteUrl: 'remoting.php',
		update: '',
		onComplete: $empty,
		registerInHistory: false,
		disablePreloader: false,
		beforePreload: false
	},

	initialize: function(options) {
		this.setOptions(options);
	},

	doRequest: function(params) {
		if ($type(params) == 'string') {
			if (params.contains('?')) params = params.split('?')[1];
			params = new Hash(params.href2object());
		} 
		params.userKey = Skelax.Auth.getUserKey();
		// Write url
		if ((this.options.registerInHistory) || (params.registerInHistory)) {
			Skelax.HTML.Location.write(params);
		}
		// Show loader
		if ((!this.options.disablePreloader) && (this.options.update)) Skelax.HTML.Spinner.show(this.options.update, this.options.beforePreload);
		// Force funcName to begin with 'remote'
		if (($type(params.func)) && (!params.func.test(/^remote.*/))) params.func='remote'+params.func;
		var jsonRequest = new Request.JSON({
			url: this.options.remoteUrl, 
			update: this.options.update, 
			onSuccess: this.processRequest.bind(this)	
		}).send(JSON.encode(params));	
	},
	processRequest: function(result) {
		if (!$type(result))
			result = Skelax.Exception.raiseError("JSON request error: No result from PHP ?!", '',  true);
		if (($type(result)) && ($type(result.errorMsg))) {
			result = Skelax.Exception.raiseError(result.errorMsg, result.errorCode, true);
		}
		if (($type(result)) && ($type(result.errorCode)) && result.errorCode == 3) {
			Skelax.Auth.logout();
		} else {
			if (($type($(this.options.update)) == 'element') && (result.content)) {
				if (this.options.update) Skelax.HTML.update(this.options.update, result);
			}
		}
		if ($type($("meminfo")) == 'element') $("meminfo").set("html",result.meminfo);
		if ($type($("timeinfo")) == 'element') $("timeinfo").set("html",result.timeinfo);
		if (result.message) {
			Skelax.UI.Notification.show({title: 'Information', message: result.message});
		}
		// Hide loader
		if (!this.options.disablePreloader) Skelax.HTML.Spinner.hide(this.options.update);
		this.fireEvent("onComplete",result);
	}
});

Skelax.Loader = new Class({
	Implements: [Events, Options],
	fileLoaded: 0,
	options: {
		files: [],
		onComplete: false,
		throwEvent: false
	},

	initialize: function(options,ref) {
		this.setOptions(options);
		this.referer = ref;
		this.addEvent("onFileLoaded", function(num) {
			if (this.fileLoaded == this.options.files.length) {
				if (this.options.throwEvent) {
					this.referer.fireEvent(this.options.throwEvent, '', 100);
				} else {
					this.fireEvent("complete", '', 100);
				}
			}
		});
		for(var i=0;i<this.options.files.length;i++) {
			this.load(this.options.files[i],i);
		}
	},
	load: function(file,num) {
		var fileExt = file.split('.').pop();
		var os = file.split('.');
		os.pop();
		var fileId=fileExt+os.join('_');
		var url=fileExt+'/'+file;
		if (!$(fileId)) {
			if (fileExt == 'js') {
				var os = new Asset.javascript(url, { 
					id: fileId, 
					onload: function() {
						this.fileLoaded+=1;
						this.fireEvent("onFileLoaded",[num]);
					}.bind(this)
				});
			} else {
				var style_node = new Element('style', $merge({
					media: 'screen', type: 'text/css'
				}, {'id': fileId, 'title': fileId})).inject(document.head);
				var request = new Request
				(
					{
						method: 'get',
						url: url,
						style_node:style_node,
						onSuccess:function(css_text){
							style_node.appendChild(document.createTextNode(css_text));
							this.fileLoaded+=1;
							this.fireEvent("onFileLoaded", [num])
						}.bind(this)
					}
				);
				request.send();
			}
		} else {

			this.fileLoaded+=1;
			this.fireEvent("onFileLoaded",[num]);
		}
	}
});

Skelax.HTML = new Hash;
Skelax.HTML.extend({
	update: function(el,args) {
		el = ($type($(el)) == "element") ? $(el) : false;
		if ($type(el) != 'element') return false;
		var tag = el.get('tag');
		if (tag == 'select') {
			var os = new Hash;
			os.extend(args.funcResult);
			os.each(function(a,b) {
				el.adopt(new Element('option').setProperties({'value': b, 'id': el.getProperty("id")+b, 'html': a}));
			}.bind(this));
		} else if (tag == 'div') {
			el.set("html", args.content);
			if (args.js) $exec(args.js);
		}
		this.disableHref();
	},
	batch: function(elements) {
		if ($type(elements) != 'array') return false;
		elements.each(function(elInfos) {
			// Create element
			if (elInfos.action == 'create') {
				var container = $(elInfos.container);
				if ($type(container) == 'element') {
					if (elInfos.clear == true) container.set('html', '');
					var os = new Element(elInfos.type).set('id',elInfos.id).set('html',elInfos.content).injectInside(container);
				}
			}
			// Update element
			if (elInfos.action == 'update') {
				var container = $(elInfos.id);
				if ($type(container) == 'element') {
					if (elInfos.clear == true) container.set('html', '');
					container.set('html',elInfos.content);
				}
			}
		}, this);
		this.disableHref();
	},
	href2json: function(options) {
		if (options.selector) {
			var list = $$(options.selector);
			list.each(function(element) {
				 if (!element.hasClass('ignore')) {
					 element.addEvent('click', function(e){
						e = e.stop();
						var url=element.get('href');
						var params=url.substr(1);
						var sl = new Skelax.JSON.Query({registerInHistory: true, onComplete: function(jsonResult) { 
							if (options.update) Skelax.HTML.update(options.update, jsonResult);
						}});
						sl.doRequest(params);
					});
				}
			});
		}
		if (options.element) {
			element = element || $(options.element) || false;
			if (element) {
				 element.addEvent('click', function(e){
					e = e.stop();
					var url=element.get('href');
					var params=url.substr(1);
					var sl = new Skelax.JSON.Query({registerInHistory: true, onComplete: function(jsonResult) { 
						if (options.update) Skelax.HTML.update(options.update, jsonResult);
					}});
					sl.doRequest(params);
				});
			}
		}
	},
	disableHref: function() {
		// stop action in links in onlick is defined
		var action = '';
		$$('a').each(function(el) {
			action = el.get('onclick');
			if (action != '') {
				el.addEvent("click", function(e) {
					e.stop();
					$exec(action);
				});
				action = '';
			}
		});
	}
});

Skelax.HTML.Tree = new Class({
	Implements: [Events, Options],
	Extends: Skelax,
	options: {
		onReady: $empty
	},
	initialize: function(options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['mifTree/mif_tree.js','mifTree/mif_addons.js'],
			throwEvent: "onReady"
		},this);
	}
});

Skelax.HTML.MultiSelect = new Class({
	Implements: [Events, Options],
	Extends: Skelax,
	initialize: function(selector, options) {
		new Skelax.Loader({
			files: ['MultiSelect/MultiSelect.js'],
			onComplete: function() {
				var multi = new MultiSelect(selector, options);
			}
		},this);
	}
});

Skelax.HTML.DropMenu = new Class({
	Implements: [Events, Options],
	options: {},
	initialize: function(el, options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['UvumiDropdown/UvumiDropdown.js'],
			onComplete: function() {
				var dropmenu = new UvumiDropdown(el, this.options);
			}.bind(this)
		},this);
	}
});

Skelax.HTML.Filter = new Class({
	Implements: [Events, Options],
	options: {},
	initialize: function(el, options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['ElementFilter/ElementFilter.js'],
			throwEvent: "onReady"
		},this);
	}
});

Skelax.Form = new Class({
	Extends: Skelax,
	Implements: [Events, Options],
	options: {
		type: $empty,
		formName: $empty,
		func: $empty,
		resetButton: 'resetButton',
		callbackFunction: $empty,
		callbackFunctionParams: $empty,
		validatorOptions: {
			throwSubmitEvent: false
		},
		onComplete: $empty,
		onFormValid: function() {
			if (($type(this.options.callbackFunction)) == 'string') {
				var os = this.options.callbackFunction.split('.');
				var funcName =	os.pop();
				var className=os.join('.');
				this.params = this.options.callbackFunctionParams || null;
				var formFields = new Hash();
				var value = null;
				var fid = null;
				this.fVal.getFields().each(function(field) {
					if (!field.hasClass('ignore')) {
						fid = field.get('id') || field.get('name');
						if (fid) {
							if ((field.get('tag') == 'select') || (field.get('tag') == 'checkbox')) {
								value = [];
								field.getSelected().each(function(f) {
									value.push(f.get('value'));
								});
								if (value.length == 1) value = value[0];
							} else {
								value = field.get('html') || field.get('value');
							}
							formFields[fid] = value;
							fid = null;
							value = null;
						}
					}
				});
				if (className.test(/skelax/i)) {
					eval(this.options.callbackFunction+'(formFields,this.options.callbackFunctionParams)');
				} else if ((this.options.callbackFunctionParams.app) && (className) && (funcName)) {
					var myClass = skelax.getApplicationByName(className);
					eval('myClass.'+funcName+'(formFields,this.params)');
				} else if ((className=='') && (funcName)) {
					eval(funcName+'(formFields,this.params)');
				}
			}
		}
	},
	initialize: function(options) {
		this.setOptions(options);
		if (!$defined(this.options.formName)) return false;
		Form.Validator.add('validate-integer-positive', {
			errorMsg: Form.Validator.getMsg.pass('validate-integer-positive'),
			test: function(element){
			if (element.value == '') return true;
			if ((element.value != element.value.toInt()) || (element.value <= 0)) return false;
				else return true;
			}
		});
		Form.Validator.add('validate-float-positive', {
			errorMsg: Form.Validator.getMsg.pass('validate-float-positive'),
			test: function(element){
			if (element.value == '') return true;
			if ((element.value != parseFloat(element.value)) || (element.value <= 0)) return false;
				else return true;
			}
		});
		MooTools.lang.set('en-US','Form.Validator', {'validate-integer-positive': 'This field must be a number with positive value.', 'validate-float-positive': 'This field must be a float with positive value. (Ex: 1, 1.1, ...)'});
		MooTools.lang.set('fr-FR','Form.Validator', {'validate-integer-positive': 'Cette valeur doit être un nombre entier supérieur à zero', 'validate-float-positive': 'Cette valeur doit être un nombre supérieur à zero (Ex: 1, 1.1, ...)'});

		this.fVal = new Form.Validator.Inline(this.options.formName, {
			scrollToErrorsOnSubmit: false,
			onFormValidate: function(validation, formElement, formEvent) {
				formEvent.stop();
				if (validation) {
					this.fireEvent("onFormValid");
				}
			}.bind(this),
			ignoreDisabled: false
		});
		if ($type($(this.options.resetButton)) == 'element') {
			$(this.options.resetButton).addEvent('click', function() {
				this.fVal.reset();
				this.fVal.element.reset();
			}.bind(this));
		}
		this.fireEvent("onComplete");
	},
	getInstance: function() {
		return this.fVal;
	}
});

Skelax.Form.Autocompleter = new Class({
	Implements: [Events, Options],
	options: {
		onReady: $empty
	},
	initialize: function(options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['MeioAutocomplete/MeioAutocomplete.js','MeioAutocomplete/MeioAutocomplete.skelax.js'],
			throwEvent: "onReady"
		},this);
	}
});

Skelax.HTML.Table = new Class({
	Implements: [Events, Options],
	options: {
		onReady: $empty
	},

	initialize: function(options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['mootable/mootable.css', 'mootable/mootable.js'],
			throwEvent: "onReady"
		},this);
	}
});

Skelax.HTML.ZebraTable = new Class({
	Implements: [Events, Options],
	options: {
		elements: 'table.zebra',
		cssEven: 'row-even',
		cssOdd: 'row-odd',
		cssMouseEnter: 'row-mouse-enter',
		cssHighlight: 'row-highlight',
	},

	initialize: function(options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['ZebraTable/ZebraTable.js'],
			onComplete: function() {
				var os = new ZebraTable({elements: this.options.elements, cssEven: this.options.cssEven, cssOdd: this.options.cssOdd, cssMouseEnter: this.options.cssMouseEnter, cssHighlight: this.options.cssHighlight});
			}.bind(this)
		},this);
	}
});

Skelax.UI = new Hash();
Skelax.UI.Modal = new Class({
	Implements: [Events, Options],
	options: {
		onReady: $empty
	},

	initialize: function(options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['MooDialog/Overlay.js', 'MooDialog/MooDialog.js', 'MooDialog/MooDialog.Confirm.js'],
			throwEvent: "onReady"
		},this);
	}
});

Skelax.UI.Dialog = new Class({
	Implements: [Events, Options],
	options: {
		onReady: $empty
	},

	initialize: function(options) {
		this.setOptions(options);
		new Skelax.Loader({
			files: ['MooDialog/Overlay.js', 'MooDialog/MooDialog.js'],
			throwEvent: "onReady"
		},this);
	}
});

Skelax.UI.Notification = new Hash();
Skelax.UI.Notification.extend({
	show: function(msg) {
		if (!skelax.getVar('messageManager')) {
			new Skelax.Loader({
				files: ['Notimoo/Notimoo.js'],
				onComplete: function() {
					var ntm = new Notimoo(); 
					skelax.registerVar('messageManager', ntm);
					ntm.show(msg);
				}.bind(this)
			}, this);
		} else {
			var msgManager = skelax.getVar('messageManager');
			msgManager.show(msg);
		}
	}
});

Skelax.Exception = new Hash;
Skelax.Exception.extend({
	raiseError: function(msg, code, log) {
		Skelax.UI.Notification.show({title: 'WARNING', message: msg});
		if ($type(log) && ($type(Skelax.Console))) Skelax.Console.log(msg, code);
		return new Skelax.Error(msg, code);
	},
	isError: function(obj) {
		if (!$chk(obj)) return false;
		if ($chk(obj.getError)) return true;
	}
});

})();

Skelax.HTML.Location = new Hash;
Skelax.HTML.Location.extend({
	parse: function(str) {
		var obj = {};
		if (!$type(str) || str.replace('#', '') == '') return false;
		var ar = str.split('/');
		ar.shift();
		obj.lang = ar.shift();
		for(i=0;i<ar.length;i++) {
			// parse tpl
			var tpl = ar[i].match(/^t_(.*)/) 
			if ($type(tpl) && tpl[1]) {
				obj.tpl = tpl[1].replace('--','/');
				continue;
			}
			// parse funcParams
			var fp = ar[i].match(/^([a-zA-Z-_]+:.*)/) 
			if ($type(fp) && fp[1]) {
				obj.funcParams = {};
				var so = fp[1].split(',');
				so.each(function(v) {
					var o = v.split(':');
					obj.funcParams[o[0]] = o[1];
				}, this);
				continue;
			}
			if (!obj.app) obj.app = ar[i];
				else obj.func = ar[i];
		}
		return obj;
	},
	write: function(params) {
		var hash = '';
		hash+='/'+MooTools.lang.getCurrentLanguage();
		if (params.app) hash+='/'+params.app;
		if (params.func) hash+='/'+params.func;
		if (params.tpl) hash+='/t_'+params.tpl.replace('/','--');
		if ($type(params.funcParams) == 'object') {
			var funcParams = new Hash(params.funcParams);
			var fp = '/';
			funcParams.each(function(v,k) {
				fp += k+':'+v+',';	
			});
			fp = fp.substring(0,fp.length-1);
			if (fp.length > 0) {
				hash += fp;
			}
		}
		Skelax.History.getInstance().setValue(0,hash);
	}
});

Skelax.HTML.Spinner = new Hash;
Skelax.HTML.Spinner.extend({
	show: function(elId, options) {
		if (elId != '') {
			if ($type($(elId)) != 'element') return false;
			var element = $(elId);
			if ($type(options) == 'array') {
					options.each(function(opts) {
					var mFx = new Fx.Tween(opts.element, {
						property: opts.property,
						duration: opts.duration || 500,
						transition: Fx.Transitions.Sine.easeInOut
					})
					mFx.start(opts.from,opts.to);
				});
			}
			element.set('html', '');
			var posY = element.getStyle('height').toInt();
			var el = new Element('div').set('id', 'spinner-'+elId).addClass('ajax-spinner').injectInside(element);
			if (posY > 32) el.setStyle('marginTop', (posY/2)-8)
		}
	},
	hide: function(elId) {
		if (elId != '') {
			if ($type($('spinner-'+elId))) $('spinner-'+elId).dispose();
			if ($type($(elId)) != 'element') return false;
			$(elId).setStyle('opacity', 0);
			var mFx = new Fx.Tween(elId, {
				property: 'opacity',
				duration: 500,
				transition: Fx.Transitions.Sine.easeInOut
			})
			mFx.start(0,1);
		}
	}
});

Skelax.Error = new Class({
	error: {},
	initialize: function(msg, c) {
		this.error.msg = msg;
		if ($type(c) == 'string') this.error.code = c;
	},
	getMessage: function() {
		return this.error.msg;
	},
	getCode: function() {
		return this.error.code;
	},
	getError: function() {
		return this.error;
	}
});

Skelax.Tools = new Hash;
Skelax.Tools.extend({
	removeAccents: function(strAccents) {
	    strAccents = strAccents.split('');
	    var strAccentsOut = [];
	    var num = 0;
	    var accents = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž';
	    var accentsOut = ['A','A','A','A','A','A','a','a','a','a','a','a','O','O','O','O','O','O','O','o','o','o','o','o','o','E','E','E','E','e','e','e','e','e','C','c','D','I','I','I','I','i','i','i','i','U','U','U','U','u','u','u','u','N','n','S','s','Y','y','y','Z','z'];
	    strAccents.each(function(acc) {
		if (accents.indexOf(acc) != -1) {
		    strAccentsOut[num] = accentsOut[accents.indexOf(strAccents[num])];
		}
		else
		    strAccentsOut[num] = strAccents[num];
		num++;
	    });
	    strAccentsOut = strAccentsOut.join('');
		return strAccentsOut;
	},

	toSysName: function(str) {
	    var name = this.removeAccents(str).clean().toLowerCase();
	    var aName = name.split(' '); 
	    var aSysName = [];
	    aName.each(function(txt) {
		    m = txt.match(/[a-zA-Z0-9-_]+/);
		    if ($type(m) && m[0] != '') {
		    aSysName.push(m[0]);
		    }
		    });
	    return aSysName.join('_');
	}
});
	
var skelax = {};

