/* Copyright Scand LLC http://www.scbr.com To use this component please contact info@scbr.com to obtain license $CVSHeader$ */ /*_TOPICS_ @0:initialization @1:selection control @2:rows control @3:colums control @4:cells controll @5:data manipulation @6:appearence control @7:overal control @8:tools @9:treegrid @10: event handlers @11: paginal output */ var globalActiveDHTMLGridObject; String.prototype._dhx_trim = function(){ return this.replace(/ /g," ").replace(/(^[ \t]*)|([ \t]*$)/g,""); } function dhtmlxArray(ar){ return dhtmlXHeir((ar||new Array()),new _dhtmlxArray()); }; function _dhtmlxArray(){ return this; }; _dhtmlxArray.prototype._dhx_find = function(pattern){ for(var i=0;i=ind;i--){ this[i] = this[i-1] } this[ind] = value } _dhtmlxArray.prototype._dhx_removeAt = function(ind){ for(var i=ind;i=9)) this.hdr.style.tableLayout = "fixed"; this.hdr.className = "hdr"; this.hdr.width = "100%"; this.xHdr = document.createElement("TABLE"); this.xHdr.cellPadding = 0; this.xHdr.cellSpacing = 0; var r = this.xHdr.insertRow(0) var c = r.insertCell(0); r.insertCell(1).innerHTML = "      "; c.appendChild(this.hdr) this.objBuf = document.createElement("DIV"); this.objBuf.appendChild(this.obj); this.entCnt = document.createElement("TABLE"); this.entCnt.insertRow(0).insertCell(0) this.entCnt.insertRow(1).insertCell(0); this.entCnt.cellPadding = 0; this.entCnt.cellSpacing = 0; this.entCnt.width = "100%"; this.entCnt.height = "100%"; this.entCnt.style.tableLayout = "fixed"; this.objBox = document.createElement("DIV"); this.objBox.style.width = "100%"; this.objBox.style.height = this.entBox.style.height; this.objBox.style.overflow = "auto"; this.objBox.style.position = "relative"; this.objBox.appendChild(this.objBuf); this.objBox.className = "objbox"; this.hdrBox = document.createElement("DIV"); this.hdrBox.style.width = "100%" if (((_isOpera)&&(_OperaRv<9)) ) this.hdrSizeA=25; else this.hdrSizeA=100; this.hdrBox.style.height=this.hdrSizeA+"px"; if (_isIE) this.hdrBox.style.overflowX="hidden"; else this.hdrBox.style.overflow = "hidden"; this.hdrBox.style.position = "relative"; this.hdrBox.appendChild(this.xHdr); this.preloadImagesAr = new Array(0) this.sortImg = document.createElement("IMG") this.sortImg.style.display = "none"; this.hdrBox.insertBefore(this.sortImg,this.xHdr) this.entCnt.rows[0].cells[0].vAlign="top"; this.entCnt.rows[0].cells[0].appendChild(this.hdrBox); this.entCnt.rows[1].cells[0].appendChild(this.objBox); this.entBox.appendChild(this.entCnt); //add links to current object this.entBox.grid = this; this.objBox.grid = this; this.hdrBox.grid = this; this.obj.grid = this; this.hdr.grid = this; /*PROPERTIES*/ this.cellWidthPX = new Array(0);//current width in pixels this.cellWidthPC = new Array(0);//width in % if cellWidthType set in pc this.cellWidthType = this.entBox.cellwidthtype || "px";//px or % this.delim = this.entBox.delimiter || ","; this._csvDelim = ","; this.hdrLabels = (this.entBox.hdrlabels || "").split(","); this.columnIds = (this.entBox.columnids || "").split(","); this.columnColor = (this.entBox.columncolor || "").split(","); this.cellType = dhtmlxArray((this.entBox.cellstype || "").split(",")); this.cellAlign = (this.entBox.cellsalign || "").split(","); this.initCellWidth = (this.entBox.cellswidth || "").split(","); this.fldSort = (this.entBox.fieldstosort || "").split(",") this.imgURL = this.entBox.imagesurl || "gridCfx/"; this.isActive = false;//fl to indicate if grid is in work now this.isEditable = true; this.raNoState = this.entBox.ranostate || null; this.chNoState = this.entBox.chnostate || null; this.selBasedOn = (this.entBox.selbasedon || "cell").toLowerCase() this.selMultiRows = this.entBox.selmultirows || false; this.multiLine = this.entBox.multiline || false; this.noHeader = this.entBox.noheader || false; this.dynScroll = this.entBox.dynscroll || false;//add/remove rows from dom this.dynScrollPageSize = 0;//will be autodetected this.dynScrollPos = 0;//position of dynamic scroll this.xmlFileUrl = this.entBox.xmlfileurl || ""; this.recordsNoMore = this.entBox.infinitloading || true;;//if true, then it will not attempt to fill the buffer from server this.useImagesInHeader = false;//use images in header or not this.pagingOn = false;//paging on/off //this.dynScrollBuffer = 100;//number of rows in buffer this.rowsBufferOutSize = 0;//number of rows rendered at a moment /*EVENTS*/ this.onCheckbox=this.onEnter=this.onRowSelect=this.onEditCell = function(){return true;}; dhtmlxEvent(window,"unload",function(){try{ self.destructor(); } catch(e){}}); /*XML LOADER(S)*/ /** * @desc: loads xml content from specified url * @param: url - XML file url * @param: afterCall - function which will be called after xml loading * @type: public * @topic: 0,5 */ this.loadXML = function(url,afterCall){ if (this._dload) { this._dload=url; this._askRealRows(); return true; }; if (this._xmlaR) this.setXMLAutoLoading(url); if(url.indexOf("?")!=-1) var s = "&"; else var s = "?"; var obj = this; if (this.onXLS) this.onXLS(this); if (afterCall) this.xmlLoader.waitCall=afterCall; this.xmlLoader.loadXML(url+""+s+"rowsLoaded="+this.getRowsNum()+"&lastid="+this.getRowId(this.getRowsNum()-1)+"&sn="+Date.parse(new Date())); //nb: //if (this.onXLS) setTimeout(function(){obj.onXLS(obj)},0); //setTimeout(function(){obj.xmlLoader.loadXML(url+""+s+"rowsLoaded="+obj.getRowsNum()+"&lastid="+obj.getRowId(obj.getRowsNum()-1)+"&sn="+Date.parse(new Date()));},1) } /** * @desc: set one of predefined css styles (currently : xp) * @param: name - style name * @type: public * @topic: 0,6 */ this.setSkin = function(name){ this.entBox.className = "gridbox gridbox_"+name; switch(name){ case "xp": this._srdh=22; break; case "gray": this._borderFix=(_isIE?1:0); break; } } //#__pro_feature:21092006{ //#loadfrom_string:21092006{ /** * @desc: loads xml content from specified string * @param: str - XML string * @param: afterCall - function which will be called after xml loading * @type: public * @topic: 0,5 * @edition: Professional */ this.loadXMLString = function(str,afterCall){ if (this.onXLS) this.onXLS(this); if (afterCall) this.xmlLoader.waitCall=afterCall; this.xmlLoader.loadXMLString(str); } //#} //#} /** * @desc: puts xml to parser * @type: private * @topic: 0,5 */ this.doLoadDetails = function(obj){ var root = self.xmlLoader.getXMLTopNode(self._tttag) if (root.tagName!="DIV") if(!self.xmlLoader.xmlDoc.nodeName){ self.parseXML(self.xmlLoader.xmlDoc.responseXML) }else{ self.parseXML(self.xmlLoader.xmlDoc) } //nb:paging if(self.pagingOn) self.createPagingBlock() } this.xmlLoader = new dtmlXMLLoaderObject(this.doLoadDetails,window,true,this.no_cashe); if (_isIE) this.preventIECashing(true); this.dragger=new dhtmlDragAndDropObject(); /*METHODS. SERVICE*/ /** * @desc: on scroll grid inner actions * @type: private * @topic: 7 */ this._doOnScroll = function(e,mode){ if (this._onSCRL) this._onSCRL(this.objBox.scrollLeft,this.objBox.scrollTop); this.doOnScroll(e,mode); } /** * @desc: on scroll grid more inner action * @type: private * @topic: 7 */ this.doOnScroll = function(e,mode){ this.hdrBox.scrollLeft = this.objBox.scrollLeft; if (this.ftr) this.ftr.parentNode.scrollLeft = this.objBox.scrollLeft; this.setSortImgPos(null,true); if (mode) return; //load more rows on scroll if(!this.pagingOn && this.objBox.scrollTop+this.hdrSizeA+this.objBox.offsetHeight>this.objBox.scrollHeight){ if(this._xml_ready && (this.objBox._oldScrollTop!=this.objBox.scrollTop) && this.addRowsFromBuffer()){ this.objBox.scrollTop = this.objBox.scrollHeight - (this.hdrSizeA+1+this.objBox.offsetHeight) this.objBox._oldScrollTop=this.objBox.scrollTop; } } if (this._dload){ if (this._dLoadTimer) window.clearTimeout(this._dLoadTimer); this._dLoadTimer=window.setTimeout(function(){ self._askRealRows(); },500); } } /** * @desc: attach this grid to some object in DOM * @param: obj - object to attach to * @type: public * @topic: 0,7 */ this.attachToObject = function(obj){ obj.appendChild(this.entBox) } /** * @desc: initialize grid * @param: fl - if to parse on page xml dataisland * @type: public * @topic: 0,7 */ this.init = function(fl){ this.editStop() /*TEMPORARY STATES*/ this.lastClicked = null;//row clicked without shift key. used in multiselect only this.resized = null;//hdr cell that is resized now this.fldSorted = null;//hdr cell last sorted this.gridWidth = 0; this.gridHeight = 0; //empty grid if it already was initialized this.cellWidthPX = new Array(0); this.cellWidthPC = new Array(0); if(this.hdr.rows.length>0){ this.clearAll(true); } if(this.cellType._dhx_find("tree")!=-1){//create hashtable for treegrid this.loadedKidsHash = new Hashtable(); this.loadedKidsHash.put("hashOfParents",new Hashtable()) } var hdrRow = this.hdr.insertRow(0); for(var i=0;i0)) this.entCnt.rows[0].cells[0].height = this.hdrBox.offsetHeight+"px"; var gridWidth = parseInt(this.entBox.offsetWidth); var gridHeight = parseInt(this.entBox.offsetHeight); var _isVSroll=(this.objBox.scrollHeight>this.objBox.offsetHeight); if (((!this._ahgr)&&(_isVSroll))||((this._ahgrM)&&(this._ahgrMthis._ahgrM?this._ahgrM:z2)*1; gridHeight=z2+zheight+scrfix; this.entBox.style.height=gridHeight+"px"; } var aRow=this.entCnt.rows[1].cells[0].childNodes[0]; if(!this.noHeader) aRow.style.top = (zheight-this.hdrBox.offsetHeight+(_isFF?0:(1-wcor)))+"px"; //nb 072006: aRow.style.height = (((gridHeight - zheight-1)<0 && _isIE)?20:(gridHeight - zheight-1))-(this.ftr?this.ftr.offsetHeight:0)+"px"; if (this.ftr) this.entCnt.style.height=this.entBox.offsetHeight-this.ftr.offsetHeight+"px"; if (this._dload) this._dloadSize=Math.floor(parseInt(this.entBox.style.height)/20)+2; //rough, but will work }; /** * @desc: changes cell width * @param: [ind] - index of row in grid * @type: private * @topic: 4,7 */ this.chngCellWidth = function(){ if ((_isOpera)&&(this.ftr)) this.ftr.width=this.objBox.scrollWidth+"px"; var l=this._cCount; for(var i=0;i1){ var a_sizes=new Array(); for (var i=0; i(this._drsclmW?(this._drsclmW[ind]||10):10)){ this.obj.firstChild.firstChild.childNodes[ind].style.width = fcolW+"px"; this.hdr.rows[0].childNodes[ind].style.width = fcolW+"px"; if (this.ftr) this.ftr.rows[0].childNodes[ind].style.width = fcolW+"px"; if(this.cellWidthType=='px'){ this.cellWidthPX[ind]=fcolW; }else{ var gridWidth = parseInt(this.entBox.offsetWidth); if (this.objBox.scrollHeight>this.objBox.offsetHeight) gridWidth-=(this._scrFix||(_isFF?19:16)); var pcWidth = Math.round(fcolW/gridWidth*100) this.cellWidthPC[ind]=pcWidth; } } } /** * @desc: sets position and visibility of sort image * @param: [state] - true/false - show/hide image * @param: [ind] - index of field * @param: [direction] - ASC/DESC - type of image * @type: public * @topic: 7 */ this.setSortImgState=function(state,ind,direction){ if (!convertStringToBoolean(state)){ this.sortImg.style.display = "none"; return; } if (direction=="ASC") this.sortImg.src = this.imgURL+"sort_asc.gif"; else this.sortImg.src = this.imgURL+"sort_desc.gif"; this.sortImg.style.display=""; this.fldSorted=this.hdr.rows[0].cells[ind]; this.setSortImgPos(ind); } /** * @desc: sets position and visibility of sort image * @param: [ind] - index of field * @type: private * @topic: 7 */ this.setSortImgPos = function(ind,mode){ if(!ind) var el = this.fldSorted; else var el = this.hdr.rows[0].cells[ind]; if(el!=null){ var pos = this.getPosition(el,this.hdrBox) var wdth = el.offsetWidth; this.sortImg.style.left = Number(pos[0]+wdth-13)+"px";//Number(pos[0]+5)+"px"; this.sortImg.defLeft = parseInt(this.sortImg.style.left) this.sortImg.style.top = Number(pos[1]+5)+"px"; if ((!this.useImagesInHeader)&&(!mode)) this.sortImg.style.display = "inline"; this.sortImg.style.left = this.sortImg.defLeft+"px";//-parseInt(this.hdrBox.scrollLeft) } } /** * @desc: manage activity of the grid. * @param: fl - true to activate,false to deactivate * @type: private * @topic: 1,7 */ this.setActive = function(fl){ if(arguments.length==0) var fl = true; if(fl==true){ //document.body.onkeydown = new Function("","document.getElementById('"+this.entBox.id+"').grid.doKey()")// globalActiveDHTMLGridObject = this; this.isActive = true; }else{ this.isActive = false; } }; /** * @desc: called on click occured * @type: private */ this._doClick = function(ev){ var selMethod = 0; var el = this.getFirstParentOfType(_isIE?ev.srcElement:ev.target,"TD"); var fl = true; if(this.selMultiRows!=false){ if(ev.shiftKey && this.row!=null){ selMethod = 1; } if(ev.ctrlKey){ selMethod = 2; } } this.doClick(el,fl,selMethod) }; /** * @desc: called onmousedown inside grid area * @type: private */ this._doContClick=function(ev){ var el = this.getFirstParentOfType(_isIE?ev.srcElement:ev.target,"TD"); if ((!el)||(el.parentNode.idd===undefined)) return true; if (ev.button==2){ if ((this.onRCL)&&(!this.onRCL(el.parentNode.idd,el._cellIndex,ev))) return; if (this._ctmndx){ if ((this.onBCM)&&(!this.onBCM(el.parentNode.idd,el._cellIndex,this))) return true; el.contextMenuId=el.parentNode.idd+"_"+el._cellIndex; el.contextMenu=this._ctmndx; el.a=this._ctmndx._contextStart; if (_isIE) ev.srcElement.oncontextmenu = function(){ event.cancelBubble=true; return false; }; el.a(el,ev); el.a=null; } } return true; } /** * @desc: occures on cell click (supports treegrid) * @param: [el] - cell to click on * @param: [fl] - true if to call onRowSelect function * @param: [selMethod] - 0 - simple click, 1 - shift, 2 - ctrl * @type: private * @topic: 1,2,4,9 */ this.doClick = function(el,fl,selMethod){ var psid=this.row?this.row.idd:0; this.setActive(true); if(!selMethod) selMethod = 0; if(this.cell!=null) this.cell.className = this.cell.className.replace(/cellselected/g,""); if(el.tagName=="TD" && (this.rowsCol._dhx_find(this.rowsAr[el.parentNode.idd])!=-1 || this.rowsBuffer[0]._dhx_find(el.parentNode.idd)!=-1)){ if (this.onSSC) var initial=this.getSelectedId(); var prow=this.row; if(selMethod==0){ this.clearSelection(); }else if(selMethod==1){ var elRowIndex = this.rowsCol._dhx_find(el.parentNode) var lcRowIndex = this.rowsCol._dhx_find(this.lastClicked) if(elRowIndex>lcRowIndex){ var strt = lcRowIndex; var end = elRowIndex; }else{ var strt = elRowIndex; var end = lcRowIndex; } this.clearSelection(); for(var i=0;i=strt && i<=end)&&(this.rowsCol[i])&&(!this.rowsCol[i]._sRow)){ if ((!this.onBFS)||(this.onBFS(this.rowsCol[i].idd,psid))){ this.rowsCol[i].className+=" rowselected"; this.selectedRows[this.selectedRows.length] = this.rowsCol[i] } }/*else{ this.rowsCol[i].className = ""; }*/ } }else if(selMethod==2){ if(el.parentNode.className.indexOf("rowselected") != -1){ el.parentNode.className=el.parentNode.className.replace("rowselected",""); this.selectedRows._dhx_removeAt(this.selectedRows._dhx_find(el.parentNode)) var skipRowSelection = true; } } this.editStop() this.cell = el; if ((prow == el.parentNode)&&(this._chRRS)) fl=false; this.row = el.parentNode; if((!skipRowSelection)&&(!this.row._sRow)){ if ((!this.onBFS)||(this.onBFS(this.row.idd,psid))){ this.row.className+= " rowselected" if(this.selectedRows._dhx_find(this.row)==-1) this.selectedRows[this.selectedRows.length] = this.row; } else this.row=true; } if(this.selBasedOn=="cell"){ if (this.cell.parentNode.className.indexOf("rowselected")!=-1) this.cell.className = this.cell.className.replace(/cellselected/g,"")+" cellselected"; } if(selMethod!=1) this.lastClicked = el.parentNode; var rid = this.row.idd; var cid = this.cell.cellIndex; if (fl) setTimeout(function(){ self.onRowSelect(rid,cid); },100) if (this.onSSC) { var afinal=this.getSelectedId(); if (initial!=afinal) this.onSSC(afinal); } } this.isActive = true; this.moveToVisible(this.cell) } /** * @desc: set selection to specified row-cell * @param: r - row object or row index * @param: cInd - cell index * @param: [fl] - true if to call onRowSelect function * @param: preserve - preserve previously selected rows true/false (false by default) * @param: edit - switch selected cell to edit mode * @type: public * @topic: 1,4 */ this.selectCell = function(r,cInd,fl,preserve,edit){ if(!fl) fl = false; if(typeof(r)!="object") r = this.rowsCol[r] //#__pro_feature:21092006{ //#colspan:20092006{ if (r._childIndexes) var c = r.childNodes[r._childIndexes[cInd]]; else //#} //#} var c = r.childNodes[cInd]; if (preserve) this.doClick(c,fl,3) else this.doClick(c,fl) if (edit) this.editCell(); } /** * @desc: moves specified cell to visible area (scrolls) * @param: cell_obj - object of the cell to work with * @param: onlyVScroll - allow only vertical positioning * @type: private * @topic: 2,4,7 */ this.moveToVisible = function(cell_obj,onlyVScroll){ try{ var distance = cell_obj.offsetLeft+cell_obj.offsetWidth+20; if(distance>(this.objBox.offsetWidth+this.objBox.scrollLeft)){ var scrollLeft = distance - this.objBox.offsetWidth; }else if(cell_obj.offsetLeft(this.objBox.offsetHeight+this.objBox.scrollTop)){ var scrollTop = distance - this.objBox.offsetHeight; }else if(cell_obj.offsetTop(new Date).valueOf()) return; this._Opera_stop=null; } if(this.editor && this.editor!=null){ this.cell.className=this.cell.className.replace("editable",""); if (this.editor.detach()) this.cell.wasChanged = true; var g=this.editor; this.editor=null; var z=this.onEditCell(2,this.row.idd,this.cell._cellIndex,g.getValue(),g.val); if ((typeof(z)=="string")||(typeof(z)=="number")) g.setValue(z); else if (!z) g.setValue(g.val); } } /** * @desc: manages keybord activity in grid * @type: private * @topic: 7 */ this.doKey = function(ev){ if (!ev) return true; if ((ev.target||ev.srcElement).value!==window.undefined){ var zx= (ev.target||ev.srcElement); if ((!zx.parentNode)||(zx.parentNode.className.indexOf("editable")==-1)) return true; } if ((globalActiveDHTMLGridObject)&&(this!=globalActiveDHTMLGridObject)) return globalActiveDHTMLGridObject.doKey(ev); if(this.isActive==false){ //document.body.onkeydown = ""; return true; } if (this._htkebl) return true; if ((this.onKPR)&&(!this.onKPR(ev.keyCode,ev.ctrlKey,ev.shiftKey))) return false; try{ var type = this.cellType[this.cell._cellIndex] //ENTER if(ev.keyCode==13 && (ev.ctrlKey || ev.shiftKey)){ var rowInd = this.rowsCol._dhx_find(this.row) if(window.event.ctrlKey && rowInd!=this.rowsCol.length-1){ if(this.row.rowIndex==this.obj._rowslength()-1 && this.dynScroll && this.dynScroll!='false') this.doDynScroll("dn") this.selectCell(this.rowsCol[rowInd+1],this.cell._cellIndex,true); }else if(ev.shiftKey && rowInd!=0){ if(this.row.rowIndex==0 && this.dynScroll && this.dynScroll!='false') this.doDynScroll("up") this.selectCell(this.rowsCol[rowInd-1],this.cell._cellIndex,true); } _isIE?ev.returnValue=false:ev.preventDefault(); } if(ev.keyCode==13 && !ev.ctrlKey && !ev.shiftKey){ this.editStop(); this.onEnter(this.row.idd,this.cell._cellIndex); _isIE?ev.returnValue=false:ev.preventDefault(); } //TAB if(ev.keyCode==9 && !ev.shiftKey ){ this.editStop(); var aind=this.cell._cellIndex; var arow=this.row; //#__pro_feature:21092006{ //#colspan:20092006{ if (arow._childIndexes) while (arow._childIndexes[aind+1]==arow._childIndexes[aind]) aind++; //#} //#} aind++; if (aind>=this.obj.rows[0].childNodes.length){ aind=0; arow=this.rowsCol[this.rowsCol._dhx_find(this.row)+1]; if (!arow){ aind=this.row.childNodes.length-1; return true; } } this.selectCell(arow||this.row,aind,((arow)&&(this.row!=arow))); this.editCell() _isIE?ev.returnValue=false:ev.preventDefault(); }else if(ev.keyCode==9 && ev.shiftKey){ this.editStop(); var aind=this.cell._cellIndex-1; var arow=this.row; //#__pro_feature:21092006{ //#colspan:20092006{ if (arow._childIndexes) while ((aind>=0)&&(arow._childIndexes[aind]==arow._childIndexes[aind+1])) aind--; //#} //#} if (aind<0) { aind=this.obj.rows[0].childNodes.length-1; //#__pro_feature:21092006{ //#colspan:20092006{ if (arow._childIndexes) while (((arow._childIndexes[aind]!="0")&&(!arow._childIndexes[aind]))&&(aind>=0)) aind--; //#} //#} arow=this.rowsCol[this.rowsCol._dhx_find(this.row)-1]; if (!arow) { aind=0; return true; } } this.selectCell(arow||this.row,aind,((arow)&&(this.row!=arow))); this.editCell() _isIE?ev.returnValue=false:ev.preventDefault(); } //UP & DOWN if(ev.keyCode==40 || ev.keyCode==38){//&& ev.ctrlKey if (this.editor && this.editor.combo){ if (ev.keyCode==40) this.editor.shiftNext(); if (ev.keyCode==38) this.editor.shiftPrev(); return false; } else{ var rowInd = this.row.rowIndex;//rowsCol._dhx_find(this.row) if(ev.keyCode==38 && rowInd!=1){ //if(this.row.rowIndex==0 && this.dynScroll && this.dynScroll!='false') // this.doDynScroll("up") this.selectCell(this.obj._rows(rowInd-2),this.cell._cellIndex,true); }else if(this.pagingOn && ev.keyCode==38 && rowInd==1 && this.currentPage!=1){ this.changePage(this.currentPage-1) this.selectCell(this.obj.rows[this.obj.rows.length-1],this.cell._cellIndex,true); }else if(ev.keyCode==40 && rowInd!=this.rowsCol.length && rowInd!=this.obj.rows.length-1){ //if(this.row.rowIndex==this.obj._rowslength-1 && this.dynScroll && this.dynScroll!='false') // this.doDynScroll("dn") this.selectCell(this.obj._rows(rowInd),this.cell._cellIndex,true); }else if(this.pagingOn && ev.keyCode==40 && (this.row!=this.rowsCol[this.rowsCol.length-1] || this.rowsBuffer[0].length>0 || !this.recordsNoMore)){ this.changePage(this.currentPage+1) this.selectCell(this.obj._rows(0),this.cell._cellIndex,true); } } _isIE?ev.returnValue=false:ev.preventDefault(); } //F2 if((ev.keyCode==113)&&(this._f2kE)){ this.editCell(); return false; } //SPACE if(ev.keyCode==32){// && (type=='ch'|| type.indexOf('ra')==0)){ var c = this.cell var ed = cells4(c); //this.cell.children(0).click() if(ed.changeState()!=false) _isIE?ev.returnValue=false:ev.preventDefault(); } //Esc if(ev.keyCode==27 && this.oe!=false){ this.editStop(); _isIE?ev.returnValue=false:ev.preventDefault(); } //PAGEUP / PAGEDOWN if(ev.keyCode==33 || ev.keyCode==34){ if(this.pagingOn){ if(ev.keyCode==33){ this.changePage(this.currentPage-1) }else{ this.changePage(this.currentPage+1) } } this.selectCell(this.getRowIndex(this.row.idd)+this.rowsBufferOutSize*(ev.keyCode!=33?1:-1),this.cell._cellIndex,true); /*if(ev.keyCode==33) this.doDynScroll("up") else this.doDynScroll("dn")*/ _isIE?ev.returnValue=false:ev.preventDefault(); } //RIGHT LEFT if (!this.editor) { if(ev.keyCode==37 && this.cellType._dhx_find("tree")!=-1){ this.collapseKids(this.row) _isIE?ev.returnValue=false:ev.preventDefault(); } if(ev.keyCode==39 && this.cellType._dhx_find("tree")!=-1){ this.expandKids(this.row) _isIE?ev.returnValue=false:ev.preventDefault(); } } return true; } catch(er){ return true; } } /** * @desc: selects row (?)for comtatibility with previous version * @param: cell - cell object(or cell's child) * @invoke: click on cell(or cell content) * @type: private * @topic: 1,2 */ this.getRow = function(cell){ if(!cell) cell = window.event.srcElement; if(cell.tagName!='TD') cell = cell.parentElement; r = cell.parentElement; if(this.cellType[cell._cellIndex]=='lk') eval(this.onLink+"('"+this.getRowId(r.rowIndex)+"',"+cell._cellIndex+")"); this.selectCell(r,cell._cellIndex,true) } /** * @desc: selects row (and first cell of it) * @param: r - row index or row object * @param: fl - if true, then call function on select * @param: preserve - preserve previously selected rows true/false (false by default) * @type: public * @topic: 1,2 */ this.selectRow = function(r,fl,preserve){ if(typeof(r)!='object') r = this.rowsCol[r] this.selectCell(r,0,fl,preserve) }; /** * @desc: sorts specified column * @param: col - column index * @param: type - str.int.date * @param: order - asc.desc * @type: public * @topic: 2,3,5,9 */ this.sortRows = function(col,type,order){ while(this.addRowsFromBuffer(true));//nb:paging - before sorting put all rows from buffer to rows collection. //if tree cell exists if(this.cellType._dhx_find("tree")!=-1){ return this.sortTreeRows(col,type,order) } var self=this; var arrTS=new Array(); var atype = this.cellType[col]; for (var i=0; iarrTS[b.idd]?1:-1 else return arrTS[a.idd]=0;i--){ var node = tmpAr[i] if(!this.deleteRow(node.idd,node)){ this.selectedRows[this.selectedRows.length] = node; }else{ if(node==this.row){ var ind = i; } } /* this.rowsAr[node.idd] = null; var posInCol = this.rowsCol._dhx_find(node) this.rowsCol[posInCol].parentNode.removeChild(this.rowsCol[posInCol]);//nb:this.rowsCol[posInCol].removeNode(true); this.rowsCol._dhx_removeAt(posInCol)*/ } if(ind){ try{ if(ind+1>this.rowsCol.length)//this.obj.rows.length) ind--; this.selectCell(ind,0,true) }catch(er){ this.row = null this.cell = null } } } /** * @desc: gets selected row id * @returns: id of selected row (list of ids with default delimiter) or null if non row selected * @type: public * @topic: 1,2,9 */ this.getSelectedId = function(){ var selAr = new Array(0); for(var i=0;i=0) { this._askRealRows(ind); return this.getRowById(id); } } else if(this.pagingOn){//use new buffer var ind = this.rowsBuffer[0]._dhx_find(id); if (ind>=0) { var r = this.createRowFromXMLTag(this.rowsBuffer[1][ind]); this.rowsBuffer[1][ind] = r; return r; }else{ return null; } } else if (this._slowParse) //smart parsing mode in treegrid return this._seekAndDeploy(id); return null; } /** * @desc: gets row by index from rowsCola and rowsBuffer * @param: ind - row index * @returns: row object * @type: private */ this.getRowByIndex = function(ind){ if(this.rowsCol.length<=ind){ if((this.rowsCol.length+this.rowsBuffer[0].length)<=ind) return null; else{ var indInBuf = ind-this.rowsCol.length-1; var r = this.createRowFromXMLTag(this.rowsBuffer[1][indInBuf]); return r; } }else{ return this.rowsCol[ind] } } /** * @desc: gets row index by id (grid only) * @param: row_id - row id * @returns: row index or -1 if there is no row with specified id * @type: public * @topic: 2 */ this.getRowIndex = function(row_id){ var ind = this.rowsCol._dhx_find(this.getRowById(row_id)); if(ind!=-1) return ind; else{ ind = this.rowsBuffer[0]._dhx_find(row_id) if(ind!=-1) return ind+this.rowsCol.length; return -1; } } /** * @desc: gets row id by index * @param: ind - row index * @returns: row id or null if there is no row with specified index * @type: public * @topic: 2 */ this.getRowId = function(ind){ var z=this.rowsCol[parseInt(ind)]; if (z) return z.idd; return (this.rowsBuffer[0][this._dload?ind:(ind-this.rowsCol.length-1)]||null); } /** * @desc: sets new id for row by its index * @param: ind - row index * @param: row_id - new row id * @type: public * @topic: 2 */ this.setRowId = function(ind,row_id){ var r = this.rowsCol[ind] this.changeRowId(r.idd,row_id) } /** * @desc: changes id of the row to the new one * @param: oldRowId - row id to change * @param: newRowId - row id to set * @type:public * @topic: 2 */ this.changeRowId = function(oldRowId,newRowId){ var row = this.rowsAr[oldRowId] row.idd = newRowId; if(this.UserData[oldRowId]){ this.UserData[newRowId] = this.UserData[oldRowId] this.UserData[oldRowId] = null; } if (this.loadedKidsHash){ var oldHash=this.loadedKidsHash.get(oldRowId); if (oldHash!=null){ for (var z=0; z0){ if(this.hdr.rows[0].cells.length>=this.columnIds.length){ for(var i=0;i0)&&(z.firstChild.nodeType==1)){ this.rowsCol[i].cells[j].firstChild.disabled = ifl; } } } } this.isEditable = !ifl; } /** * @desc: selects row * @param: row_id - row id * @param: multiFL - VOID. select multiple rows * @param: show - VOID. scroll row to view * @param: call - true to call function on select * @type: public * @topic: 1,2 */ this.setSelectedRow = function(row_id, multiFL,show,call){ if(!call) call = false; this.selectCell(this.getRowById(row_id),0,call,multiFL);//selectRow(this.getRowById(row_id),false) if(arguments.length>2 && show==true){ this.moveToVisible(this.getRowById(row_id).cells[0],true) } } /** * @desc: removes selection from the grid * @type: public * @topic: 1,9 */ this.clearSelection = function(){ this.editStop() for(var i=0;i]+)\].*/,"$1"); label = label.substr(label.indexOf("]")+1,label.length) hdrHTML+="" } hdrHTML+=label; hdrHTML+=""; z.cells[col].innerHTML = hdrHTML; }else{//if images in header header z.cells[col].style.textAlign = "left"; z.cells[col].innerHTML = ""; //preload sorting headers (asc/desc) var a = new Image(); a.src = this.imgURL+""+label.replace(/(\.[a-z]+)/,".desc$1"); this.preloadImagesAr[this.preloadImagesAr.length] = a; var b = new Image(); b.src = this.imgURL+""+label.replace(/(\.[a-z]+)/,".asc$1"); this.preloadImagesAr[this.preloadImagesAr.length] = b; } } /** * @desc: deletes all rows in grid * @param: header - (boolean) enable/disable cleaning header * @type: public * @topic: 5,7,9 */ this.clearAll = function(header){ this.limit=this._limitC=0; this.editStop(); if (this._dload){ this.objBox.scrollTop=0; this.limit=this._limitC||0; this._initDrF=true; } var len = this.rowsCol.length; //treegrid if(this.loadedKidsHash!=null){ this.loadedKidsHash.clear(); this.loadedKidsHash.put("hashOfParents",new Hashtable()); } //for some case len = this.obj._rowslength(); for(var i=len-1;i>=0;i--){ var t_r=this.obj._rows(i); t_r.parentNode.removeChild(t_r); } if (header){ this.obj.rows[0].parentNode.removeChild(this.obj.rows[0]); for(var i=this.hdr.rows.length-1;i>=0;i--){ var t_r=this.hdr.rows[i]; t_r.parentNode.removeChild(t_r); } } //.. this.row = null; this.cell = null; this._hrrar=null; this.rowsCol = new dhtmlxArray(0) this.rowsAr = new Array(0);//array of rows by idd this.rowsBuffer = new Array(new dhtmlxArray(0),new dhtmlxArray(0));//buffer of rows loaded, but not rendered (array of ids, array of cell values arrays) this.UserData = new Array(0) if(this.pagingOn){ this.changePage(1); //this.createPagingBlock(); } if ((this._hideShowColumn)&&(this.hdr.rows[0])) for (var i=0; i=el._cellIndex && this.fldSort[el._cellIndex]!='na'){//this.entBox.fieldstosort!="" && if((((this.sortImg.src.indexOf("_desc.gif")==-1) && (!repeatFl)) || ((this.sortImg.style.filter!="") && (repeatFl))) && (this.fldSorted==el)){//desc var sortType = "desc"; this.sortImg.src = this.imgURL+"sort_desc.gif"; }else{//asc var sortType = "asc"; this.sortImg.src = this.imgURL+"sort_asc.gif"; } if ((this.onCLMS)&&(!this.onCLMS(ind,this,sortType))) return; //for header images if(this.useImagesInHeader){ var cel=this.hdr.rows[1].cells[el._cellIndex].firstChild; if(this.fldSorted!=null){ var celT=this.hdr.rows[1].cells[this.fldSorted._cellIndex].firstChild; celT.src = celT.src.replace(/\.[ascde]+\./,"."); } cel.src = cel.src.replace(/(\.[a-z]+)/,"."+sortType+"$1") } //. this.sortRows(el._cellIndex,this.fldSort[el._cellIndex],sortType) this.fldSorted = el; var c=this.hdr.rows[1]; var real_el=c._childIndexes?c._childIndexes[el._cellIndex]:el._cellIndex; this.setSortImgPos(this.hdr.rows[1].childNodes[real_el]._cellIndex); } } //#__pro_feature:21092006{ //#custom_sort:21092006{ /** * @desc: set custom sorting (custom sort has three params - valueA,valueB,order; where order can be asc or des) * @param: func - column index * @param: col - str.int.date * @type: public * @edition: Professional * @topic: 3 */ this.setCustomSorting = function(func,col){ if (!this._customSorts) this._customSorts=new Array(); this._customSorts[col]=func; this.fldSort[col]="cus"; } //#} //#} /** * @desc: specify if values passed to Header are images names * @param: fl - true to treat column header values as image names * @type: public * @before_init: 1 * @topic: 0,3 */ this.enableHeaderImages = function(fl){ this.useImagesInHeader = fl; } /** * @desc: set header label and default params for new headers * @param: hdrStr - header string with delimiters * @param: splitMarker - string used as a split marker, optional * @type: public * @before_init: 1 * @topic: 0,3 */ this.setHeader = function(hdrStr,splitSign){ var arLab = hdrStr.split(this.delim); var arWdth = new Array(0); var arTyp = new dhtmlxArray(0); var arAlg = new Array(0); var arVAlg = new Array(0); var arSrt = new Array(0); for(var i=0;i4)&&(typeof(window[this.fldSort[i]])=="function")) { if (!this._customSorts) this._customSorts=new Array(); this._customSorts[i]=window[this.fldSort[i]]; this.fldSort[i]="cus"; } //#} //#} } /** * @desc: set align of columns * @param: alStr - align string with delimiters * @before_init: 1 * @type: public * @topic: 0,3 */ this.setColAlign = function(alStr){ this.cellAlign = alStr.split(this.delim) } /** * @desc: set vertical align of columns * @param: alStr - align string with delimiters * @before_init: 1 * @type: public * @topic: 0,3 */ this.setColVAlign = function(alStr){ this.cellVAlign = alStr.split(this.delim) } /** * @desc: sets grid to multiline row support (call before init) * @param: fl - true to set multiline support * @type: deprecated * @before_init: 1 * @topic: 0,2 */ this.setMultiLine = function(fl){ if(fl==true) this.multiLine = -1; } /** * @desc: use to create grid with no header * @param: fl - true to use no header in the grid * @type: public * @before_init: 1 * @topic: 0,7 */ this.setNoHeader = function(fl){ if(fl==true) this.noHeader = true; } /** * @desc: scrolls row to the visible area * @param: rowID - row id * @type: public * @topic: 2,7 */ this.showRow = function(rowID){ this.moveToVisible(this.getRowById(rowID).cells[0],true) } /** * @desc: modify default style of grid and its elements. Call before or after Init * @param: ss_header - style def. expression for header * @param: ss_grid - style def. expression for grid cells * @param: ss_selCell - style def. expression for selected cell * @param: ss_selRow - style def. expression for selected Row * @type: public * @before_init: 2 * @topic: 0,6 */ this.setStyle = function(ss_header,ss_grid,ss_selCell,ss_selRow){ this.ssModifier = [ss_header, ss_grid , ss_selCell,ss_selCell, ss_selRow]; var prefs=["#"+this.entBox.id+" table.hdr td","#"+this.entBox.id+" table.obj td","#"+this.entBox.id+" table.obj tr.rowselected td.cellselected","#"+this.entBox.id+" table.obj td.cellselected","#"+this.entBox.id+" table.obj tr.rowselected td"]; for (var i=0; ithis.rowsCol.length){ this.addRowsFromBuffer() } this.dynScrollPos+=this.dynScrollPageSize } var start = Math.max(this.dynScrollPos-this.dynScrollPageSize,0); for(var i = start;i=this.dynScrollPos && ithis.objBox.offsetHeight) this.dynScrollPos-=(this.dynScrollPageSize-i) } this.setSizes() } /** * @desc: counts the number of rows to fit the grid for dyn scroll * @type: private * @topic: 0 */ this.setDynScrollPageSize = function(){ if(this.dynScroll && this.dynScroll!='false'){ var rowsH = 0; try{ var rowH = this.obj._rows(0).scrollHeight; }catch(er){ var rowH = 20 } for(var i=0;i<1000;i++){ rowsH = i*rowH; if(this.objBox.offsetHeight"; var i=0; for(var jj=0;jj"; i++; } out+=""; return out; } /** * @desc: serialize TR or xml node to grid formated xml (row tag) * @param: r - TR or xml node (row) * @retruns: string - xml representation of passed row * @type: private */ this._serializeRow = function(r){ var out = ""; if ((!r)||(r._sRow)||(r._rLoad)) { if (this.xmlSerializer) out+=this.xmlSerializer.serializeToString(this.rowsBuffer[1][i]); else out+=this.rowsBuffer[1][i].xml; return out; } var selStr = ""; //serialize selection if(this._sAll && this.selectedRows._dhx_find(r)!=-1) selStr = " selected='1'"; out += ""; //userdata if(this._sUDa && this.UserData[r.idd]){ keysAr = this.UserData[r.idd].getKeys() for(var ii=0;ii"+this.UserData[r.idd].get(keysAr[ii])+""; } } //cells var changeFl=false; for(var jj=0;jj1) out+=" colspan=\""+cvx.colSpan+"\" "; //#} if (this._chAttr){ if (zx.wasChanged()){ out+=" changed=\"1\""; changeFl=true; } } else if ((this._onlChAttr)&&(zx.wasChanged())) changeFl=true; if (this._sAll) out+=(cvx._aimage?(" image='"+cvx._aimage+"'"):"")+">"+((zxVal===null)?"":zxVal)+""; else out+=">"+((zxVal===null)?"":zxVal)+""; //#colspan:20092006{ if ((this._ecspn)&&(cvx.colSpan)){ cvx=cvx.colSpan-1; for (var u=0; u"; out+=this.hdr.rows[1].cells[i].childNodes[0].innerHTML; var z=this.getCombo(i); if (z) for (var j=0; j"+z.values[j]+""; out+="" } return out+=""; } /** * @desc: return actual xml of grid * @type: public * @edition: Professional * @topic: 5,7 */ this.serialize = function(){ if(_isFF) this.xmlSerializer = new XMLSerializer(); var out=''; if (this._mathSerialization) this._agetm="getMathValue"; else this._agetm="getValue"; if(this._sUDa && this.UserData["gridglobaluserdata"]){ var keysAr = this.UserData["gridglobaluserdata"].getKeys() for(var i=0;i"+this.UserData["gridglobaluserdata"].get(keysAr[i])+""; } } if (this._sConfig) out+=this._serialiseConfig(); out+=this._serialise(this.rowsCol)[0]; if (!this._dload){ //rows buffer for(var i=0;i8.5)) { this.hdr.onmousemove = new Function("e","this.grid.changeCursorState(e||window.event)"); this.hdr.onmousedown = new Function("e","this.grid.startColResize(e||window.event)"); } this.obj.onmousemove = this._drawTooltip; this.obj.onclick = new Function("e","this.grid._doClick(e||window.event); if (this.grid._sclE) this.grid.editCell(e||window.event); (e||event).cancelBubble=true; "); this.entBox.onmousedown = new Function("e","return this.grid._doContClick(e||window.event);"); this.obj.ondblclick = new Function("e","if(!this.grid.wasDblClicked(e||window.event)){return false}; if (this.grid._dclE) this.grid.editCell(e||window.event); (e||event).cancelBubble=true;"); this.hdr.onclick = this._onHeaderClick; this.hdr.ondblclick = this._onHeaderDblClick; //VOID this.grid.ondblclick = this.onDoubleClick; if (!document.body._dhtmlxgrid_onkeydown){ dhtmlxEvent(document,"keydown",new Function("e","if (globalActiveDHTMLGridObject) return globalActiveDHTMLGridObject.doKey(e||window.event); return true;")); document.body._dhtmlxgrid_onkeydown=true; } dhtmlxEvent(document.body,"click",function(){ if (self.editStop) self.editStop(); return true;}); //nb:document.body.attachEvent("onclick",new Function("","if(this.document.getElementById('"+this.entBox.id+"').grid.isActive==-1)this.document.getElementById('"+this.entBox.id+"').grid.setActive(false)")) //activity management this.entBox.onbeforeactivate = new Function("","this.grid.setActive(); event.cancelBubble=true;"); this.entBox.onbeforedeactivate = new Function("","this.grid.isActive=-1; event.cancelBubble=true;"); //postprocessing events (method can be redeclared to react on some events during processing) this.doOnRowAdded = function(row){}; return this; } /** * @desc: detect is current grid is a treeGrid * @type: private * @topic: 2 */ dhtmlXGridObject.prototype.isTreeGrid= function(){ return (this.cellType._dhx_find("tree")!=-1); } /** * @desc: adds row to the specified position * @param: new_id - id for new row * @param: text - Array of values or String(with delimiter as in delimiter parameter) * @param: [ind] - index of row (0 by default) * @returns: new row dom object * @type: public * @topic: 2 */ dhtmlXGridObject.prototype.addRow = function(new_id,text,ind){ var r = this._addRow(new_id,text,ind); if(this.onRowAdded) this.onRowAdded(new_id); if (this.onRowCr) this.onRowCr(r.idd,r,null); if(this.pagingOn) this.changePage(this.currentPage) this.setSizes(); return r; } /** * @desc: first step of add row, created a TR * @type: private */ dhtmlXGridObject.prototype._prepareRow=function(new_id){ var r=document.createElement("TR"); r.idd = new_id; r.grid = this; for(var i=0;ithis.rowsCol.length) ind = this.rowsCol.length; } if (!skip) if ((ind==(this.obj.rows.length-1))||(!this.rowsCol[ind])) if (_isKHTML) this.obj.appendChild(r); else{ this.obj.firstChild.appendChild(r); } else { this.rowsCol[ind].parentNode.insertBefore(r,this.rowsCol[ind]); } this.rowsAr[r.idd] = r; this.rowsCol._dhx_insertAt(ind,r); if (this._cssEven){ if (ind%2==1) r.className+=" "+this._cssUnEven; else r.className+=" "+this._cssEven; if (ind!=(this.rowsCol.length-1)) this._fixAlterCss(ind+1); } //this.chngCellWidth(ind) this.doOnRowAdded(r); //bad code, need to be rethinked if ((this.math_req)&&(!this._parsing_)){ for(var i=0;ithis.rowsCol.length && ind<(this.rowsCol.length+this.rowsBuffer[0].length)){ var inBufInd = ind - this.rowsCol.length; this.rowsBuffer[0]._dhx_insertAt(inBufInd,new_id); this.rowsBuffer[1]._dhx_insertAt(inBufInd,row); return row; } return this._insertRowAt(row,ind); } /** * @desc: hide/show row (warning! - this command doesn't affect row indexes, only visual appearance) * @param: ind - column index * @param: state - true/false - hide/show column * @type: public */ dhtmlXGridObject.prototype.setRowHidden=function(id,state){ var f=convertStringToBoolean(state); //var ind=this.getRowIndex(id); //if (id<0) // return; var row= this.getRowById(id)//this.rowsCol[ind]; if(!row) return; if (row.expand==="") this.collapseKids(row); if ((state)&&(row.style.display!="none")){ row.style.display="none"; var z=this.selectedRows._dhx_find(row); if (z!=-1){ row.className=row.className.replace("rowselected",""); for (var i=0; i