﻿Date.parseISO = function(value) {
	if (typeof value === 'string') {
		var a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
		if (a)
			return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));
	}
	throw new SyntaxError('Date.parseISO');
}

function cors(src, options) {
	if($.isFunction(options)) options = {callback:options};
	var xhr = new cors.xhr(),
		method = (options.method||"GET").toUpperCase();
	xhr.open(method, src, true);
	xhr.onload = function(){
		if(options.success)options.success(src, xhr);
		if (options.callback) options.callback(src, xhr);
	}
	xhr.onerror = function () {
		if(options.error)options.error(src, xhr);
		if(options.callback)options.callback(src, xhr);
	}
	if(options.data && (method=="POST" || method=="PUT"))
		xhr.send(options.data);
	else xhr.send();
	return xhr;
}
cors.xhr = (window.XDomainRequest) ? XDomainRequest : ('withCredentials' in new XMLHttpRequest()) ? XMLHttpRequest : function(){throw "NA"};
cors.api = function(method, path, callback){return cors(path, {callback:callback,method:method})};

jQuery.ajaxSetup({
	dataFilter: function(data, type) {
		if (data === "") return null;
		if (type == "json")
			data = JSON.parse(data.replace(/^for\(;;\);/, ''));
		return data;
	}
});
(function($) {
	var origionalVal = $.fn.val;
	$.fn.watermark = function(text, className) {
		className = className || "watermark";
		return this.each(
			function() {
				var $this = $(this).focus(focus).blur(blur).data("watermark",text);
				function focus() {
					if (this.value == text) $this.val("");
					$this.removeClass(className);
				}
				function blur() {
					if ($.trim(this.value).length == 0 || this.value == text)
						$this.val(text).addClass(className);
				}
				blur();
			}
		);
	};
	$.fn.val = function (text) {
		var val = origionalVal.call(this, text);
		if (text === undefined){
			var watermark = this.data("watermark");
			if(watermark === val) return "";
		}
		return val;
	};
	$.fn.wait = function(show) {
		show = arguments.length == 0 || !!show;
		return this.each(function() {
			var $this = $(this);
			if (show) {
				var w = $this.outerWidth(),
					h = $this.outerHeight(),
					v = $this.val(),
					o = $this.offset(),
					d = $("<div class='wait'>").width(w).height(h)
					.css({ top: o.top, left: o.left })
					.appendTo(document.body);
				$("body").css("cursor", "wait");
				$this.width(w).height(h).data("wait", { v: v, d: d }).attr("disabled", "disabled").val("");
			}
			else {
				var data = $this.data("wait");
				$this.removeAttr("disabled").val(data.v);
				$("body").css("cursor", "");
				data.d.remove();
			}
		});
	};
})(jQuery);

var SR = {}; //String Resources
var SH = {
	HtmlEncode: function clean(v) {
		return $("<div>").html(v.replace("<", "&lt;")).html();
	},
	Form: function (form) {
		var $form = form.jquery ? form.jquery : $(form);
		function showErrors(errs, prefix) {
			for (var name in errs) {
				var item = errs[name];
				name = (prefix || "") + name;
				if (typeof item === "object")
					processErrors(item, name + "_");
				else
					$($form[0].elements[name]).closest("fieldset").addClass("invalid").find("aside").html(item);
			}
		};
		return {
			showErrors: showErrors,
			toObject: function () { return SH.Form.toObject($form[0]) },
			submit: function (success, error) {
				var obj = SH.Form.toObject($form[0]);
				if (!obj) return false;

				$form.find(".invalid").removeClass("invalid");
				$form.find(".errormsg").html("");

				var action = $form.attr("action");
				var isRelative = /^\//.test(action);
				if (isRelative) action = window.APIURL + action;

				cors(action, {
					method: $form[0].method,
					success: success,
					data:JSON.stringify(obj),
					error: function (src, xhr) {
						if (xhr.status < 400) return;
						var errors = xhr.responseText ? JSON.parse(xhr.responseText) : null;
						var message = xhr.getResponseHeader("X-Message");
						if (xhr.status >= 500 || (!errors && !message)) {
							SH.Dialog.ServerError();
							return;
						}
						if (error) {
							var result = error(xhr, errors, message);
							if (result === false) return;
							if (result) errors = result;
						}
						showErrors(errors);
					}
				});
			}
		};
	},
	Dialog: function (title, message, buttons) {
		return $("<div>").html(message)
			.dialog({ modal: true,
				title: title,
				close: function () { $(this).remove(); },
				buttons: buttons || { OK: SH.Dialog.Closer }
			});
	},
	Bind: function (template, data, context) {
		var func = SH._templateCache[template];
		if (!func) {
			var fn = function (m) {
				if (m.charAt(0) == "\t") {
					m = m.substring(1);
					return (m.charAt(0) == "=") ? "p.push(" + m.substr(1) + ");" : m + "\r";
				}
				m = m.replace(new RegExp("'", "g"), "\\'");
				return "p.push('" + m + "');";
			};
			var a = template.replace(/[\r\t\n]| {2,}/g, " ").replace(/<#(.+?)#>/g, "\r\t$1\r").replace(/([^\r]+)/g, fn).replace(/\);\rp\.push\(/g, ",");
			func = new Function("o", "var p=[];\rwith(o){\r" + a + "}return p.join('');");
			SH._templateCache[template] = func;
		}
		return func.call(context || this, data);
	}
};
SH.Form.toObject = function(form) {
	//html form to json
	if (form.nodeType && form.nodeName == "FORM") {
		var obj = {};
		function add(path, value) {
			var names = path.split('_'),
				n = names[0],
				o = obj;
			for (var i = 0; i < names.length - 1; n = names[++i]) {
				if (o[n] && typeof o[n] !== 'object')
					throw "Cannot extend primitives";

				if (!o[n]) o = o[n] = {}; //extend the object
				else o = o[n];
			}
			//if ($.trim(value) === "") return;
			if (o[n]) { //multiple with same name
				if (!$.isArray(o[n]))
					o[n] = [o[n]]; //turn it into an array
				o[n].push($.trim(value));
			}
			else o[n] = $.trim(value);
		}
		for (i = 0; i < form.elements.length; i++) {
			var input = form.elements[i];
			if (input.disabled) continue;
			var name = input.name || input.id;
			if (!name || input.type == "submit") continue;
			if (input.type == "checkbox") {
				if(input.checked) add(name, "true");
			}
			else if (input.type == "radio") {
				if (input.checked) add(name, input.value);
			}
			else add(name, input.value);
		}
		return obj;
	}
	else return {};
};

SH._templateCache = {};
SH.Dialog.Closer = function() { $(this).dialog('close'); };
SH.Dialog.ServerError = function() {
	return SH.Dialog("Error!", "There seems to be a problem with the StoreHours service " +
					"right now. Your request <b>did not complete</b>. If you continue to " +
					"have this error, please try again later.");
};
