jqGridをJSONで使用するときのjqGrid間ドラッグアンドドロップの実装(gridDnD)

jqGrid : 3.8.1
jQuery : 1.4.4
jQuery UI: 1.8.6
IE8

2011/11/28 追記

jqGrid: 3.8.1 でgridDnDとjQuery UIのdialogなどのDraggableな物を使用するとnodeNameエラーが発生します。
最新のソースでは訂正されているので次のリリースを待つかgithubからgrid.jqueryui.jsを差し替えましょう。
詳細は下記の関連するエントリーを参照してください。

目的

同一ページ内の条件別に複数あるjqGrid間で表示されているデータをドラッグアンドドロップで移動させると同時にデータの更新を行う。

基本のおさらい

参考:grid.jqueryui.jsのgridDnD部分

単純なグリッド間におけるドラッグアンドドロップはドキュメントそのままで実装可能です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>グリッド間におけるドラッグアンドドロップ 1</title>

<link rel="stylesheet" type="text/css" href="./css/jquery-ui-1.8.4.custom.css"></link>
<link rel="stylesheet" type="text/css" href="./css/jquery.searchFilter.css"></link>
<link rel="stylesheet" type="text/css" href="./css/ui.jqgrid.css"></link>

<style>
div.a {
    float: left;
}
</style>

<script type="text/javascript" src="./js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="./js/jquery-ui-1.8.6.custom.min.js"></script>
<script type="text/javascript" src="./js/grid.locale-ja.js"></script>
<script type="text/javascript" src="./js/jquery.jqGrid.min.js"></script>

<script type="text/javascript">

$(function() {

    var opt = 
    {
        'datatype': 'local',
        'colModel': [
            {'name':'famiry', 'label':'姓'},
            {'name':'given', 'label':'名'},
            {'name':'place', 'label':'場所'}
        ]
    };

    $('#a_grid').jqGrid($.extend(opt, {'caption':'家'}));
    $('#b_grid').jqGrid($.extend(opt, {'caption':'会社'}));
    $('#c_grid').jqGrid($.extend(opt, {'caption':'学校'}));
    $('#d_grid').jqGrid($.extend(opt, {'caption':'電車'}));

    $('#a_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#b_grid, #c_grid,#d_grid'
    });

    $('#b_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#a_grid,#c_grid,#d_grid'
    });

    $('#c_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#a_grid,#b_grid,#d_grid'
    });

    $('#d_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#a_grid,#b_grid,#c_grid'
    });

    var people = [
        {'famiry':'山田', 'given':'太郎', 'place':'家'},
        {'famiry':'山田', 'given':'花子', 'place':'家'},
        {'famiry':'山田', 'given':'次郎', 'place':'家'}
    ];

    for (var i = 0; i <= people.length; i++)
    {
        $('#a_grid').jqGrid('addRowData', i+1, people[i]);
    }

});

</script>

</head>
<body>

<div class="a"><table id="a_grid"></table></div>
<div class="a"><table id="b_grid"></table></div>
<div class="a"><table id="c_grid"></table></div>
<div class="a"><table id="d_grid"></table></div>

</body>
</html>

たとえば、この例では家グリッドから電車グリッドに移動しても場所は家のままです。
これじゃおかしいですよね。



移動時にデータを書き換える

そこで、gridDnDのbeforedropイベントを使って移動時にデータの書き換えを行います。
※ただし、3個以上グリッドがある場合は引数sourceに問題が生じるため回避する必要があります。

    var fn_beforedrop = function (event, ui, data, source, target)
    {
        // var s = $(source).attr('id');
        var s = $(ui.draggable.parent().parent()).attr('id');
        var t = $(target).attr('id');

        alert(data['given'] + 'が' + s + 'から' + t + 'へ移動します。');

        data['place'] = $('#' + t).jqGrid('getGridParam', 'caption');
    };

    $('#a_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#b_grid, #c_grid,#d_grid',
        'beforedrop'  : fn_beforedrop
    });

    $('#b_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#a_grid,#c_grid,#d_grid',
        'beforedrop'  : fn_beforedrop
    });

    $('#c_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#a_grid,#b_grid,#d_grid',
        'beforedrop'  : fn_beforedrop
    });

    $('#d_grid').jqGrid('gridDnD',
    {
        'connectWith' : '#a_grid,#b_grid,#c_grid',
        'beforedrop'  : fn_beforedrop
    });


データをJSONでサーバーから取得する

ここの説明を書くのはめんどくさい。

参考:http://www.trirand.com/blog/jqgrid/jqgrid.html
jqGrid DemosのLoading Data->JSON Dataを参考に作ってください。

ajaxを呼び出す

ここまでくれば後はfn_beforedropにてajaxでサーバーのAPIをコールするだけです。
ajaxでサーバーサイドの値を変更しているので、JSONデータの再読み込み(.trigger('reloadGrid'))とgridDnDによるローカルのデータ移動を抑止するため、ui.helper.droppe=falseとします。

    var fn_beforedrop = function (event, ui, data, source, target)
    {
        // var s = $(source).attr('id');
        var s = $(ui.draggable.parent().parent()).attr('id');
        var t = $(target).attr('id');

        alert(data['given'] + 'が' + s + 'から' + t + 'へ移動します。');

        // CHANGE data
        data['place'] = $('#' + t).jqGrid('getGridParam', 'caption');

        // Call server api
        $.ajax(
        {
            'url'     : 'peoplemove.php',
            'type'    : 'POST',
            'data'    : data,
            'timeout' : 3000,
            'dataType': 'json',
            'success' : function(data)
            {
                $('#' + s).trigger('reloadGrid');
                $('#' + t).trigger('reloadGrid');
            },
            'error'   : function(xhr, status, error)
            {
                alert('ERROR\n' + xhr.statusText);
            }
        });


        // CANCEL Default DnD action
        ui.helper.dropped = false;
    };