/** * jqGrid extension - Tree Grid * Tony Tomov tony@trirand.com * http://trirand.com/blog/ * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html **/ /*global document, jQuery, $ */ (function($) { $.jgrid.extend({ setTreeNode : function(i, len){ return this.each(function(){ var $t = this; if( !$t.grid || !$t.p.treeGrid ) {return;} var expCol = $t.p.expColInd, expanded = $t.p.treeReader.expanded_field, isLeaf = $t.p.treeReader.leaf_field, level = $t.p.treeReader.level_field, icon = $t.p.treeReader.icon_field, loaded = $t.p.treeReader.loaded, lft, rgt, curLevel, ident,lftpos, twrap, ldat, lf; while(i"; twrap += "
").prepend(twrap); if(curLevel !== parseInt($t.p.tree_root_level,10)) { var pn = $($t).jqGrid('getNodeParent',ldat); expan = pn && pn.hasOwnProperty(expanded) ? pn[expanded] : true; if( !expan ){ $($t.rows[i]).css("display","none"); } } $($t.rows[i].cells[expCol]) .find("div.treeclick") .bind("click",function(e){ var target = e.target || e.srcElement, ind2 =$(target,$t.rows).closest("tr.jqgrow")[0].id, pos = $t.p._index[ind2]; if(!$t.p.data[pos][isLeaf]){ if($t.p.data[pos][expanded]){ $($t).jqGrid("collapseRow",$t.p.data[pos]); $($t).jqGrid("collapseNode",$t.p.data[pos]); } else { $($t).jqGrid("expandRow",$t.p.data[pos]); $($t).jqGrid("expandNode",$t.p.data[pos]); } } return false; }); if($t.p.ExpandColClick === true) { $($t.rows[i].cells[expCol]) .find("span.cell-wrapper") .css("cursor","pointer") .bind("click",function(e) { var target = e.target || e.srcElement, ind2 =$(target,$t.rows).closest("tr.jqgrow")[0].id, pos = $t.p._index[ind2]; if(!$t.p.data[pos][isLeaf]){ if($t.p.data[pos][expanded]){ $($t).jqGrid("collapseRow",$t.p.data[pos]); $($t).jqGrid("collapseNode",$t.p.data[pos]); } else { $($t).jqGrid("expandRow",$t.p.data[pos]); $($t).jqGrid("expandNode",$t.p.data[pos]); } } $($t).jqGrid("setSelection",ind2); return false; }); } i++; } }); }, setTreeGrid : function() { return this.each(function (){ var $t = this, i=0, pico, ecol = false, nm, key, dupcols=[]; if(!$t.p.treeGrid) {return;} if(!$t.p.treedatatype ) {$.extend($t.p,{treedatatype: $t.p.datatype});} $t.p.subGrid = false;$t.p.altRows =false; $t.p.pgbuttons = false;$t.p.pginput = false; $t.p.gridview = true; $t.p.multiselect = false;$t.p.rowList = []; $t.p.expColInd = 0; pico = 'ui-icon-triangle-1-' + ($t.p.direction=="rtl" ? 'w' : 'e'); $t.p.treeIcons = $.extend({plus:pico,minus:'ui-icon-triangle-1-s',leaf:'ui-icon-radio-off'},$t.p.treeIcons || {}); if($t.p.treeGridModel == 'nested') { $t.p.treeReader = $.extend({ level_field: "level", left_field:"lft", right_field: "rgt", leaf_field: "isLeaf", expanded_field: "expanded", loaded: "loaded", icon_field: "icon" },$t.p.treeReader); } else if($t.p.treeGridModel == 'adjacency') { $t.p.treeReader = $.extend({ level_field: "level", parent_id_field: "parent", leaf_field: "isLeaf", expanded_field: "expanded", loaded: "loaded", icon_field: "icon" },$t.p.treeReader ); } for ( key in $t.p.colModel){ if($t.p.colModel.hasOwnProperty(key)) { nm = $t.p.colModel[key].name; if( nm == $t.p.ExpandColumn && !ecol ) { ecol = true; $t.p.expColInd = i; } i++; // for(var tkey in $t.p.treeReader) { if($t.p.treeReader[tkey] == nm) dupcols.push(nm); } } } $.each($t.p.treeReader,function(j,n){ if(n && $.inArray(n, dupcols) === -1){ if(j==='leaf_field') { $t.p._treeleafpos= i; } i++; $t.p.colNames.push(n); $t.p.colModel.push({name:n,width:1,hidden:true,sortable:false,resizable:false,hidedlg:true,editable:true,search:false}); } }); }); }, expandRow: function (record){ this.each(function(){ var $t = this; if(!$t.grid || !$t.p.treeGrid) {return;} var childern = $($t).jqGrid("getNodeChildren",record), //if ($($t).jqGrid("isVisibleNode",record)) { expanded = $t.p.treeReader.expanded_field; $(childern).each(function(i){ var id = $.jgrid.getAccessor(this,$t.p.localReader.id); $("#"+id,$t.grid.bDiv).css("display",""); if(this[expanded]) { $($t).jqGrid("expandRow",this); } }); //} }); }, collapseRow : function (record) { this.each(function(){ var $t = this; if(!$t.grid || !$t.p.treeGrid) {return;} var childern = $($t).jqGrid("getNodeChildren",record), expanded = $t.p.treeReader.expanded_field; $(childern).each(function(i){ var id = $.jgrid.getAccessor(this,$t.p.localReader.id); $("#"+id,$t.grid.bDiv).css("display","none"); if(this[expanded]){ $($t).jqGrid("collapseRow",this); } }); }); }, // NS ,adjacency models getRootNodes : function() { var result = []; this.each(function(){ var $t = this; if(!$t.grid || !$t.p.treeGrid) {return;} switch ($t.p.treeGridModel) { case 'nested' : var level = $t.p.treeReader.level_field; $($t.p.data).each(function(i){ if(parseInt(this[level],10) === parseInt($t.p.tree_root_level,10)) { result.push(this); } }); break; case 'adjacency' : var parent_id = $t.p.treeReader.parent_id_field; $($t.p.data).each(function(i){ if(this[parent_id] === null || String(this[parent_id]).toLowerCase() == "null") { result.push(this); } }); break; } }); return result; }, getNodeDepth : function(rc) { var ret = null; this.each(function(){ if(!this.grid || !this.p.treeGrid) {return;} var $t = this; switch ($t.p.treeGridModel) { case 'nested' : var level = $t.p.treeReader.level_field; ret = parseInt(rc[level],10) - parseInt($t.p.tree_root_level,10); break; case 'adjacency' : ret = $($t).jqGrid("getNodeAncestors",rc).length; break; } }); return ret; }, getNodeParent : function(rc) { var result = null; this.each(function(){ var $t = this; if(!$t.grid || !$t.p.treeGrid) {return;} switch ($t.p.treeGridModel) { case 'nested' : var lftc = $t.p.treeReader.left_field, rgtc = $t.p.treeReader.right_field, levelc = $t.p.treeReader.level_field, lft = parseInt(rc[lftc],10), rgt = parseInt(rc[rgtc],10), level = parseInt(rc[levelc],10); $(this.p.data).each(function(){ if(parseInt(this[levelc],10) === level-1 && parseInt(this[lftc],10) < lft && parseInt(this[rgtc],10) > rgt) { result = this; return false; } }); break; case 'adjacency' : var parent_id = $t.p.treeReader.parent_id_field, dtid = $t.p.localReader.id; $(this.p.data).each(function(i,val){ if(this[dtid] == rc[parent_id] ) { result = this; return false; } }); break; } }); return result; }, getNodeChildren : function(rc) { var result = []; this.each(function(){ var $t = this; if(!$t.grid || !$t.p.treeGrid) {return;} switch ($t.p.treeGridModel) { case 'nested' : var lftc = $t.p.treeReader.left_field, rgtc = $t.p.treeReader.right_field, levelc = $t.p.treeReader.level_field, lft = parseInt(rc[lftc],10), rgt = parseInt(rc[rgtc],10), level = parseInt(rc[levelc],10); $(this.p.data).each(function(i){ if(parseInt(this[levelc],10) === level+1 && parseInt(this[lftc],10) > lft && parseInt(this[rgtc],10) < rgt) { result.push(this); } }); break; case 'adjacency' : var parent_id = $t.p.treeReader.parent_id_field, dtid = $t.p.localReader.id; $(this.p.data).each(function(i,val){ if(this[parent_id] == rc[dtid]) { result.push(this); } }); break; } }); return result; }, getFullTreeNode : function(rc) { var result = []; this.each(function(){ var $t = this, len; if(!$t.grid || !$t.p.treeGrid) {return;} switch ($t.p.treeGridModel) { case 'nested' : var lftc = $t.p.treeReader.left_field, rgtc = $t.p.treeReader.right_field, levelc = $t.p.treeReader.level_field, lft = parseInt(rc[lftc],10), rgt = parseInt(rc[rgtc],10), level = parseInt(rc[levelc],10); $(this.p.data).each(function(i){ if(parseInt(this[levelc],10) >= level && parseInt(this[lftc],10) >= lft && parseInt(this[lftc],10) <= rgt) { result.push(this); } }); break; case 'adjacency' : if(rc) { result.push(rc); var parent_id = $t.p.treeReader.parent_id_field, dtid = $t.p.localReader.id; $(this.p.data).each(function(i){ len = result.length; for (i = 0; i < len; i++) { if (result[i][dtid] == this[parent_id]) { result.push(this); break; } } }); } break; } }); return result; }, // End NS, adjacency Model getNodeAncestors : function(rc) { var ancestors = []; this.each(function(){ if(!this.grid || !this.p.treeGrid) {return;} var parent = $(this).jqGrid("getNodeParent",rc); while (parent) { ancestors.push(parent); parent = $(this).jqGrid("getNodeParent",parent); } }); return ancestors; }, isVisibleNode : function(rc) { var result = true; this.each(function(){ var $t = this; if(!$t.grid || !$t.p.treeGrid) {return;} var ancestors = $($t).jqGrid("getNodeAncestors",rc), expanded = $t.p.treeReader.expanded_field; $(ancestors).each(function(){ result = result && this[expanded]; if(!result) {return false;} }); }); return result; }, isNodeLoaded : function(rc) { var result; this.each(function(){ var $t = this; if(!$t.grid || !$t.p.treeGrid) {return;} var isLeaf = $t.p.treeReader.leaf_field; if(rc !== undefined ) { if(rc.loaded !== undefined) { result = rc.loaded; } else if( rc[isLeaf] || $($t).jqGrid("getNodeChildren",rc).length > 0){ result = true; } else { result = false; } } else { result = false; } }); return result; }, expandNode : function(rc) { return this.each(function(){ if(!this.grid || !this.p.treeGrid) {return;} var expanded = this.p.treeReader.expanded_field, parent = this.p.treeReader.parent_id_field, loaded = this.p.treeReader.loaded, level = this.p.treeReader.level_field, lft = this.p.treeReader.left_field, rgt = this.p.treeReader.right_field; if(!rc[expanded]) { var id = $.jgrid.getAccessor(rc,this.p.localReader.id); var rc1 = $("#"+id,this.grid.bDiv)[0]; var position = this.p._index[id]; if( $(this).jqGrid("isNodeLoaded",this.p.data[position]) ) { rc[expanded] = true; $("div.treeclick",rc1).removeClass(this.p.treeIcons.plus+" tree-plus").addClass(this.p.treeIcons.minus+" tree-minus"); } else { rc[expanded] = true; $("div.treeclick",rc1).removeClass(this.p.treeIcons.plus+" tree-plus").addClass(this.p.treeIcons.minus+" tree-minus"); this.p.treeANode = rc1.rowIndex; this.p.datatype = this.p.treedatatype; if(this.p.treeGridModel == 'nested') { $(this).jqGrid("setGridParam",{postData:{nodeid:id,n_left:rc[lft],n_right:rc[rgt],n_level:rc[level]}}); } else { $(this).jqGrid("setGridParam",{postData:{nodeid:id,parentid:rc[parent],n_level:rc[level]}} ); } $(this).trigger("reloadGrid"); rc[loaded] = true; if(this.p.treeGridModel == 'nested') { $(this).jqGrid("setGridParam",{postData:{nodeid:'',n_left:'',n_right:'',n_level:''}}); } else { $(this).jqGrid("setGridParam",{postData:{nodeid:'',parentid:'',n_level:''}}); } } } }); }, collapseNode : function(rc) { return this.each(function(){ if(!this.grid || !this.p.treeGrid) {return;} if(rc.expanded) { rc.expanded = false; var id = $.jgrid.getAccessor(rc,this.p.localReader.id); var rc1 = $("#"+id,this.grid.bDiv)[0]; $("div.treeclick",rc1).removeClass(this.p.treeIcons.minus+" tree-minus").addClass(this.p.treeIcons.plus+" tree-plus"); } }); }, SortTree : function( sortname, newDir, st, datefmt) { return this.each(function(){ if(!this.grid || !this.p.treeGrid) {return;} var i, len, rec, records = [], $t = this, query, roots, rt = $(this).jqGrid("getRootNodes"); // Sorting roots query = $.jgrid.from(rt); query.orderBy(sortname,newDir,st, datefmt); roots = query.select(); // Sorting children for (i = 0, len = roots.length; i < len; i++) { rec = roots[i]; records.push(rec); $(this).jqGrid("collectChildrenSortTree",records, rec, sortname, newDir,st, datefmt); } $.each(records, function(index, row) { var id = $.jgrid.getAccessor(this,$t.p.localReader.id); $('#'+$t.p.id+ ' tbody tr:eq('+index+')').after($('tr#'+id,$t.grid.bDiv)); }); query = null;roots=null;records=null; }); }, collectChildrenSortTree : function(records, rec, sortname, newDir,st, datefmt) { return this.each(function(){ if(!this.grid || !this.p.treeGrid) {return;} var i, len, child, ch, query, children; ch = $(this).jqGrid("getNodeChildren",rec); query = $.jgrid.from(ch); query.orderBy(sortname, newDir, st, datefmt); children = query.select(); for (i = 0, len = children.length; i < len; i++) { child = children[i]; records.push(child); $(this).jqGrid("collectChildrenSortTree",records, child, sortname, newDir, st, datefmt); } }); }, // experimental setTreeRow : function(rowid, data) { var success=false; this.each(function(){ var t = this; if(!t.grid || !t.p.treeGrid) {return;} success = $(t).jqGrid("setRowData",rowid,data); }); return success; }, delTreeNode : function (rowid) { return this.each(function () { var $t = this, rid = $t.p.localReader.id, left = $t.p.treeReader.left_field, right = $t.p.treeReader.right_field, myright, width, res, key; if(!$t.grid || !$t.p.treeGrid) {return;} var rc = $t.p._index[rowid]; if (rc !== undefined) { // nested myright = parseInt($t.p.data[rc][right],10); width = myright - parseInt($t.p.data[rc][left],10) + 1; var dr = $($t).jqGrid("getFullTreeNode",$t.p.data[rc]); if(dr.length>0){ for (var i=0;i= 0 ) { while(i>=0){max = Math.max(max, parseInt($t.p.data[i][$t.p.localReader.id],10)); i--;} } nodeid = max+1; } var prow = $($t).jqGrid('getInd', parentid); leaf = false; // if not a parent we assume root if ( parentid === undefined || parentid === null || parentid==="") { parentid = null; rowind = null; method = 'last'; parentlevel = $t.p.tree_root_level; i = $t.p.data.length+1; } else { method = 'after'; parentindex = $t.p._index[parentid]; parentdata = $t.p.data[parentindex]; parentid = parentdata[$t.p.localReader.id]; parentlevel = parseInt(parentdata[level],10)+1; var childs = $($t).jqGrid('getFullTreeNode', parentdata); // if there are child nodes get the last index of it if(childs.length) { i = childs[childs.length-1][$t.p.localReader.id]; rowind = i; i = $($t).jqGrid('getInd',rowind)+1; } else { i = $($t).jqGrid('getInd', parentid)+1; } // if the node is leaf if(parentdata[isLeaf]) { leaf = true; parentdata[expanded] = true; //var prow = $($t).jqGrid('getInd', parentid); $($t.rows[prow]) .find("span.cell-wrapperleaf").removeClass("cell-wrapperleaf").addClass("cell-wrapper") .end() .find("div.tree-leaf").removeClass($t.p.treeIcons.leaf+" tree-leaf").addClass($t.p.treeIcons.minus+" tree-minus"); $t.p.data[parentindex][isLeaf] = false; parentdata[loaded] = true; } } len = i+1; data[expanded] = false; data[loaded] = true; data[level] = parentlevel; data[isLeaf] = true; if( $t.p.treeGridModel === "adjacency") { data[parent] = parentid; } if( $t.p.treeGridModel === "nested") { // this method requiere more attention var query, res, key; //maxright = parseInt(maxright,10); // ToDo - update grid data if(parentid !== null) { maxright = parseInt(parentdata[right],10); query = $.jgrid.from($t.p.data); query = query.greaterOrEquals(right,maxright,{stype:'integer'}); res = query.select(); if(res.length) { for( key in res) { res[key][left] = res[key][left] > maxright ? parseInt(res[key][left],10) +2 : res[key][left]; res[key][right] = res[key][right] >= maxright ? parseInt(res[key][right],10) +2 : res[key][right]; } } data[left] = maxright; data[right]= maxright+1; } else { maxright = parseInt( $($t).jqGrid('getCol', right, false, 'max'), 10); res = $.jgrid.from($t.p.data) .greater(left,maxright,{stype:'integer'}) .select(); if(res.length) { for( key in res) { res[key][left] = parseInt(res[key][left],10) +2 ; } } res = $.jgrid.from($t.p.data) .greater(right,maxright,{stype:'integer'}) .select(); if(res.length) { for( key in res) { res[key][right] = parseInt(res[key][right],10) +2 ; } } data[left] = maxright+1; data[right] = maxright + 2; } } if( parentid === null || $($t).jqGrid("isNodeLoaded",parentdata) || leaf ) { $($t).jqGrid('addRowData', nodeid, data, method, rowind); $($t).jqGrid('setTreeNode', i, len); } if(parentdata && !parentdata[expanded]) { $($t.rows[prow]) .find("div.treeclick") .click(); } } //}); } }); })(jQuery);