论坛首页 Web前端技术论坛

扩展dhtmlGrid,使其支持自定义公式和动态列,表头合并

浏览 28274 次
该帖已经被评为良好帖
作者 正文
   发表时间:2006-10-20  
dhtmlGrid是一个功能比较齐全的html Grid控件,在其profesonal版中生成支持公式编辑到cell级别,我只想动态求任意列的和
,又不想花钱,就自己扩展了一下dhtmlgrid,使其支持在任意cell上添加求和公式,同时如果没个cell的值发生了改变,那么关联的
公式项会自动变化,跟excell有点像了,当然他的功能远不及excell强大。
1:扩展eXcell
eXcell是dhmtlGrid所有的cell的基类,所有的cell都是扩展自eXcell,dhtml中自带的类型有readOnly(eXcell_ro),editable(eXcell_ed)
图片,link,等等可以自己看它的doc有介绍,我扩展的类就叫eXcell_formulas
2:扩展eXcell步骤:
function eXcell_formulas(cell){
		try{
			this.cell = cell;
			this.grid = this.cell.parentNode.grid;
		}catch(er){}
		/**
		*	@desc: method called by grid to start editing
		*/
		this.edit = function(){
					
			}
		/**
		*	@desc: get real value of the cell
		*/
		this.getValue = function(){
				return "";
			}
		/**
		*	@desc: set formated value to the cell
		*/
		this.setValue = function(val){
				if(val.toString().trim()=="")
					val = " ";
				this.cell.innerHTML = val;
			}
		/**
		*	@desc: this method called by grid to close editor
		*/
		this.detach = function(){
				this.setValue(this.obj.value);
				return this.val!=this.getValue();
			}
}
eXcell_formulas.prototype = new eXcell;

这是扩展的骨架,要实现setValue,getValue,edit,detach四个方法,也可以继承已有的类
看看我的代码吧
/*==== add by ivan li math begin====*/
function eXcell_formulas(cell)
{
 	try
	{
		this.cell = cell;
		//指向grid控件
		this.grid = this.cell.parentNode.grid;
		
	}catch(er){}
}
//再这里我扩展自eXcell_ed
eXcell_formulas.prototype = new eXcell_ed;
//这个方法接受外界传来的cell的值,在这里是公式的值,
//当让,在这里cell是可以编辑的,如果输入的是公式那么要以=号开头
eXcell_formulas.prototype.setValue = function(val)
{
	if((typeof(val)!="number")&& val.toString()._dhx_trim()=="")
	{
 		val=" "
 		this.cell._clearCell=true;
	}
	
	if(val.toString()._dhx_trim().indexOf('=') != -1)
	{
		//以=号开头,说明是公式,那么存下来公式
		this.cell._val = val.toString()._dhx_trim();
		this.cell.innerHTML="formulas";
		
	}
	else
	{
		//如果不是以=号开头那么仍然保留原来的公式
		this.cell.innerHTML=val.toString()._dhx_trim();
	}
	//add cell observer
	//prototype.addCellObserver()
	//计划在此处把用obserer模式存下targetCell ->this,但是现在没成功,
        //主要式在callBack时不能调用存下的this.calcVale方法
}
//就算公式的值并显示
eXcell_formulas.prototype.calcValue = function()
{
	var innerFormulas;
	//如果没有存公式那么就不用计算了
	if(!this.cell._val)
	{
		return;
	}
	else
	{
		innerFormulas = this.cell._val.substr(1);
	}
	var cellAr = innerFormulas.split(',');
	
	var formulasResult = 0;
	for(icell=0; icell<cellAr.length;icell++)
	{
		
		cellChild = cellAr[icell].split('^');
		//得到targetCell对象
		var ex = this.grid.cells(cellChild[0],cellChild[1]);
		//目前只实现了加法,对于公式的解析还有待实现
		formulasResult= Number(formulasResult)+Number(ex.getValue());
	}
	this.cell.innerHTML = formulasResult;
	//如果有公式,那么把cell的颜色设置成黄色,以做提示
	this.setBgColor("yellow");
}
//此处添加CellObserver
eXcell_formulas.prototype.addCellObserver = function()
{
	var cellAr = this.cell._val.split(',');
	for(i = 0; i< cellAr.length; i++)
	{
		//if already has observer on the cell
		if(this.grid.formulasObserver.hasKey(cellAr[i]))
		{
			formulasCellAr = this.grid.formulasObserver.getValue(cellAr[i]);
			var hasRegistered = false;
			
			for(j = 0; j<formulasCellAr.length;j++)
			{
				if(this._val == formulasCellAr[j]._val)
				{
					hasRegistered = true;
					break;
				}
			}
			//if has not registered then add this formulascell in
			if(!hasRegistered)
			{
				formulasCellAr.push(this);
			}
		}
		//if no observer on the cell then add a new one
		else
		{
			var cellObservers = new Array();
			cellObservers.push(this);
			
			this.grid.formulasObserver.add(cellAr[i], cellObservers);
		}
	}
}

/*====add by ivan li math end====*/

3:修改grid部分
/*add by Ivan Li 2006-10-20 begin*/
	this.calcFormulas = function()
	{
		for(i = 0; i<this.getColumnCount();i++)
		{
			if("formulas" == this.getColType(i))
			{
				this._calcFormulasCol(i)
			}
		}
	};
	this._calcFormulasCol = function(colIdx)
	{
		for(j = 0; j < this.getRowsNum(); j++)
		{
			this.cells2(j, colIdx).calcValue();
		}
	};
	this.notifyCellChange = function(rowId,cellInd)
	{
		
		formulasCells = this.formulasObserver.getValue(rowId+"^"+cellInd);
		
		for(i = 0; i<formulasCells.length; i++)
		{
			
			//formulasCells[i] is eXcell_formulas type
			formulasCells[i].calcValue();
		}
	};
	/*add by Ivan Li 2006-10-20 end*/

有关dhtmlGrid可以自己到http://www.scbr.com/docs/products/dhtmlxGrid/index.shtml下载
   发表时间:2006-10-20  
很不错的组件,可以用在以后的财务模块。
0 请登录后投票
   发表时间:2006-10-23  
pro 版的还可以在xml里定义table的header,现在的还不可以,等我有时间了,搞一搞
0 请登录后投票
   发表时间:2006-10-25  
居然不支持中文
0 请登录后投票
   发表时间:2006-10-27  
测试reloaddata,发现同样的xml也报错,"LoadXML Incorrect XML",跟踪了一下发现
dhtmlXCommon.js中
dtmlXMLLoaderObject.prototype.getXMLTopNode=function(tagName){
if(this.xmlDoc.responseXML){
var temp=this.xmlDoc.responseXML.getElementsByTagName(tagName);
var z=temp[0];
}else
var z=this.xmlDoc.documentElement;
if(z)
return z;

if((_isIE)&&(!this._retry)){

var xmlString=this.xmlDoc.responseText;
this._retry=true;
this.xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
this.xmlDoc.async=false;
this.xmlDoc.loadXML(xmlString);
return this.getXMLTopNode(tagName);
}

dhtmlxError.throwError("LoadXML","Incorrect XML",[this.xmlDoc])
return document.createElement("DIV");
};


必须把this._retry=true;这句注释掉才行,不清楚_retry有什么用


0 请登录后投票
   发表时间:2006-10-27  
这个问题我跟作者交流了好几次,他说是ie在处理http://和file://文件不一样,如果用firefox就没事
0 请登录后投票
   发表时间:2006-10-30  
没有试过firefox,ie下即使采用http也必须注释那句
0 请登录后投票
   发表时间:2006-10-30  
我也出现过这个问题,但是在1.0版本中,不论是ie 还是ff, reload都能正常工作
0 请登录后投票
   发表时间:2006-11-03  
今天不太忙,我把从xml里配置header的js搞出来了,这也是它的pro版才提供的功能哦
在dhtmXGrid.js里加上这个方法,
dhtmlXGridObject.prototype._parseHeader = function(headCols)
{
	var arLab = new Array(0);
	var arWdth = new Array(0);
	var arTyp = new Array(0);
	var arAlg = new Array(0);
	var arSrt = new Array(0);
	for (var i=0; i < headCols.length; i++) 
	{
		arLab[arLab.length] = headCols[i].firstChild?headCols[i].firstChild.data:"col"+(i+1);
		arWdth[arWdth.length] = headCols[i].getAttribute("width");
		arTyp[arTyp.length] = headCols[i].getAttribute("type");
 		arAlg[arAlg.length] = headCols[i].getAttribute("align");
		arSrt[arSrt.length] = headCols[i].getAttribute("sort");
	}
	
	this.setHeader(arLab.join(','));
	this.setInitWidths(arWdth.join(','));
	this.setColTypes(arTyp.join(','));
	this.setColAlign(arAlg.join(','));
	this.setColSorting(arSrt.join(','));
	this.init();
}

然后在parseXML方法里
var ar = new Array();
var idAr = new Array();

的上一行加上这几句
        // add by ivan li 2006-11-03 begin for config header in xml begin
	var headCol = this.xmlLoader.doXPath("//rows/head/column", xmlDoc);
	if(headCol.length > 0)
	{// have config the rowheader in the xml
		this._parseHeader(headCol);
	}
	// add by ivan li 2006-11-03 begin for config header in xml end

就搞定了
现在的xml里可以这样配置了
<?xml version="1.0" encoding="utf-8"?>
<rows>
	<head>
		<column width="50" type="ro" align="right"  sort="str">a</column>
		<column width="50" type="ro" align="right"  sort="str">b</column>
		<column width="50" type="ro" align="right"  sort="str">c</column>
		<column width="50" type="ro" align="right"  sort="str">d</column>
		<column width="50" type="ro" align="right"  sort="str">e</column>
		<column width="50" type="ro" align="right"  sort="str">f</column>
		<column width="50" type="ro" align="right"  sort="str">g</column>
		<column width="50" type="ro" align="right"  sort="str">h</column>
	</head>
 	<row id="1">
		<cell>-1500</cell>
		<cell>A Time to Kill</cell>
		<cell><![CDATA[gavin king]]></cell>
		<cell>=2^3,3^3</cell>
		<cell>1</cell>
		<cell>24</cell>
		<cell>=1^4,1^3,2^4</cell>
		<cell>05/01/1998</cell>
	</row>
	<row id="2">
		<cell>1000</cell>
		<cell>Blood and Smoke</cell>
		<cell><![CDATA[<font color="red">Ste</font>phen King]]></cell>
		<cell>0</cell>
		<cell>1</cell>
		<cell>24</cell>
		<cell>=2^4,2^3</cell>
		<cell>01/01/2000</cell>
	</row>
</rows>

在页面里只需要
        mygrid = new dhtmlXGridObject('gridbox');
	mygrid.setImagePath("../imgs/");
        mygrid.init();
	mygrid.loadXML("formulas.xml");

就可以了,这个功能的实现对于要生成动态列的用户来说提供了很大的方便,在我们系统里就要求表格的列是动态的,原来必须把动态的列用taglib打到页面上去,例如
mygrid.setHeader('<bean:write name="myform" property="headerData"/>');

感觉很丑陋,现在好了,只要在后台构建好xml就搞定了
0 请登录后投票
   发表时间:2006-11-27  
老大能把dhtmlxGrid1.1 pro版里面的setSerializationLevel(userData,fullXML,config,changedAttr,onlyChanged)函数提取出来吗?
非常感激!
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics