/// <reference path="jquery.js" />
/*
 ww.jQuery.js  
 West Wind jQuery plug-ins and utilities

 Copyright (c) 2008 Rick Strahl, West Wind Technologies 
 www.west-wind.com

 Licensed under MIT License
 http://en.wikipedia.org/wiki/MIT_License

 Version 0.90.672 - 12/01/08
*/
this.HttpClient = function(opt) {
		var _I = this;

		this.completed = null;
		this.errorHandler = null;
		this.errorMessage = "";
		this.async = true;
		this.evalResult = false;
		this.isMsAjaxJson = false;
		this.contentType = "application/x-www-form-urlencoded";
		this.method = "GET";
		this.timeout = 20000;
		this.headers = {};

		$.extend(_I, opt);

		this.appendHeader = function(header, value) {
				_I.headers[header] = value;
		}
		this.send = function(url, postData, completed, errorHandler) {
				completed = completed || _I.completed;
				errorHandler = errorHandler || _I.errorHandler;

				$.ajax(
					 { url: url,
							 data: postData,
							 type: (postData ? "POST" : _I.method),
							 processData: false,  // always process on our own!
							 contentType: _I.contentType,
							 timeout: _I.timeout,
							 dataType: "text",
							 global: false,
							 async: _I.async,
							 beforeSend: function(xhr) {
									 for (var header in _I.headers) xhr.setRequestHeader(header, _I.headers[header]);
							 },
							 success: function(result, status) {
									 var errorException = null;

									 if (_I.evalResult) {
											 try {
													 result = JSONC.parse(result);
													 if (result != null) {
															 if (result.d && result.d.__type)
																	 result = result.d;
															 else if (_I.isMsAjaxJson) {
																	 // Wrapped message: return first property
																	 for (var property in result) {
																			 result = result[property];
																			 break;
																	 }
															 }
													 }
											 }
											 catch (e) { errorException = new CallbackException(e); }
									 }
									 if (errorException) {
											 if (errorHandler)
													 errorHandler(errorException, _I);
											 return;
									 }
									 if (result && (result.isCallbackError || result.iscallbackerror)) {
											 if (errorHandler)
													 errorHandler(result, _I);
									 }
									 if (completed)
											 completed(result, _I);
							 },
							 error: function(xhr, status) {
									 var res = xhr.responseText;
									 var err = null;                   
									 if (res && res.charAt(0) == '{')
											 var err = JSONC.parse(res);
									 if (!err) {
											 if (xhr.status != 200)
													 err = new CallbackException(xhr.status + " " + xhr.statusText);
											 else
													 err = new CallbackException("Unknown Error Response");
											 err.detail = res;
									 }
									 else
											 err = new CallbackException(err); // force error to common format

									 if (errorHandler)
											 errorHandler(err, _I, xhr);
							 }
					 });
		}
		this.returnError = function(message) {
				var error = new CallbackException(message);
				if (_I.errorHandler)
						_I.errorHandler(error, _I);
		}
}

this.CallbackException = function(message, detail) {
		this.isCallbackError = true;
		if (typeof (message) == "object") {
				if (message.message)
						this.message = message.message;
				else if (message.Message)
						this.message = message.Message;
		}
		else
				this.message = message;

		if (detail)
				this.detail = detail;
		else
				this.detail = null;
}



this.ServiceProxy = function(serviceUrl) {
		/// <summary>
		/// Generic Service Proxy class that can be used to 
		/// call JSON Services generically using jQuery
		/// </summary>
		/// <param name="serviceUrl" type="string">The Url of the service ready to accept the method name</param>
		/// <example>
		/// var proxy = new ServiceProxy("JsonStockService.svc/");
		/// proxy.invoke("GetStockQuote",{symbol:"msft"},function(quote) { alert(result.LastPrice); },onPageError);
		///</example>        
		var _I = this;
		this.serviceUrl = serviceUrl;

		// Call a wrapped object
		this.invoke = function(method, params, callback, errorCallback, isBare) {
				/// <summary>
				/// Calls a WCF/ASMX service and returns the result.
				/// </summary>    
				/// <param name="method" type="string">The method of the service to call</param>
				/// <param name="params" type="object">An object that represents the parameters to pass {symbol:"msft",years:2}       
				/// <param name="callback" type="function">Function called on success. Receives a single parameter of the parsed result value</parm>
				/// <param name="errorCallback" type="function">Function called on failure. Receives a single error object with Message and StackDetail</parm>
				/// <param name="isBar" type="boolean">Set to true if response is not a WCF/ASMX style wrapped object</parm>

				// Convert input data into JSON using internal code
				var json = JSONC.serialize(params);

				// The service endpoint URL MyService.svc/       
				var url = _I.serviceUrl + method;

				var http = new HttpClient(
				{ contentType: "application/json",
					evalResult: true,
					isMsAjaxJson: !isBare
				});
				http.send(url, json, callback, errorCallback);
		}
}


//Copyright (c) 2005 JSON.org
//Modifications for MS AJAX by Rick Strahl
//Added dates in object parser,} and ] encoding, MS Date Support
this.JSONC = {
		copyright: '(c)2005 JSON.org',
		license: 'http://www.crockford.com/JSON/license.html',
		serialize: function(v) {
				var a = [];
				//	Emit a string.
				function e(s) {
						a[a.length] = s;
				}

				// Convert a value.
				function g(x) {
						var b, c, i, l, v;

						switch (typeof x) {
								case 'string':

										e('"');
										if (/["\\\x00-\x1f\x7d\x5d]/.test(x)) {
												l = x.length;
												for (i = 0; i < l; i += 1) {
														c = x.charAt(i);
														if (c >= ' ' && c != '}' && c != ']') {
																if (c == '\\' || c == '"')
																		e('\\');
																e(c);
														} else {
																switch (c) {
																		case '\b':
																				e('\\b');
																				break;
																		case '\f':
																				e('\\f');
																				break;
																		case '\n':
																				e('\\n');
																				break;
																		case '\r':
																				e('\\r');
																				break;
																		case '\t':
																				e('\\t');
																				break;
																		case '}':
																				e('\\u007D');
																				break;
																		case ']':
																				e('\\u005D');
																				break;
																		default:
																				c = c.charCodeAt();
																				e('\\u00' +
		Math.floor(c / 16).toString(16) +
		(c % 16).toString(16));
																}
														}
												}
										} else {
												e(x);
										}
										e('"');
										return;
								case 'number':
										e(isFinite(x) ? x : 'null');
										return;
								case 'object':
										if (x) {
												// RAS: Added Date Parsing
												if (x.toUTCString)
														return e('\"\\/Date(' + x.getTime() + ')\\/\"'); // MS Ajax style

												if (x instanceof Array) {
														e('[');
														l = a.length;
														for (i = 0; i < x.length; i += 1) {
																v = x[i];
																if (typeof v != _ud &&
		typeof v != 'function') {
																		if (b) {
																				e(',');
																		}
																		g(v);
																		b = true;
																}
														}
														e(']');
														return;
												} else if (typeof x.valueOf == 'function') {
														e('{');
														l = a.length;
														for (i in x) {
																v = x[i];
																if (typeof v != _ud &&
		typeof v != 'function' &&
		(!v || typeof v != 'object' ||
		typeof v.valueOf == 'function')) {
																		if (b) {
																				e(',');
																		}
																		g(i);
																		e(':');
																		g(v);
																		b = true;
																}
														}
														return e('}');
												}
										}
										e('null');
										return;
								case 'boolean':
										e(x);
										return;
								default:
										e('null');
										return;
						}
				}
				g(v);
				return a.join('');
		},
		// *** RAS Update: RegEx handler for dates ISO and MS AJAX style
		regExDate: function(str, p1, p2, offset, s) {
				str = str.substring(1).replace('"', '');
				var date = str;
				//MS Ajax date
				var regEx = /\/Date(.*)\//;
				if (regEx.test(str)) {
						str = str.match(/Date\((.*?)\)/)[1];
						date = "new Date(" + parseInt(str) + ")";
				}
				else { // ISO Date 2007-12-31T23:59:59Z                                     
						var matches = str.split(/[-,:,T,Z]/);
						matches[1] = (parseInt(matches[1], 0) - 1).toString();
						date = "new Date(Date.UTC(" + matches.join(",") + "))";
				}
				return date;
		},
		parse: function(text, noCheck) {

				if (!noCheck && !(!(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
 text.replace(/"(\\.|[^"\\])*"/g, '')))))
						throw new Error("Invalid characters in JSON parse string.");

				// *** RAS Update:  Fix up Dates: ISO and MS AJAX format support
				var regEx = /(\"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}.*?\")|(\"\\*\/Date\(.*?\)\\*\/")/g;
				//var regEx = /(\"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}.*?\")|(\"\\\/Date\(.*?\)\\\/")/g;
				text = text.replace(regEx, this.regExDate);

				return eval('(' + text + ')');
		},
		parseSafe: function(text) {
				try { return this.parse(text); } catch (e) { return null; }
		}
}

/// <script type="text/html" id="script">
/// <div> 
///   <#= content #>
///   <# for(var i=0; i < names.length; i++) { #>
///   Name: <#= names[i] #> <br/>
///   <# } #>
/// </div>
/// </script>
///
/// var tmpl = $("#itemtemplate").html();
/// var data = { content: "This is some textual content",
///              names: ["rick", "markus"]
/// };
/// $(document.body).html(parseTemplate(tmpl, data));
/// based on John Resig's Micro Templating engine
var _tmplCache = {}
this.parseTemplate = function(str, data) {
		/// <summary>
		/// Client side template parser that uses &lt;#= #&gt; and &lt;# code #&gt; expressions.
		/// and # # code blocks for template expansion.
		/// </summary>    
		/// <param name="str" type="string">The text of the template to expand</param>    
		/// <param name="data" type="var">
		/// Any data that is to be merged. Pass an object and
		/// that object's properties are visible as variables.
		/// </param>    
		/// <returns type="string" />  
		var err = "";
		try {
				var func = _tmplCache[str];
				if (!func) {
						var strFunc =
						"var p=[],print=function(){p.push.apply(p,arguments);};" +
												"with(obj){p.push('" +
						str.replace(/[\r\t\n]/g, " ")
							 .replace(/'(?=[^#]*#>)/g, "\t")
							 .split("'").join("\\'")
							 .split("\t").join("'")
							 .replace(/<#=(.+?)#>/g, "',$1,'")
							 .split("<#").join("');")
							 .split("#>").join("p.push('")
							 + "');}return p.join('');";

						func = new Function("obj", strFunc);
						_tmplCache[str] = func;
				}
				return func(data);
		} catch (e) { err = e.message; }
		return "< # ERROR: " + err.htmlEncode() + " # >";
}



String.prototype.htmlEncode = function() {
		var div = document.createElement('div');
		if (typeof (div.textContent) == 'string')
				div.textContent = this.toString();
		else
				div.innerText = this.toString();
		return div.innerHTML;
}
String.prototype.trimEnd = function(c) {
		return this.replace(/\s+$/, '');
}
String.prototype.trimStart = function(c) {
		return this.replace(/^\s+/, '');
}
String.repeat = function(chr, count) {
		var str = "";
		for (var x = 0; x < count; x++) { str += chr };
		return str;
}
String.prototype.padL = function(width, pad) {
		if (!width || width < 1)
				return this;

		if (!pad) pad = " ";
		var length = width - this.length
		if (length < 1) return this.substr(0, width);

		return (String.repeat(pad, length) + this).substr(0, width);
}
String.prototype.padR = function(width, pad) {
		if (!width || width < 1)
				return this;

		if (!pad) pad = " ";
		var length = width - this.length
		if (length < 1) this.substr(0, width);

		return (this + String.repeat(pad, length)).substr(0, width);
}
String.startsWith = function(str) {
		if (!str) return false;
		return this.substr(0, str.length) == str;
}
String.format = function(frmt, args) {
		for (var x = 0; x < arguments.length; x++) {
				frmt = frmt.replace("{" + x + "}", arguments[x + 1]);
		}
		return frmt;
}
String.prototype.format = function() {
		var a = [this];
		$.merge(a, arguments);
		return String.format.apply(this, a);
}
String.prototype.isNumber = function() {   

		if (this.length == 0) return false;
		if ("0123456789".indexOf(this.substr(0,1)) > -1)
				return true;
		return false;
}
var _monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
Date.prototype.formatDate = function(format) {
		var date = this;
		if (!format)
				format = "MM/dd/yyyy";

		var month = date.getMonth();
		var year = date.getFullYear();

		if (format.indexOf("yyyy") > -1)
				format = format.replace("yyyy", year.toString());
		else if (format.indexOf("yy") > -1)
				format = format.replace("yy", year.toString().substr(2, 2));

		format = format.replace("dd", date.getDate().toString().padL(2, "0"));

		var hours = date.getHours();
		if (format.indexOf("t") > -1) {
				if (hours > 11)
						format = format.replace("t", "pm")
				else
						format = format.replace("t", "am")
		}
		if (format.indexOf("HH") > -1)
				format = format.replace("HH", hours.toString().padL(2, "0"));
		if (format.indexOf("hh") > -1) {
				if (hours > 12) hours -= 12;
				if (hours == 0) hours = 12;
				format = format.replace("hh", hours.toString().padL(2, "0"));
		}
		if (format.indexOf("mm") > -1)
				format = format.replace("mm", date.getMinutes().toString().padL(2, "0"));
		if (format.indexOf("ss") > -1)
				format = format.replace("ss", date.getSeconds().toString().padL(2, "0"));

		if (format.indexOf("MMMM") > -1)
				format = format.replace("MMMM", _monthNames[month]);
		else if (format.indexOf("MMM") > -1)
				format = format.replace("MMM", _monthNames[month].substr(0, 3));
		else
				format = format.replace("MM", month.toString().padL(2, "0"));

		return format;
}
Number.prototype.formatNumber = function(format, option) {
		var num = this;
		var fmt = Number.getNumberFormat();
		if (format == "c") {
				num = Math.round(num * 100) / 100;
				option = option || "$";
				num = num.toLocaleString();
				var s = num.split(".");
				var p = s.length > 1 ? s[1] : '';
				return option + s[0] + fmt.d + p.padR(2, '0');
		}
		if (format.substr(0, 1) == "n") {
				if (format.length == 1)
						return num.toLocaleString()
				var dec = format.substr(1);
				dec = parseInt(dec);
				if (typeof (dec) != "number")
						return num.toLocaleString();
				num = num.toFixed(dec);
				var x = num.split(fmt.d);
				var x1 = x[0];
				var x2 = x.length > 1 ? fmt.d + x[1] : '';
				var rgx = /(\d+)(\d{3})/;
				while (rgx.test(x1))
						x1 = x1.replace(rgx, '$1' + fmt.c + '$2');
				return x1 + x2
		}
		if (format.substr(0, 1) == "f") {
				if (format.length == 1)
						return num.toString();
				var dec = format.substr(1);
				dec = parseFloat(dec);
				if (typeof (dec) != "number")
						return num.toString();
				return num.toFixed(dec);
		}
		return num.toString();
}
Number.getNumberFormat = function(cur) {
		var t = 1000.1.toLocaleString();
		var r = {};        
		r.d = t.substr(5,1);     
		if (r.d.isNumber())
			 r.d = t.substr(4,1);           
		r.c = t.substr(1, 1);    
		if (r.c.isNumber())
				r.c = ",";        
		r.s = cur || "$";
		return r;
}
registerNamespace = function(ns) {
		var pts = ns.split('.');
		var stk = window;
		var nsp = "";
		for (var i = 0; i < pts.length; i++) {
				var pt = pts[i];
				if (stk[pt])
						stk = stk[pt];
				else
						stk = stk[pt] = {};
		}
}
$.fn.serializeNoViewState = function() {
		return this.find("input,textarea,select,hidden").not("#__VIEWSTATE,#__EVENTVALIDATION").serialize();
}
$.fn.makeAbsolute = function(rebase) {
		/// <summary>
		/// Makes an element absolute
		/// </summary>    
		/// <param name="rebase" type="boolean">forces element onto the body tag. Note: might effect rendering or references</param>    
		/// </param>    
		/// <returns type="jQuery" /> 
		return this.each(function() {
				var el = $(this);
				var pos = el.position();
				el.css({ position: "absolute",
						marginLeft: 0, marginTop: 0,
						top: pos.top, left: pos.left
				});        
				if (rebase)
						el.remove().appendTo("body");
		});
}
var _ud = "undefined";

//})(jQuery);


