function utf8_encode (argString) {
    // Encodes an ISO-8859-1 string to UTF-8  
    // 
    // version: 1103.1210
    // discuss at: http://phpjs.org/functions/utf8_encode    // +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: sowberry
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman    // +   improved by: Yves Sucaet
    // +   bugfixed by: Onno Marsman
    // +   bugfixed by: Ulrich
    // *     example 1: utf8_encode('Kevin van Zonneveld');
    // *     returns 1: 'Kevin van Zonneveld'    
	var string = (argString + ''); // .replace(/\r\n/g, "\n").replace(/\r/g, "\n");
    var utftext = "",
        start, end, 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.slice(start, end);            }
            utftext += enc;
            start = end = n + 1;
        }
    } 
    if (end > start) {
        utftext += string.slice(start, stringl);
    }
     return utftext;
}

function _encode (data) {
    // Encodes string using MIME base64 algorithm  
    // 
    // version: 1103.1210
    // discuss at: http://phpjs.org/functions/base64_encode    // +   original by: Tyler Akins (http://rumkin.com)
    // +   improved by: Bayron Guevara
    // +   improved by: Thunder.m
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Pellentesque Malesuada    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // -    depends on: utf8_encode
    // *     example 1: base64_encode('Kevin van Zonneveld');
    // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
    // mozilla has this native    // - but breaks in 2.0.0.12!
    //if (typeof this.window['atob'] == 'function') {
    //    return atob(data);
    //}
    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($) {
	
	// Arrays
	$.inject = function(array, memo, fn) {
		for(var i = 0; i < array.length; i++)
			memo = fn(memo, array[i]);

	    return memo;
	};
	
	$.flatten = function(array) {
		return $.inject(array, [], function(memo, value) {
			return memo.concat($.isArray(value) ? $.flatten(value) : [value]);
		});
	};
	
	$.select = function(array, fn) {
		var returns = [];
		
		for(var i = 0; i < array.length; i++)
			fn(array[i], i) && returns.push(array[i]);
		
		return returns;
	}
	
	$.compact = function(array) {
		return $.select(array, function(value) { return !!value; });
	}
	
	$.uniq = function(array) {
		return $.inject(array, [], function(arr, val) {
			if ($.inArray(val, arr) === -1) { arr.push(val); }
      		return arr;
		});
	}

	
	// Functions
	$.curry = function() {
		var argsArray = Array.prototype.slice.call(arguments),
			fn = argsArray.shift();
		
		return function() {
			return fn.apply(this, argsArray.concat(Array.prototype.slice.call(arguments)));		
		};
	};

	$.args = {
		extractOptions: function(args) {
			args = Array.prototype.slice.call(args);
			if (args.length) {
				for(var i = args.length; i >= 0; i--) {
					if ($.isPlainObject(args[i])) {
						return args[i];
					}
				}
			}

			return {};
		},
		extractNonOptions: function(args) {
			args = Array.prototype.slice.call(args);
			return $.select(args, function(arg, i) {
				return !($.isPlainObject(arg) && i === (args.length - 1));
			});
		}
	};
	
	// Objects
	function map(obj, fn) {
		var returns = [];
		$.each(obj, function() {
			var argsArray = Array.prototype.slice.call(arguments);
			returns.push(fn.apply(this, argsArray));
		});
		return returns;
	}
	
	$.obj = {
		map: map,
		keysFor: function(obj) {
			return map(obj, function(property) { return property; });
		},
		valuesFor: function(obj) {
			return map(obj, function(property, value) { return value; });
		}
	};
	
	
	// jQuery
	$.coalesce = function() {
		var argsArray = Array.prototype.slice.call(arguments),
			returnValue = null;
		
		$.each(argsArray, function() {
			var $tmp = $(this);
			
			if(!returnValue && $tmp.length)
				returnValue = $tmp;
		});
		
		return returnValue;
	};
	
	
	// String
	$.supplant = function(template, data) {
		return template.replace(/{([^{}]*)}/g,
	        function (a, b) {
	            var r = data[b];
	            return typeof r === 'string' || typeof r === 'number' ? r : a;
	        }
	    );
	};

	$.w = function(string) { return string.split(' '); };

	$.pluralize = function(count, singular, plural) {
		return [
			count || 0,
			' ',
			count === 1 || count.match(/^1(\.0+)?$/) ?
				singular :
				plural
		].join('');
	};


	// Namespace
	$.namespace = function(name) {
		var namespaces = name.split('.');
		return $.inject(namespaces, null, function(lastNamespace, currentNamespace) {
			lastNamespace = lastNamespace || window;
			lastNamespace[currentNamespace] = lastNamespace[currentNamespace] || {};

			return lastNamespace[currentNamespace];
		});
	}

	// Event
	$.delay = (function() {
		var timers = {};
		return function(callback, time) {
			clearTimeout(timers[callback]);
			timers[callback] = setTimeout(callback, time);
		}
	})();
})(jQuery);
