Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Implementation of rowattr callback #284

Merged
merged 1 commit into from

4 participants

@OlegKi

(copy of the previous pull request)

Hello Tony,

I posted some time before the suggestion to implement rowattr callback with the functionality close to cellattr. The pool request contains the implementation of the suggestion.

In main difference to cellattr is the format of return value which should be an object and not a string, so be implemented like in the example

rowattr: function (rowData, inputRowData) {
    return rowData.closed ? {class: "myRowClass"} : {};
}

or

rowattr: function (rowData, inputRowData) {
    return rowData.closed ? {style: "background:yellow"} : {};
}

It simplifys the analyzing. The usage of it in the form ' class="mystyle"' should be parsed more carefully (celp.indexOf('style') > -1, but we have no style attribute inside).

The demo uses XML and another uses JSON as input. The demos use modified version of grid.base.js.

The first parameter of rowattr callback - rowData parameter has "named format" (object with the properties like in name from items of colModel). The format is the same for XML and JSON and it's not depend from jsonReader or xmlReader settings. The second parameter inputRowData is the row exactly like it be in the input data.

Additional advantage is that one have now rd variable which can be used as additional parameter of addCell which will be forwarded to formatter. So one could add later one more parameter to custom formatter to have the same format of input data in case of first loading of data and the call of the next time (in case of loadonce: true option).

Best regards
Oleg

Signed-off-by: Dr. Oleg Kiriljuk oleg.kiriljuk@ok-soft-gmbh.com

@OlegKi OlegKi Implementation of rowattr callback
(copy of [the previous pull request](tonytomov/jqGrid#276)

Hello Tony,

I posted some time before [the suggestion](http://www.trirand.com/blog/?page_id=393/feature-request/introduce-rowattr-jqgrid-like-cellattr-but-for-setting-attributes-on-tr-element-instead-of-td/#p25555)  to implement `rowattr` callback with the functionality close to `cellattr`. The pool request contains the implementation of the suggestion.

In main difference to `cellattr` is the format of return value which should be an **object** and not a **string**, so be implemented like in the example

    rowattr: function (rowData, inputRowData) {
        return rowData.closed ? {class: "myRowClass"} : {};
    }

or

    rowattr: function (rowData, inputRowData) {
        return rowData.closed ? {style: "background:yellow"} : {};
    }

It simplifys the analyzing. The usage of it in the form `' class="mystyle"'` should be parsed more carefully (`celp.indexOf('style') > -1`, but we have no `style` attribute inside).

[The demo](http://www.ok-soft-gmbh.com/jqGrid/AbhishekSimon10-rowattr-.htm) uses XML and [another](http://www.ok-soft-gmbh.com/jqGrid/ChangeFiledNameInSearchingDialog-rowattr-.htm) uses JSON as input. The demos use modified version of `grid.base.js`.

The first parameter of `rowattr` callback - `rowData` parameter has "named format" (object with the properties like in `name` from items of `colModel`). The format is the same for XML and JSON and it's not depend from `jsonReader` or `xmlReader` settings. The second parameter `inputRowData` is the row exactly like it be in the input data.

Additional advantage is that one have now `rd` variable which can be used as additional parameter of `addCell` which will be forwarded to `formatter`. So one could add later one more parameter to custom formatter to have the same format of input data in case of first loading of data and the call of the next time (in case of `loadonce: true` option).

Best regards
Oleg

Signed-off-by: Dr. Oleg Kiriljuk <oleg.kiriljuk@ok-soft-gmbh.com>
cf109be
@tojocky

Very nice patch!

Tony, please add this patch.

Thank you!

@tonytomov
Owner

Oleg,
I can not accept this patch. I have commented it before, but can not find my comment.
Qick:
1. Speed will decrease
2. These functions (cellattr and formatter) should return strings - common approach.

Regards
Tony

@wildraid

By the way, if i need really complex row formatting, i do it into gridComplete with common jQuery methods.
More importanly, this approach doesn't have natural limitations like any hook would have.

@OlegKi

Hello Tony,

It's fine that you are back. I thought to write you an email already.

What problems you see with the performance? I think it should be practically the same as before. I can explain this on the example of my suggestions of the modification of the addJSONData method.

The current implementation of the addJSONData method pushes the string representation of <tr> with all attributes in the array rowData (see the line of code):

rowData.push("<tr"+hiderow+" id=\""+ idr +"\" tabindex=\"-1\" ... "\">");

Then inside of the loop

for (j=0;j<F.length;j++) {
    v = $.jgrid.getAccessor(cur,F[j]);
    rowData.push( addCell(idr,v,j+gi+si+ni,i+rcnt,cur) );
    rd[ts.p.colModel[j+gi+si+ni].name] = v;
}

a) it will be filled rd object which has the same format as the item in the p.data array.
b) The rowData will be appended with string representation of <td> elements constructed by addCell(idr,v,j+gi+si+ni,i+rcnt,cur).

It' clear that the call addCell(idr,v,j+gi+si+ni,i+rcnt,cur) depend only from the v which will be saved in rd[ts.p.colModel[j+gi+si+ni].name]. So the current code could be divided it two separate loops

for (j=0;j<F.length;j++) {
    v = $.jgrid.getAccessor(cur,F[j]);
    rd[ts.p.colModel[j+gi+si+ni].name] = v;
}

and

for (j=0;j<F.length;j++) {
    v = rd[ts.p.colModel[j+gi+si+ni].name];
    rowData.push( addCell(idr,v,j+gi+si+ni,i+rcnt,cur) );
}

The JSON data will be read only once by $.jgrid.getAccessor(cur,F[j]);. So the performance should be practically the same as before. What I suggest is just to fill the rd first and then use it in the separate loop. So we can fill the rd before we will place <tr> in the rowData. The advantage is that we can add additional attributes of <tr> based on the contain from the raw JSON input cur and rd which has named properties and which format is independent from the format of the row data. The jsonmap was used (or called) already.

The constructTr function do just the same as the original line, but it parses and concatenates the attributes returned from rowattr with the standard attributes of <tr>. One can change a little the code of constructTr to place the code like if (rowAttrObj.hasOwnProperty("...")) {...} inside of if ($.isFunction(ts.p.rowattr)) {/* here */}. If you want I can modify the code of constructTr accordingly. It would bring only minimal performance improvement because {}.hasOwnProperty("") (currently used) works very quickly, but probably the code can be better read.

Now I want to clear why I decided to change interface of rowattr. Corresponds to the current interface of cellattr it returns string which will be parsed by jqGrid. As I tried to wrote the same code for rowattr I mentioned some disadvantages of existing cellattr implementation. If the cellattr returns the string like ' class="myTitle myRowStyle1"' for example the parsing of the value will have some side effects. First the string will be changed to ' class="mytitle myRowstyle1"' see [here]. Then cm.title will be set to false and clas variable to undefined. The next statement acp = celp.split("style"); will be initialized to [' class="mytitle myRow', '1"'] and so on. I understand that the example with ' class="myTitle myRowStyle1"' is not really realistic, but nevertheless it shows the problems with parsing of the cellattr returns the string. It's not so easy and the current implementation works correctly not in all cases.

So to simplify the paring of the information returned from rowattr I decided to define it as a plain object (map). Exactly like it does the jQuery.css method for example. The analyzing of the plain object consists from for (prop in obj) loop and is very easy. I don't think that it decreases the performance of jqGrid. I think that the performance of the function constructTr is almost the same as the performance of the original line rowData.push("<tr"+...+"\">");

What do you think Tony about my clarification?

Best regards
Oleg

@OlegKi

@wildraid: If one dose some modifications of the rows inside of gridComplete or loadComplete one have important performance disadvantage. The content of the grid body is already on the page. So If you modify an element exsiting on the page the web browser will have to recalculate position of all elements currently existing on the page. The only way which I know to improve performance will be to use jQuery.detach() method to detach (to remove temporary) the grid body (<tbody>) from the page (from the <table>), make all the modifications and then place the body back. The problem only that in the way not any changes can be done. How you know you can do not all operations with detached element. It don't inherit any parent CSS classes for example and so many parameters like row height can't be calculated.

The usage of cellattr and rowattr on the other side allows to generate some cell or row attributes based on the input data. One do this before the DOM elements will be generate and before there will be placed on the page. I think that if one would generate disconnected <td>, as DOM element or as jQuery wrapper then place all in disconnected <tr> and <tbody> all will work pretty quick. Important is only that one place the whole <tbody> on the page inside of <table> and not place every the <tr> like one do this currently if gridview: false or if afterInsertRow is defined.

In my opinion the main performance advantage of gridview: true is not the working with strings instead of DOM elements of jQuery wrapper. I think that the main performance advantage exist because of placing the whole grid body at one on the page and reducing the number of modifications on the existing page.

Best regards
Oleg

@tonytomov
Owner

Oleg,
Ignore my last comment.

Regards
Tony

@tonytomov tonytomov merged commit 5abdd9f into tonytomov:master
@tonytomov
Owner

Oleg,
Instead the speed is decreased two times.
Here is the code:
One time you do:
if(xmlRd.repeatitems){
if (!F) { F=orderedCols(gi+si+ni); }
var cells = $.jgrid.getXmlData( xmlr, xmlRd.cell, true);
$.each(F, function (k) {
var cell = cells[this];
if (!cell) { return false; }
v = cell.textContent || cell.text;
rd[ts.p.colModel[k+gi+si+ni].name] = v;
});
} else {
for(i = 0; i < f.length;i++) {
v = $.jgrid.getXmlData( xmlr, f[i]);
rd[ts.p.colModel[i+gi+si+ni].name] = v;
}
}

After this again:

            if(xmlRd.repeatitems){
                if (!F) { F=orderedCols(gi+si+ni); }
                $.each(F, function (k) {
                    v = rd[ts.p.colModel[k+gi+si+ni].name];
                    if (typeof v === "undefined") { return false; }
                    rowData.push( addCell(rid,v,k+gi+si+ni,j+rcnt,xmlr) );
                });
            } else {
                for(i = 0; i < f.length;i++) {
                    v = rd[ts.p.colModel[i+gi+si+ni].name];
                    rowData.push( addCell(rid, v, i+gi+si+ni, j+rcnt, xmlr) );
                }
            }

Before this was with one pass. I understand you want the data, but IMHO it is better to omit the first loop and to pass the raw data to rowattr

Regards

@OlegKi

Sorry, Tony but I don't see where we will have decreasing of speed in two times.

The first loop do the most work with the parsing of XML. It calls getXmlData and save the result in the rd object as the named properties. The second loop just get previous saved data from rd with v = rd[ts.p.colModel[k+gi+si+ni].name]; and call rowData.push( addCell(rid,v,k+gi+si+ni,j+rcnt,xmlr) );. By the way, the line if (!F) { F=orderedCols(gi+si+ni); } can be removed because the F will be already initialized and if (!F) is always false.

I agree that the code will be longer, but the performance will be definitively not twice slowly. In the simple test (which is not quite correct because I don't test my changes only, but the last version of jqGrid with my suggestions and the jquery.jqGrid.src.js from jqGrid 4.3.1) I displayed p.totaltime after reading of XML file with about 100 items. The demo which uses new code is maximum 10-15% slowly (sometimes new code works event quickly as the old one) as another demo which uses jqGrid 4.3.1. I tested the demo in different browsers and on different computers. I didn't analysed more exactly why the code is slowly at all. Probably other changes which are done after jqGrid 4.3.1 are the real reason. One can examine the problem more detailed, but in any way there are no 2x factor in the time of executing of the code with rowAttr.

I wrote detailed about this because the usage of raw input elements is really larger problem in custom formatters and in cellattr especially if one uses loadonce: true and setRowData. So it would be very good to have named properties as the parameter.

Best regards
Oleg

@tonytomov
Owner

Well,
This tests are for 5- 6 columns only- what about if we have 15, 20, 30 columns?
In this case you will see the difference.

I will try to perform some other test instead.

Tony

@OlegKi

I think that the more columns you will have the more close the time of processing will be in both cases. I don't have enough test data. Do you have there? If I would see any reason why it we should have performance decreasing I would generate the tests, but I see no reason why dividing of the loop which fill the row in two loops where we don't repeat the same work should work much slowly as before. I think we will have almost the same performance results.

By the way if one would change the $.each( loop to for loop one improves the performance. If one would start the loop not with 0, but with gi+si+ni instead (which can be calculated only once and saved in a variable) one can improve the performance a little bit more. The saving of ts.p.colModel in variable and the usage it inside of loop can improve the performance more... I can continue. My suggestion was just so to stay mostly close to existing code.

My main statement is that dividing of the loop in two parts should don't decrease the performance, but will improve the usage of the suggested feature in many times. One will have clear separation between the code which uses the knowledge of the structure of input JSON or XML data (mostly jsonReader, xmlReader, jsonmap and xmlmap) and another parts which can just use named objects which represents the data of the row. As I wrote before I think that the later modification of the code which forward the rd (named representation of the row) to formatters (especially to the custom formatters) and cellattr could be the next step in the same direction.

Best regards
Oleg

@OlegKi

The reason why the previous demo with new code was a little slowly as the original code from jqGrid 4.3.1 was because the demo used gridview: false mode and the new version of code triggered jqGridAfterInsertRow event after inserting of any from 113 rows. If you use gridview: true mode I can't see difference.

To continue my old post I made some simple modifications in the code of the main loop and made some changes. The demo with optimized code of the loop is here. The demo use more rows of data. The corresponding demo which used original code of jqGrid 4.3.1 is here. In my tests the new code works about 3,4% quickly as original code of jqGrid 4.3.1. In any way dividing of one loop in two loops don't make any notable performance decreasing.

Best regards
Oleg

P.S. The optimized code of the loop is below.

// now we cache all properties which we use in the loop in variables
var iFirst = gi+si+ni, iLast = f.length, p = ts.p, getXmlData = $.jgrid.getXmlData,
    idPrefix = p.idPrefix, repeatitems = xmlRd.repeatitems, xmlRdCell = xmlRd.cell,
    $ts = $(ts), grouping = p.grouping,
    groupField = grouping ? p.groupingView.groupField: [],
    grlen = groupField.length, grpitem, z, colModel = p.colModel, page = p.page,
    rowNum = p.rowNum, data = p.data, index = p._index,
    gridview = p.gridview, locdataOrTreeGrid = locdata || (p.treeGrid === true),
    afterInsertRow = p.afterInsertRowm, $gridBody = $("tbody:first",t);
// the old code
//    if (!F) { F=orderedCols(gi+si+ni); }
// inside of loop initialize. it uses only ts.p.remapColumns and ts.p.colModel and
// the constant gi+si+ni. So one can just initialize it once
if (repeatitems) {
    F=orderedCols(iFirst); // we can move the code to initializing of variable F.
}
while (j<gl) {
    xmlr = gxml[j];
    rid = idPrefix + getId(xmlr,br+j);
    altr = rcnt === 0 ? 0 : rcnt+1;
    cn1 = (altr+j)%2 == 1 ? cn : '';
    if(repeatitems){
        var cells = getXmlData( xmlr, xmlRdCell, true);
        $.each(F, function (k) {
            var cell = cells[this];
            if (!cell) { return false; }
            rd[colModel[k+iFirst].name] = cell.textContent || cell.text;
        });
    } else {
        for(i = 0; i < iLast;i++) {
            rd[colModel[i+iFirst].name] = getXmlData( xmlr, f[i]);
        }
    }
    rowData.push(constructTr(rid, hiderow, cn1, rd, xmlr));
    if(ni) {
        rowData.push( addRowNum(0,j,page,rowNum) );
    }
    if(gi) {
        rowData.push( addMulti(rid,ni,j) );
    }
    if (si) {
        rowData.push( $(ts).jqGrid("addSubGridCell",gi+ni,j+rcnt) );
    }
    if(repeatitems){
        $.each(F, function (k) {
            v = rd[colModel[k+iFirst].name];
            rowData.push( addCell(rid,v,k+iFirst,j+rcnt,xmlr) );
        });
    } else {
        for(i = 0; i < iLast;i++) {
            v = rd[colModel[i+iFirst].name];
            rowData.push( addCell(rid, v, i+iFirst, j+rcnt, xmlr) );
        }
    }
    rowData.push("</tr>");
    if(grouping) {
        grpitem = [];
        for(z=0;z<grlen;z++) {
            grpitem.push(rd[groupField[z]]);
        }
        grpdata = ts.jqGrid('groupingPrepare',rowData, grpitem, grpdata, rd);
        rowData = [];
    }
    if(locdataOrTreeGrid) {
        index[rid] = data.length;
        rd[xmlid] = rid;
        data.push(rd);
    }
    if(gridview === false ) {
        $gridBody.append(rowData.join(''));
        $ts.triggerHandler("jqGridAfterInsertRow", [rid, rd, xmlr]);
        if(afterInsRow) {afterInsertRow.call(ts,rid,rd,xmlr);}
        rowData=[];
    }
    rd={};
    ir++;
    j++;
    if(ir==rn) {break;}
}
@tpeczek tpeczek referenced this pull request in tpeczek/Lib.Web.Mvc
Closed

[Work Item #12880] Add support for 'rowattr' callback #65

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 26, 2012
  1. @OlegKi

    Implementation of rowattr callback

    OlegKi authored
    (copy of [the previous pull request](tonytomov/jqGrid#276)
    
    Hello Tony,
    
    I posted some time before [the suggestion](http://www.trirand.com/blog/?page_id=393/feature-request/introduce-rowattr-jqgrid-like-cellattr-but-for-setting-attributes-on-tr-element-instead-of-td/#p25555)  to implement `rowattr` callback with the functionality close to `cellattr`. The pool request contains the implementation of the suggestion.
    
    In main difference to `cellattr` is the format of return value which should be an **object** and not a **string**, so be implemented like in the example
    
        rowattr: function (rowData, inputRowData) {
            return rowData.closed ? {class: "myRowClass"} : {};
        }
    
    or
    
        rowattr: function (rowData, inputRowData) {
            return rowData.closed ? {style: "background:yellow"} : {};
        }
    
    It simplifys the analyzing. The usage of it in the form `' class="mystyle"'` should be parsed more carefully (`celp.indexOf('style') > -1`, but we have no `style` attribute inside).
    
    [The demo](http://www.ok-soft-gmbh.com/jqGrid/AbhishekSimon10-rowattr-.htm) uses XML and [another](http://www.ok-soft-gmbh.com/jqGrid/ChangeFiledNameInSearchingDialog-rowattr-.htm) uses JSON as input. The demos use modified version of `grid.base.js`.
    
    The first parameter of `rowattr` callback - `rowData` parameter has "named format" (object with the properties like in `name` from items of `colModel`). The format is the same for XML and JSON and it's not depend from `jsonReader` or `xmlReader` settings. The second parameter `inputRowData` is the row exactly like it be in the input data.
    
    Additional advantage is that one have now `rd` variable which can be used as additional parameter of `addCell` which will be forwarded to `formatter`. So one could add later one more parameter to custom formatter to have the same format of input data in case of first loading of data and the call of the next time (in case of `loadonce: true` option).
    
    Best regards
    Oleg
    
    Signed-off-by: Dr. Oleg Kiriljuk <oleg.kiriljuk@ok-soft-gmbh.com>
This page is out of date. Refresh to see the latest.
Showing with 63 additions and 31 deletions.
  1. +63 −31 js/grid.base.js
View
94 js/grid.base.js
@@ -1076,6 +1076,36 @@ $.fn.jqGrid = function( pin ) {
ts.p._index[val] = i;
}
},
+ constructTr = function(id, hide, altClass, rd, cur) {
+ var tabindex = '-1', restAttr = '', attrName, style = hide ? 'display:none;' : '',
+ classes = 'ui-widget-content jqgrow ui-row-' + ts.p.direction + altClass,
+ rowAttrObj = $.isFunction(ts.p.rowattr) ? ts.p.rowattr.call(ts, rd, cur) : {};
+ if (rowAttrObj.hasOwnProperty("id")) {
+ id = rowAttrObj.id;
+ delete rowAttrObj.id;
+ }
+ if (rowAttrObj.hasOwnProperty("tabindex")) {
+ tabindex = rowAttrObj.tabindex;
+ delete rowAttrObj.tabindex;
+ }
+ if (rowAttrObj.hasOwnProperty("style")) {
+ style += rowAttrObj.style;
+ delete rowAttrObj.style;
+ }
+ if (rowAttrObj.hasOwnProperty("class")) {
+ classes += ' ' + rowAttrObj.class;
+ delete rowAttrObj.class;
+ }
+ // dot't allow to change role attribute
+ delete rowAttrObj.role;
+ for (attrName in rowAttrObj) {
+ if (rowAttrObj.hasOwnProperty(attrName)) {
+ restAttr += ' ' + attrName + '=' + rowAttrObj[attrName];
+ }
+ }
+ return '<tr role="row" id="' + id + '" tabindex="' + tabindex + '" class="' + classes + '"' +
+ (style === '' ? '' : ' style="' + style + '"') + restAttr + '>';
+ },
addXmlData = function (xml,t, rcnt, more, adjust) {
var startReq = new Date(),
locdata = (ts.p.datatype != "local" && ts.p.loadonce) || ts.p.datatype == "xmlstring",
@@ -1093,7 +1123,7 @@ $.fn.jqGrid = function( pin ) {
rcnt=1;
} else { rcnt = rcnt > 1 ? rcnt :1; }
} else { return; }
- var i,fpos,ir=0,v,gi=0,si=0,ni=0,idn, getId,f=[],F,rd ={}, xmlr,rid, rowData=[], cn=(ts.p.altRows === true) ? " "+ts.p.altclass:"",cn1;
+ var i,fpos,ir=0,v,gi=ts.p.multiselect===true?1:0,si=ts.p.subGrid===true?1:0,ni=ts.p.rownumbers===true?1:0,idn, getId,f=[],F,rd ={}, xmlr,rid, rowData=[], cn=(ts.p.altRows === true) ? " "+ts.p.altclass:"",cn1;
if(!xmlRd.repeatitems) {f = reader(frd);}
if( ts.p.keyIndex===false) {
idn = $.isFunction( xmlRd.id ) ? xmlRd.id.call(ts, xml) : xmlRd.id;
@@ -1134,43 +1164,48 @@ $.fn.jqGrid = function( pin ) {
if(gxml && gl){
var br=ts.p.scroll?$.jgrid.randId():1,altr;
if (adjust) { rn *= adjust+1; }
- var afterInsRow = $.isFunction(ts.p.afterInsertRow), hiderow="";
- if(ts.p.grouping && ts.p.groupingView.groupCollapse === true) {
- hiderow = " style=\"display:none;\"";
- }
+ var afterInsRow = $.isFunction(ts.p.afterInsertRow), hiderow=ts.p.grouping && ts.p.groupingView.groupCollapse === true;
while (j<gl) {
xmlr = gxml[j];
rid = getId(xmlr,br+j);
rid = ts.p.idPrefix + rid;
altr = rcnt === 0 ? 0 : rcnt+1;
cn1 = (altr+j)%2 == 1 ? cn : '';
- rowData.push( "<tr"+hiderow+" id=\""+rid+"\" tabindex=\"-1\" role=\"row\" class =\"ui-widget-content jqgrow ui-row-"+ts.p.direction+""+cn1+"\">" );
+ if(xmlRd.repeatitems){
+ if (!F) { F=orderedCols(gi+si+ni); }
+ var cells = $.jgrid.getXmlData( xmlr, xmlRd.cell, true);
+ $.each(F, function (k) {
+ var cell = cells[this];
+ if (!cell) { return false; }
+ v = cell.textContent || cell.text;
+ rd[ts.p.colModel[k+gi+si+ni].name] = v;
+ });
+ } else {
+ for(i = 0; i < f.length;i++) {
+ v = $.jgrid.getXmlData( xmlr, f[i]);
+ rd[ts.p.colModel[i+gi+si+ni].name] = v;
+ }
+ }
+ rowData.push(constructTr(rid, hiderow, cn1, rd, xmlr));
if(ts.p.rownumbers===true) {
rowData.push( addRowNum(0,j,ts.p.page,ts.p.rowNum) );
- ni=1;
}
if(ts.p.multiselect===true) {
rowData.push( addMulti(rid,ni,j) );
- gi=1;
}
if (ts.p.subGrid===true) {
rowData.push( $(ts).jqGrid("addSubGridCell",gi+ni,j+rcnt) );
- si= 1;
}
if(xmlRd.repeatitems){
if (!F) { F=orderedCols(gi+si+ni); }
- var cells = $.jgrid.getXmlData( xmlr, xmlRd.cell, true);
$.each(F, function (k) {
- var cell = cells[this];
- if (!cell) { return false; }
- v = cell.textContent || cell.text;
- rd[ts.p.colModel[k+gi+si+ni].name] = v;
+ v = rd[ts.p.colModel[k+gi+si+ni].name];
+ if (typeof v === "undefined") { return false; }
rowData.push( addCell(rid,v,k+gi+si+ni,j+rcnt,xmlr) );
});
} else {
for(i = 0; i < f.length;i++) {
- v = $.jgrid.getXmlData( xmlr, f[i]);
- rd[ts.p.colModel[i+gi+si+ni].name] = v;
+ v = rd[ts.p.colModel[i+gi+si+ni].name];
rowData.push( addCell(rid, v, i+gi+si+ni, j+rcnt, xmlr) );
}
}
@@ -1277,7 +1312,7 @@ $.fn.jqGrid = function( pin ) {
dReader = ts.p.jsonReader;
frd='json';
}
- var ir=0,v,i,j,f=[],F,cur,gi=0,si=0,ni=0,len,drows,idn,rd={}, fpos, idr,rowData=[],cn=(ts.p.altRows === true) ? " "+ts.p.altclass:"",cn1,lp;
+ var ir=0,v,i,j,f=[],F,cur,gi=ts.p.multiselect?1:0,si=ts.p.subGrid?1:0,ni=ts.p.rownumbers===true?1:0,len,drows,idn,rd={}, fpos, idr,rowData=[],cn=(ts.p.altRows === true) ? " "+ts.p.altclass:"",cn1,lp;
ts.p.page = $.jgrid.getAccessor(data,dReader.page) || 0;
lp = $.jgrid.getAccessor(data,dReader.total);
ts.p.lastpage = lp === undefined ? 1 : lp;
@@ -1303,10 +1338,7 @@ $.fn.jqGrid = function( pin ) {
if (len > 0 && ts.p.page <= 0) { ts.p.page = 1; }
var rn = parseInt(ts.p.rowNum,10),br=ts.p.scroll?$.jgrid.randId():1, altr;
if (adjust) { rn *= adjust+1; }
- var afterInsRow = $.isFunction(ts.p.afterInsertRow), grpdata={}, hiderow="";
- if(ts.p.grouping && ts.p.groupingView.groupCollapse === true) {
- hiderow = " style=\"display:none;\"";
- }
+ var afterInsRow = $.isFunction(ts.p.afterInsertRow), grpdata={}, hiderow=ts.p.grouping && ts.p.groupingView.groupCollapse === true;
while (i<len) {
cur = drows[i];
idr = $.jgrid.getAccessor(cur,idn);
@@ -1323,27 +1355,27 @@ $.fn.jqGrid = function( pin ) {
idr = ts.p.idPrefix + idr;
altr = rcnt === 1 ? 0 : rcnt;
cn1 = (altr+i)%2 == 1 ? cn : '';
- rowData.push("<tr"+hiderow+" id=\""+ idr +"\" tabindex=\"-1\" role=\"row\" class= \"ui-widget-content jqgrow ui-row-"+ts.p.direction+""+cn1+"\">");
+ if (dReader.repeatitems) {
+ if(dReader.cell) {cur = $.jgrid.getAccessor(cur,dReader.cell);}
+ if (!F) { F=orderedCols(gi+si+ni); }
+ }
+ for (j=0;j<F.length;j++) {
+ v = $.jgrid.getAccessor(cur,F[j]);
+ rd[ts.p.colModel[j+gi+si+ni].name] = v;
+ }
+ rowData.push(constructTr(idr, hiderow, cn1, rd, cur));
if(ts.p.rownumbers===true) {
rowData.push( addRowNum(0,i,ts.p.page,ts.p.rowNum) );
- ni=1;
}
if(ts.p.multiselect){
rowData.push( addMulti(idr,ni,i) );
- gi = 1;
}
if (ts.p.subGrid) {
rowData.push( $(ts).jqGrid("addSubGridCell",gi+ni,i+rcnt) );
- si= 1;
- }
- if (dReader.repeatitems) {
- if(dReader.cell) {cur = $.jgrid.getAccessor(cur,dReader.cell);}
- if (!F) { F=orderedCols(gi+si+ni); }
}
for (j=0;j<F.length;j++) {
- v = $.jgrid.getAccessor(cur,F[j]);
+ v = rd[ts.p.colModel[j+gi+si+ni].name];
rowData.push( addCell(idr,v,j+gi+si+ni,i+rcnt,cur) );
- rd[ts.p.colModel[j+gi+si+ni].name] = v;
}
rowData.push( "</tr>" );
if(ts.p.grouping) {
Something went wrong with that request. Please try again.