function utf8_encode ( argString ) {
    // Encodes an ISO-8859-1 string to UTF-8
    var string = (argString+'').replace(/\r\n/g, "\n").replace(/\r/g, "\n");

    var utftext = "";
    var start, end;
    var stringl = 0;

    start = end = 0;
    stringl = string.length;
    for (var n = 0; n < stringl; n++) {
        var c1 = string.charCodeAt(n);
        var enc = null;

        if (c1 < 128) {
            end++;
        } else if((c1 > 127) && (c1 < 2048)) {
            enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
        } else {
            enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
        }
        if (enc !== null) {
            if (end > start) {
                utftext += string.substring(start, end);
            }
            utftext += enc;
            start = end = n+1;
        }
    }

    if (end > start) {
        utftext += string.substring(start, string.length);
    }

    return utftext;
}


function base64_encode( data ) {
    // Encodes string using MIME base64 algorithm
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = [];

    if (!data) {
        return data;
    }

    data = this.utf8_encode(data+'');

    do { // pack three octets into four hexets
        o1 = data.charCodeAt(i++);
        o2 = data.charCodeAt(i++);
        o3 = data.charCodeAt(i++);

        bits = o1<<16 | o2<<8 | o3;

        h1 = bits>>18 & 0x3f;
        h2 = bits>>12 & 0x3f;
        h3 = bits>>6 & 0x3f;
        h4 = bits & 0x3f;

        // use hexets to index into b64, and append result to encoded string
        tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
    } while (i < data.length);

    enc = tmp_arr.join('');

    switch( data.length % 3 ){
        case 1:
            enc = enc.slice(0, -2) + '==';
        break;
        case 2:
            enc = enc.slice(0, -1) + '=';
        break;
    }

    return enc;
}



function number_format( number, decimals, dec_point, thousands_sep ) {
    // Formats a number with grouped thousands
    var n = number, prec = decimals;

    var toFixedFix = function (n,prec) {
        var k = Math.pow(10,prec);
        return (Math.round(n*k)/k).toString();
    };

    n = !isFinite(+n) ? 0 : +n;
    prec = !isFinite(+prec) ? 0 : Math.abs(prec);
    var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
    var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;

    var s = (prec > 0) ? toFixedFix(n, prec) : toFixedFix(Math.round(n), prec); //fix for IE parseFloat(0.55).toFixed(0) = 0;

    var abs = toFixedFix(Math.abs(n), prec);
    var _, i;

    if (abs >= 1000) {
        _ = abs.split(/\D/);
        i = _[0].length % 3 || 3;

        _[0] = s.slice(0,i + (n < 0)) +
              _[0].slice(i).replace(/(\d{3})/g, sep+'$1');
        s = _.join(dec);
    } else {
        s = s.replace('.', dec);
    }

    var decPos = s.indexOf(dec);
    if (prec >= 1 && decPos !== -1 && (s.length-decPos-1) < prec) {
        s += new Array(prec-(s.length-decPos-1)).join(0)+'0';
    }
    else if (prec >= 1 && decPos === -1) {
        s += dec+new Array(prec).join(0)+'0';
    }
    return s;
}



function _wrap_indent ( a_str , a_w_total , a_w_indent )
{
	var i=0;
	var txt_line = [];
	var w_total = a_w_total || 600;
	var w_indent = a_w_indent || 36;
	var w_indented = w_total - w_indent;
	var w_cut;


	//--------------------------------------
	//-- insert a ruler div.
	//-- <div id="test_area" style="display:inline;"></div>
	if ( !$('div_ruler') )
	{
		var div_ruler = new Element ('div' , { id : 'div_ruler' , style : 'display:inline' });
		$(document.body).insert(div_ruler);
	}


	//--------------------------------------
	//-- insert css tag for indent.
	//-- <style type="text/css">span.tr_idnt {margin-left:36px;}</style>
	//-- !!!!!!!!!! Unfortunately, this method does not work in chrome and safari. !!!!!!!!!!
	//var css_indent = new Element('style', {'type': 'text/css'}).update('span.tr_idnt {margin-left:' + w_indent + 'px;}');
	//$(document.body).insert(css_indent);


	//--------------------------------------
	//-- trim and cut string by \n
	var text_1 = a_str.strip().split ( "\n" );


	//--------------------------------------


	text_1.each ( function (e)
	{
		//-- multispaces to single space.
		var text_2 = e.gsub(/\s+/, ' ');

		//--------------------------------------

		//-- split by single space.
		var text_3 = text_2.strip().split ( " " );

		text_3.each ( function (ee)
		{
			$('div_ruler').insert (ee + ' ');

			var w = $('div_ruler').offsetWidth ;

			if ( $('div_ruler').innerHTML.include(':') )
			{
				w_cut = w_total ;
			}
			else
			{
				w_cut = w_indented;
			}

			if ( w > w_cut )
			{
				i++;
				txt_line[i] = ee + ' ';
				$('div_ruler').update (txt_line[i]);
			}
			else
			{
				if (txt_line[i])
				{
					txt_line[i] = txt_line[i] + ee + ' ';
				}
				else
				{
					txt_line[i] = ee + ' ';
				}
			}
		});

		//--------------------------------------

		i++;
		$('div_ruler').update ();
	});

	//--------------------------------------

	var arr_line = txt_line.map ( function (eee)
	{
		if ( !eee.include(':') )
		{
			//eee = '<span class="tr_idnt">' + eee + '</span>' ;
			eee = '<span style="margin-left:' + w_indent + 'px;">' + eee + '</span>' ;
		}

		return eee;
	});

	return arr_line.join('<br />');
}



function nl2br (str) {
    var breakTag = '<br />';

    return (str + '').replace(/([^>]?)\n/g, '$1'+ breakTag +'\n');
}



function _format_date (formatDate, formatString)
{
	if(formatDate instanceof Date)
	{
		var months = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
		var yyyy = formatDate.getFullYear();
		var yy = yyyy.toString().substring(2);
		var m = formatDate.getMonth() + 1;
		var mm = m < 10 ? "0" + m : m;
		var mmm = months[m];
		var d = formatDate.getDate();
		var dd = d < 10 ? "0" + d : d;

		var h = formatDate.getHours();
		var hh = h < 10 ? "0" + h : h;
		var n = formatDate.getMinutes();
		var nn = n < 10 ? "0" + n : n;
		var s = formatDate.getSeconds();
		var ss = s < 10 ? "0" + s : s;

		formatString = formatString.replace(/yyyy/i, yyyy);
		formatString = formatString.replace(/yy/i, yy);
		formatString = formatString.replace(/mmm/i, mmm);
		formatString = formatString.replace(/mm/i, mm);
		formatString = formatString.replace(/m/i, m);
		formatString = formatString.replace(/dd/i, dd);
		formatString = formatString.replace(/d/i, d);
		formatString = formatString.replace(/hh/i, hh);
		formatString = formatString.replace(/h/i, h);
		formatString = formatString.replace(/nn/i, nn);
		formatString = formatString.replace(/n/i, n);
		formatString = formatString.replace(/ss/i, ss);
		formatString = formatString.replace(/s/i, s);

		return formatString;
	}
	else
	{
		return "";
	}
}
