Capture double click on Yii’s CGridView row

I was using a simple Javascript code (attached to CGridView.selectionChanged property) to capture click on any grid view's row and redirect user to row-specific URL. I wanted to change it to double click only.

CGridView exposes selectionChanged even only, no click or dblclick, so that was a quite nice challenge. It seems that the only way is to capture this event yourself.

Capturing dblclick on CGridView is an easy task:

<script>
    $(document).ready(function()
    {
        $('body').on('dblclick', '#files-grid tbody tr', function(event)
        {
            //Do something...
        });
    });
</script>

Where #files-grid is an ID of your CGridView, given in id key of its configuration array.

Obtaining the ID of model / row / record, that was clicked also seems to be an easy task:

var rowId = parseInt($.fn.yiiGridView.getSelection('files-grid')[0]);

Unfortunately, this approach is unreliable (if not: totally wrong), because it is 100% based on selection currently made by user in grid view. If you drop id to console (console.log(rowId);) and begin to click over and over all the time on the same grid view's row, you'll soon notice, that you're getting correct values only every second click. In all other time, you're gettin NaN.

Why? Quite simple. This method is based on selection and every second click removes selection from current row. Take a look at jquery.yiigridview.js implementation for more details.

So, we need to come with something better, more reliable. Analysing getSelection method in above mentioned jquery.yiigridview.js code got me some clue and I've came with something like that:

$('body').on('dblclick', '#files-grid tbody tr', function(event)
{
    var
        rowNum = $(this).index(),
        keys = $('#files-grid > div.keys > span'),
        rowId = keys.eq(rowNum).text();

    console.log(rowId);
});

This code is totally selection-independent and you should always get correct value of rowId.

Now put it into URL change code:

location.href = '< ?php echo Yii::app()->createUrl('manage/view'); ?>?id=' + rowId;

And... voila! You have redirection to your selected action, with proper model's ID, happening only on double click on any of your grid view's rows.

BTW: You can change dblclick event to click and use event.ctrlKey (or event.altKey or event.shiftKey), if you want, for example, to react on single click with Ctrl (or Alt or Shift) key pressed on keyboard. You can check, if event.which is equal to 2 (or 3), if you want to react on middle (or right) mouse button click (only in jQuery, which normalizes this property -- details).

Here is the entire code, for reference:

<script>
    $(document).ready(function()
    {
        $('body').on('dblclick', '#files-grid tbody tr', function(event)
        {
            var
                rowNum = $(this).index(),
                keys = $('#files-grid > div.keys > span'),
                rowId = keys.eq(rowNum).text();

            location.href = '< ?php echo Yii::app()->createUrl('manage/view'); ?>?id=' + rowId;
        });
    });
</script>

Of course, this is written for learning purposes. For production version of your application, you should write a more generic code (so it could be attached to any grid view), migrate it to an external .js file, minify and obsfucate it and do a few other things.

Leave a Reply