	function strtr (str, from, to) {
		var fr = '',
			i = 0,
			j = 0,
			lenStr = 0,
			lenFrom = 0,
			tmpStrictForIn = false,
			fromTypeStr = '',
			toTypeStr = '',
			istr = '';
		var tmpFrom = [];
		var tmpTo = [];
		var ret = '';
		var match = false;

		// Received replace_pairs?
		// Convert to normal from->to chars
		if (typeof from === 'object') {
			//tmpStrictForIn = this.ini_set('phpjs.strictForIn', false); // Not thread-safe; temporarily set to true
			from = this.krsort(from);
			//this.ini_set('phpjs.strictForIn', tmpStrictForIn);

			for (fr in from) {
				if (from.hasOwnProperty(fr)) {
					tmpFrom.push(fr);
					tmpTo.push(from[fr]);
				}
			}

			from = tmpFrom;
			to = tmpTo;
		}

		// Walk through subject and replace chars when needed
		lenStr = str.length;
		lenFrom = from.length;
		fromTypeStr = typeof from === 'string';
		toTypeStr = typeof to === 'string';

		for (i = 0; i < lenStr; i++) {
			match = false;
			if (fromTypeStr) {
				istr = str.charAt(i);
				for (j = 0; j < lenFrom; j++) {
					if (istr == from.charAt(j)) {
						match = true;
						break;
					}
				}
			} else {
				for (j = 0; j < lenFrom; j++) {
					if (str.substr(i, from[j].length) == from[j]) {
						match = true;
						// Fast forward
						i = (i + from[j].length) - 1;
						break;
					}
				}
			}
			if (match) {
				ret += toTypeStr ? to.charAt(j) : to[j];
			} else {
				ret += str.charAt(i);
			}
		}

		return ret;
	}
	
	function trim (str, charlist) {
		var whitespace, l = 0,
			i = 0;
		str += '';

		if (!charlist) {
			// default list
			whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
		} else {
			// preg_quote custom list
			charlist += '';
			whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1');
		}

		l = str.length;
		for (i = 0; i < l; i++) {
			if (whitespace.indexOf(str.charAt(i)) === -1) {
				str = str.substring(i);
				break;
			}
		}

		l = str.length;
		for (i = l - 1; i >= 0; i--) {
			if (whitespace.indexOf(str.charAt(i)) === -1) {
				str = str.substring(0, i + 1);
				break;
			}
		}

		return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
	}
	
	function strip_tags (input, allowed) {
		allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
		var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
			commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
		return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
			return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
		});
	}
	
	function krsort (inputArr, sort_flags) {
		var tmp_arr = {},
			keys = [],
			sorter, i, k, that = this,
			strictForIn = false,
			populateArr = {};
	 
		switch (sort_flags) {
		case 'SORT_STRING':
			// compare items as strings
			sorter = function (a, b) {
				return that.strnatcmp(b, a);
			};
			break;
		case 'SORT_LOCALE_STRING':
			// compare items as strings, based on the current locale (set with  i18n_loc_set_default() as of PHP6)
			var loc = this.i18n_loc_get_default();
			sorter = this.php_js.i18nLocales[loc].sorting;
			break;
		case 'SORT_NUMERIC':
			// compare items numerically
			sorter = function (a, b) {
				return (b - a);
			};
			break;
		case 'SORT_REGULAR':
			// compare items normally (don't change types)
		default:
			sorter = function (b, a) {
				var aFloat = parseFloat(a),
					bFloat = parseFloat(b),
					aNumeric = aFloat + '' === a,
					bNumeric = bFloat + '' === b;
				if (aNumeric && bNumeric) {
					return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
				} else if (aNumeric && !bNumeric) {
					return 1;
				} else if (!aNumeric && bNumeric) {
					return -1;
				}
				return a > b ? 1 : a < b ? -1 : 0;
			};
			break;
		}
	 
		// Make a list of key names
		for (k in inputArr) {
			if (inputArr.hasOwnProperty(k)) {
				keys.push(k);
			}
		}
		keys.sort(sorter);
	 
		// BEGIN REDUNDANT
		this.php_js = this.php_js || {};
		this.php_js.ini = this.php_js.ini || {};
		// END REDUNDANT
		strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
		populateArr = strictForIn ? inputArr : populateArr;
	 
	 
		// Rebuild array with sorted key names
		for (i = 0; i < keys.length; i++) {
			k = keys[i];
			tmp_arr[k] = inputArr[k];
			if (strictForIn) {
				delete inputArr[k];
			}
		}
		for (i in tmp_arr) {
			if (tmp_arr.hasOwnProperty(i)) {
				populateArr[i] = tmp_arr[i];
			}
		}
	 
		return strictForIn || populateArr;
	}
	
	function strtolower (str) {
		return (str + '').toLowerCase();
	}
	
	function totranslit(str)
	{
		var NpjLettersFrom = "àáâãäåçèêëìíîïðñòóôöû³";
        var NpjLettersTo   = "abvgdeziklmnoprstufcyi";
		
		var NpjBiLetters = {
      "é" : "jj", "¸" : "jo", "æ" : "zh", "õ" : "kh", "÷" : "ch", 
      "ø" : "sh", "ù" : "shh", "ý" : "je", "þ" : "ju", "ÿ" : "ja",
      "ú" : "", "ü" : "", "¿" : "yi", "º" : "ye"
                              };
		
        var NpjCaps  = "ÀÁÂÃÄÅ¨ÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÜÚÛÝÞß¯ª²";
        var NpjSmall = "àáâãäå¸æçèéêëìíîïðñòóôõö÷øùüúûýþÿ¿º³";
		
		str = trim(strip_tags(str));
		str = str.replace(/\s+/i, '-');
		str = strtr( str, NpjCaps, NpjSmall );
		str = strtr( str, NpjBiLetters );
		str = strtr( str, NpjLettersFrom, NpjLettersTo );
		
		str = str.replace(/[^a-z0-9\_\-.]+/i, '');
		str = str.replace(/[\-]+/i, '-');
		return strtolower(str);
	}
