
function muuvo_form_handler_submit(form_name, act)
{
	return muuvo_form_handler_generic(form_name, act, "", true, muuvo_form_gather_data, muuvo_form_show_errors);
}

function muuvo_form_handler(form_name, act, go_to)
{

	return muuvo_form_handler_generic(form_name, act, go_to, false, muuvo_form_gather_data, muuvo_form_show_errors);
}

function muuvo_form_close(form_name)
{
	$("div[id^="+form_name+"_error]").remove();
	$("tr[class=muuvoFormTr]").remove();

	if (addData.el)
	{
		addData.el.css("height", addData.el.height() - addData.size);
		addData.el = null;
	}
}

function muuvo_form_handler_generic(form_name, act, go_to, do_submit, gather_func, error_func)
{
	muuvo_form_close(form_name);
	$.post("index.php", gather_func(form_name, act),
	       function(data)
	       {
				if (data.ok == 1)
				{
					if (do_submit)
					{
						document.muuvoForm.submit();
					}
					else
					{
						if (data.url && data.url != "undefined" && data.url != "")
						{
							window.location.href = data.url;
						}
						else
						if (typeof go_to == "function")
						{
							go_to();
						}
						else
						{
							window.location.href = "?act="+go_to;
						}
						return false;
					}
				}
				else
				{
					error_func(data, form_name);
					return false;
				}
			}, 
			"json"
	);

}

function muuvo_form_gather_data(form_name, act)
{
	s = $("form[name^="+form_name+"] > input[type^=hidden]").serialize()+"&"+$("input[name^="+form_name+"]").serialize()+"&"+$("textarea[name^="+form_name+"]").serialize()+"&"+$("input[name=id]").serialize()+"&act="+act;
	return s;
}

function muuvo_form_show_errors(data, form_name)
{
	var num = 0;
	for(var i in data)
	{
		num++;
		html = "<div id=\""+form_name+"_error_"+i+"\" class=\"form_error\" style=\"display: none; border: 1px solid red; padding: 5px; margin: 5px;\">";
		for(var a in data[i])
		{
//						alert("i = "+i+" a = "+a+" val = "+data[i][a].validator);
			if (data[i][a].error_string != "")
			{
				html += "<font color=red>"+data[i][a].error_string+"</font><br/>";
			}
			if (data[i][a].validator == "muuvo_form_validator_filled")
			{
				html += "<font color=red>You have to fill this element!</font><br/>";
			}
			else
			if (data[i][a].validator == "muuvo_form_validator_nohtml")
			{
				html += "<font color=red>Please do not enter html tags!</font><br/>";
			}
			else
			if (data[i][a].validator == "muuvo_form_validator_valid_uid")
			{
				html += "<font color=red>Please enter a valid uid! Valid characters are letters, numbers and underscore. Length must be between 3 and 32 characters.</font><br/>";
			}
			else
			if (data[i][a].validator == "muuvo_form_validator_valid_password")
			{
				html += "<font color=red>Please enter a valid password! Valid characters are letters, numbers and underscore. Length must be between 3 and 32 characters.</font><br/>";
			}
			else
			if (data[i][a].validator == "muuvo_form_validator_valid_email")
			{
				html += "<font color=red>Please enter a valid email address!</font><br/>";
			}
			else
			if (data[i][a].validator == "muuvo_form_validator_length")
			{
				html += "<font color=red>The text is too long!</font><br/>";
			}
		}
		html += "</div>";

		// check if we are in a dialog. and if so, resize it		
		var el = $("label[for=\""+form_name+"_"+i+"\"]");
		while (el.parent())
		{
			el = el.parent();
			if (el.hasClass("dialog"))
			{
				// add to height
				var h = el.height();
				el.css("height", (num * 30) + h);
				addData.el = el;
				addData.size = num * 30;
				break;
			}
		}

		if ($("label[for=\""+form_name+"_"+i+"\"]").parent().get(0).tagName == "TD")
		{
			// insert row
			var tr = $("label[for=\""+form_name+"_"+i+"\"]").parent().parent();
			tr.before("<tr class='muuvoFormTr'><td class='genericText' colspan='2'>"+html+"</td></tr>");
		}
		else
		{
			$("label[for=\""+form_name+"_"+i+"\"]").before(html);
		}
		$("#"+form_name+"_error_"+i).show("slow");
	}
}

var addData = {};

function muuvoComponentInit(component, frame)
{
		$.get(
			"?act=muuvo_components_"+component+".init_component",
			{ },
			function (ret)
			{
				$('#'+frame).html(ret);
				$('#'+frame).show();
			}
		);
}


function muuvoIsValidEmail(str)
{
	var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
	if(reg.test(str) == false) 
	{
		return false;
	}
	return true;
}

function muuvoFormatDate(date)
{
	var days = new Array(
		"Sunday",
		"Monday",
		"Tuesday",
		"Wednesday",
		"Thursday",
		"Friday",
		"Saturday"
	);
	return days[date.getDay()]+" "+date.getDate()+"."+(date.getMonth()+1)+"."+date.getFullYear();
}

function muuvoFormatDateSlash(date)
{
	return date.getDate()+"/"+(date.getMonth()+1)+"/"+date.getFullYear();
}

function muuvoElementOffsetLeft(id)
{
	var el = document.getElementById(id);
	var offset = 0;
	while(el)
	{
		offset += el.offsetLeft;
		el = el.offsetParent;
	}
	return offset;
}

function muuvoElementOffsetTop(id)
{
	var el = document.getElementById(id);
	var offset = 0;
	while(el)
	{
		offset += el.offsetTop;
		el = el.offsetParent;
	}
	return offset;
}

/** moves element with given id to the absolute x/y position **/
function muuvoMoveElementAbsolute(id, x, y)
{
	return $("#"+id).css("position", "absolute").css("top", (y - muuvoElementOffsetTop(id))+"px").css("left", (x-muuvoElementOffsetLeft(id))+"px");
}

function muuvoRemoveArrayElement(ar, i)
{
	var ret = [];
	for(var ii in ar)
	{
		if (parseInt(ii) != parseInt(i))
		{
			ret[ret.length] = ar[ii];
		}
	}
	return ret;
}

function number_format( number, decimals, dec_point, thousands_sep ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // *     example 1: number_format(1234.5678, 2, '.', '');
    // *     returns 1: 1234.57     
 
    var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals;
    var d = dec_point == undefined ? "." : dec_point;
    var t = thousands_sep == undefined ? "," : thousands_sep, s = n < 0 ? "-" : "";
    var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
    
    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
}

function sprintf( ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Ash Searle (http://hexmen.com/blog/)
    // + namespaced by: Michael White (http://getsprink.com)
    // +    tweaked by: Jack
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: sprintf("%01.2f", 123.1);
    // *     returns 1: 123.10
 
    var regex = /%%|%(\d+\$)?([-+#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
    var a = arguments, i = 0, format = a[i++];
 
    // pad()
    var pad = function(str, len, chr, leftJustify) {
        var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
        return leftJustify ? str + padding : padding + str;
    };
 
    // justify()
    var justify = function(value, prefix, leftJustify, minWidth, zeroPad) {
        var diff = minWidth - value.length;
        if (diff > 0) {
            if (leftJustify || !zeroPad) {
                value = pad(value, minWidth, ' ', leftJustify);
            } else {
                value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
            }
        }
        return value;
    };
 
    // formatBaseX()
    var formatBaseX = function(value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
        // Note: casts negative numbers to positive ones
        var number = value >>> 0;
        prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
        value = prefix + pad(number.toString(base), precision || 0, '0', false);
        return justify(value, prefix, leftJustify, minWidth, zeroPad);
    };
 
    // formatString()
    var formatString = function(value, leftJustify, minWidth, precision, zeroPad) {
        if (precision != null) {
            value = value.slice(0, precision);
        }
        return justify(value, '', leftJustify, minWidth, zeroPad);
    };
 
    // finalFormat()
    var doFormat = function(substring, valueIndex, flags, minWidth, _, precision, type) {
        if (substring == '%%') return '%';
 
        // parse flags
        var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false;
        var flagsl = flags.length;
        for (var j = 0; flags && j < flagsl; j++) switch (flags.charAt(j)) {
            case ' ': positivePrefix = ' '; break;
            case '+': positivePrefix = '+'; break;
            case '-': leftJustify = true; break;
            case '0': zeroPad = true; break;
            case '#': prefixBaseX = true; break;
        }
 
        // parameters may be null, undefined, empty-string or real valued
        // we want to ignore null, undefined and empty-string values
        if (!minWidth) {
            minWidth = 0;
        } else if (minWidth == '*') {
            minWidth = +a[i++];
        } else if (minWidth.charAt(0) == '*') {
            minWidth = +a[minWidth.slice(1, -1)];
        } else {
            minWidth = +minWidth;
        }
 
        // Note: undocumented perl feature:
        if (minWidth < 0) {
            minWidth = -minWidth;
            leftJustify = true;
        }
 
        if (!isFinite(minWidth)) {
            throw new Error('sprintf: (minimum-)width must be finite');
        }
 
        if (!precision) {
            precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0);
        } else if (precision == '*') {
            precision = +a[i++];
        } else if (precision.charAt(0) == '*') {
            precision = +a[precision.slice(1, -1)];
        } else {
            precision = +precision;
        }
 
        // grab value using valueIndex if required?
        var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];
 
        switch (type) {
            case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad);
            case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
            case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
            case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'i':
            case 'd': {
                        var number = parseInt(+value);
                        var prefix = number < 0 ? '-' : positivePrefix;
                        value = prefix + pad(String(Math.abs(number)), precision, '0', false);
                        return justify(value, prefix, leftJustify, minWidth, zeroPad);
                    }
            case 'e':
            case 'E':
            case 'f':
            case 'F':
            case 'g':
            case 'G':
                        {
                        var number = +value;
                        var prefix = number < 0 ? '-' : positivePrefix;
                        var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
                        var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
                        value = prefix + Math.abs(number)[method](precision);
                        return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
                    }
            default: return substring;
        }
    };
 
    return format.replace(regex, doFormat);
}



function date ( format, date ) {
    // Format a local date/time  
    // 
    // version: 810.114
    // discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_date

    // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
    // +      parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: MeEtc (http://yass.meetcweb.com)
    // +   improved by: Brad Touesnard
    // +   improved by: Tim Wiel
    // *     example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);
    // *     returns 1: '09:09:40 m is month'
    // *     example 2: date('F j, Y, g:i a', 1062462400);
    // *     returns 2: 'September 2, 2003, 2:26 am'
    var a, jsdate=date;
    var pad = function(n, c){
        if( (n = n + "").length < c ) {
            return new Array(++c - n.length).join("0") + n;
        } else {
            return n;
        }
    };
    var txt_weekdays = ["Sunday","Monday","Tuesday","Wednesday",
        "Thursday","Friday","Saturday"];
    var txt_ordin = {1:"st",2:"nd",3:"rd",21:"st",22:"nd",23:"rd",31:"st"};
    var txt_months =  ["", "January", "February", "March", "April",
        "May", "June", "July", "August", "September", "October", "November",
        "December"];

    var f = {
        // Day
            d: function(){
                return pad(f.j(), 2);
            },
            D: function(){
                t = f.l(); return t.substr(0,3);
            },
            j: function(){
                return jsdate.getDate();
            },
            l: function(){
                return txt_weekdays[f.w()];
            },
            N: function(){
                return f.w() + 1;
            },
            S: function(){
                return txt_ordin[f.j()] ? txt_ordin[f.j()] : 'th';
            },
            w: function(){
                return jsdate.getDay();
            },
            z: function(){
                return (jsdate - new Date(jsdate.getFullYear() + "/1/1")) / 864e5 >> 0;
            },

        // Week
            W: function(){
                var a = f.z(), b = 364 + f.L() - a;
                var nd2, nd = (new Date(jsdate.getFullYear() + "/1/1").getDay() || 7) - 1;

                if(b <= 2 && ((jsdate.getDay() || 7) - 1) <= 2 - b){
                    return 1;
                } else{

                    if(a <= 2 && nd >= 4 && a >= (6 - nd)){
                        nd2 = new Date(jsdate.getFullYear() - 1 + "/12/31");
                        return date("W", Math.round(nd2.getTime()/1000));
                    } else{
                        return (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0);
                    }
                }
            },

        // Month
            F: function(){
                return txt_months[f.n()];
            },
            m: function(){
                return pad(f.n(), 2);
            },
            M: function(){
                t = f.F(); return t.substr(0,3);
            },
            n: function(){
                return jsdate.getMonth() + 1;
            },
            t: function(){
                var n;
                if( (n = jsdate.getMonth() + 1) == 2 ){
                    return 28 + f.L();
                } else{
                    if( n & 1 && n < 8 || !(n & 1) && n > 7 ){
                        return 31;
                    } else{
                        return 30;
                    }
                }
            },

        // Year
            L: function(){
                var y = f.Y();
                return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0;
            },
            //o not supported yet
            Y: function(){
                return jsdate.getFullYear();
            },
            y: function(){
                return (jsdate.getFullYear() + "").slice(2);
            },

        // Time
            a: function(){
                return jsdate.getHours() > 11 ? "pm" : "am";
            },
            A: function(){
                return f.a().toUpperCase();
            },
            B: function(){
                // peter paul koch:
                var off = (jsdate.getTimezoneOffset() + 60)*60;
                var theSeconds = (jsdate.getHours() * 3600) +
                                 (jsdate.getMinutes() * 60) +
                                  jsdate.getSeconds() + off;
                var beat = Math.floor(theSeconds/86.4);
                if (beat > 1000) beat -= 1000;
                if (beat < 0) beat += 1000;
                if ((String(beat)).length == 1) beat = "00"+beat;
                if ((String(beat)).length == 2) beat = "0"+beat;
                return beat;
            },
            g: function(){
                return jsdate.getHours() % 12 || 12;
            },
            G: function(){
                return jsdate.getHours();
            },
            h: function(){
                return pad(f.g(), 2);
            },
            H: function(){
                return pad(jsdate.getHours(), 2);
            },
            i: function(){
                return pad(jsdate.getMinutes(), 2);
            },
            s: function(){
                return pad(jsdate.getSeconds(), 2);
            },
            //u not supported yet

        // Timezone
            //e not supported yet
            //I not supported yet
            O: function(){
               var t = pad(Math.abs(jsdate.getTimezoneOffset()/60*100), 4);
               if (jsdate.getTimezoneOffset() > 0) t = "-" + t; else t = "+" + t;
               return t;
            },
            P: function(){
                var O = f.O();
                return (O.substr(0, 3) + ":" + O.substr(3, 2));
            },
            //T not supported yet
            //Z not supported yet

        // Full Date/Time
            c: function(){
                return f.Y() + "-" + f.m() + "-" + f.d() + "T" + f.h() + ":" + f.i() + ":" + f.s() + f.P();
            },
            //r not supported yet
            U: function(){
                return Math.round(jsdate.getTime()/1000);
            }
    };

    return format.replace(/[\\]?([a-zA-Z])/g, function(t, s){
        if( t!=s ){
            // escaped
            ret = s;
        } else if( f[s] ){
            // a date function exists
            ret = f[s]();
        } else{
            // nothing special
            ret = s;
        }

        return ret;
    });
}

