function dump(arr, level)
{
	var dumped_text = "";
	if(!level) level = 0;

	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";

	if(typeof(arr) == 'object') { //Array/Hashes/Objects
	 for(var item in arr) {
	  var value = arr[item];

	  if(typeof(value) == 'object') { //If it is an array,
	   dumped_text += level_padding + "'" + item + "' ...\n";
	   dumped_text += dump(value,level+1);
	  } else {
	   dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
	  }
	 }
	} else { //Stings/Chars/Numbers etc.
	dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}

(function(){
// start ring core functions:
var undefined;
var access;
var loadapp_callback = 'default';

// query manager base object, (stores array and methods)
jQuery.query = new function()
{
	var qarray = [];
};

// parse query string
jQuery.query.load = function(q)
{
	q = q.replace(/^\#/,'');
	q = q.replace(/\&$/,'');
	qarray = [];	// clear array
	jQuery.each(q.split('&'), function()
	{
		var key = this.split('=')[0];
		var val = this.split('=')[1];
		if ( val )
			qarray[key] = val;
	});
//	alert('parsequery:'+location.hash+' dump:'+dump(qarray));
};

// retrieve query string elements
jQuery.query.get = function(param)
{
	if ( param === 'undefined' )
		return qarray;

	if ( typeof (qarray) == "undefined" ) return;
	if ( typeof (qarray[param]) == "undefined" ) return;

	return qarray[param];
};

// manage general ring options
jQuery.ring = function(options)
{
	var op = jQuery.extend({setappsuccess:'default',parsequery:'no'}, options);

	if ( op.setappsuccess == 'none' )
		loadapp_callback = 'default';
	else
	if ( op.setappsuccess != 'default' )
		loadapp_callback = op.setappsuccess;
};

// manage access card
jQuery.access = function(tag)
{
	if ( (!access) || (tag == '_refresh') )
	{
		if ( $.cookie('AccessCard') )
			access = eval('(' + $.cookie('AccessCard') + ')');
		else
			access = null;;
	}
	if ( !access )
	{
		if ( tag === undefined )
			return false;
		switch(tag)
		{
			case 'level':	return 0;
			case 'user':	return 'UNKNOWN';
			case 'lang':	return 'en';
			case 'status':	return 'OK';
		}
		return false;
	}
	if ( tag === undefined )
		return true;
	if ( tag == 'firstname' )
		return 'test';
	return eval('access.'+tag);
};

// obtain access to domain
jQuery.setdomain = function(domain)
{
	// check current domain
	var mydom = jQuery.access('domain');

	var loc = '/api/auth/obtain/domain/'+domain+'.cookie';
	$.ajax({url: loc, async: false, success:function()
	{
		jQuery.access('_refresh');
	},
	error:function(req, stat, e)
	{
//		if ( req.status == 404 )
//			alert('No access to '+domain);
	}});
};

// obtain access to email 
jQuery.setemail = function(email)
{
	// check current domain
	var mymail = jQuery.access('mail');
	var mydomain = jQuery.access('domain');
	var parts = email.split('@');
	var edomain = parts[1];
	var eaccount = parts[0];

	if ( typeof(mymail) == 'undefined' || mymail != email )
	{
		jQuery.setdomain(edomain);
		var loc = '/api/auth/obtain/email/'+edomain+'/'+eaccount+'.cookie';
		$.ajax({url: loc, async: false, success:function()
		{
			jQuery.access('_refresh');
		},
		error:function(req, stat, e)
		{
//			if ( req.status == 404 )
//				alert('No access to '+email);
		}});
	}
};

//
jQuery.setftpuser = function(user)
{
	// check current ftpuser
	var myftp = jQuery.access('ftpuser');

	if ( typeof(myftp) == 'undefined' || myftp != user )
	{
		var loc = '/api/auth/obtain/ftpuser/'+user+'.cookie';
		$.ajax({url: loc, async: false, success:function()
		{
            jQuery.access('_refresh');
        },
        error:function(req, stat, e)
        {
//            if ( req.status == 404 )
//                alert('No access to '+user);
        }});
	}
};

// enable drop menu (drop effect only)
jQuery.fn.dropmenu = function(name)
{
	return this.each(function()
	{
		if ( name === undefined )
			name = $(this).attr('id');

		$("#"+name+" ul").css({display: "none"});
		$("#"+name+" li").hover(function(){
			// disable hover if all suboptions are disabled
			if ( $(this).find('a:[rel].disabled').length == $(this).find('a:[rel]').length )
				return false;
			$(this).find('ul:first').css({visibility: "visible",display: "none"}).show(400);
		},function(){
//			if ( $(this).find('a:[rel].disabled').length == $(this).find('a:[rel]') )
//				return false;
			$(this).find('ul:first').css({visibility: "hidden"});
		});
	});
};


// ring menu
// ringmenu({enable})
jQuery.fn.ringmenu = function(options)
{
	var op = jQuery.extend({enable:'all', disable:'none', target:'#applet', success:'default'}, options);
	var ena = op.enable.split(' ');
	var dis = op.disable.split(' ');

	return this.find('a:[rel]').each(function()
	{
		// disable all options
		if ( (op.disable == 'all' && op.enable == 'all') || op.enable == 'none' )
		{
			$(this).addClass('disabled').unbind('click').click(function(){return false;});
			return;
		}

		var allowks = $(this).attr('rel');

		if ( allowks != '*' )
		{
			var allowksL = allowks.toString().toLowerCase();
			var userks = new String(jQuery.access('keys'));
			var userksL = userks.toLowerCase();
			var userkeys = userksL.split('+');
			var allowkeys = allowksL.split(' ');
			var allowed = false;

			// disable options current level does not allow
			for ( var i = 0; i < userkeys.length; i++ )
			{
				for ( var j = 0; j < allowkeys.length; j++ )
				{
					if ( userkeys[i] == allowkeys[j] )
					{
						allowed = true;
						break;
					}
				}
				if ( allowed )
					break;
			}

			if ( !allowed )
			{
				$(this).addClass('disabled').unbind('click').click(function(){return false;});
				return;
			}
		}

		// determine app name
		var loc = new String($(this).attr('href'));
		var spl = loc.split('#');
		var aname = spl[1];

		// determine if app is enabled
		if ( (op.enable == 'all' && op.disable == 'none')
		||   (op.enable == 'all' && jQuery.inArray(aname, dis) == -1)
		||   (op.disable == 'all' && jQuery.inArray(aname, ena) != -1) )
		{
			if ( aname != 'buyservices' )
			{
				if ( aname == 'logout' )
					$(this).removeClass('disabled').unbind('click').click(function(){logout();});
				else
				{
					$(this).removeClass('disabled').unbind('click').click(function()
					{
	//					alert(loc);
						$.query.load(loc);
						if ( $.browser.msie )
							$(op.target).loadapplet({name:aname});
							if ( $.browser.safari ) {
							$(op.target).loadapplet({name:aname});
						}
					});
				}
			}
			else
			{
				$(this).removeClass('disabled').unbind('click').click(
					function() {
						return false;
						//alert($(this).attr("href"));
					}
				);
			}
			return;
		}
		$(this).addClass('disabled').unbind('click').click(function(){return false;});
	});
};

// load language table
jQuery.fn.loadlang = function(aow, name)
{
	return this.each(function()
	{
		if ( name === undefined )
			name = $(this).attr('id');

		var lang = 'en';
		var loc;

		if ( aow == 'widget' )
			loc = widgetpath+name+'/'+lang+'.js';
		else
		if ( aow == 'root' )
			loc = rootpath+name+'/'+lang+'.js';
		else
			loc = appletpath+name+'/'+lang+'.js';

		$.ajax({url: loc, async: false, success:function(data)
		{
			var _langmap = eval('('+data+')');
			if ( typeof _langmap == 'object' )
				$(document).translate(_langmap);
		}});
	});
};

// translate lang tags
jQuery.fn.translate = function(map)
{
	if ( map === undefined )
		throw 'no language map specified';
	if ( typeof map != 'object' )
		throw 'invalid language map';

	return this.each(function()
	{
		$(this).find('.Langs').each(function()
		{
			var id = $(this).attr('_key_');
			if ( typeof map[id] != 'undefined' )
			{
				var tag = map[id];
				if ( tag )
					$(this).text(tag);
			}
		});
	});
};

// load a named widget into a target div
// name defaults to id of matching target
// target defaults to this
jQuery.fn.loadwidget = function(options)
{
	var op = jQuery.extend({name:'default', target:'default', success:'default'}, options);

	return this.each(function()
	{
		if ( op.name === 'default' )
			op.name = $(this).attr('id');

		if ( op.target === 'default' )
			op.target = '#'+$(this).attr('id');

		var wddir = op.name;
		var sel = op.name;
		var sl = op.name.indexOf('/');
		if ( sl != -1 )
		{
			sel = op.name.substr(0, sl-1);
			var ls = op.name.lastIndexOf('/');
			op.name = op.name.substr(ls+1);
		}

		var loc = widgetpath+wddir+'/'+op.name+'.html';

//		alert('loading '+op.name+' into '+op.target);

		$.ajax({url: loc, success:function(data)
		{
			$(op.target).html(data);

			// if access card, then check to remap any contact tags
			if ( $.access() )
			{
				$(op.target).find('.contact').each(function()
				{
					var id = $(this).attr('id');
					var tag = $.access(id.substr(2));
					if ( tag )
						$(this).text(tag);
				});
			}

			if ( op.success != 'default' )
				op.success();
		}});
	});
};

// load root application
// target defaults to this
jQuery.fn.loadroot = function(options)
{
	var op = jQuery.extend({name:'default', target:'default', success:'default'}, options);

	return this.each(function()
	{
//		if ( op.name === 'default' )
//			op.name = $(this).attr('id');

		if ( op.target === 'default' )
			op.target = '#'+$(this).attr('id');

		var loc = rootpath+op.name+'/'+op.name+'.html';

		$.ajax({url: loc, success:function(data)
		{
			$(op.target).html(data);

			if ( op.success != 'default' )
				op.success();
		}});
	});
};

// load a named applet into a target div
// name defaults to id of matching target
// target defaults to this
jQuery.fn.loadapplet = function(options)
{
	WaitSlide.showSlide();	
	var bkpName = "none";
	var op = jQuery.extend({name:'default', target:'default', success:'default'}, options);

	// override
	if ( op.success == 'default' )
		op.success = loadapp_callback;

	return this.each(function()
	{
		if ( op.name === 'default' )
			op.name = $(this).attr('id');
		else	// ignore query options
		{
			var spl = op.name.split('&');
			op.name = spl[0];
		}
		if (!$.access()) {
			if (op.name != 'login')
			{
				op.name = 'login';
			}
		}

		if ($.browser.safari)
		{
			if ($("#currentPage").val() != op.name)
			{
				$("#currentPage").val(op.name);
				if (op.name != bkpName)
				{
					
				}
			}
			//op.name = $("#currentPage").val();
			//bkpName = $("#currentPage").val();
		}
		
		if ( op.target === 'default' )
			op.target = '#'+$(this).attr('id');

		var apdir = op.name;
		var sel = op.name;
		var sl = op.name.indexOf('/');
		if ( sl != -1 )
		{
			sel = op.name.substr(0, sl-1);
			var ls = op.name.lastIndexOf('/');
			op.name = op.name.substr(ls+1);
		}

		var loc = appletpath+apdir+'/'+op.name+'.html';

		//if ($.browser.safari) alert('loading '+op.name+' into '+op.target);

		$.ajax({url: loc, success:function(data)
		{
			$(op.target).hide();
			$(op.target).html(data);
			$(op.target).css({"visibility":"visible"});
			$(op.target).fadeIn();
			// if access card, then check to remap any contact tags
			if ( $.access() )
			{
				$(op.target).find('.contact').each(function()
				{
					var id = $(this).attr('id');
					var tag = $.access(id);
					if ( tag )
						$(this).text(tag);
				});
			}
//			alert('loc:'+location+' dump:'+dump($.query.get()));
			// check for any get param remapping
			$(op.target).find('.get').each(function()
			{
				var id = $(this).attr('id');
				var tag = jQuery.query.get(id);
//				alert('loc.search:'+window.location.search+' jQuery.query.get('+id+') = '+tag);
				if ( tag )
					$(this).text(tag);
			});

			if ( op.success != 'default' )
				op.success({name:op.name,section:sel,dir:apdir,target:op.target});

			delay = setTimeout("WaitSlide.hideSlide()",1500);

		},error:function(req, stat, e)
		{
			if ( req.status == 404 )
				alert('Applet '+op.name+' not found');
		}});
	});
};

jQuery.webdir = function(url, q, callback)
{
	var url = '/api/web/home/' + q.dir + '?&accept=json&stats=mode';
	jQuery.ajax({url:url, dataType:'json', success:function(data)
	{
		var ret;
		if ( data.length > 2 )
		{
			ret = '<ul class="jqueryFileTree" style="display: none;">';
			for ( i in data )
			{
				if ( data[i]['mode'] & 16384 && data[i]['name'][0] != '.' )
					ret += '<li class="directory collapsed"><a href="#" rel="'+q.dir+data[i]['name']+'/">'+data[i]['name']+'</a></li>';
			}
			for ( i in data )
			{
				if ( !(data[i]['mode'] & 16384) )
				{
					var lio = data[i]['name'].lastIndexOf('.');
					var ext;
					if ( lio == -1 )
						ext = 'txt';
					else
						ext = data[i]['name'].substring(lio+1);
					ret += '<li class="file ext_'+ext+'"><a href="#" rel="'+q.dir+data[i]['name']+'">'+data[i]['name']+'</a></li>';
				}
			}
		}
		callback(ret);
	}});
};

jQuery.fn.getCDATA = function()
{
	if ( jQuery.browser.msie )
		return this[0].childNodes[0].nodeValue;
	return this[0].childNodes[1].nodeValue;
};

jQuery.isLoginName = function(name) {
	var RegExp = /^([A-z0-9.,_:\'` -]+){4,}$/;
	if(RegExp.test(name))
		return true;
	else
		return false;
};

jQuery.isPass = function(pass) {
	if ( !pass || pass == "" || pass.length <= 0 )
		return false;
	
	return true;
};

jQuery.mousePos = function(e) {
    this.x = 0;
    this.y = 0;
    if (!e) var e = window.event;
    if (e.pageX || e.pageY)
    {
        this.x = e.pageX;
        this.y = e.pageY;
    }
    else if (e.clientX || e.clientY)
    {
        this.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        this.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
};

jQuery.wHigh = function() {
    var windowHeight = 0;
    if (typeof(window.innerHeight) == 'number')
    {
        windowHeight = window.innerHeight;
    }
    else
    {
        if (document.documentElement && document.documentElement.clientHeight)
        {
            windowHeight = document.documentElement.clientHeight;
        }
        else
        {
            if (document.body && document.body.clientHeight)
            {
                windowHeight = document.body.clientHeight;
            }
        }
    }
    return windowHeight;
};

jQuery.wWide = function() {
    return window.innerWidth ? window.innerWidth : document.body.offsetWidth;
};

jQuery.array_merge = function() {
    var args = Array.prototype.slice.call(arguments);
    var retObj = {}, k, j = 0, i = 0;
    var retArr;

    for (i=0, retArr=true; i < args.length; i++) {
        if (!(args[i] instanceof Array)) {
            retArr=false;
            break;
        }
    }

    if (retArr) {
        return args;
    }
    var ct = 0;

    for (i=0, ct=0; i < args.length; i++) {
        if (args[i] instanceof Array) {
            for (j=0; j < args[i].length; j++) {
                retObj[ct++] = args[i][j];
            }
        } else {
            for (k in args[i]) {
                if ($.is_int(k)) {
                    retObj[ct++] = args[i][k];
                } else {
                    retObj[k] = args[i][k];
                }
            }
        }
    }

    return retObj;
};

jQuery.is_array = function(mixed_var) {
    var key = '';
    var getFuncName = function (fn) {
        var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn);
        if (!name) {
            return '(Anonymous)';
        }
        return name[1];
    };
 
    if (!mixed_var) {
        return false;
    }
 
    this.php_js = this.php_js || {};
    this.php_js.ini = this.php_js.ini || {};
 
    if (typeof mixed_var === 'object') {
 
        if (this.php_js.ini['phpjs.objectsAsArrays'] &&
            (
            (this.php_js.ini['phpjs.objectsAsArrays'].local_value.toLowerCase &&
                    this.php_js.ini['phpjs.objectsAsArrays'].local_value.toLowerCase() === 'off') ||
                parseInt(this.php_js.ini['phpjs.objectsAsArrays'].local_value, 10) === 0)
            ) {
            return mixed_var.hasOwnProperty('length') && 
                            !mixed_var.propertyIsEnumerable('length') && 
                                getFuncName(mixed_var.constructor) !== 'String';
        }
 
        if (mixed_var.hasOwnProperty) {
            for (key in mixed_var) {
                if (false === mixed_var.hasOwnProperty(key)) {
                    return false;
                }
            }
        }
 
        return true;
    }
 
    return false;
};

jQuery.isObject = function(mixed_var) {
	if ( typeof(mixed_var) == 'string' ) return false;
	if ( typeof(mixed_var) != 'object' ) return false;
	if ( !jQuery.is_array(mixed_var) ) return false;
	if ( mixed_var.indexOf("{") == -1) return false;

	return true;    	
};

jQuery.in_array = function(needle, haystack, argStrict) {
    var found = false, key, strict = !!argStrict;

    for (key in haystack) {
        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
            found = true;
            break;
        }
		else
		{
			if ((key === needle) || (key == needle)) {
				found = true;
				break;
			}
		}
    }

    return found;
};

jQuery.is_int = function( mixed_var ) {
    if (typeof mixed_var !== 'number') {
        return false;
    }

    if (parseFloat(mixed_var) != parseInt(mixed_var, 10)) {
        return false;
    }

    return true;
};

jQuery.ucfirst = function( str ) {
    str += '';
    var f = str.charAt(0).toUpperCase();
    return f + str.substr(1);
};

jQuery.function_exists = function( function_name ) {
    if (typeof function_name == 'string'){
        return (typeof this.window[function_name] == 'function');
    } else{
        return (function_name instanceof Function);
    }
};

jQuery.strcmp = function( str1, str2 ) {
    // *     example 1: strcmp( 'waldo', 'owald' );
    // *     returns 1: 1
    // *     example 2: strcmp( 'owald', 'waldo' );
    // *     returns 2: -1
 
    return ( ( str1 == str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ) );
};

jQuery.strnatcmp = function( f_string1, f_string2, f_version ) {
    // *     example 1: strnatcmp('Price 12.9', 'Price 12.15');
    // *     returns 1: 1
    // *     example 2: strnatcmp('Price 12.09', 'Price 12.15');
    // *     returns 2: -1
    // *     example 3: strnatcmp('Price 12.90', 'Price 12.15');
    // *     returns 3: 1
    // *     example 4: strnatcmp('Version 12.9', 'Version 12.15', true);
    // *     returns 4: -6
    // *     example 5: strnatcmp('Version 12.15', 'Version 12.9', true);
    // *     returns 5: 6
 
    if (f_version == undefined) {
        f_version = false;
    }
 
    var __strnatcmp_split = function( f_string ) {
        var result = [];
        var buffer = '';
        var chr = '';
        var i = 0, f_stringl = 0;
 
        var text = true;
 
        f_stringl = f_string.length;
        for (i = 0; i < f_stringl; i++) {
            chr = f_string.substring(i, i + 1);
            if (chr.match(/[0-9]/)) {
                if (text) {
                    if(buffer.length > 0){
                        result[result.length] = buffer;
                        buffer = '';
                    }
 
                    text = false;
                }
                buffer += chr;
            } else if ((text == false) && (chr == '.') && (i < (f_string.length - 1)) && (f_string.substring(i + 1, i + 2).match(/[0-9]/))) {
                result[result.length] = buffer;
                buffer = '';
            } else {
                if (text == false) {
                    if (buffer.length > 0) {
                        result[result.length] = parseInt(buffer);
                        buffer = '';
                    }
                    text = true;
                }
                buffer += chr;
            }
        }
 
        if (buffer.length > 0) {
            if (text) {
                result[result.length] = buffer;
            } else {
                result[result.length] = parseInt(buffer);
            }
        }
 
        return result;
    };
 
    var array1 = __strnatcmp_split(f_string1+'');
    var array2 = __strnatcmp_split(f_string2+'');
 
    var len = array1.length;
    var text = true;
 
    var result = -1;
    var r = 0;
 
    if (len > array2.length) {
        len = array2.length;
        result = 1;
    }
 
    for (i = 0; i < len; i++) {
        if (isNaN(array1[i])) {
            if (isNaN(array2[i])) {
                text = true;
 
                if ((r = this.strcmp(array1[i], array2[i])) != 0) {
                    return r;
                }
            } else if (text){
                return 1;
            } else {
                return -1;
            }
        } else if (isNaN(array2[i])) {
            if(text) {
                return -1;
            } else{
                return 1;
            }
        } else {
            if(text || f_version){
                if ((r = (array1[i] - array2[i])) != 0) {
                    return r;
                }
            } else {
                if ((r = this.strcmp(array1[i].toString(), array2[i].toString())) != 0) {
                    return r;
                }
            }
 
            text = false;
        }
    }
 
    return result;
};

jQuery.sort = function(inputArr, sort_flags) {
    var valArr = [], keyArr=[];
    var k = '', i = 0, sorter = false, that = this;
    
    for (k in inputArr) { // Get key and value arrays
        valArr.push(inputArr[k]);
        delete inputArr[k];
    }
 
    switch (sort_flags) {
        case 'SORT_STRING': // compare items as strings
            sorter = function (a, b) {
                return that.strnatcmp(a, b);
            };
            break;
        case 'SORT_LOCALE_STRING': // compare items as strings, based on the current locale (set with  i18n_loc_set_default() as of PHP6)
            sorter = function (a, b) {
                return(a.localeCompare(b));
            };
            break;
        case 'SORT_NUMERIC': // compare items numerically
            sorter = function (a, b) {
                return(a - b);
            };
            break;
        case 'SORT_REGULAR': // compare items normally (don not change types)
        default:
            sorter = function (a, b) {
                if (a > b) {
                    return 1;
                }
                if (a < b) {
                    return -1;
                }
                return 0;
            };
            break;
    }
    valArr.sort(sorter);
 
    for (i = 0; i < valArr.length; i++) { // Repopulate the old array
        inputArr[i] = valArr[i];
    }
    return true;
};

jQuery.url_decode = function(str) {
	var hash_map = {}, ret = str.toString(), unicodeStr='', hexEscStr='';
    
    var replacer = function(search, replace, str) {
        var tmp_arr = [];
        tmp_arr = str.split(search);
        return tmp_arr.join(replace);
    };
    
    // The hash_map is identical to the one in urlencode.
    hash_map["'"]   = '%27';
    hash_map['(']   = '%28';
    hash_map[')']   = '%29';
    hash_map['*']   = '%2A';
    hash_map['~']   = '%7E';
    hash_map['!']   = '%21';
    hash_map['%20'] = '+';
    hash_map['\u00DC'] = '%DC';
    hash_map['\u00FC'] = '%FC';
    hash_map['\u00C4'] = '%D4';
    hash_map['\u00E4'] = '%E4';
    hash_map['\u00D6'] = '%D6';
    hash_map['\u00F6'] = '%F6';
    hash_map['\u00DF'] = '%DF';
    hash_map['\u20AC'] = '%80';
    hash_map['\u0081'] = '%81';
    hash_map['\u201A'] = '%82';
    hash_map['\u0192'] = '%83';
    hash_map['\u201E'] = '%84';
    hash_map['\u2026'] = '%85';
    hash_map['\u2020'] = '%86';
    hash_map['\u2021'] = '%87';
    hash_map['\u02C6'] = '%88';
    hash_map['\u2030'] = '%89';
    hash_map['\u0160'] = '%8A';
    hash_map['\u2039'] = '%8B';
    hash_map['\u0152'] = '%8C';
    hash_map['\u008D'] = '%8D';
    hash_map['\u017D'] = '%8E';
    hash_map['\u008F'] = '%8F';
    hash_map['\u0090'] = '%90';
    hash_map['\u2018'] = '%91';
    hash_map['\u2019'] = '%92';
    hash_map['\u201C'] = '%93';
    hash_map['\u201D'] = '%94';
    hash_map['\u2022'] = '%95';
    hash_map['\u2013'] = '%96';
    hash_map['\u2014'] = '%97';
    hash_map['\u02DC'] = '%98';
    hash_map['\u2122'] = '%99';
    hash_map['\u0161'] = '%9A';
    hash_map['\u203A'] = '%9B';
    hash_map['\u0153'] = '%9C';
    hash_map['\u009D'] = '%9D';
    hash_map['\u017E'] = '%9E';
    hash_map['\u0178'] = '%9F';
 
    for (unicodeStr in hash_map) {
        hexEscStr = hash_map[unicodeStr]; // Switch order when decoding
        ret = replacer(hexEscStr, unicodeStr, ret); // Custom replace. No regexing
    }
    
    // End with decodeURIComponent, which most resembles PHPs encoding functions
    ret = decodeURIComponent(ret);
 
    return ret;
};

jQuery.asort = function(inputArr, sort_flags) {
    var valArr=[], keyArr=[], k, i, ret, sorter;
 
    switch (sort_flags) {
        case 'SORT_STRING': // compare items as strings
            sorter = function (a, b) {
                return strnatcmp(a, b);
            };
            break;
        case 'SORT_LOCALE_STRING': // compare items as strings, based on the current locale (set with i18n_loc_set_default() as of PHP6)
            sorter = function (a, b) {
                return(a.localeCompare(b));
            };
            break;
        case 'SORT_NUMERIC': // compare items numerically
            sorter = function (a, b) {
                return(a - b);
            };
            break;
        case 'SORT_REGULAR': // compare items normally (don not change types)
        default:
            sorter = function (a, b) {
                if (a > b) {
                    return 1;
                }
                if (a < b) {
                    return -1;
                }
                return 0;
            };
            break;
    }
 
    var bubbleSort = function(keyArr, inputArr) {
        var i, j, tempValue, tempKeyVal;
        for (i = inputArr.length-2; i >= 0; i--) {
            for (j = 0; j <= i; j++) {
                ret = sorter(inputArr[j+1], inputArr[j]);
                if (ret < 0) {
                    tempValue = inputArr[j];
                    inputArr[j] = inputArr[j+1];
                    inputArr[j+1] = tempValue;
                    tempKeyVal = keyArr[j];
                    keyArr[j] = keyArr[j+1];
                    keyArr[j+1] = tempKeyVal;
                }
            }
        }
    };
 
    // Get key and value arrays
    for (k in inputArr) {
        valArr.push(inputArr[k]);
        keyArr.push(k);
        delete inputArr[k];
    }
    try {
        // Sort our new temporary arrays
        bubbleSort(keyArr, valArr);
    } catch(e) {
        return false;
    }
 
    // Repopulate the old array
    for (i = 0; i < valArr.length; i++) {
        inputArr[keyArr[i]] = valArr[i];
    }
 
    return true;
};

// end
})();
