7

I have created a jqGrid that contains some fields such as:

job_id, name, etc

What I am trying to do is make so that when the click on the value in the job_id column, it will redirect them to:

job.php?job_id=(value that they clicked on)

I started by trying to use the following as my colModel:

{ name:'job_id', index:'job_id', edittype:'select', formatter:'showlink',
  formatoptions:{baseLinkUrl:'job.php'}, width:50, align:'center' }

But what this results in is a redirection to:

job.php?job_id=(row_id)

I did some searching, and found a post by the developer of the open source version of this software who suggested using the following colModel and additional JS:

{ name:'job_id', index:'job_id', edittype:'select', formatter:'showlink',
  formatoptions:{baseLinkUrl:'#'}, width:50, align:'center' }

loadComplete: function() {
    var myGrid = $("#home_list");
    var ids = myGrid.getDataIDs();
    for (var i = 0, idCount = ids.length; i < idCount; i++) {
        $("#"+ids[i]+" a",myGrid[0]).click(function(e) {
            var hash=e.currentTarget.hash;// string like "#?id=0"
            if (hash.substring(0,5) === '#?id=') {
                var id = hash.substring(5,hash.length);
                var text = this.textContent;
                location.href="job.php?id="+text;
            }
            e.preventDefault();
        });
    }   
}

But this is not compatible with IE. In addition to this, when displaying a large number of rows in the jqGrid, it takes a extremely long time to load, say 5 seconds + for 500 rows.

I'm going to keep working on this, but is this something that anyone else has done?

Oleg
  • 220,925
  • 34
  • 403
  • 798
Linnay
  • 163
  • 1
  • 6
  • 15

1 Answers1

7

You used code example from my old answer so I decide I should answer on you question.

I agree with the critic about performance of the code of the loadComplete. So +1 from me for your question. The construct $("#"+ids[i]+" a", myGrid[0]) inside of long loop can work very slowly. One can easy fix the problem if one will use the following

var getColumnIndexByName = function (columnName) {
    var cm = $(this).jqGrid("getGridParam", "colModel"), l = cm.length, i;
    for (i = 0; i < l; i++) {
        if (cm[i].name === columnName) {
            return i; // return the index
        }
    }
    return -1;
};

var myGrid = $("#list");
myGrid.jqGrid({
    ...
    loadComplete: function () {
        var i = getColumnIndexByName.call(this, 'Subcategory');
        // nth-child need 1-based index so we use (i+1) below
        $("tbody>tr.jqgrow>td:nth-child(" + (i+1) + ")>a", this).click(function (e) {
            var hash=e.currentTarget.hash;// string like "#?id=0"
            if (hash.substring(0,5) === '#?id=') {
                var id = hash.substring(5, hash.length);
                var text = this.textContent || this.innerText;
                alert("clicked the row with id='"+id+"'. Link contain '"+text+"'");
                location.href = "http://en.wikipedia.org/wiki/" + text;
            }
            e.preventDefault();
        });
    }
});

You can see that the improved version of the demo works exactly as the original demo. To show the performance of the method on 1000 rows I created one more demo. One can see that the new method works quickly.

Now back to your main problem. The best performance we will receive if you write your custom formatter and unformatter instead of the usage of the predefined formatter showlink. The code can be about following:

formatter: function (cellvalue, options, rowObject) {
    return "<a href=\"job.php?job_id=" + rowObject.job_id + "\">" + cellvalue + "</a>";
},
unformat: function (cellvalue, options, cellobject) {
   return cellobject.job_id;
}

The exact code depend on which datatype you use, whether you use loadonce:true or not and which jsonReader you use. It can be for example, that rowObject is array in your case and you have to use array index of the corresponding data field (like rowObject[4]) instead of rowObject.job_id.

UPDATED: I think the best implementation way will be the usage of onCellSelect or beforeSelectRow instead of binding click event to every element in the column. I recommend to read the following answers for details: this one, another one and one more old answer.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • 1
    Hi Oleg, thanks for your answer. I have tested your two sites and have found the following. http://www.ok-soft-gmbh.com/jqGrid/UnobtrusiveLinks1.htm is compatible with Internet Explorer, but the rows return undefined with Mozilla Firefox. The original was compatible with Firefox, but not IE. I will be returning to this issue shortly, but I thought I would make you aware of this. – Linnay Feb 16 '11 at 19:31
  • @Linnay: Thank you for the feedback. I fixed both http://www.ok-soft-gmbh.com/jqGrid/UnobtrusiveLinks.htm and http://www.ok-soft-gmbh.com/jqGrid/UnobtrusiveLinks1.htm. Now both work in all browsers. – Oleg Feb 16 '11 at 20:54
  • @Oleg: Hate to be your personal tester, but they're still throwing issues. When I'm tinkering with your code in my web application, I'm getting the same problems. One working with IE, one working with Firefox. When comparing them the other way around, you get an undefined variable error. `clicked the row with id='1'. Link contain 'undefined'` – Linnay Feb 16 '11 at 21:02
  • @Linnay: Are you sure that you use the new version of both codes and not from the cache? In the new version you should find `var text = this.textContent || this.innerText;` instead of `var text = this.textContent;` or `var text = this.innerText;`. If any version not work please say exactly which versions of browsers you use. At me it works in IE8, FF 3.6.13 and Chrome 9. – Oleg Feb 16 '11 at 21:10
  • @Oleg: I've cleared by cache before testing your pages and neither of them are showing `var text = this.textContent || this.innerText;`. But I'll give this snippet a try and report back here. Thanks a lot. – Linnay Feb 16 '11 at 21:22
  • @Linnay: It is very strange what you explains. Probably you have some proxy which are on the way? You can try to access to the same pages later. Nevertheless, the only change which I made in the new version is replaceing of `this.innerText` or `this.textContent` to `this.textContent || this.innerText`. Please let me known that your code made based on my example work correct after this changes. – Oleg Feb 16 '11 at 21:31
  • @Oleg: Thanks for all your help, I've tidied up all my code and it is working perfectly. You are the man. – Linnay Feb 16 '11 at 21:42
  • @Oleg thanks a lot for the comprehensive and complete answer, just implemented the custom formatter in one of my apps. Just wanted to let you know that there's a small typo in your formatter example, the `rowObject.job_id=+` shouldn't have an equal sign before the plus sign, also `cellval` should be changed to `cellvalue` and for consistency you should use `rowObject` in both formatter and unformatter. Perhaps you could modify the upper example? Thanks! – SaschaM78 May 07 '13 at 16:54
  • @SaschaM78: Thanks, I'll fix the code. The answer is relatively old. The better way you find in [the answer](http://stackoverflow.com/a/14537512/315935) or in [this one](http://stackoverflow.com/a/13765086/315935). – Oleg May 07 '13 at 19:05
  • @Oleg: Thank you for the wonderful demo on the best way to go when it comes to Keep-It-Simple-Stupid coding and jqGrid performances. Also, I almost missed the new link you just posted. Google search got me here. :-) Basically I just want to attach a javascript function to the non-hyperlink html tag for features. – fletchsod May 16 '13 at 14:52
  • @fletchsod: You are welcome! I recommend now mostly to use the approach from the **UPDATED** part of my answer. – Oleg May 16 '13 at 15:02