datagrid

/**
* DataGrid widget
*
* @param appendTo   		{String}		element id which will be appended.
* @param target     		{HTMLELement}	data element.
* @param aData      		{Array}			[[],[],...,[]].
* @param aNames   	  		{Array}       	["name1", "name2",...].
* @param isEdit    			{Boolean}     	decide whether datagrid can be edited
* @param hasHeader  		{Boolean}
* @param headerCont 		{Array}
* @param hasTotal   		{Boolean}
* @param trEvent    		{JSON}        	ex. {event:function}.
* @param tdEvent    		{JSON}       	ex. {event:function}.
* @param tdUnbind  	 		{Array}      	the cell index which event do not bind.
* @param zebras    			{JSON}        	tr css.
* @param norTrCss   		{JSON}        	tr css.
* @param curTrCss   		{JSON}        	tr css.
* @param align      		{String} 	  	td align.
* @param editPos    		{String} 	  	row edit area position.
* @param editBtns    		{Array}       	array of edit buttons.
* @param editBtnHandler 	{Array}    	 	event function of edit buttons. ex.[{event1:function}, {event1:function},...].
* @param deleteBtnCss    	{String}  		default delete button style.
* @param deleteRowCallback 	{Function} 		delete callback function.
* @param batchBarPos 		{String} 		batch bar position
* @param batchBtns 			{Array} 		array of batch buttons
* @param batchBtnHandler 	{Array} 		the same with editBtnHandler
* @param selectAllCss 		{String} 		the style of select all checkbox
* @param batchDeleteCss  	{String}  		default batch delete button style.
* @param batchDeleteCallback{Function} 		batch delete callback function.
*
*/
var datagrid = function(params, undefined){
	this.options = {
		appendTo:"",
		target:"",
		
		//data and post names
		aData:[],
		aNames:[],
		
		
		isEdit:true,
		
		//header and total handler
		hasHeader:false,
		headerCont:[],
		hasTotal:false,
		//totalCells:[],
		//totalHandler:{},
		
		//td event
		trEvent:{},
		tdEvent:{},	
		tdUnbind:[],
		
		//tr css
		zebras:{background:"#d4e4ff"},
		norTrCss:{background:""},
		curTrCss:{background:"#dddddd"},
		
		align:"center",
		
		//edit area
		editPos:"right",		
		editBtns:[],
		editBtnHandler:[],
		deleteBtnCss:"",
		deleteRowCallback:function(){},
		
		
		
		//batch area
		batchBarPos:"top",
		batchBtns:[],
		batchBtnHandler:[],
		selectAllCss:"",
		batchDeleteCss:"",
		batchDeleteCallback:function(){}
		
	};
	
	wapi.extend(this.options, params);
	
	
	if(this.options.appendTo != "" && document.getElementById(this.options.appendTo)) wapi("#" + this.options.appendTo).append(this.options.target);
	else if(this.options.target == ""){
		this.options.target =  wapi("<table>").attr({cellspacing:0, cellpadding:0})[0];
		wapi("body").append(this.options.target);
	}
	
	//default edit button and handler
	this.editBtns = [wapi("<a>").html("DELETE").attr("style", this.options.deleteBtnCss)];
	this.editBtnHandler = [{click:function(){
			if(this.datagrid.block) return; //block edit mode
		
			wapi(this.tr).remove();
			
			this.datagrid.block = false;
			
			this.datagrid.options.deleteRowCallback.apply(this, arguments);
		}
	}];
	
	//default batch button and handlers
	this.batchBtns = [wapi("<input>").attr({type:"checkbox", name:"selectAll"}).attr("style", this.options.selectAllCss), wapi("<a>").html("DELETE").attr("style", this.options.batchDeleteCss)];
	this.batchBtnHandler = [
		{
			click:function(){
				var chkBox = this.datagrid.getChkbox();
				
				function set(chk){
					wapi.each(chkBox.chkBox, function(i, elem){
						elem.checked = chk;
					});
				}
				
				if(chkBox.chkBox.length > 0) set(!(chkBox.selectAllBox.checked == false));
				
			}
		},
	
		{
			click:function(){
				if(this.datagrid.block) return; //block edit mode
				
				if(this.tr.length > 0){
					var chkBox = this.datagrid.getChkbox(true);
					chkBox.selectAllBox.checked = false;
				}
				
				wapi.each(this.tr, function(i, elem){
					wapi(this).remove();
				});
				
				this.datagrid.block = false;
				
				this.datagrid.options.batchDeleteCallback.apply(this, arguments);
			}
		}
	];
	
	//handler array
	this.curTr = [];
	this.curTd = [];
	
	//edit block	
	this.block = false;
	
	this.cellsNum = 0;
	
	this.init();
};
datagrid.prototype = {
	init:function(){
		this.createHeader();
		
		if(this.options.isEdit) {
			this.bindBtnHandler(this.batchBtns.concat(this.options.batchBtns), this.batchBtnHandler.concat(this.options.batchBtnHandler), this.batchBar = wapi(this.options.target.insertRow((this.options.batchBarPos === "bottom" ? this.options.target.rows.length : 0)).insertCell(0)).attr({colspan:this.cellsNum}));
		}
		
		var add = wapi.bindScope(this, this.add);
		
		wapi.each(this.options.aData, function(index, dataItem){
			if(dataItem.length > 0) add(dataItem);
		});		
	},
	
	createHeader:function(){
		if(this.options.hasHeader){
			if(this.options.headerCont.length > 0) {
				var tr = this.options.target.insertRow(0);
				this.setCellsNum(this.options.headerCont);
				for(var i=0; i<this.cellsNum; i++){
					if(i == this.cellsNum -1 && this.options.isEdit){
						if(this.options.editPos == "left") tr.insertCell(1);
						else tr.insertCell(i);
					}else wapi(tr.insertCell(i)).html(this.options.headerCont[i]);
					
				}
			}else{
				this.setCellsNum(this.options.aData[0]);
				var tr = this.options.target.rows[0];
				if(this.options.isEdit){
					if(this.options.editPos == "left") tr.insertCell(1);
					else tr.insertCell(tr.cells.length);
				}
			}
		}
	},
	
	setCellsNum:function(aData){
		//if(this.cellsNum != 0) return;
		
		if(!!aData) this.cellsNum = aData.length > 0 ? this.options.isEdit ? aData.length + 1 : aData.length : 0;
		
		if(typeof this.headerCellsNum === "undefined" && this.options.hasHeader) this.headerCellsNum = this.options.isEdit ? this.options.target.rows[0].cells.length + 1 : this.options.target.rows[0].cells.length;
		
		this.cellsNum = Math.max(this.headerCellsNum, this.cellsNum);
	},
	
	bindBtnHandler:function(aElem, aFn, target, source){
		var getSelected = wapi.bindScope(this, this.getSelected);
		var bindTrEvent = wapi.bindScope(this, this.bindTrEvent);
		
		wapi.each(aElem, function(i, btn){
			btn = wapi(btn[0].cloneNode(true));
			if(!!aFn[i] && !wapi.isEmptyObject(aFn[i])){
				wapi.each(aFn[i], function(pro, fn){
					target.append(
						btn[pro](function(){
							fn.apply(getSelected(source), arguments);
							bindTrEvent();
						})
					);
				});
			}else target.append(btn);
		});
	},
	
	bindTdEvent:function(td, fn, event){
		var datagrid = {
			td:td,
			datagrid:this
		};
		
		this.curTd = td;
		
		this.cancelBubble(event);
		
		if(!this.options.isEdit) return;
		if(!this.block)	fn.call(datagrid, event);
	},
	
	bindTrEvent:function(tr){
		var target = this.options.target;
		var isEdit = this.options.isEdit;
		var hasTotal = this.options.hasTotal;
		var hasHeader = this.options.hasHeader;
		
		var mouseOver = wapi.bindScope(this, function(tr){
			if(!this.block) wapi(tr).css(this.options.curTrCss);
		});
					
		var norMouseout = wapi.bindScope(this, function(tr){
			wapi(tr).css(this.options.norTrCss);
		});
		
		var zebrasMouseout = wapi.bindScope(this, function(tr){
			wapi(tr).css(this.options.zebras);
		})
		
		var bindMouseEvent = wapi.bindScope(this, function(a, tr){
			if(a) tr.css(this.options.zebras).mouseout(function(){zebrasMouseout(this)});
			else tr.mouseout(function(){norMouseout(this)});
			
			tr.mouseover(function(){
				mouseOver(this);
			});
		});
		
		var setEvent = wapi.bindScope(this, function(tr){
			var index = tr.rowIndex;
			
			tr = wapi(tr);
			
			tr.css(this.options.norTrCss);
			
			switch(this.options.batchBarPos)
			{
				case "bottom":
					if(isEdit && index == target.rows.length - 1) return;
					if(isEdit && index == 0 && hasHeader) return;
					if(hasTotal && ((isEdit && index == target.rows.length - 2) || (!isEdit && index == target.rows.length - 1))) return;
					
					bindMouseEvent(index%2 != 0, tr);
					
					break;
				case "top":
					if(isEdit && index == 0) return;
					if(isEdit && index == 1 && hasHeader) return;
					if(hasTotal && index == target.rows.length - 1) return;
					
					bindMouseEvent(index%2 == 0, tr);
					break;
			}
		});
		
		if(tr) {
			setEvent(tr);
			this.curTr = tr;
		} else {
			var _target = wapi(this.options.target);
			if(_target.child("tbody").length > 0) _target = _target.child("tbody");
			
			_target.child("tr").each(function(i, tr){
				setEvent(tr);
			});
		}
	},
	
	update:function(aData){
		var index = 0;
		var endIndex = 0;
		
		if(this.block) return;
		
		if(this.options.hasHeader){
			if(this.options.isEdit && this.options.batchBarPos == "top") index = 2;
			else index = 1;
		}else if(this.options.isEdit && this.options.batchBarPos == "top") index = 1;
		
		if(this.options.hasTotal ){
			if(this.options.isEdit && this.options.batchBarPos == "bottom") endIndex = 2;
			else endIndex = 1;
		}else if(this.options.isEdit && this.options.batchBarPos == "bottom") endIndex = 1;
		
		while(this.options.target.rows.length > index + endIndex){
			this.options.target.deleteRow(index);
		}
		
		this.options.aData = aData;
		
		var add = wapi.bindScope(this, this.add);
		
		wapi.each(this.options.aData, function(index, dataItem){
			if(dataItem.length > 0) add(dataItem);
		});	
		
		this.resetSelectAll();
	},
	
	add:function(aData){
		var target = this.options.target;
		var tick = this.options.isEdit && this.options.batchBarPos === "bottom" ? 1 : 0;
		var index = this.options.hasTotal ? target.rows.length - 1 - tick : target.rows.length - tick;
		var tr = target.insertRow(index);
		this.bindTrEvent(tr);
		
		this.items(tr, aData, this.options.aNames);
		
		wapi(tr).css("opacity", 0).animate({opacity:"=1"}, 300);
		
		this.resetSelectAll();
	},
	
	items:function(tr, aData, aNames){
		var bindTdEvent = wapi.bindScope(this, this.bindTdEvent);
		
		if(this.cellsNum === 0) {
			this.setCellsNum(aData);
			if(this.options.isEdit && this.batchBar.attr("colspan") == 0) this.batchBar.attr("colspan", this.cellsNum);
		}
		
		for(var i = 0; i < this.cellsNum; i++){
			(function(i, datagrid){
				var td = tr.insertCell(i);
				var name = typeof aNames[i] !== "undefined" ? aNames[i] : "";
				var data = aData[i];
				
				td.align = datagrid.options.align;
				td.data = wapi("<input>").attr({name:name, type:"hidden", value:data});
				
				if(datagrid.options.isEdit){
					if(i == 0) {
						var chkBox = datagrid.getChkbox();
						wapi(td).append(wapi("<input>").attr({type:"checkbox", name:name, value:data})).append(td.data).click(function(){
							chkBox.selectAllBox.checked = false;
						}); //for batch edit
						return;
					}
					else if(i == datagrid.cellsNum - 1){
						if(datagrid.options.editPos === "left") td = tr.insertCell(1);
						datagrid.bindBtnHandler(datagrid.editBtns.concat(datagrid.options.editBtns), datagrid.editBtnHandler.concat(datagrid.options.editBtnHandler), wapi(td), td);
						return;
					}
				}
				
				if(typeof data === "undefined" || data == "" || data == 0 || data == "disabled" || data == "none") td.innerHTML = "-";//no data					
				else {
					wapi(td).html(data).append(td.data);
					
					var isBind = true;
					if(datagrid.options.tdUnbind.length > 0) wapi.each(datagrid.options.tdUnbind, function(i, index){
						if(td.cellIndex == index) isBind = false;
					});
					if(isBind && !wapi.isEmptyObject(datagrid.options.tdEvent)) wapi.each(datagrid.options.tdEvent, function(pro, fn){
						wapi(td)[pro](function(event){
							bindTdEvent(this, fn, event);
						});
					});
				}
			})(i, this)
		}
		return tr;
	},
				
	getSelected:function(elem){
		var curTr = [];
		var curTd = [];
		var datagridObject = this;
		var getIt = wapi.bindScope(this, this.getIt);
		
		if(elem !== undefined && elem){
			var aSelect = this.getIt(elem);
			curTr = aSelect.tr;
			curTd = aSelect.td;
		}else{
			wapi.each(this.getChkbox(true).chkBox, function(i, elem){
				curTr.push(getIt(elem).tr);
			});
		}
		
		this.curTr = curTr;
		this.curTd = curTd
		
		return {
			tr:curTr,
			td:curTd,
			datagrid:datagridObject
		}
	},
	
	resetSelectAll:function(){
		var chkbox = this.getChkbox();
		if(this.options.isEdit) chkbox.selectAllBox.checked = false;
	},
	
	getIt:function(elem){
		var _tr, _td;
		while(elem){
			if(elem.tagName === "TR"){
				_tr = elem;
				break;
			}
			if(elem.tagName === "TD") _td = elem;
			elem = elem.parentNode;
		}
		
		return{
			tr:_tr,
			td:_td
		}
	},
/*
* get checkbox
* 
* @param filter {Boolean}	filter checkbox
*
* return {JSON}
*/
	getChkbox:function(filter){
		var inputs = this.options.target.getElementsByTagName("input");
		var selectAllBox = [];
		var chkBox = [];
		
		if(typeof filter !== "undefined") wapi.each(inputs, function(i, elem){
			if(wapi(elem).attr("type") === "checkbox"){
				if(wapi(elem).attr("name") === "selectAll") selectAllBox = elem;
				else if(elem.checked == filter) chkBox.push(elem);
			}
		});
		else  wapi.each(inputs, function(i, elem){
			if(wapi(elem).attr("type") === "checkbox" ) {
				if(wapi(elem).attr("name") === "selectAll") selectAllBox = elem;
				else chkBox.push(elem);
			}
		});
		
		return {
			chkBox:chkBox,
			selectAllBox:selectAllBox
		}
	},
	
	cancelBubble:function(e){
		e = e || window.event;
		window.event ? e.cancelBubble = true : e.stopPropagation();
	}
};

test page:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>data grid</title>
<script src="wishfi.js" type="text/javascript"></script>
<script src="dataGrid.js" type="text/javascript"></script>
</head>

<body>
<input id="minimum_impression" name="" type="text">
<div style="width:660px;">
<table  id="categoryData" width="100%" border="0" cellspacing="0" cellpadding="3">
  <tbody>
    <tr>
        <th width="30"></th>
        <th width="180">Category Name</th>
        <th width="170">Impressions Budget</th>
        <th width="170">Percentage(%)</th>
    </tr>
    <tr> 
        <th width="30"> </th> 
        <th width="180">total</th> 
        <th width="170" id="impressionTotal">0</th> 
        <th width="170" id="percentTotal">0%</th> 
    </tr>
  </tbody>
</table>
<div id="addCategory" style="position:relative; height:27px; overflow:hidden;">
    <table cellspacing="0" cellpadding="3" border="0" width="100%"  style="position:absolute; top:-35px;">
        <tbody>
            <tr>
                <td width="30"> </td>
                <td align="center" width="180" valign="middle">
                <select style="height: 18px; width: 130px; display: block;" name="category" class="category" id="category">
                <option selected="" value="">Choose an category</option>
                <option value="1">	TELECO NETWK,FIXED&MOBILEPHONE</option><option value="2">INTERNET SP/ PORTAL ALL</option><option value="3">BANKING/FINANCE</option><option value="4">AIRLINES</option><option value="5">GOVT SVCS (STAT BOARD,GOVT CAMPAIGN)</option><option value="6">CREDIT/CHARGE/DEBIT CARD/TRAVEL</option><option value="7">MOVIE</option><option value="8">INSURANCE</option><option value="9">LOTTERIES/COMPETITIONS</option><option value="10">HOTELS/RESORTS</option><option value="11">PHOTOGRAPHIC</option><option value="12">HAIR CARE PRODUCTS</option><option value="13">FASTFOOD OUTLETS</option><option value="14">EDUCATION (OTHERS)</option><option value="15">BEAUTY & FITNESS SVCS</option><option value="16">TRAVEL AGENCIES/TOURIST COMMIS</option><option value="17">ALL CARS + MOTORING</option><option value="18">SPORTS/GYM EQUIPMENT/SPORTS CTR/CLUB</option><option value="19">PC/NOTEBOOK/TABLET PC/SERVER/N</option><option value="20">SKIN CARE PRODUCTS</option><option value="21">OPTICALS</option><option value="22">FREIGHT/LOGISTICS/COURIER/SHIP</option><option value="23">EVENTS/ CONCERTS/ EXHIBTIONS ALL</option><option value="24">TELEVISION</option><option value="25">INVESTMENT/FUNDS</option><option value="26">CONFECTIONARY ALL</option><option value="27">BEER & STOUT ALL</option><option value="28">SUPER/HYPER/MINI MARKET/FOOD STORES</option><option value="29">PERFUME/COLOGNE</option><option value="30">AUDIO VISUAL EQUIPMENT</option>                                            </select>
                </td>
                <td align="center" width="170" valign="middle"><input type="text" style="width: 130px; text-align: center;" id="impressions" name="impressions_temp[]" class="impressions[]" value=""></td>
                <td align="center"  width="170" valign="middle"><input type="text" style="width: 130px; text-align: center;" id="percentage" name="percentage_temp[]" class="percentage[]" value=""></td>
                <td align="center" width="">
                <a id="upload">upload</a>  <a id="exitAdd">exit</a>
                </td>
            </tr>
        </tbody>
    </table>
</div>
</div>
<script>
(function(){

/**
* init category datagrid
*
*/
var categoryData = new datagrid({
	target:wapi("#categoryData")[0],
	aData:[
		[3, "a", "10"],
		[4, "b", "10"]
	],
	aNames:["category_id[]", "category_name[]", "impressions[]", "percentage[]"],
	
	isEdit:true,
	hasHeader:true,
	hasTotal:true,
	
	//row edit
	deleteRowCallback:function(){
		deleteTotal(this.tr);
	},
	
	//batch handler area
	selectAllCss:"margin:0 9px; padding:0;",
	batchBarPos:"bottom",
	batchDeleteCallback:function(){
		wapi.each(this.tr, function(i, tr){
			deleteTotal(tr);
		})
	},
	batchBtns:[
		wapi("<input>").attr({type:"button", value:"add"})
	],
	batchBtnHandler:[
		{
			click:function(){			
				if(!this.datagrid.block) wapi("#addCategory").child("table").animate({top:"=0"}, 300);
				this.datagrid.block = true; //enter edit mode
				
				var i = 0;
				if(categoryData.options.isEdit) i++;
				if(categoryData.options.hasTotal) i++;
				if(categoryData.options.hasHeader) i++;
				if(categoryData.options.target.rows.length == i) {
					impressions.attr("value", "").css("color", "")[0].removeAttribute("disabled");
					percentage.attr("value", "").css("color", "")[0].removeAttribute("disabled");
				}
				
				var exitAdd = wapi.bindScope(this, function(){
					wapi("#addCategory").child("table").animate({top:"=-35"}, 300);
					
					hidErro(category[0]);
					hidErro(impressions[0]);
					hidErro(percentage[0]);
										
					this.datagrid.block = false; //exit edit mode
				});
				
				wapi("#exitAdd").click(exitAdd);
			}
		}
	],
	
	tdUnbind:[1],
	tdEvent:{
		click:editCell
	}
});

var categoryReg = {
	reg:/^[1-9]\d*$|^[0]\d+$/i,
	msg:"Integer required."
}

var emptyFN = function(){};

var upload = wapi("#upload");

var category = wapi("#category").change(function(){
	chkData({
		reg:/^[1-9]\d*$|^[0]\d+$/i,
		msg:"Select a category."
	}, this);
});

var impressions = wapi("#impressions").keyup(function(){
	keyuphandler(impressions, percentage);
});

var percentage = wapi("#percentage").keyup(function(){
	keyuphandler(percentage, impressions);
});

initTotal();

/*total handler*/

function initTotal(){
	var percentageTotal = 0
	var impressionsTotal = 0;
	
	function disabled(elem){
		elem.attr({value:"disabled", disabled:"disabled"}).css("color", "#cccccc");
	}
	
	wapi.each(categoryData.options.target.rows, function(i, tr){
		wapi.each(tr.cells, function(i, td){
			if(typeof td.data !== "undefined"){
				var input = td.data
				var name = input.attr("name");
				var value = parseFloat(input.attr("value")) + "" === "NaN" ? 0 :parseFloat(input.attr("value"))
				
				if(name == "percentage[]") percentageTotal += value;
				else if(name == "impressions[]") impressionsTotal += value;
			}
		});
	});
	wapi("#percentTotal").html(percentageTotal + "%");
	wapi("#impressionTotal").html(impressionsTotal);
	
	if(percentageTotal == 0) disabled(percentage);
	else if(impressionsTotal == 0) disabled(impressions);
}

function deleteTotal(tr){
	var td = tr.cells;
	for(var i = 0 , l = td.length; i < l; i++){			
		if(typeof td[i].data !== "undefined") {
			if(i == 1){
				category.child("option").each(function(n, elem){
					if(elem.innerHTML == td[i].data.attr("value")) elem.removeAttribute("disabled");
				});
			}
			
			var total = 0;
			var input = td[i].data
			var name = input.attr("name");			
			var percentTotal = parseFloat(wapi("#percentTotal").html());
			var impressionTotal = parseFloat(wapi("#impressionTotal").html());
			
			if(name == "percentage[]" && percentTotal > 0) {
				percentTotal -= parseFloat(input.attr("value"));
				wapi("#percentTotal").html(percentTotal + "%");
			}
			else if(name == "impressions[]" && impressionTotal > 0) {
				impressionTotal -= parseFloat(input.attr("value"));
				wapi("#impressionTotal").html(impressionTotal);
			}
		}
	}
}

function totalHandler(name){
	var total = 0;
	var isPass = true;
	
	wapi.each(categoryData.options.target.getElementsByTagName("input"), function(i, elem){
		elem = wapi(elem);
		if(elem.attr("type") === "hidden" && elem.attr("name") === name){
			total += parseFloat(elem.attr("value"));
		}
	});
	
	if(name == "percentage[]"){
		if(total / 100 > 1) isPass = false;
		else wapi("#percentTotal").html(total + "%");
	}else if(name == "impressions[]"){
		var totalLimit = parseFloat(wapi("#minimum_impression").attr("value")) + "" !== "NaN" ? parseFloat(wapi("#minimum_impression").attr("value")) : 0;
		
		if(totalLimit != 0){
			if(total > totalLimit) isPass = false;
			else wapi("#impressionTotal").html(total);
		}
		else if(totalLimit == 0) wapi("#impressionTotal").html(total);
		else wapi("#impressionTotal").html(total);
	}
	
	return {
		isPass:isPass,
		total:total
	}
}

/*-- total handler end --*/

function keyuphandler(a, b){
	var name = a.attr("name");
	name = name.slice(0, name.indexOf("_")) + "[]";
	
	var total = totalHandler(name).total;
	total = total + parseFloat(a.attr("value"));
	
	var totalLimit = parseFloat(wapi("#minimum_impression").attr("value")) + "" !== "NaN" ? parseFloat(wapi("#minimum_impression").attr("value")) : 0;
	totalLimit = name == "percentage[]" ? 100 : totalLimit;
	
	if(a.attr("value") == "") {
		hidErro(a[0]);
		return;
	}
	
	if(chkData(categoryReg, a[0])){
		if(total > totalLimit && totalLimit != 0){
			showErro(a[0], "Out of limit.");
			upload.click(emptyFN);
		}else{
			hidErro(b[0]);
			b.attr({value:"disabled", disabled:"disabled"}).css("color", "#cccccc");		
			upload.click(addCategory);
		}		
	}else if(a.attr("value") == ""){
		hidErro(a[0]);
		var i = 0;
		if(categoryData.options.isEdit) i++;
		if(categoryData.options.hasTotal) i++;
		if(categoryData.options.hasHeader) i++;
		if(categoryData.options.target.rows.length == i) b.attr("value", "").css("color", "")[0].removeAttribute("disabled");
		upload.click(emptyFN);
	}else upload.click(emptyFN);
}

function addCategory(){
	var v0 = category[0].value;
	var v1 = category[0].options[category[0].selectedIndex].innerHTML;
	var v2 = impressions.attr("value") === "disabled" ? "" : impressions.attr("value");
	var v3 = percentage.attr("value") === "disabled" ? "" : percentage.attr("value");
	
	if(v0 == ""){
		chkData({
			reg:/^[1-9]\d*$|^[0]\d+$/i,
			msg:"Select a category."
		}, category[0]);
		return;
	}
	
	categoryData.add([v0, v1, v2, v3]);
	
	//reset select&input element
	category[0].options[category[0].selectedIndex].disabled = "disabled";
	category[0].options[0].selected = "selected";
	if(v2 !== "") impressions.attr("value","");
	if(v3 !== "") percentage.attr("value","");
	
	initTotal();
}

/**
* category cell edit method
*
*/
function editCell(){
	var td = wapi(this.td);
	var datagrid = this.datagrid;
	var name = td[0].data.attr("name");
	var oldValue = td.child("input").attr("value");
	var oldTotal = totalHandler(name).total - parseFloat(td[0].data.attr("value"));
	
	var input = wapi("<input>").attr({type:"text", value:oldValue}).css({width:"80px", height:"16px", textAlign:"center"}).click(function(event){
		datagrid.cancelBubble(event);
	}).blur(function(){
		if(chkData(categoryReg, this)){			
			td[0].data.attr("value", this.value);
			if(!totalHandler(name).isPass){
				td[0].data.attr("value", oldValue);
				showErro(input[0], "Out of limit.");
			}else{
				td.html(this.value);
				td.append(td[0].data).css("background", "");
				datagrid.block = false;
				
				hidErro(input[0]);
				input = null;
			}
		}
	}).keyup(function(event){
		if(this.value == ""){
			hidErro(this);
			if(name == "percentage[]") wapi("#percentTotal").html(oldTotal + "%");
			else if(name == "impressions[]") wapi("#impressionTotal").html(oldTotal);
		}else {
			if(chkData(categoryReg, this)){
				td[0].data.attr("value", this.value);//set current data
				if(!totalHandler(name).isPass){//check total limite and calculate
					td[0].data.attr("value", oldValue);
					totalHandler(name) //restore last total
					showErro(input[0], "Out of limit.");
				}else hidErro(input[0]);
				td[0].data.attr("value", oldValue);//restore original data
			}
		}
		
		if(event.keyCode == 27){
			this.onblur = function(){}; // unbind onblur event
			hidErro(this);
			
			td[0].data.attr("value", oldValue);
			td.html(oldValue);
			td.append(td[0].data).css("background", "");
			datagrid.block = false;
			
			input = null;
		}
	});
	
	td.html("").append(input).append(td[0].data).css("background", "#F60");
	
	input[0].focus();
	
	this.datagrid.block = true;
}

/*-- cell edit method end --*/

/**
* check data format
*
*/
function chkData(reg, elem){
	var value = elem.value;
	
	if(!reg.reg.test(elem.value)) {
		showErro(elem, (typeof reg.msg === "undefined" ? "" : reg.msg));
		return false;
	} else{
		hidErro(elem);
		return true;
	}
}

function showErro(elem, msg){
	var erroCss = {
		height:"16px", 
		lineHeight:"16px", 
		padding:"0 3px", 
		border:"1px solid #666666", 
		background:"#FFFFFF"
	};
	
	msg = wapi("<div>").css(erroCss).html(msg);
	
	if(typeof elem.hover !== "undefined"){
		if(elem.hover.element.css("display") == "none") {
				elem.hover.element.html("").append(msg);
				elem.hover.show("fast");
		}else elem.hover.element.html("").append(msg);
	}else {
		wapi(elem).hover("right", msg, {left:1});
		elem.hover.show("fast");
	}
}

function hidErro(elem){
	if(typeof elem.hover !== "undefined" && elem.hover.element.css("display") != "none") elem.hover.hidden("fast");
}

/*-- check format end --*/
})()
</script>
</body>
</html>
posted on 2011-03-10 16:42  y.l  阅读(314)  评论(0编辑  收藏  举报