前端時間在論壇里回了fins的一個帖子(http://daoger.javaeye.com/blog/40310)后,有幾個網友想看我的例子代碼,由于搞自己的一個小系統比較忙,在這里簡單說一下dhtmlXGrid的使用心得!
我現在使用的版本是1.2(免費版),我的實現也大部分基于這個免費版,有哪位老兄能提供一份專業版的話更好了!
1.2免費版中的一些功能其實是1.1專業版中的!廢話少說,切入正題!
1. 基本使用方法
dhtmlXGrid使用起來還是比較簡單的,下面是一段它自帶例子中的代碼:
代碼
-
- <script>
- mygrid = new dhtmlXGridObject('gridbox');
- mygrid.setImagePath("../imgs/");
- mygrid.setHeader("Sales,Book Title,Author,Price,In Store,Shipping,Bestseller,Date of Publication");
- mygrid.setInitWidths("50,150,100,80,80,80,80,200")
- mygrid.setColAlign("right,left,left,right,center,left,center,center")
- mygrid.setColTypes("dyn,ed,ed,price,ch,co,ra,ro");
- mygrid.getCombo(5).put(2,2);
- mygrid.setColSorting("int,str,str,int,str,str,str,date")
- //mygrid.setColumnColor("white,#d5f1ff,#d5f1ff")
- mygrid.setSkin("xp");
- mygrid.init();
- mygrid.loadXML("../grid.xml");
- </script>
-
先說一下數據的取得,上面
代碼
- mygrid.loadXML("../grid.xml");
是從一個xml文件中取得數據,這個方法的實現基于ajax,下面是dhtmlXCommon.js中的發送請求的實現:
代碼
- dtmlXMLLoaderObject.prototype.loadXML = function (filePath, postMode, postVars) {
- this.filePath = filePath;
- try {
- this.xmlDoc = new XMLHttpRequest();
- this.xmlDoc.open(postMode ? "POST" : "GET", filePath, this.async);
- if (postMode) {
- this.xmlDoc.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
- }
- this.xmlDoc.onreadystatechange = new this.waitLoadFunction(this);
- this.xmlDoc.send(null || postVars);
- }
- catch (e) {
- if (document.implementation && document.implementation.createDocument) {
- this.xmlDoc = document.implementation.createDocument("", "", null);
- this.xmlDoc.onload = new this.waitLoadFunction(this);
- this.xmlDoc.load(filePath);
- } else {
- this.xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");
- this.xmlDoc.open(postMode ? "POST" : "GET", filePath, this.async);
- if (postMode) {
- this.xmlDoc.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
- }
- this.xmlDoc.onreadystatechange = new this.waitLoadFunction(this);
- this.xmlDoc.send(null || postVars);
- }
- }
- };
這樣你就可以通過這個loadXML()方法向服務器端發送請求,如:
代碼
- mygrid.loadXML("aaaa.do?para1=para1&2=para2");
服務器端可以有多種方式處理請求,我使用的java來處理的,接收請求后根據需要構建返回客戶端的數據,我采用的是用Jdom生成XML文件流的方式;然后用XMLOutputter將生成的數據文件發送給客戶端,dhtmlXGrid 會自己解析數據,顯示數據!
下面是發送數據的代碼:
代碼
- xmlDocument = new Document(rowsElement);
- XMLOutputter outputter = new XMLOutputter();
- try
- {
- response.setContentType("text/xml; charset=UTF-8");
- response.setHeader("Cache-Control", "no-cache");
- outputter.output(xmlDocument, response.getWriter());
- // outputter.output(xmlDocument, System.out);//在控制臺輸出,查看構建的xml文件是否正確規范
- } catch (IOException e)
- {
- log.error(e);
- try
- {
- response.getWriter().write("<flag>0</flag>");
- } catch (Exception fe)
- {
- }
- }
2. 數據保存及信息反饋
由于版本限制,免費版中沒有提供數據保存的api,在專業版中還有用.net和php實現的服務器端實例代碼;這一功能我是根據dhtmlXGrid提供的api自己用ajax實現的:
代碼
- //deal with data from mygrid
- document.write("<script type='text/javascript' src='script/prototype/infodialog.js'></script>");
- function mydataProcessorObject() {
- var imagesurl = "script/dhtmlXGrid/images/";
- var xmlHttp;//request and response
- var mygrid = new dhtmlXGridObject("gridbox");
- this.dealServer = "";//
- this.querycondithon = "";
- this.dataXml = "";
- this.checkFlag = "";//whether check the cell is null
- this.header = "";
- var newcell;//new record eg."","","","", and so on
- var alertInfotimeout = 3;//alert info show time
- var haveSaved = false;
- this.setDealServer = function (server) {
- this.dealServer = server;
- };
- this.setQueryCondition = function (condition) {
- this.querycondithon = condition;
- };
- /////////////////////////////////////////////////////////
- this.init = function (para) {
- if (para == "query") {
- if (this.querycondithon.length === 0 || this.querycondithon == "" || this.querycondithon == null) {
- mygrid.setImagePath(imagesurl);
- mygrid.enableLightMouseNavigation(true);
- mygrid.loadXML(this.dealServer + "?action=query&ts=" + new Date().getTime());
- } else {
- mygrid.clearAll();
- mygrid.loadXML(this.dealServer + "?action=query&ts=" + new Date().getTime() + "&" + this.querycondithon);
- }
- } else {
- if (para == "add") {
- if (this.readyingAdd()) {
- //mygrid.addRow("A"+(new Date()).valueOf(),['','','','','','','',''],0);
- mygrid.addRow("A" + (new Date()).valueOf(), newcell, 0);
- } else {
- //alert("Exist null cell!");
- openinfodialog("\u5b58\u5728\u7a7a\u5355\u5143\u683c\uff01", 150, 40);
- }
- } else {
- if (para == "save" && !haveSaved) {
- this.readyingSave();
- } else {
- if (para == "delete") {
- var iddel = mygrid.getSelectedId();
- //just whether the record has saved or not
- if (iddel.indexOf("A") === 0) {
- mygrid.deleteSelectedItem();
- openinfodialog("\u6570\u636e\u5df2\u5220\u9664\uff01", 150, 40);
- } else {
- this.loadDelete(iddel);
- }
- }
- }
- }
- }
- };
- /////////////////////////////////////////////////////////
- this.createXMLHttpRequest = function () {
- if (window.ActiveXObject) {
- try {
- xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
- }
- catch (e) {
- try {
- xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
- }
- catch (e) {
- }
- }
- } else {
- if (window.XMLHttpRequest) {
- xmlHttp = new XMLHttpRequest();
- }
- }
- };
- /////////////////////////////////////////////////////////
- this.readyingAdd = function () {
- var allitemid = new Array(0);
- allitemid = mygrid.getAllItemIds().split(",");
- var cc = mygrid.getColumnCount();
- newnewcell = new Array(cc + 1);
- var addflag = true;
- if (allitemid.length > 0) {
- for (var i = 0; i < allitemid.length; i++) {
- for (var j = 0; j < cc; j++) {
- var cellValue = mygrid.cells(allitemid[i], j).getValue();
- if (cellValue == null || cellValue.length == 0 || cellValue == "") {
- addflag = false;
- }
- }
- }
- }
- if (addflag) {
- for (var n = 0; n < cc; n++) {
- newcell[n] = "";
- }
- }
- return addflag;
- };
- /////////////////////////////////////////////////////////
- this.readyingSave = function () {
- var allitemid = new Array(0);
- var modiitemid = new Array(0);
- allitemid = mygrid.getAllItemIds().split(",");
- var cc = mygrid.getColumnCount();
- var saveflag = false;
- var blankflag = false;
- var a = 0;
- for (var i = 0; i < allitemid.length; i++) {
- var modiflag = false;
- for (var j = 0; j < cc; j++) {
- if (mygrid.cells(allitemid[i], j).wasChanged()) {
- modiflag = true;
- }
- var cellValue = mygrid.cells(allitemid[i], j).getValue();
- if (cellValue == "" || cellValue.length == 0 || cellValue == null) {
- blankflag = true;
- }
- }
- if (modiflag && !blankflag) {
- modiitemid[a++] = allitemid[i];
- }
- }
- if (this.dealServer.length > 0 && modiitemid.length > 0) {
- this.dataXml = "<?xml version='1.0' encoding='UTF-8'?><data>";
- for (var i = 0; i < modiitemid.length; i++) {
- if (modiitemid[i].length > 0) {
- this.dataXml += "<row id='" + modiitemid[i] + "'>";
- for (var j = 0; j < cc; j++) {
- this.dataXml += "<cell>";
- var mycell = mygrid.cells(modiitemid[i], j).getValue();
- if (mycell.indexOf("<") != -1) {
- this.dataXml += mycell.substring(mycell.indexOf(">") + 1, mycell.indexOf("</"));
- } else {
- this.dataXml += mycell;
- }
- this.dataXml += "</cell>";
- }
- this.dataXml += "</row>";
- }
- }
- this.dataXml += "</data>";
- alert(this.dataXml);
- this.loadSave();
- this.init("query");
- } else {
- if (blankflag) {
- openinfodialog("\u5b58\u5728\u7a7a\u503c\uff01", 100, 40);
- } else {
- //alert("u5df2u7ecfu5b58u50a8u6216u6ca1u6709u6570u636eu6539u52a8uff01");
- openinfodialog("\u5df2\u4fdd\u5b58\u6216\u6ca1\u6709\u53ef\u4fdd\u5b58\u7684\u6570\u636e\uff01", 200, 40);
- }
- }
- };
- /////////////////////////////////////////////////////////
- this.loadSave = function () {
- this.createXMLHttpRequest();
- var url = this.dealServer + "?action=save&ts=" + new Date().getTime();
- xmlHttp.open("POST", url, false);
- xmlHttp.onreadystatechange = this.goCallBackSave;
- xmlHttp.setRequestHeader("Content-Type", "text/xml");
- xmlHttp.setRequestHeader("charset", "UTF-8");
- xmlHttp.send(this.dataXml);
- };
- /////////////////////////////////////////////////////////
- this.goCallBackSave = function () {
- if (xmlHttp.readyState == 4) {
- if (xmlHttp.status == 200) {
- var returnFlag = xmlHttp.responseXML.getElementsByTagName("flag");
- var saveflag = returnFlag[0].firstChild.nodeValue;
- if (saveflag == "1") {
- //alert("u4fddu5b58u6210u529fuff01");
- openinfodialog("\u4fdd\u5b58\u6210\u529f\uff01", 120, 40);
- } else {
- if (saveflag == "0") {
- //alert("u4fddu5b58u5931u8d25!");
- openinfodialog("\u4fdd\u5b58\u5931\u8d25\uff01", 120, 40);
- }
- }
- }
- }
- };
- /////////////////////////////////////////////////////////
- this.loadDelete = function (id) {
- this.createXMLHttpRequest();
- var url = this.dealServer + "?action=delete&id=" + id + "&ts=" + new Date().getTime();
- xmlHttp.open("GET", url, true);
- xmlHttp.onreadystatechange = this.goCallBackDelete;
- xmlHttp.send();
- };
- /////////////////////////////////////////////////////////
- this.goCallBackDelete = function () {
- if (xmlHttp.readyState == 4) {
- if (xmlHttp.status == 200) {
- var returnFlag = xmlHttp.responseXML.getElementsByTagName("flag");
- var delflag = returnFlag[0].firstChild.nodeValue;
- if (delflag == "1") {
- mygrid.deleteSelectedItem();
- //alert("ddddddddd");
- openinfodialog("\u8bb0\u5f55\u5df2\u5220\u9664\uff01", 140, 40);
- } else {
- if (delflag == "0") {
- //alert("u5220u9664u5931u8d25!");
- openinfodialog("\u8bb0\u5f55\u672a\u80fd\u5220\u9664\uff0c\u8bf7\u68c0\u67e5\u539f\u56e0\uff01", 170, 40);
- }
- }
- }
- }
- };
- }
-
簡單說一下思路:通過dhtmlXGrid提供的api wasChange()來判斷是否有單元格的數據修改過,如果有修改,在客戶端構建要保存數據的xml后,用send方式將其發送到服務器端處理,用服務器端返回的flag標志位提示反饋信息,在提示信息顯示的同時,頁面中的腳本再向服務器端發送一次查詢請求,刷新數據,顯示最新數據記錄!
還有一個問題是:填寫完數據保存時,焦點還在表格中,這時在取數據的時候要注意清除掉<texteare>標簽,這樣才能取到單元格的值!
代碼中的很多方法都是來源于dhtmlXGrid的api,代碼有點亂,請盡量參考它自帶的文檔!
3. 其他問題
操作后的反饋信息我是使用的ouspec 推薦的一個小控件windows_js,現在的版本是1.0;這里是例子:http://prototype-window.xilinus.com/samples.html#
另外,我還使用了yui-ext組件,由于dhtmlXGrid中日期控件是基于YUI開發的,所以兩個都使用的時候會有底層方法方面的沖突;我現在的解決方法是把dhtmlXGrid下js文件夾中dhtmlXGrid_excell_calendar.js文件中對event.js的引用替換為YUI包中的event.js;
如果你有更好的解決辦法,還請告訴我!
說得有點羅嗦,希望各位網友能聽的明白,用起來少走彎路!呵呵!
#################################################################################################
注釋:擴展的ajax請求部分如果換成prototype的Ajax.Request會更簡潔一些。