// JavaScript Document

// Array Extensions
// By Nelis Elorm Duhadzi
(function () {
	// Removes all keys with undefined values from an array
	// if a boolean true is supplied as argument, an object
	// is returned instead of array of numeric keys
	Array.prototype.trim = function () {
		var a=this, ret=[], k, f=arguments[0]||false;
		
		for (k in a) {
			if (a.propertyIsEnumerable(k) && a[k]!=null) {
				if (f) {
					ret[k] = a[k];
				} else {					
					ret.push(a[k]);
				}
			}
		}
		
		return !f&&!ret.length ? false : ret;
	}
	
	// Trims an array and converts the result into an object
	// NB: this only works with untrimmed arrays
	Array.prototype.object = function () {
		return this.trim(true);	
	}
	
	// Check if an array is empty or not.
	// Returns true if empty and false if not
	Array.prototype.isEmpty = function () {
		return this.length == 0;
	}
	
	// Selects entries from an array according to a specified rule
	// Only entries satisfying the keytype and/or valuetype properties are returned
	// Supported keytypes: string, number
	// Supported valuetypes: string, number, object(including arrays), function
	Array.prototype.extract = function () {		
		var k, a=[], arr=this, 
		ktype=arguments[0]?arguments[0]:null, 
		vtype=arguments[1]?arguments[1]:null;
		
		for (k in arr) {
			if (arr.propertyIsEnumerable(k)) {
				
				var keyIsValidNumber = ktype=="number" && !isNaN(k),
				keyIsValidString = ktype=="string" && isNaN(k),
				anyValidKey = keyIsValidNumber || keyIsValidString,
				valueIsValidType = vtype==typeof(arr[k]),
				validKeyAndValue = anyValidKey && valueIsValidType;
				
				// if both keytype and valuetype are specified,
				// both the key and the value must satisfy their type conditions				
				if (ktype && vtype) {
					if (validKeyAndValue) {
						a[k] = arr[k];
					}
				} 
				// if only a keytype is specified, then check for only a valid key type
				else if (ktype && !vtype) {
					if (anyValidKey) {
						a[k] = arr[k];
					}
				} 
				// if only a valuetype is specified, then check for only a valid value type
				else if (!ktype && vtype) {
					if (valueIsValidType) {
						a[k] = arr[k];
					}
				}
				
			}
		}
		return a;
	}
				 
})();



// jQuery Extensions
// By Nelis Elorm Duhadzi
(function($){
	$.extend($.fx.speeds, 
		{
			crawl: 2000,
			snail: 5000
		}
	);
	
	// example: if(!$("#email-field").validate("#login-notice")) return false;
	$.extend($.fn, {
		valid: true,
		validate: function () {
			var v, f, o=$(this), e, err="";
			v = o.val();
			e = arguments[0] ? $(arguments[0]) : false;
			f = new RegExp(arguments[1]||o.attr("format"));
			
			if (f && !v) {
				err = "This field is required";
			}
			else if (f && v && !f.test(v)) {
				err = '"'+v+'" is not a valid value for this filed';
			}
			
			if ("" != err) {
				o.attr("disabled","disabled");
				if (e) {
					o.valid = false;
					e.show().html(err);
					setTimeout(function () {		
						e.html("").hide();
						o.removeAttr("disabled");
						o.focus();						 
					}, 2000);
				}
				else {
					o.valid = false;
					alert(err);	
					o.removeAttr("disabled");
					o.focus();
				}			
			}
			return o.valid;
		},
		reset: function () {
			$(this).val("");
		}		
	});
	
	// example: if(!$.validate(".login-input", "#login-notice")) return false;
	$.extend($, {
		validate: function (s) {
			var valid=true, notice=arguments[1]||false;
			$(s).each(function (i, e) {
				if ($(e).attr("format")) {
					valid = $(e).validate(notice);
					if (!valid) return false;
				}																 
			});
			return valid;
		}				 
	});
	
	// Cookie methods
	// TODO: set, unset
	$.extend($, {
		cookie: {
			// example: alert($.cookie.get("name"));
			get: function (k) {
				if (document.cookie) {
					var i, c, cs = document.cookie.split(/;[\s]/g);
					for (i=0; i<cs.length; i+=1) {
						c = cs[i].split(/=/g);
						if (c[0] == k && c[1]) {
							return c[1];	
						}
					}
				}
				return null;
			}, 
			// example: $.cookie.set({name:"nelis"},{expire:3});	
			set: function (obj) {				
				for (var i in obj) {
					if (obj.hasOwnProperty(i)) {
						var props=arguments[1]||{}, e="", p, d, s, dt=new Date();
						p = props.path ? "; path="+props.path : "";
						d = props.domain ? "; domain="+props.domain : "";
						s = (props.secure && true === props.secure) ? "; secure" : "";
						
						if (props.expire) {
							dt.setTime(dt.getTime()+(props.expire*60*1000));
							e = "; expire="+dt.toGMTString();
						}
						document.cookie = i+"="+obj[i]+e+p+d+s;
					}
				}
			}, 
			// example: $.cookie.unset("name");
			unset: function (k) {
				if ($.cookie.get(k)) {
					document.cookie = k+"=;expires=Thu, 01-Jan-70 00:00:01 GMT";
				}
			}
		}				 
	});
	
	// quick ajax	
	$.extend($, {
		ax: function (opt, fn) {
			var code, msg;
			if (opt.loading) {
				$(opt.div).html(opt.loading);
			}
			$(opt.div).show(function () {
				$.ajax(
					{
						type: opt.method?opt.method:"post",
						url: opt.url?opt.url:"ajaxer.php",
						data: opt.data,
						success: function (rsp) {
							rsp=decodeURIComponent(rsp);
							code=parseInt(rsp.substr(0, 1)), msg=rsp.substr(1);
							if (fn) {
								fn(msg)
							} else {
								$(opt.div).html(msg);
							}
						}			 
					}
				);
			});
		},
		
		delay: function (fn, t) {
			setTimeout(function () {
				fn();
			}, t);
		return this;
		}
	});
	
	$.extend($.fn, {
		// copy element
		copy: function (e, a, fn) {
			var f=$(e), t=$(this);
			if (a) {
				var p=a.split(",");
				for (var i in p) {
					if (f.attr(p[i])) {
						t.attr(p[i], f.attr(p[i]));
					}	else if (f.css(p[i])) {
						t.css(p[i], f.css(p[i]));
					}
				}
			}	else {
				t = f.clone();
			}
			if (fn) {
				fn(t);
			}
		return t;
		},
			
		snv: function (s) {
			var o=$(this),v=parseFloat(o.css(s).match(/\.*?(\d+).*?/g));
			return isNaN(v)?0:v;
			},
					 
		attachFloater: function (fid, opt, fopt) {
			var props=["location","position","trigger","release"];
			for (i in props) {
				if (!opt[props[i]]) {
					opt[props[i]] = "";
				}
			};
			
			var f=$("#"+fid).clone(),
			o=this,
			l=opt.location.toLowerCase()||"top-right",
			p=opt.position.toLowerCase()||"inside",
			t=opt.trigger.toLowerCase()||"mouseover",
			u=opt.release.toLowerCase()||"mouseout";
			
			o.css({position:"relative"});
			var dim = {
				top: o.attr("clientTop"),
				left: o.attr("clientLeft"),
				height: o.outerHeight(),
				width: o.outerWidth()
			},				
			dir = {
				v: l.split("-")[0],
				h: l.split("-")[1]
			};
				
			f.css({
				position: "absolute",
				top: dir.v=="top"?dim.top:dir.v=="bottom"?dim.height:0,
				left: dir.h=="left"?dim.left:dir.h=="right"?dim.width:0
				}
			);
			
			//$("#"+fid).hide();
			$("#"+fid).css("display","none");
			
			var coating = {
				top: o.snv("padding-top")+o.snv("border-top-width")+f.outerHeight(),
				right: o.snv("padding-right")+o.snv("border-right-width")+f.outerWidth(),
				bottom: o.snv("padding-bottom")+o.snv("border-bottom-width"),
				left: o.snv("padding-left")+o.snv("border-left-width")+f.outerWidth()
			},
			positionmap = {
				inside: {
					"top-left": {vd:o.snv("top"),hd:o.snv("left")},
					"top-right": {vd:o.snv("top"),hd:o.outerWidth()-coating.right},
					"bottom-right": {vd:o.outerHeight()-coating.bottom,hd:o.outerWidth()-coating.right},
					"bottom-left": {vd:o.outerHeight()-coating.bottom,hd:o.snv("left")}
				},
				outside: {
					"top-left": {vd:o.snv("top")-coating.top,hd:o.snv("left")-coating.left},
					"top-right": {vd:o.snv("top"),hd:o.outerWidth()+coating.right},
					"bottom-right": {vd:o.outerHeight()+coating.bottom,hd:o.outerWidth()+coating.right},
					"bottom-left": {vd:o.outerHeight()+coating.bottom,hd:o.snv("left")-coating.left}			
				}
			};				
			
			f.css({
				top: positionmap[p][l].vd,
				left: positionmap[p][l].hd,
				display: "block"
				}
			);
			
			//f.appendTo(o).fadeTo("slow",".9").hide();
			f.appendTo(o).hide();
			
			o.bind(t, 
				function () {
					f.css("display","block");
				}
			).bind(u, 
				function () {
					f.css("display","none");
				}
			);
				
			$(f.children()).each(function (i, e) {
				if($(e).attr("id") in fopt){
					$(e).bind("click", function () {
						fopt[$(e).attr("id")](o, e);
					});
				}
			});
			
		},
		
		// make textarea autoheight
		// @depends: $.fn.copy
		autoheight: function (fn) {
			var ta = $(this);
			ta.css(
						 {
							 height: "auto",
							 overflow: "hidden"
							}
						);
			
			var dv = $("<div></div>").copy(ta,"class,width,line-height,text-align,font-family,font-size,padding");
			dv.css(
						 {
							 position: "absolute",
							 top: "0px",
							 left: "0px",
							 background: "yellow",
							 opacity: "0"
							}
						);
			
			dv.css(
						 {
							 position: "absolute",
							 top: "0px",
							 left: "0px",
							 background: "yellow",
							 visibility: "visible"
							}
						);
			
			ta.bind("keydown", function () {
					ta.keyup();
				}
			).bind("keyup", function () {
				dv.html(ta.val().replace(/\n/g, "<br />"));
				ta.css(
							 {
								 height: dv.attr("clientHeight")
								}
							);				
				if (fn) {
					fn(dv);
					return dv;
				}
			}).bind("blur", function () {
					dv.remove();
				}
			).bind("focus", function () {
					dv.appendTo("body");
				}
			);		
		},
			
		/////////////////////////////////////////////////////
		// convert object/array to URL string
		/*toURLString:function(){
			var obj=this;
			var delim=arguments[1]?arguments[1]:"&",sep=arguments[2]?arguments[2]:"=",s=[];
			for(var i in obj){s.push(i+sep+encodeURIComponent(obj[i]))};
			return s.join(delim);
			},
		// convert URL string to object/array
		toURLObject:function(){
			var str=this;
			var delim=arguments[1]?arguments[1]:"&",sep=arguments[2]?arguments[2]:"=",o={},pairs=str.split(delim);
			for(var i in pairs){var p=decodeURIComponent(pairs[i]).split(sep);o[p[0]]=p[1]};
			return o;
			},*/
		/////////////////////////////////////////////////////
		
		// in place editor
		// @depends: $.fn.copy, $.dalay
		totextarea:function(opt){
			var dv = $(this),ta = $("<textarea></textarea>").copy(dv,"class,width,line-height").insertAfter(dv).hide();		
			var sl=$("<a href=\"javascript:{}\">Save</a>").css({display:"block",width:"50px",padding:"4px"}).attr("class","txt_save_link").insertAfter(ta).hide();
			var _saved=false;
			dv.bind("click",function(){
				dv.hide();ta.css({height:"auto"}).val("").show().focus();
				if(opt!==undefined&&opt["edit"])opt["edit"](ta);				
				sl.fadeIn(500);
				return ta;
				});		
			sl.bind("click",function(){
				if(ta.val()){
					dv.show().html(ta.val().replace(/\n/g,"<br />"));ta.val("").hide();
					if(opt!==undefined&&opt["save"])opt["save"](dv);sl.fadeOut(500);_saved=true;
					}
				});		
			ta.bind("blur",function(){
				if(!_saved||!ta.val()){
					$.delay(function(){ta.hide();dv.show();sl.fadeOut(500)},300);
					}
				});
			}
		});
		
	})($);
	
	