jqGrid implementing of custom cell: integration of raty-plugin

I already work a few days at a first glance at the simple task - to implement a custom cell. The task is following: to make a custom cell with a div element with an id (eg "mydiv"), then to call a function for this div like $('#mydiv').raty({start: cellvaue, readonly:true}) and then, the 3rd subtask - in the edit mode (editGridRow) I have to change the parameter of raty-function to readonly:false as it should be possible to change the value.

Firstly, I have worked with formatter. In formatter I defined my div element, and with calling in afterInsertRow my function $('# mydiv').raty({start: cellvalue, readonly: true}). For the overview it worked perfectly. But, in edit modal dialog of editGridRow the form input text was always rendered, which I do not need here. I need here still only my div element. If I understand correctly, the formatter only modify the values, but still renders form input text.

Then I swithed to edittype: custom, but it has not help, because these functions are invoked for the first time only in editGridRow.

I am sure that this problem is solvable, the only question is how.

Thanks for any tips.

UPDATE Thanks to Oleg now I am very close to a functioning implementation of this task. Here I will describe my solution (based on Oleg's advices, or at least on my interpretion of his tips). The jqGrid is defined with datatype: "json". The custom cell is defined as:

name:'ranking', editable:true, edittype:'custom',formatter:ratingFormatter, 
editoptions:{custom_element:ratingFormatter, custom_value:ratingValue}

The mentioned functions are defined as follows:

function ratingFormatter(cellvalue, options, rowObject) {return '<div class="rnk"></div>';}; 

function ratingValue(elem, operation, value) {return $('#ranking-score').val();};

Then modal edit dialog:

ondblClickRow: function(id) {
jQuery('#grid').jqGrid('editGridRow',id,
{closeOnEscape:true,width:400, 
savekey:[true,13],
recreateForm:true,beforeShowForm:initRating
});

The initRating function:

function initRating() {$('#ranking').raty({path:'/img/'})};

And finally the loadComplete event

 loadComplete: function (data) {
 var ids = jQuery("#grid").getDataIDs();
 for(var i=0;i<ids.length;i++){
 var rowid = ids[i];
 var ranking = data.rows[i].cell[6];
 $('#' + rowid +'> td > div.rnk').raty({path:'/img/',start:ranking,readOnly:true});
 $('#' + rowid).contextMenu('MenuJqGrid', eventsMenu);
 }
 }

So many steps for such small thing as rating plugin. Unbelievable. The last unresolved issue is getting the current rating score into initRating function. It means if I go to the editGridRow I do not have already defined rating score. Hmmm.


About the edittype:custom option I recommend you to read this and this old answers. It is important to use recreateForm:true setting to make custom edit functions custom_element and custom_value be called not ony once.

You don't include any code in your question. Your description of the problem allows different interpretations how you implemented what you described. For example it is not clear for me how you change the parameter of raty-function to readonly:false. Do you use beforeShowForm event (see this as an example) or you use dataInit property of the editoptions. In both cases all should work in case of correct implementation.

One more thing which is uncler for me. Why you need to include id="mydiv" in the cell? Is your implementation allows inserting multiple ids with the same name? It would be a bug. If you can find the cell based on the cell contain or the row contain, that you can call .raty({start: cellvaue, readonly:true}) inside of loadComplete event handler and you don't need to insert additional id attribute to the <td> element. The usage of afterInsertRow makes grid more slow, because it force to render the grid on adding every row and not only after all rows will be inserted in the grid (see gridview:true option).

UPDATED: After spending so time for writing comments and after you posted your code I modified the code to show how the raty-plugin could be integrated. As the results is the demo which looks like enter image description here
I used inline editing instead of the form editing only because form editing not full support local editing, but I wanted to make the demo without any server components.

Like in your code I used double-click for the row editing. Here are the main code fragments:

var lastSel;
var grid = $("#list");
var initRaty = function(rowid) {
    var ranking = grid.getCell(rowid,4); // the Ranking column has the index 4
    // because we use rownumbers:true the index of the Ranking column will be 1 higher
    $('#' + rowid +'> td:nth-child(5) > div').raty({
        path:'http://www.ok-soft-gmbh.com/jquery.raty/1.0.1/img/',
        start:ranking,
        readOnly:true
    });
};
grid.jqGrid({
    // ...
    colModel: [
        // other column definition
        { name:'Ranking', editable:true, width: 100, title: false,
          formatter: function(cellvalue, options, rowObject) {
              // insert div needed for the raty plugin
              // and insert a hidden span with the rating value
              return '<div></div><span style="display: none;">'+cellvalue+'</span>';
          }, unformat: function (cellvalue, options, cellobject) {
              // get rating value from the hidden span
              return cellobject.find("span").text();
          }, edittype:'custom', editoptions: {
              custom_element: function(value, options) {
                  var val = $(value);
                  var elem = $('<div id="'+options.id+'"/>');
                  setTimeout(function(){
                      elem.raty({
                          path:'http://www.ok-soft-gmbh.com/jquery.raty/1.0.1/img/',
                          start:(val.length>1? val[1].innerText: value)
                      });
                  }, 100);
                  return elem[0];
              },
              custom_value: function(elem) {
                  return elem.find("input").val();
              }
          }
        }
    ],
    editurl: 'clientArray',
    loadComplete: function (data) {
        var ids = grid.getDataIDs();
        for(var i=0;i<ids.length;i++){
            initRaty(ids[i]);
        }
    },
    ondblClickRow: function(id, ri, ci) {
        grid.jqGrid('editRow',id,true,null,null, 'clientArray', {}, initRaty);
    },
    onSelectRow: function(id) {
        if (id && id !== lastSel) {
            if (typeof lastSel !== "undefined") {
                grid.jqGrid('restoreRow',lastSel);
                var cell = $('#' + lastSel +'> td:nth-child(5)');
                var spans = cell.find('span');
                if (spans.length > 1) {
                    // if the lastSel row was not only selected, but also
                    // was in editing mode, get the hidden text with the ranking
                    var ranking = cell.find('span')[1].innerText;
                    cell.find('div').raty({
                        path:'http://www.ok-soft-gmbh.com/jquery.raty/1.0.1/img/',
                        start:ranking,
                        readOnly:true
                    });
                }
            }
            lastSel = id;
        }
    },
    // other jqGrid parameters
});

If you will use form editing and call editGridRow function instead of editRow you will need to use recreateForm:true option and use afterComplete or afterSubmit to call initRaty with the modified values (exactly like I use aftersavefunc parameter of editRow in my code example).