Post edited 20:41 – 18/05/2012 by OlegK
I wanted to wrote the post already befor, but doing it only now. There are exist small performance issue in jqGrid with the usage of pseudo-selectors like :first or :gt for example. If you look in the current version of jQuery documentation (for example here) you will find the following
Because :first is a jQuery extension and not part of the CSS specification, queries using :first cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using :first to select elements, first select the elements using a pure CSS selector, then use .filter(":first").
One can seen the problem in Developer Tools of Chrome very clear. First of all one should open Developer Tools (for example with Ctrl-Shift-J), choose "Scripts" tab and then enable the following button:
After that one can load any test page which uses jqGrid. For example one can load the demo. During loading the page one will see that some exceptions was thrown which origing was pseudo-selectors used in jqGrid. One will see the picture like below
The exceptions will be in the querySelectorAll function in the line of jQuery code. The problem is that jQuery don't parse selectors for not common supported pseudo selectors. And how one can see on w3 the :first is not in the list of supported selectors.
During loaging of the demo one will see exceptions in the following selectors:
"#list tbody:first tr:first"
"thead tr:first th"
One can fix the problem and improve a little the performance in at least one from the following ways
- one can use :nth-of-type(1) selector (see the post) instead :first, but it's not good way because :nth-of-type(1) selector is not supported by old browsers.
- one can replace the code like $("tbody:first",t) to $("tbody",t).eq(0) and it will works without any problem and will work quickly.
- One can use slice(1) instead of :gt(0). For example the expression $("#"+$.jgrid.jqID(ts.p.id)+" tbody:first tr:gt(0)").remove(); from code of emptyRows one can simplify to $(ts.rows).slice(1).remove();.
- In some places one can rewrite the existing selectors where :first so that :first-child or :last-child will be used. For example tbody:first or >tbody:first will be frequently used to select tbody inside of grid or grid header div. In the case one can use :first-child. The selector $('table:first',this.hDiv) like here can be rewritten as $(this.hDiv).find('>div>table:first-child'). In the same way $('table:first',this.bDiv) selector from the previous line can be rewritten as $(this.bDiv).find('>div>table:last-child'). One can't use :first-child here because the first child are empty div. Instead of $(this.hDiv).find('>div>table:first-child') one can use $(this.hDiv).find('>div:first-child>table:first-child') or $(this.hDiv).find('>:first-child>table:first-child'). In the same way instead of $(this.bDiv).find('>div>table:last-child') one can use $(this.bDiv).find('>div:first-child>table:last-child') or $(this.bDiv).find('>:first-child>table:last-child'). In all the selectors it will be no exception and the full searching will be made in the native code by querySelectorAll function.
In the way one can eliminate exceptions which improve the performance itself. Additionally rewriting selectors to the form which produce one element as the result instead of array and usage of eq(0) will improve the performance additionally because the querySelectorAll function are implemented in native code of modern browsers and so gives us the best performance.
I understand, that all the described performance improvements could be not always so extrem visible, but I recommend to do there nevertheless. The more modern web browsers will be used the more large will be the performance advantage from the changes.