Grid Stack Two grids demo 예제

■ gridstack.js에서 2개의 grid간에 서로 Drag & Drop하는 기능을 필요에 따라 수정했다.

■ 참고

■ gridstack은 drag & drop을 할 수 있는 객체를 widget이라고 하고, widget을 움직일 수 있는 바탕을 grid라고 정의한다.

gridstack demo 화면 캡쳐

■ gridstack에서 grid의 위치를 정의한다. row, col-md-2, col-md-6은 bootstrap 스타일이다. grid-stack은 gridstack임을 표시하고 grid-stack-2는 widget이 최대 2칸이 들어감을 표시, grid-stack-6은 widget이 최대 6칸이 들어갈 수 있음을 표시한다.

<div class="row">
    <div class="col-md-2">
        <div class="grid-stack grid-stack-2" id="grid1"></div>
    </div>
    <div class="col-md-6">
        <div class="grid-stack grid-stack-6" id="grid2"></div>
    </div>
</div>

■ 표시될 grid의 옵션. 다양한 option이 있으며 API에서 확인 가능하다.

width는 최소단위의 widget이 들어갈 수 있는 개수라고 생각하면 된다.

float 속성이 false이면 자동으로 위쪽으로 widget이 정렬이 되고 grid 크기도 widget에 맞게 조정된다. true이면 grid위에 drop된 위치 그대로 widget이 고정된다.

var options1 = {
    width: 2,//2칸
    float: false,
    acceptWidgets: '.grid-stack-item'
};

var options2 = {
    width: 6,   // 6칸
    float: true,
    removable: '.trash',
    removeTimeout: 100,
    acceptWidgets: '.grid-stack-item',
    horizontalMargin: 3,
    verticalMargin:5
};

■ gridstack 초기화 – 위에서 지정한 options1, option2를 가지고 gridstack을 초기화 하였다.

$('#grid1').gridstack(options1);
$('#grid2').gridstack($.extend({}, options2, {
    float: true
}));

■ grid에 그려줄 단위 widget들을 json 형식으로 정의한다.

x, y는 grid에서 widget이 위치할 좌표이다. 값은 자연수 형태로 지정하며 width, height는 각 widget의 크기이다. label은 widget에 표시할 목적으로 임의로 추가했다.

var items1 = [
    {id: 'A', x: 0, y: 0, width: 1, height: 1, label: 'A'},
    {id: 'B', x: 1, y: 0, width: 1, height: 1, label: 'B'},
    {id: 'L', x: 0, y: 1, width: 1, height: 1, label: 'L'},
    {id: 'M', x: 1, y: 1, width: 1, height: 1, label: 'M'},
    {id: 'N', x: 0, y: 2, width: 1, height: 1, label: 'N'},
    {id: 'O', x: 1, y: 2, width: 1, height: 1, label: 'O'},
    {id: 'P', x: 0, y: 3, width: 1, height: 1, label: 'P'}
];

var items2 = [
    {id: 'C', x: 0, y: 0, width: 1, height: 1, label: 'C'},
    {id: 'D', x: 1, y: 0, width: 1, height: 1, label: 'D'},
    {id: 'E', x: 2, y: 0, width: 1, height: 1, label: 'E'},
    {id: 'F', x: 3, y: 0, width: 1, height: 1, label: 'F'},
    {id: 'G', x: 4, y: 0, width: 1, height: 1, label: 'G'},
    {id: 'H', x: 5, y: 0, width: 1, height: 1, label: 'H'},
    {id: 'I', x: 0, y: 0, width: 1, height: 1, label: 'I'},
    {id: 'J', x: 1, y: 1, width: 1, height: 1, label: 'J'},
    {id: 'K', x: 2, y: 1, width: 1, height: 1, label: 'K'}
];

■ grid에 widget그리기

grid객체를 구한 후 addWidget함수를 이용해서 widget을 grid에 그려준다. 이 함수에 대한 상세한 설명은 역시 API를 참조한다.

var grid1 = $("#grid1").data('gridstack');
var grid2 = $("#grid2").data('gridstack');

items1.forEach(function (node) {
    grid1.addWidget($('<div><div class="grid-stack-item-content">'+node.label+'</div></div>'),
        node.x, node.y, node.width, node.height, false,1,3,1,3,node.id);
});

items2.forEach(function (node) {
    grid2.addWidget($('<div><div class="grid-stack-item-content">'+node.label+'</div></div>'),
        node.x, node.y, node.width, node.height, false,1,3,1,3,node.id);
});

■ grid에 그려진 widget정보를 확인하기 위해 Refresh Widget Info 버튼을 클릭하면 아래의 함수가 실행된다. 화면이 로딩될 때 그려진 widget은 $(“#grid1”).data(‘gridstack’).grid.nodes에서 widget의 ID가 확인 가능한데 drag & drop기능으로 grid간에 이동된 widget은 ID가 확인불가능하다. 이 경우는 item.el.data()함수를 이용해서 widget의 ID를 확인한다.

$("#showInfo").click(function() {


    var items1 = $("#grid1").data('gridstack').grid.nodes;
    var items2 = $("#grid2").data('gridstack').grid.nodes;
    
    console.log(">>> widgets ");
    items1.forEach(function(item){
        console.log(item);
        if( item.id ) {
            console.log(item.id +' '+item.x +' '+item.y +' '+item.width +' '+item.height);
        }
        else {
            itm = item.el.data();
            console.log(itm.gsId +' '+itm.gsX +' '+itm.gsY +' '+itm.gsWidth +' '+itm.gsHeight);
        }
    });
    
    console.log(">>> dashboards ");
    items2.forEach(function(item){
        console.log(item);
        if( item.id ) {
            console.log(item.id +' '+item.x +' '+item.y +' '+item.width +' '+item.height);
        }
        else {
            itm = item.el.data();
            console.log(itm.gsId +' '+itm.gsX +' '+itm.gsY +' '+itm.gsWidth +' '+itm.gsHeight);
        }
    });
});

■ gridstack widget에 클릭 이벤트 추가 – gridstack에서는 added, change, disable, dragstart등의 다양한 이벤트가 제공되고 있기는 하지만 widget에 대한 click이벤트는 없었다. widget은 화면이 로딩되고 난 후에 추가되기 때문에 jquery의 $(document).on(‘click’, ‘.grid-stack-item’, function() {…}); 함수를 이용해서 click이벤트를 구현했다.

$(document).on('click', '.grid-stack-item', function() {
    console.log('grid id : ' + $(this).parent().attr("id")); 
    console.log('widget id : ' + $(this).attr("data-gs-id")); 
});

■ 전체 소스 – 아래 소스내의 로컬로 링크된 css나 js파일들은 github에서 다운로드받은 파일중에서 찾을 수 있다.

<!DOCTYPE html>
<html lang="en">
<head>
    <!--&#91;if lt IE 9&#93;>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <!&#91;endif&#93;-->

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Two grids demo</title>

    
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="./css/gridstack.css"/>
    <link rel="stylesheet" href="./css/gridstack-extra.css"/>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/shim.min.js"></script>
    <script src="./js/gridstack.js"></script>
    <script src="./js/gridstack.jQueryUI.js"></script>

    <style type="text/css">
        #grid1 {
            background: lightgoldenrodyellow;
        }

        #grid2 {
            background: lightcyan;
        }

        .grid-stack-item-content {
            color: #2c3e50;
            text-align: center;
            background-color: #18bc9c;
        }

        #grid2 .grid-stack-item-content {
            background-color: #9caabc;
        }
    </style>
</head>
<body>
    <div style="width:1500px">
    <div class="container-fluid">
        <h1>Two grids demo</h1>
        <div>
            <a id="showInfo" class="btn btn-primary" href="#">Refresh Widget Info</a>
        </div>
        <br>


        <div class="row">
            <div class="col-md-2">
                <div class="grid-stack grid-stack-2" id="grid1"></div>
            </div>
            <div class="col-md-6">
                <div class="grid-stack grid-stack-6" id="grid2"></div>
            </div>
        </div>



    </div>
    </div>


<script type="text/javascript">
$(function () {
    var options1 = {
        width: 2,//2칸
        float: false,
        acceptWidgets: '.grid-stack-item'
    };
    
    var options2 = {
        width: 6,   // 6칸
        float: true,
        removable: '.trash',
        removeTimeout: 100,
        acceptWidgets: '.grid-stack-item',
        horizontalMargin: 3,
        verticalMargin:5
    };
    
    $('#grid1').gridstack(options1);
    $('#grid2').gridstack($.extend({}, options2, {
        float: true
    }));

    var items1 = [
        {id: 'A', x: 0, y: 0, width: 1, height: 1, label: 'A'},
        {id: 'B', x: 1, y: 0, width: 1, height: 1, label: 'B'},
        {id: 'L', x: 0, y: 1, width: 1, height: 1, label: 'L'},
        {id: 'M', x: 1, y: 1, width: 1, height: 1, label: 'M'},
        {id: 'N', x: 0, y: 2, width: 1, height: 1, label: 'N'},
        {id: 'O', x: 1, y: 2, width: 1, height: 1, label: 'O'},
        {id: 'P', x: 0, y: 3, width: 1, height: 1, label: 'P'}
    ];

    var items2 = [
        {id: 'C', x: 0, y: 0, width: 1, height: 1, label: 'C'},
        {id: 'D', x: 1, y: 0, width: 1, height: 1, label: 'D'},
        {id: 'E', x: 2, y: 0, width: 1, height: 1, label: 'E'},
        {id: 'F', x: 3, y: 0, width: 1, height: 1, label: 'F'},
        {id: 'G', x: 4, y: 0, width: 1, height: 1, label: 'G'},
        {id: 'H', x: 5, y: 0, width: 1, height: 1, label: 'H'},
        {id: 'I', x: 0, y: 0, width: 1, height: 1, label: 'I'},
        {id: 'J', x: 1, y: 1, width: 1, height: 1, label: 'J'},
        {id: 'K', x: 2, y: 1, width: 1, height: 1, label: 'K'}
    ];

    var grid1 = $("#grid1").data('gridstack');
    var grid2 = $("#grid2").data('gridstack');

    items1.forEach(function (node) {
        grid1.addWidget($('<div><div class="grid-stack-item-content">'+node.label+'</div></div>'),
            node.x, node.y, node.width, node.height, false,1,3,1,3,node.id);
    });
    
    items2.forEach(function (node) {
        grid2.addWidget($('<div><div class="grid-stack-item-content">'+node.label+'</div></div>'),
            node.x, node.y, node.width, node.height, false,1,3,1,3,node.id);
    });


    $("#showInfo").click(function() {


        var items1 = $("#grid1").data('gridstack').grid.nodes;
        var items2 = $("#grid2").data('gridstack').grid.nodes;
        
        console.log(">>> widgets ");
        items1.forEach(function(item){
            console.log(item);
            if( item.id ) {
                console.log(item.id +' '+item.x +' '+item.y +' '+item.width +' '+item.height);
            }
            else {
                itm = item.el.data();
                console.log(itm.gsId +' '+itm.gsX +' '+itm.gsY +' '+itm.gsWidth +' '+itm.gsHeight);
            }
        });
        
        console.log(">>> dashboards ");
        items2.forEach(function(item){
            console.log(item);
            if( item.id ) {
                console.log(item.id +' '+item.x +' '+item.y +' '+item.width +' '+item.height);
            }
            else {
                itm = item.el.data();
                console.log(itm.gsId +' '+itm.gsX +' '+itm.gsY +' '+itm.gsWidth +' '+itm.gsHeight);
            }
        });
    });

    $(document).on('click', '.grid-stack-item', function() {
        console.log('grid id : ' + $(this).parent().attr("id")); 
        console.log('widget id : ' + $(this).attr("data-gs-id")); 
    });
    
});
</script>
</body>
</html>