function init() {
	// jQuery/Blueprint tabs
	$("ul.tabs li.label").hide(); 
	$("#tab-set > div").hide();
	
	default_tab = $("#tab-set > ul > li > .selected").attr("href")
	if (default_tab == undefined) {
		$("#tab-set > div").eq(0).show();
		$("#tab-set > .tabs > li > a").eq(0).addClass("selected")
	} else {
		$("#tab-set > " + default_tab).show();
	}

	$("ul.tabs a").click(function() { 
		$("ul.tabs a.selected").removeClass('selected'); 
		$("#tab-set > div").hide();
		$(""+$(this).attr("href")).show(); 
		$(this).addClass('selected'); 
		return false; 
	});

	$("#toggle-label").click(function() {
		$(".tabs li.label").toggle(); 
		return false; 
	});

	//Add hover to table rows
	$('table.hover tr').hover(function() {
		$(this).addClass('hover');
	}, function() {
		$(this).removeClass('hover');
	})

	// Expanding textarea
	$('.expanding').autogrow({
		maxHeight: 300,
		minHeight: 70,
		lineHeight: 14
	});
	$('.expanding').css('font-size', '1.2em')

	// Add callback to validation
	$('.validate').blur(function() {
		validate_entry(this);
	})

	$.tablesorter.addParser({ 
		// set a unique id 
		id: 'date', 
		is: function(s) { 
			// return false so this parser is not auto detected 
			return false; 
		}, 
		format: function(s) { 
			// format your data for normalization 
			if (s.search('span') != -1) {
				s = s.replace('<span class="negative">', '')
				s = s.replace('</span>', '')
				s = s.trim()
				if (s.search('In quarantaine') != -1) {
					s = '01/01/1983'
				} 
			} else if (s == '') {
				s = '01/01/1983'
			} 
			s = s.replace(/^\s+|\s+$/g, '')
			return s.substring(6) + s.substring(3,5) + s.substr(0,2);
		}, 
		// set type, either numeric or text 
		type: 'numeric' 
	});

	// Set the Zebra widget on the sorter to fix the alternating rows
	$.tablesorter.defaults.widgets = ['zebra'];
  
  	// Alternating row colors on table
	$('table.alternate tr:even:not(.information):not(.warning)').addClass('even');
	$('table.alternate tr:odd:not(.information):not(.warning)').addClass('odd');
  
	try {
		document_ready_module()
	} catch (e) {}
}

function submit_form(url, data) {
	form = ''
	form += '<form action="' + url + '" method="post" id="js_created_form">'
	$.each(data, function(i, val){
		form += '<input type="hidden" name="' + i + '" value="' + val + '">'
	});
	form += '</form>'
	$('#empty_div').append(form)
	$('#js_created_form').submit()	
}

// Chow an html snippet in JQM
function show_snippet(identifier) {
	init_overlay('dialog_' + identifier);
	var api = $("#dialog_" + identifier).overlay();
	api.load()
}

function close_overlay(element) {
	$("#" + element).overlay().close()
}

function init_overlay(element) {
	$(function() {
			$('#' + element).overlay( {		speed: 'fast',
											finish: {top: 150},
											fadeInSpeed: 'fast',
											onBeforeLoad:	function() {
													this.getBackgroundImage().expose({	color: '#222',
																						opacity: 0.5,
																						speed: 1
																					});
											},
										closeOnClick:	true,
										onClose:	function() {
														 $.expose.close();
													}
										});
	});
}

// Hide the JQM window
function hide_snippet(identifier) {
	$("#dialog_" + identifier).overlay().close()
	return false
}

function start_loading() {
	$("#ajax_loading").expose( { color: '#000',
								opacity: 0.8,
								speed: 10,
								onBeforeLoad: function() {
													$('#ajax_loading').hide();
												},
								onLoad: function() {
													$('#ajax_loading').show();
												},
								closeOnClick: true,
								onBeforeClose: function() {
													$("#ajax_loading").toggle()
												}
								})
	$("#ajax_loading").toggle()

}

function stop_loading() {
	$("#ajax_loading").toggle()
	$.unexpose()
}

var validated_element = ""

function validate_entry(element) {
	validated_element = element.id
	if (validated_element == 'vat') {
		jQuery.post('/ajax', {	action: 'validate', 
					'type': $(element).attr('id'), 
					'value': $(element).val(),
					'country_id': $('#country_id').val()
					}, validated_entry);
	} else {
		jQuery.post('/ajax', {action: 'validate', 'type': $(element).attr('id'), 'value': $(element).val()}, validated_entry);
	}
}

function validated_entry(data, textStatus) {
	result = JSONstring.toObject(data)
	$('#' + validated_element + ' + .validation_error').remove()
	$('#' + validated_element).removeClass('validation_error')
	if (!result.valid) {
		$('#' + validated_element).after('<span class="validation_error">' + result.message + '</span>')
		$('#' + validated_element).addClass('validation_error')
	}
}

/**
 * Part of PHPJS
 * http://phpjs.org/
 */
function strpos( haystack, needle, offset){
	// Finds position of first occurrence of a string within another 
	//
	// version: 905.1314
	// discuss at: http://phpjs.org/functions/strpos
	// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   improved by: Onno Marsman   
	// +   bugfixed by: Daniel Esteban
	// *	 example 1: strpos('Kevin van Zonneveld', 'e', 5);
	// *	 returns 1: 14
	var i = (haystack+'').indexOf(needle, (offset ? offset : 0));
	return i === -1 ? false : i;
}

/**
 * JSONstring v 1.01
 * copyright 2006 Thomas Frank
 * (small sanitizer added to the toObject-method, May 2008)
 * 
 * This EULA grants you the following rights:
 * Installation and Use. You may install and use an unlimited number of copies of the SOFTWARE PRODUCT.
 * Reproduction and Distribution. You may reproduce and distribute an unlimited number of copies of the SOFTWARE PRODUCT either
 * in whole or in part; each copy should include all copyright and trademark notices, and shall be accompanied by a copy of
 * this EULA. Copies of the SOFTWARE PRODUCT may be distributed as a standalone product or included with your own product.
 *
 * Commercial Use. You may sell for profit and freely distribute scripts and/or compiled scripts that were created with the SOFTWARE PRODUCT.
 * 
 * Based on Steve Yen's implementation:
 * http://trimpath.com/project/wiki/JsonLibrary
 * 
 * Sanitizer regExp:
 * Andrea Giammarchi 2007
 */
JSONstring={
	compactOutput:false, 		
	includeProtos:false, 	
	includeFunctions: false,
	detectCirculars:true,
	restoreCirculars:true,
	make:function(arg,restore) {
		this.restore=restore;
		this.mem=[];this.pathMem=[];
		return this.toJsonStringArray(arg).join('');
	},
	toObject:function(x){
		if(!this.cleaner){
			try{this.cleaner=new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')}
			catch(a){this.cleaner=/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/}
		};
		if(!this.cleaner.test(x)){return {}};
		eval("this.myObj="+x);
		if(!this.restoreCirculars || !alert){return this.myObj};
		if(this.includeFunctions){
			var x=this.myObj;
			for(var i in x){if(typeof x[i]=="string" && !x[i].indexOf("JSONincludedFunc:")){
				x[i]=x[i].substring(17);
				eval("x[i]="+x[i])
			}}
		};
		this.restoreCode=[];
		this.make(this.myObj,true);
		var r=this.restoreCode.join(";")+";";
		eval('r=r.replace(/\\W([0-9]{1,})(\\W)/g,"[$1]$2").replace(/\\.\\;/g,";")');
		eval(r);
		return this.myObj
	},
	toJsonStringArray:function(arg, out) {
		if(!out){this.path=[]};
		out = out || [];
		var u; // undefined
		switch (typeof arg) {
		case 'object':
			this.lastObj=arg;
			if(this.detectCirculars){
				var m=this.mem; var n=this.pathMem;
				for(var i=0;i<m.length;i++){
					if(arg===m[i]){
						out.push('"JSONcircRef:'+n[i]+'"');return out
					}
				};
				m.push(arg); n.push(this.path.join("."));
			};
			if (arg) {
				if (arg.constructor == Array) {
					out.push('[');
					for (var i = 0; i < arg.length; ++i) {
						this.path.push(i);
						if (i > 0)
							out.push(',\n');
						this.toJsonStringArray(arg[i], out);
						this.path.pop();
					}
					out.push(']');
					return out;
				} else if (typeof arg.toString != 'undefined') {
					out.push('{');
					var first = true;
					for (var i in arg) {
						if(!this.includeProtos && arg[i]===arg.constructor.prototype[i]){continue};
						this.path.push(i);
						var curr = out.length; 
						if (!first)
							out.push(this.compactOutput?',':',\n');
						this.toJsonStringArray(i, out);
						out.push(':');					
						this.toJsonStringArray(arg[i], out);
						if (out[out.length - 1] == u)
							out.splice(curr, out.length - curr);
						else
							first = false;
						this.path.pop();
					}
					out.push('}');
					return out;
				}
				return out;
			}
			out.push('null');
			return out;
		case 'unknown':
		case 'undefined':
		case 'function':
			if(!this.includeFunctions){out.push(u);return out};
			arg="JSONincludedFunc:"+arg;
			out.push('"');
			var a=['\n','\\n','\r','\\r','"','\\"'];
			arg+=""; for(var i=0;i<6;i+=2){arg=arg.split(a[i]).join(a[i+1])};
			out.push(arg);
			out.push('"');
			return out;
		case 'string':
			if(this.restore && arg.indexOf("JSONcircRef:")==0){
				this.restoreCode.push('this.myObj.'+this.path.join(".")+"="+arg.split("JSONcircRef:").join("this.myObj."));
			};
			out.push('"');
			var a=['\n','\\n','\r','\\r','"','\\"'];
			arg+=""; for(var i=0;i<6;i+=2){arg=arg.split(a[i]).join(a[i+1])};
			out.push(arg);
			out.push('"');
			return out;
		default:
			out.push(String(arg));
			return out;
		}
	}
};

