//Configuring jqGrid to use only the new API

$.ajaxSetup({
	dataType: "json",
	type: "POST",
	traditional: true,
	success: function(data){
		if(app.handlerServiceResponse(data)){
			$("#jgrid_list").trigger("reloadGrid");
			$(this).dialog("close"); 
		}
	},
	error: function(){
		app.showError();
		app.helper.closeLoadingTip();
	},
	complete: function(){
	}
});

var app = {};

app.helper = {
		contextPath: "",
		mergeArray: function(array1, array2){
			var array = new Array();
			if(typeof array1 != "undefined"){
				if($.type(array1) == "array"){
					for(var i=0;i<array1.length;i++){
						array.push(array1[i]);
					}
				}else array.push(array1);
			}
			if(typeof array2 != "undefined"){
				if($.type(array2) == "array"){
					for(var i=0;i<array2.length;i++){
						array.push(array2[i]);
					}
				}else array.push(array2);
			}
			return array;
		},
		getContextPath: function(){
	          var contextPath = location.pathname;
	          var index =contextPath.substr(1).indexOf("/");
	          contextPath = contextPath.substr(0,index+1);
	          delete index;
	          return contextPath;
	     },
	     getFullContextPath: function(){
	          var contextPath = app.helper.getContextPath();
	          return location.protocol+"//"+location.host+contextPath;
	     },
	     removeArray: function(array, delObj) { //扩展Array.prototype与jquery冲突，故采用此法
	    	 var index = -1;
	    	 for (var i = 0; i < array.length; i++) {
 		        if (array[i] == delObj) {
 		        	index = i;
 		        }
 		     }
	    	 if (index > -1) {
	    		 array.splice(index, 1);
 		     }
	    	 return array;
	     },
	     showBg: function() {
    		$("#bg").css("display", "block");
	    	$("#popIframe").css("display", "block");
	     },
	     closeBg: function() {
	    	 $("#bg").css("display", "none");
	    	 $("#popIframe").css("display", "none");
	     },
	     showLoadingTip: function() {
    		//$("#bg").css("display", "block");
	    	//$("#popIframe").css("display", "block");
	    	$("#loadingTip").css("display", "block");
	     },
	     closeLoadingTip: function() {
	    	 //$("#bg").css("display", "none");
	    	 //$("#popIframe").css("display", "none");
	    	 $("#loadingTip").css("display", "none");
	     },
	     formatNumber: function(nData,opts){
	    	if(!opts) opts = {};
	    	return $.fmatter.util.NumberFormat(nData,opts); 
	     },
	     formatCurrency: function(nData){
	    	return $.fmatter.util.NumberFormat(nData,{thousandsSeparator:",",decimalPlaces:2}); 
	     },
	     formatDate: function(dateString, pattern) {
	    	 var date;
	    	 if(dateString) date = new Date(dateString);
	    	 else return "";
	 		 return date.pattern(pattern?pattern : 'yyyy-MM-dd');
	     },
	     formatCurrentDate: function(pattern) {
	    	 var date = new Date();
	 		 return date.pattern(pattern?pattern : 'yyyy-MM-dd');
	     },
	     initDatePicker: function(options){
	    	 var settings = $.extend({},{
	    		 showOn: "both",
	    		 buttonImage: app.helper.contextPath+"/static/admin/images/calendar.gif",
	    		 buttonImageOnly: true,
	    		 dateFormat:"yy-mm-dd",
	    		 defaultDate: "${nowTimestamp?string('yyyy-MM-dd')}"
	    	 },options);
	    	 $(".datepicker").datepicker(settings);
	     },
	     safeRender: function(s){
	    	 return (s && s !="" && s != '_NA_') ? s : "无";
	     },
	     validateFormBeforeSubmit: function(validatorGroup){
			if (!$.formValidator.pageIsValid(validatorGroup)) {
				return false;
			}
			app.helper.showLoadingTip();
			return true;
	     },
	     download: function(url){
	    	 var downloadIframe = $("#downloadIframe");
	    	 var downloadForm = $("#downloadForm");
	    	 if(downloadIframe.size() <= 0){
	    		 $('<iframe name="downloadIframe" id="downloadIframe" width="0" height="0" frameborder="0" marginheight="0" marginwidth="0" hspace="0" allowtransparency="true" scrolling="no" vspace="0"></iframe>').appendTo("body");	 
	    	 }
	    	 if(downloadForm.size() <= 0){
	    		 $('<form id="downloadForm" target="downloadIframe" action="" method="post"></form>').appendTo("body");	 
	    	 }
	    	 $("#downloadForm").attr("action",url).submit();
	     },
	     loadStatus: function(id, status, defaultValue){
	    	var e = $("#"+id);
	    	if(e.size() > 0){
	    		e.empty();
	    		$("<option value=''>请选择</option>").appendTo(e);
	    		for(var s in status){
	    			var str = "<option value='" + s + "' ";
	    			if(defaultValue && defaultValue==s) str += "selected";;
	    			str += ">" +  status[s] + "</option>";
	    			$(str).appendTo(e);
	    		}
	    	}
	     }
	}

app.handlerServiceResponse = function(data){
	app.helper.closeLoadingTip();
	if(typeof data.result == "undefined"){
		app.showError({messages:["数据格式错误"]});
		return false;
	}else if(data.result == "success"){
		return true;
	}else if(data.result == "error"){
		var message = data.message || "系统错误";
		app.showError({messages:[message]});
		return false;
	}else if(data.result == "nosession"){
		app.confirm({message:"长时间未操作，请重新登录！",sure:function(){
			top.location.reload();
		}});
		return false;
	}else{
		app.showError({messages:["数据格式错误"]});
		return false;
	}
};

app.confirm = function(options){
	var op = {
			title: "确认",
			buttons:[
				{
				    text: "确定",
				    click: function() {
				    	op.sure();
				    	$(this).dialog("close"); 
				    }
				},
				{
				    text: "取消",
				    click: function() { $(this).dialog("close"); }
				}
			],
			message:"确定删除该记录吗？",
			sure:function(){
				alert("请务必传入确认操作fucntion！");
			}
		};
	
	$.extend(op, options);
	var s = '<div><p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>'+op.message+'</p></div>';
	$(s).dialog(op);
};

app.showError = function(options){
	var op = {
			messages:["处理失败，请重试！"]
    };
	
	$.extend(op, options);

	var messages = app.helper.mergeArray([],op.messages);
	var errorHtml = "";
	for(var i=0;i<messages.length;i++){
		errorHtml += messages[i];
	}
	alert(errorHtml);
};

app.showAlertTip = function(options){
	var op = {
			messages:["警告信息！"]
	};
	
	$.extend(op, options);
	
	var s = "";
	var messages = app.helper.mergeArray([],op.messages);
	for(var i=0;i<messages.length;i++){
		s += messages[i];
	}
	alert(s);
};

app.opTips = function(options){
	var messages = app.helper.mergeArray([],options.messages);
	if(messages.length <= 0) return;
	var s = "";
	for(var i=0;i<messages.length;i++){
		s += "<p>"+messages[i]+"</p>";
	}
	$("#op_tips div").append(s).show();
};

app.showDialog = function(content) {
	
};

app.dialog = {
		show: function(content) {
			var dialog = '<div class="dialog" id="dialog">\
						  	<div class="dgwrap">\
						    	<a href="javascript:app.dialog.close();" class="dgclose">关闭</a>\
								'+content+'\
						    </div>\
						  </div>';
			$(dialog).appendTo(document.body);
		},
		close: function() {
			$("#dialog").remove();
		}
};

app.alertTips = {
		show: function(id, message, width) {
			var msg = message || "无";
			var w = width || 150;
			jQuery.tips.show($("#"+id)[0], w, msg);
			setTimeout('jQuery.tips.close()', 1000);
		},
		close: function() {
			jQuery.tips.close();
		}
};

app.ajaxHelper = {
	success: function(data, textStatus, jqXHR, options){
		var settings = $.extend({},options);
		if(app.handlerServiceResponse(data)){
			if(settings.dialog) $("#"+settings.dialog).dialog("close");
			if(settings.gridId) $("#"+settings.gridId).trigger("reloadGrid");
			app.opTips({
				messages:settings.opTips
			});
		}
		//app.helper.closeLoadingTip();
	},
	submitRequest: function(options){
		var settings = $.extend(true,{data:{}},options);
		if(!settings.url) settings.url = app.helper.getFullContextPath()+"/control/submitRequestAjax";
		if(!settings.type) settings.type = 'POST';
		//app.helper.showLoadingTip();
		$.ajax(settings.url,{
			type: settings.type,
    		data: settings.data,
    		success: settings.success
    	});
	},
	confirm: function(options){
		var settings = $.extend(true,{},options);
		if(!settings.url) settings.url = app.helper.getFullContextPath()+"/control/submitRequestAjax";
		var sure = function(){
			$.ajax(settings.url,{
	    		data: settings.data,
	    		success: settings.success
	    	});
		};
		app.confirm({
			message:settings.message,
			sure:sure
		});
		return false;
	}
};



app.areaCascadeHelper = {
	defaultOptions: {
		provinceGeoId: "provinceGeoId",
		cityGeoId: "cityGeoId",
		countyGeoId: "countyGeoId",
		provinceGeoIdValue: null,
		cityGeoIdValue: null,
		countyGeoIdValue: null
	},
	init: function (options) {
		var settings = $.extend({},this.defaultOptions,options);
		var areaData = settings.areaData || {};
		var provinceSelect = $("#" + settings.provinceGeoId);
		var citySelect = $("#" + settings.cityGeoId);
		var countySelect = $("#" + settings.countyGeoId);
		if (provinceSelect.length == 0 || citySelect.length == 0 || countySelect.length == 0 ) {
			//return;//注释掉，以单独支持省市级
		}
    	provinceSelect.empty();
    	citySelect.empty();
    	countySelect.empty();
    	$("<option value=''>请选择</option>").appendTo(provinceSelect);
    	$("<option value=''>请选择</option>").appendTo(citySelect);
    	$("<option value=''>请选择</option>").appendTo(countySelect);
    	for(var i=0;i<areaData.length;i++){
            $("<option value='" + areaData[i].provinceId + "'>" + areaData[i].provinceName + "</option>").appendTo(provinceSelect);
        }
    	
    	provinceSelect.change(function(){
    		app.areaCascadeHelper.selectCities();
    	});
    	
    	citySelect.change(function(){
    		app.areaCascadeHelper.selectCounties();
    	});
    	
    	$('body').data("areaCascade", settings);
    	if(settings.provinceGeoIdValue) $("#" + settings.provinceGeoId).val(settings.provinceGeoIdValue).change();
    	if(settings.cityGeoIdValue) $("#" + settings.cityGeoId).val(settings.cityGeoIdValue).change();
    	if(settings.countyGeoIdValue) $("#" + settings.countyGeoId).val(settings.countyGeoIdValue);
	},
	selectCities: function(provinceValue) {
		var areaOptions = $('body').data("areaCascade");
		var areaData = areaOptions.areaData;
		var provinceSelectValue = provinceValue || $("#" + areaOptions.provinceGeoId).val();
		var citySelect = $("#" + areaOptions.cityGeoId);
		var countySelect = $("#" + areaOptions.countyGeoId);
    	citySelect.empty();
    	countySelect.empty();
    	$("<option value=''>请选择</option>").appendTo(citySelect);
    	$("<option value=''>请选择</option>").appendTo(countySelect);
    	for(var i = 0; i < areaData.length; i++){
    		if(provinceSelectValue == areaData[i].provinceId){
    		    for(var j = 0; j < areaData[i].cities.length; j++) {
    		    	$("<option value='" + areaData[i].cities[j].cityId + "'>" + areaData[i].cities[j].cityName + "</option>").appendTo(citySelect);
    		    }
    		}
        }
	},
	selectCounties: function(provinceValue, cityValue) {
		var areaOptions = $('body').data("areaCascade");
		var areaData = areaOptions.areaData;
		var provinceSelectValue = provinceValue || $("#" + areaOptions.provinceGeoId).val();
		var citySelectValue = cityValue || $("#" + areaOptions.cityGeoId).val();
    	var countySelect = $("#" + areaOptions.countyGeoId);
    	countySelect.empty();
    	$("<option value=''>请选择</option>").appendTo(countySelect);
    	for(var i = 0; i < areaData.length; i++){
    		if(provinceSelectValue == areaData[i].provinceId){
    		    for(var j = 0; j < areaData[i].cities.length; j++) {
    		         if (citySelectValue == areaData[i].cities[j].cityId) {
    		             for (var k = 0; k < areaData[i].cities[j].counties.length; k++) {
    		             	$("<option value='" + areaData[i].cities[j].counties[k].countyId + "'>" + areaData[i].cities[j].counties[k].countyName + "</option>").appendTo(countySelect);
    		             }
    		         }
    		    }
    		}
        }
	}
};

app.CascadeSelect= function(options){
	this.settings={};
	this.data=[];
	this.dataMap={};
	this.elements=null;
	this.uiIds=[];
	this.defaultOptions={
		nameKey:"name",
		valueKey:"id",
		childsKey:"childs"
	};
	this.init=function(options){
		var this_ = this;
		this.settings = $.extend({},this.defaultOptions,options);
		this.data = this.settings.data || [];
		this.uiIds = this.settings.uiIds || [];
		this.elements = new Array(this.uiIds.length);
		for(var i=0;i<this.uiIds.length;i++){
			var e = $("#"+this.uiIds[i]+":first");
			if(!e || e.size() == 0){
				app.showError({messages:["元素"+this.uiIds[i]+"不是下拉框！"]});
				return;
			}
			e.empty();
			$("<option value=''>请选择</option>").appendTo(e);
			e.change(function(){
				this_.clearSub(this.id);
				this_.updateSub(this.id);
	    	});
			this.elements[i] = e;
		}
		
		this.loadData2UI(0);
    	
    	if(this.settings.defaultValues){
    		for(var i=0;i<this.settings.defaultValues.length;i++){
    			//TODO ie下有问题
    			//this.elements[i].val(this.settings.defaultValues[i]).change();
    		}
    	}
	};
	this.loadData2UI=function(uiIndex){
		if(uiIndex+1>this.uiIds.length) return;
		var index = uiIndex || 0;
		var data = (index>0)?this.dataMap[this.uiIds[index-1]+this.elements[index-1].val()]:this.data;
		if(!data) return;
		var e = this.elements[uiIndex];
		e.empty();
		$("<option value=''>请选择</option>").appendTo(e);
		for(var i=0;i<data.length;i++){
    		var key = data[i][this.settings.nameKey];
    		var value = data[i][this.settings.valueKey];
            $("<option value='" + value + "'>" + key + "</option>").appendTo(e);
            this.dataMap[this.uiIds[uiIndex]+value]=data[i][this.settings.childsKey];
        }
	};
	this.updateSub=function(id){
		var index = this.uiIds.indexOf(id);
		this.loadData2UI(index+1);
	};
	this.clearSub=function(id){
		var index = this.uiIds.indexOf(id)+1;
		for(;index<this.uiIds.length;index++){
			var e = this.elements[index];
			e.empty();
			$("<option value=''>请选择</option>").appendTo(e);
		}
	}
	this.init(options);
};

app.geoHelper = {
	getGeoName: function(geoId){
		if(typeof geoJson == "undefined"){
			//alert("未装载geo数据！");
			return "";
		}
		if(typeof geoId  == "undefined" || !geoId){
			//alert("未指定geoId！");
			return "";
		}
		if(geoId.length == 5) return geoJson[geoId].geoName;
		if(geoId.length == 7){
			var princeGeoId = geoId.substring(0,5);
			return geoJson[princeGeoId].children[geoId].geoName;
		}
		if(geoId.length == 9){
			var princeGeoId = geoId.substring(0,5);
			var cityGeoId = geoId.substring(0,7);
			return geoJson[princeGeoId].children[cityGeoId].children[geoId].geoName;
		}
		return "";
	}
};

Date.prototype.pattern=function(fmt) {     
    var o = {     
    "M+" : this.getMonth()+1, //月份     
    "d+" : this.getDate(), //日     
    "h+" : this.getHours()%12 == 0 ? 12 : this.getHours()%12, //小时     
    "H+" : this.getHours(), //小时     
    "m+" : this.getMinutes(), //分     
    "s+" : this.getSeconds(), //秒     
    "q+" : Math.floor((this.getMonth()+3)/3), //季度     
    "S" : this.getMilliseconds() //毫秒     
    };     
    var week = {     
    "0" : "/u65e5",     
    "1" : "/u4e00",     
    "2" : "/u4e8c",     
    "3" : "/u4e09",     
    "4" : "/u56db",     
    "5" : "/u4e94",     
    "6" : "/u516d"    
    };     
    if(/(y+)/.test(fmt)){     
        fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));     
    }     
    if(/(E+)/.test(fmt)){     
        fmt=fmt.replace(RegExp.$1, ((RegExp.$1.length>1) ? (RegExp.$1.length>2 ? "/u661f/u671f" : "/u5468") : "")+week[this.getDay()+""]);     
    }     
    for(var k in o){     
        if(new RegExp("("+ k +")").test(fmt)){     
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));     
        }     
    }     
    return fmt;     
};

jQuery.cookie = function (key, value, options) {
    if (arguments.length > 1 && (value === null || typeof value !== "object")) {
        options = jQuery.extend({}, options);
        if (value === null) {
            options.expires = -1;
        }
        if (typeof options.expires === 'number') {
            var days = options.expires, t = options.expires = new Date();
            t.setDate(t.getDate() + days);
        }
        return (document.cookie = [
            encodeURIComponent(key), '=',
            options.raw ? String(value) : encodeURIComponent(String(value)),
            options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
            options.path ? '; path=' + options.path : '',
            options.domain ? '; domain=' + options.domain : '',
            options.secure ? '; secure' : ''
        ].join(''));
    }
    options = value || {};
    var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
    return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
};
//添加ie []的indexOf功能
if(!Array.indexOf){ 
    Array.prototype.indexOf = function(obj){                
        for(var i=0; i<this.length; i++){ 
            if(this[i]==obj){ 
                return i; 
            } 
        } 
        return -1; 
    } 
};
app.test = function(){
	
};

//扩展jquey Jquery 将表单序列化为Json对象
(function($){
	$.fn.serializeJson=function(){
		var serializeObj={};
		var array=this.serializeArray();
		var str=this.serialize();
		$(array).each(function(){
			if(serializeObj[this.name]){
				if($.isArray(serializeObj[this.name])){
					serializeObj[this.name].push(this.value);
				}else{
					serializeObj[this.name]=[serializeObj[this.name],this.value];
				}
			}else{
				serializeObj[this.name]=this.value;	
			}
		});
		return serializeObj;
	};
})(jQuery);


(function($) {
	$.fmatter = {};
	// opts can be id:row id for the row, rowdata:the data for the row,
	// colmodel:the column model for this column
	// example {id:1234,}
	$.fn.fmatter = function(formatType, cellval, opts, rwd, act) {
		// debug(this);
		// debug(cellval);
		// build main options before element iteration
		opts = $.extend({}, $.jgrid.formatter, opts);
		return fireFormatter(formatType, cellval, opts, rwd, act);
	};
	$.fmatter.util = {
		// Taken from YAHOO utils
		NumberFormat : function(nData, opts) {
			if (!isNumber(nData)) {
				nData *= 1;
			}
			if (isNumber(nData)) {
				var bNegative = (nData < 0);
				var sOutput = nData + "";
				var sDecimalSeparator = (opts.decimalSeparator) ? opts.decimalSeparator
						: ".";
				var nDotIndex;
				if (isNumber(opts.decimalPlaces)) {
					// Round to the correct decimal place
					var nDecimalPlaces = opts.decimalPlaces;
					var nDecimal = Math.pow(10, nDecimalPlaces);
					sOutput = Math.round(nData * nDecimal) / nDecimal + "";
					nDotIndex = sOutput.lastIndexOf(".");
					if (nDecimalPlaces > 0) {
						// Add the decimal separator
						if (nDotIndex < 0) {
							sOutput += sDecimalSeparator;
							nDotIndex = sOutput.length - 1;
						}
						// Replace the "."
						else if (sDecimalSeparator !== ".") {
							sOutput = sOutput.replace(".", sDecimalSeparator);
						}
						// Add missing zeros
						while ((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
							sOutput += "0";
						}
					}
				}
				if (opts.thousandsSeparator) {
					var sThousandsSeparator = opts.thousandsSeparator;
					nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
					nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
					var sNewOutput = sOutput.substring(nDotIndex);
					var nCount = -1;
					for ( var i = nDotIndex; i > 0; i--) {
						nCount++;
						if ((nCount % 3 === 0) && (i !== nDotIndex)
								&& (!bNegative || (i > 1))) {
							sNewOutput = sThousandsSeparator + sNewOutput;
						}
						sNewOutput = sOutput.charAt(i - 1) + sNewOutput;
					}
					sOutput = sNewOutput;
				}
				// Prepend prefix
				sOutput = (opts.prefix) ? opts.prefix + sOutput : sOutput;
				// Append suffix
				sOutput = (opts.suffix) ? sOutput + opts.suffix : sOutput;
				return sOutput;

			} else {
				return nData;
			}
		},
		// Tony Tomov
		// PHP implementation. Sorry not all options are supported.
		// Feel free to add them if you want
		DateFormat : function(format, date, newformat, opts) {
			var token = /\\.|[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]/g, timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g, pad = function(
					value, length) {
				value = String(value);
				length = parseInt(length, 10) || 2;
				while (value.length < length) {
					value = '0' + value;
				}
				return value;
			}, ts = {
				m : 1,
				d : 1,
				y : 1970,
				h : 0,
				i : 0,
				s : 0,
				u : 0
			}, timestamp = 0, dM, k, hl, dateFormat = [ "i18n" ];
			// Internationalization strings
			dateFormat["i18n"] = {
				dayNames : opts.dayNames,
				monthNames : opts.monthNames
			};
			if (format in opts.masks) {
				format = opts.masks[format];
			}
			if (date.constructor === Date) {
				timestamp = date;
			} else {
				date = date.split(/[\\\/:_;.\t\T\s-]/);
				format = format.split(/[\\\/:_;.\t\T\s-]/);
				// parsing for month names
				for (k = 0, hl = format.length; k < hl; k++) {
					if (format[k] == 'M') {
						dM = $.inArray(date[k], dateFormat.i18n.monthNames);
						if (dM !== -1 && dM < 12) {
							date[k] = dM + 1;
						}
					}
					if (format[k] == 'F') {
						dM = $.inArray(date[k], dateFormat.i18n.monthNames);
						if (dM !== -1 && dM > 11) {
							date[k] = dM + 1 - 12;
						}
					}
					if (date[k]) {
						ts[format[k].toLowerCase()] = parseInt(date[k], 10);
					}
				}
				ts.m = parseInt(ts.m, 10) - 1;
				var ty = ts.y;
				if (ty >= 70 && ty <= 99) {
					ts.y = 1900 + ts.y;
				} else if (ty >= 0 && ty <= 69) {
					ts.y = 2000 + ts.y;
				}
				timestamp = new Date(ts.y, ts.m, ts.d, ts.h, ts.i, ts.s, ts.u);
			}

			if (newformat in opts.masks) {
				newformat = opts.masks[newformat];
			} else if (!newformat) {
				newformat = 'Y-m-d';
			}
			var G = timestamp.getHours(), i = timestamp.getMinutes(), j = timestamp
					.getDate(), n = timestamp.getMonth() + 1, o = timestamp
					.getTimezoneOffset(), s = timestamp.getSeconds(), u = timestamp
					.getMilliseconds(), w = timestamp.getDay(), Y = timestamp
					.getFullYear(), N = (w + 6) % 7 + 1, z = (new Date(Y,
					n - 1, j) - new Date(Y, 0, 1)) / 86400000, flags = {
				// Day
				d : pad(j),
				D : dateFormat.i18n.dayNames[w],
				j : j,
				l : dateFormat.i18n.dayNames[w + 7],
				N : N,
				S : opts.S(j),
				// j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1)
				// % 10, 3)] : 'th',
				w : w,
				z : z,
				// Week
				W : N < 5 ? Math.floor((z + N - 1) / 7) + 1 : Math
						.floor((z + N - 1) / 7)
						|| ((new Date(Y - 1, 0, 1).getDay() + 6) % 7 < 4 ? 53
								: 52),
				// Month
				F : dateFormat.i18n.monthNames[n - 1 + 12],
				m : pad(n),
				M : dateFormat.i18n.monthNames[n - 1],
				n : n,
				t : '?',
				// Year
				L : '?',
				o : '?',
				Y : Y,
				y : String(Y).substring(2),
				// Time
				a : G < 12 ? opts.AmPm[0] : opts.AmPm[1],
				A : G < 12 ? opts.AmPm[2] : opts.AmPm[3],
				B : '?',
				g : G % 12 || 12,
				G : G,
				h : pad(G % 12 || 12),
				H : pad(G),
				i : pad(i),
				s : pad(s),
				u : u,
				// Timezone
				e : '?',
				I : '?',
				O : (o > 0 ? "-" : "+")
						+ pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o)
								% 60, 4),
				P : '?',
				T : (String(timestamp).match(timezone) || [ "" ]).pop()
						.replace(timezoneClip, ""),
				Z : '?',
				// Full Date/Time
				c : '?',
				r : '?',
				U : Math.floor(timestamp / 1000)
			};
			return newformat.replace(token, function($0) {
				return $0 in flags ? flags[$0] : $0.substring(1);
			});
		}
	};
	$.fn.fmatter.defaultFormat = function(cellval, opts) {
		return (isValue(cellval) && cellval !== "") ? cellval
				: opts.defaultValue ? opts.defaultValue : "&#160;";
	};
	$.fn.fmatter.email = function(cellval, opts) {
		if (!isEmpty(cellval)) {
			return "<a href=\"mailto:" + cellval + "\">" + cellval + "</a>";
		} else {
			return $.fn.fmatter.defaultFormat(cellval, opts);
		}
	};
	$.fn.fmatter.checkbox = function(cval, opts) {
		var op = $.extend({}, opts.checkbox), ds;
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend({}, op, opts.colModel.formatoptions);
		}
		if (op.disabled === true) {
			ds = "disabled";
		} else {
			ds = "";
		}
		if (isEmpty(cval) || isUndefined(cval)) {
			cval = $.fn.fmatter.defaultFormat(cval, op);
		}
		cval = cval + "";
		cval = cval.toLowerCase();
		var bchk = cval.search(/(false|0|no|off)/i) < 0 ? " checked='checked' "
				: "";
		return "<input type=\"checkbox\" " + bchk + " value=\"" + cval
				+ "\" offval=\"no\" " + ds + "/>";
	};
	$.fn.fmatter.link = function(cellval, opts) {
		var op = {
			target : opts.target
		};
		var target = "";
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend({}, op, opts.colModel.formatoptions);
		}
		if (op.target) {
			target = 'target=' + op.target;
		}
		if (!isEmpty(cellval)) {
			return "<a " + target + " href=\"" + cellval + "\">" + cellval
					+ "</a>";
		} else {
			return $.fn.fmatter.defaultFormat(cellval, opts);
		}
	};
	$.fn.fmatter.showlink = function(cellval, opts) {
		var op = {
			baseLinkUrl : opts.baseLinkUrl,
			showAction : opts.showAction,
			addParam : opts.addParam || "",
			target : opts.target,
			idName : opts.idName
		}, target = "", idUrl;
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend({}, op, opts.colModel.formatoptions);
		}
		if (op.target) {
			target = 'target=' + op.target;
		}
		idUrl = op.baseLinkUrl + op.showAction + '?' + op.idName + '='
				+ opts.rowId + op.addParam;
		if (isString(cellval)) { // add this one even if its blank string
			return "<a " + target + " href=\"" + idUrl + "\">" + cellval
					+ "</a>";
		} else {
			return $.fn.fmatter.defaultFormat(cellval, opts);
		}
	};
	$.fn.fmatter.integer = function(cellval, opts) {
		var op = $.extend({}, opts.integer);
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend({}, op, opts.colModel.formatoptions);
		}
		if (isEmpty(cellval)) {
			return op.defaultValue;
		}
		return $.fmatter.util.NumberFormat(cellval, op);
	};
	$.fn.fmatter.number = function(cellval, opts) {
		var op = $.extend({}, opts.number);
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend({}, op, opts.colModel.formatoptions);
		}
		if (isEmpty(cellval)) {
			return op.defaultValue;
		}
		return $.fmatter.util.NumberFormat(cellval, op);
	};
	$.fn.fmatter.currency = function(cellval, opts) {
		var op = $.extend({}, opts.currency);
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend({}, op, opts.colModel.formatoptions);
		}
		if (isEmpty(cellval)) {
			return op.defaultValue;
		}
		return $.fmatter.util.NumberFormat(cellval, op);
	};
	$.fn.fmatter.date = function(cellval, opts, rwd, act) {
		var op = $.extend({}, opts.date);
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend({}, op, opts.colModel.formatoptions);
		}
		if (!op.reformatAfterEdit && act == 'edit') {
			return $.fn.fmatter.defaultFormat(cellval, opts);
		} else if (!isEmpty(cellval)) {
			return $.fmatter.util.DateFormat(op.srcformat, cellval,
					op.newformat, op);
		} else {
			return $.fn.fmatter.defaultFormat(cellval, opts);
		}
	};
	$.fn.fmatter.select = function(cellval, opts, rwd, act) {
		// jqGrid specific
		cellval = cellval + "";
		var oSelect = false, ret = [];
		if (!isUndefined(opts.colModel.editoptions)) {
			oSelect = opts.colModel.editoptions.value;
		}
		if (oSelect) {
			var msl = opts.colModel.editoptions.multiple === true ? true
					: false, scell = [], sv;
			if (msl) {
				scell = cellval.split(",");
				scell = $.map(scell, function(n) {
					return $.trim(n);
				});
			}
			if (isString(oSelect)) {
				// mybe here we can use some caching with care ????
				var so = oSelect.split(";"), j = 0;
				for ( var i = 0; i < so.length; i++) {
					sv = so[i].split(":");
					if (sv.length > 2) {
						sv[1] = jQuery.map(sv, function(n, i) {
							if (i > 0) {
								return n;
							}
						}).join(":");
					}
					if (msl) {
						if (jQuery.inArray(sv[0], scell) > -1) {
							ret[j] = sv[1];
							j++;
						}
					} else if ($.trim(sv[0]) == $.trim(cellval)) {
						ret[0] = sv[1];
						break;
					}
				}
			} else if (isObject(oSelect)) {
				// this is quicker
				if (msl) {
					ret = jQuery.map(scell, function(n, i) {
						return oSelect[n];
					});
				} else {
					ret[0] = oSelect[cellval] || "";
				}
			}
		}
		cellval = ret.join(", ");
		return cellval == "" ? $.fn.fmatter.defaultFormat(cellval, opts)
				: cellval;
	};
	$.fn.fmatter.rowactions = function(rid, gid, act, keys) {
		switch (act) {
		case 'edit':
			var restorerow = function() {
				$(
						"tr#" + rid + " div.ui-inline-edit, " + "tr#" + rid
								+ " div.ui-inline-del", "#" + gid).show();
				$(
						"tr#" + rid + " div.ui-inline-save, " + "tr#" + rid
								+ " div.ui-inline-cancel", "#" + gid).hide();
			};
			$('#' + gid).jqGrid('editRow', rid, keys, null, null, null, {
				oper : 'edit'
			}, restorerow, null, restorerow);
			$(
					"tr#" + rid + " div.ui-inline-edit, " + "tr#" + rid
							+ " div.ui-inline-del", "#" + gid).hide();
			$(
					"tr#" + rid + " div.ui-inline-save, " + "tr#" + rid
							+ " div.ui-inline-cancel", "#" + gid).show();
			break;
		case 'save':
			$('#' + gid).jqGrid('saveRow', rid, null, null);
			$(
					"tr#" + rid + " div.ui-inline-edit, " + "tr#" + rid
							+ " div.ui-inline-del", "#" + gid).show();
			$(
					"tr#" + rid + " div.ui-inline-save, " + "tr#" + rid
							+ " div.ui-inline-cancel", "#" + gid).hide();
			break;
		case 'cancel':
			$('#' + gid).jqGrid('restoreRow', rid);
			$(
					"tr#" + rid + " div.ui-inline-edit, " + "tr#" + rid
							+ " div.ui-inline-del", "#" + gid).show();
			$(
					"tr#" + rid + " div.ui-inline-save, " + "tr#" + rid
							+ " div.ui-inline-cancel", "#" + gid).hide();
			break;
		}
	};
	$.fn.fmatter.actions = function(cellval, opts, rwd) {
		var op = {
			keys : false,
			editbutton : true,
			delbutton : true
		};
		if (!isUndefined(opts.colModel.formatoptions)) {
			op = $.extend(op, opts.colModel.formatoptions);
		}
		var rowid = opts.rowId, str = "", ocl;
		if (typeof (rowid) == 'undefined' || isEmpty(rowid)) {
			return "";
		}
		if (op.editbutton) {
			ocl = "onclick=$.fn.fmatter.rowactions('" + rowid + "','"
					+ opts.gid + "','edit'," + op.keys + ");";
			str = str
					+ "<div style='margin-left:8px;'><div title='"
					+ $.jgrid.nav.edittitle
					+ "' style='float:left;cursor:pointer;' class='ui-pg-div ui-inline-edit' "
					+ ocl
					+ "><span class='ui-icon ui-icon-pencil'></span></div>";
		}
		if (op.delbutton) {
			ocl = "onclick=jQuery('#" + opts.gid + "').jqGrid('delGridRow','"
					+ rowid + "');";
			str = str
					+ "<div title='"
					+ $.jgrid.nav.deltitle
					+ "' style='float:left;margin-left:5px;' class='ui-pg-div ui-inline-del' "
					+ ocl
					+ "><span class='ui-icon ui-icon-trash'></span></div>";
		}
		ocl = "onclick=$.fn.fmatter.rowactions('" + rowid + "','" + opts.gid
				+ "','save',false);";
		str = str
				+ "<div title='"
				+ $.jgrid.edit.bSubmit
				+ "' style='float:left;display:none' class='ui-pg-div ui-inline-save'><span class='ui-icon ui-icon-disk' "
				+ ocl + "></span></div>";
		ocl = "onclick=$.fn.fmatter.rowactions('" + rowid + "','" + opts.gid
				+ "','cancel',false);";
		str = str
				+ "<div title='"
				+ $.jgrid.edit.bCancel
				+ "' style='float:left;display:none;margin-left:5px;' class='ui-pg-div ui-inline-cancel'><span class='ui-icon ui-icon-cancel' "
				+ ocl + "></span></div></div>";
		return str;
	};
	$.unformat = function(cellval, options, pos, cnt) {
		// specific for jqGrid only
		var ret, formatType = options.colModel.formatter, op = options.colModel.formatoptions
				|| {}, sep, re = /([\.\*\_\'\(\)\{\}\+\?\\])/g;
		unformatFunc = options.colModel.unformat
				|| ($.fn.fmatter[formatType] && $.fn.fmatter[formatType].unformat);
		if (typeof unformatFunc !== 'undefined' && isFunction(unformatFunc)) {
			ret = unformatFunc($(cellval).text(), options, cellval);
		} else if (typeof formatType !== 'undefined' && isString(formatType)) {
			var opts = $.jgrid.formatter || {}, stripTag;
			switch (formatType) {
			case 'integer':
				op = $.extend({}, opts.integer, op);
				sep = op.thousandsSeparator.replace(re, "\\$1");
				stripTag = new RegExp(sep, "g");
				ret = $(cellval).text().replace(stripTag, '');
				break;
			case 'number':
				op = $.extend({}, opts.number, op);
				sep = op.thousandsSeparator.replace(re, "\\$1");
				stripTag = new RegExp(sep, "g");
				ret = $(cellval).text().replace(stripTag, "").replace(
						op.decimalSeparator, '.');
				break;
			case 'currency':
				op = $.extend({}, opts.currency, op);
				sep = op.thousandsSeparator.replace(re, "\\$1");
				stripTag = new RegExp(sep, "g");
				ret = $(cellval).text().replace(stripTag, '').replace(
						op.decimalSeparator, '.').replace(op.prefix, '')
						.replace(op.suffix, '');
				break;
			case 'checkbox':
				var cbv = (options.colModel.editoptions) ? options.colModel.editoptions.value
						.split(":")
						: [ "Yes", "No" ];
				ret = $('input', cellval).attr("checked") ? cbv[0] : cbv[1];
				break;
			case 'select':
				ret = $.unformat.select(cellval, options, pos, cnt);
				break;
			case 'actions':
				return "";
			default:
				ret = $(cellval).text();
			}
		}
		return ret ? ret : cnt === true ? $(cellval).text() : $.jgrid
				.htmlDecode($(cellval).html());
	};
	$.unformat.select = function(cellval, options, pos, cnt) {
		// Spacial case when we have local data and perform a sort
		// cnt is set to true only in sortDataArray
		var ret = [];
		var cell = $(cellval).text();
		if (cnt === true) {
			return cell;
		}
		var op = $.extend({}, options.colModel.editoptions);
		if (op.value) {
			var oSelect = op.value, msl = op.multiple === true ? true : false, scell = [], sv;
			if (msl) {
				scell = cell.split(",");
				scell = $.map(scell, function(n) {
					return $.trim(n);
				});
			}
			if (isString(oSelect)) {
				var so = oSelect.split(";"), j = 0;
				for ( var i = 0; i < so.length; i++) {
					sv = so[i].split(":");
					if (msl) {
						if (jQuery.inArray(sv[1], scell) > -1) {
							ret[j] = sv[0];
							j++;
						}
					} else if ($.trim(sv[1]) == $.trim(cell)) {
						ret[0] = sv[0];
						break;
					}
				}
			} else if (isObject(oSelect)) {
				if (!msl) {
					scell[0] = cell;
				}
				ret = jQuery.map(scell, function(n) {
					var rv;
					$.each(oSelect, function(i, val) {
						if (val == n) {
							rv = i;
							return false;
						}
					});
					if (rv) {
						return rv;
					}
				});
			}
			return ret.join(", ");
		} else {
			return cell || "";
		}
	};
	$.unformat.date = function(cellval, opts) {
		var op = $.jgrid.formatter.date || {};
		if (!isUndefined(opts.formatoptions)) {
			op = $.extend({}, op, opts.formatoptions);
		}
		if (!isEmpty(cellval)) {
			return $.fmatter.util.DateFormat(op.newformat, cellval,
					op.srcformat, op);
		} else {
			return $.fn.fmatter.defaultFormat(cellval, opts);
		}
	};
	function fireFormatter(formatType, cellval, opts, rwd, act) {
		var v = cellval;

		if ($.fn.fmatter[formatType]) {
			v = $.fn.fmatter[formatType](cellval, opts, rwd, act);
		}

		return v;
	}
	//private methods and data
	function debug($obj) {
		if (window.console && window.console.log) {
			window.console.log($obj);
		}
	}
	/**
	 * A convenience method for detecting a legitimate non-null value.
	 * Returns false for null/undefined/NaN, true for other values,
	 * including 0/false/''
	 * --taken from the yui.lang
	 */
	isValue = function(o) {
		return (isObject(o) || isString(o) || isNumber(o) || isBoolean(o));
	};
	isBoolean = function(o) {
		return typeof o === 'boolean';
	};
	isNull = function(o) {
		return o === null;
	};
	isNumber = function(o) {
		return typeof o === 'number' && isFinite(o);
	};
	isString = function(o) {
		return typeof o === 'string';
	};
	/**
	 * check if its empty trim it and replace \&nbsp and \&#160 with '' and check if its empty ===""
	 * if its is not a string but has a value then it returns false, Returns true for null/undefined/NaN
	essentailly this provdes a way to see if it has any value to format for things like links
	 */
	isEmpty = function(o) {
		if (!isString(o) && isValue(o)) {
			return false;
		} else if (!isValue(o)) {
			return true;
		}
		o = $.trim(o).replace(/\&nbsp\;/ig, '').replace(/\&#160\;/ig, '');
		return o === "";

	};
	isUndefined = function(o) {
		return typeof o === 'undefined';
	};
	isObject = function(o) {
		return (o && (typeof o === 'object' || isFunction(o))) || false;
	};
	isFunction = function(o) {
		return typeof o === 'function';
	};

})(jQuery);

