들어가며

이번 강좌에서는 FusionCharts와 RealGrid를 연계하여 동작하는 방법을 배워보겠습니다.

이론

RealGrid에는 셀 렌더러Cell Renderer라는 기능을 통해 기본적인 스타일에 비해 확장된 개념의 그래피컬한 기능을 제공하고 있습니다. 셀 렌더러 중에서도 아래와 같이 차트와 유사한 형태의 인라인 그래프 기능의 렌더러가 있습니다.

셀 렌더러에 대해서는[B Class]의 강좌에서 자세히 다루게 됩니다.

이번 강좌에서는 차트 라이브러리인 FusionCharts와 RealGrid가 서로 데이터를 공유하고, FusionCharts가 그리드의 동작에 반응하도록 하는 방법을 배워보겠습니다.

What is FusionCharts?

FusionCharts는 Web 사이트 나 Web 응용 프로그램에 인터랙티브 한 차트를 추가하기 위해 쉬운 방법을 제공하는 순수한 JavaScript로 작성된 그래프 라이브러리입니다.
라이브러리 파일은 http://www.fusioncharts.com/download 페이지에서 다운 받을수 있습니다.
본 강좌는 FusionCharts의 기초지식에 의거하여 구현한 예제입니다. 보다 전문적인 지식이 필요한 경우 http://www.fusioncharts.com/dev 페이지를 참조해 주세요.

RealGrid와 FusionCharts간 데이터 공유하기

먼저 RealGrid에 로드된 데이터를 FusionCharts에 설정하기 위해 그리드에 데이터를 로드한 후 setFusionChart 함수를 호출합니다.

setFusionChart()

FusionCharts.ready(function () {}) 는 FusionChart를 그릴 준비가 되었을때 실행됩니다.
var fusioncharts = new FusionCharts({})는 FusionChart 객체를 생성하고 fusioncharts 변수에 할당 합니다.
fusioncharts.render() 는 설정한대로 FusionChart를 그리는 명령입니다.

그리드와 데이터를 연계하기 위해 FusionCharts의 categories와 dataset에 DataProvider값을 설정해야 합니다.
FusionCharts가 요구하는 형식의 데이터로 만들기 위해 generateChartData() 함수를 만들어 사용하였습니다.

FusionCharts를 그리기 위해서 사용된 코드들은 아래와 같습니다. 내부적으로 사용된 사용자 정의 함수들은 아래에 별도로 기술하였습니다.

function setFusionChart(provider) {
    FusionCharts.ready(function () {

        var chartData = generateChartData(provider);

        var fusioncharts = new FusionCharts({
            id: "realChart",
            type: 'mscolumn2d',
            renderAt: 'container',
            width: '100%',
            height: '350',
            dataFormat: 'json',
            dataSource: {
                "chart": {
                    "caption": "통계청 총생산소득",
                    "subCaption": "www.realgrid.com",
                    "xAxisname": "Year",
                    "yAxisName": "소득 ($)",
                    "numberPrefix": "$",                    
                    //Theme                    
                    "theme": "fint",
                    "showValues": "0",
                    "labelDisplay": "rotate",
                    "slantLabels": "1",
                    "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
                    "showLegend": "1"                   
                },
                "categories": [{
                    "category": chartData.category
                }],
                "dataset": chartData.dataSet
                    
            }
        });
        fusioncharts.render();

        setColumnBackground(fusioncharts);
    });
}

generateChartData()

FusionCharts가 MultiSerise 인 경우 사용하는 categories와 dataset의 형태는 아래와 같습니다.

    "categories": [
        {
            "category": [
                { "label": "2008" }, 
                { "label": "2009" }, 
                { "label": "2010" }, 
                { "label": "2011" },
                { "label": "2012" }
            ]
        }
    ],
    "dataset": [
        {
            "seriesname": "GDP",
            "data": [
                { "value": "9309" }, 
                { "value": "8344" }, 
                { "value": "10147" }, 
                { "value": "11147" }, 
                { "value": "11292" }
            ]
        }, 
        {
            "seriesname": "GNI",
            "data": [
                { "value": "9379" }, 
                { "value": "8381" }, 
          ...이후 생략...
        }
    ]

이런 형태를 만들기 위해 리얼그리드에 로드된 데이터를 아래 코드를 사용하여 가공하였습니다.

function generateChartData(provider) {
    var category = [];
    var colNames = ["GDP", "GNI", "PGNI", "DIncome"];
    var seriseNames = [];
    var dataSet = [];
    var data = { GDP: [], GNI: [], PGNI: [], DIncome: [] };
    var returnVal = {};

    for (var i = 0; i < provider.getRowCount() ; i++) {
        var label = { "label": provider.getValue(i, "year") }
        category.push(label);

        for (var j in colNames) {
            data[colNames[j]].push({ "value": provider.getValue(i, colNames[j]) });
        }
    }

    for (var i = 0 ; i < colNames.length ; i++) {
        if (gridView.getColumnProperty(colNames[i], "checked")) {
            dataSet.push({
                serisename: colNames[i],
                data: data[colNames[i]]
            });
        }
    }

    returnVal.category = category;
    returnVal.dataSet = dataSet;

    return returnVal;
}

setColumnBackground()

그리드화면을 좀 더 직관적으로 보기위해 활성화된 FusionCharts의 Serise색상과 그리드 컬럼의 배경색을 매칭하는 소스입니다.

function setColumnBackground(chart) {
    var colNames = ["GDP", "GNI", "PGNI", "DIncome"];

    var color = chart.getChartAttribute("paletteColors").split(",");

    var colorIdx = 0
    for (var i = 0 ; i < colNames.length ; i++) {
        if (gridView.getColumnProperty(colNames[i], "checked")) {
            gridView.setColumnProperty(colNames[i], "styles", { background: color[colorIdx++] });
        } else {
            gridView.setColumnProperty(colNames[i], "styles", { background: "#00000000" });
        }
    }
}

LocalDataProvider.onRowUpdated()

onRowUpdated()는 그리드의 데이터를 변경 하였을때 호출되는 콜백 함수로 변동된 데이터를 FusionCharts와 연계하기 위해 사용합니다.

dataProvider.onRowUpdated = function (provider, row) {
    var chart = getChartFromId('realChart');
    var data = generateChartData(dataProvider);
    var chartData = {
        "chart": {
            "caption": "통계청 총생산소득",
            "subCaption": "www.realgrid.com",
            "xAxisname": "Year",
            "yAxisName": "소득 ($)",
            "numberPrefix": "$",                    
            //Theme                    
            "theme": "fint",
            "showValues": "0",
            "labelDisplay": "rotate",
            "slantLabels": "1",
            "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
            "showLegend": "1"                   
        },
            "categories": [{
                "category": data.category
            }],
            "dataset": data.dataSet
                
    }
    chart.setChartData(chartData);
}
컬럼헤더의 CheckBox에 체크된 데이터만 FusionCharts에 표시하기

GridBase.onColumnCheckedChanged()

컬럼의 checkbox선택/해제하였을때 호출되는 콜백 함수인 onColumnCheckedChanged()에 FusionCharts의 Serise를 숨기거나 보이게하는 기능을 작성합니다.

FusionCharts의 함수인 getChartFromId()를 이용하여 화면에 생성된 FusionCharts를 가져옵니다. generateChartData를 사용하여 컬럼 헤더에 체크된 데이터셋들만 가져오고 setChartData()를 사용하여 다시 그려줍니다.

리얼그리드의 컬럼 색상을 사용자 정의 함수 setColumnBackground()를 사용하여 다시 칠해줍니다.

gridView.onColumnCheckedChanged = function (grid, column, checked) {        
    var chart = getChartFromId('realChart');

    var data = generateChartData(dataProvider);

    var chartData = {
        "chart": {
            "caption": "통계청 총생산소득",
            "subCaption": "www.realgrid.com",
            "xAxisname": "Year",
            "yAxisName": "소득 ($)",
            "numberPrefix": "$",                    
            //Theme                    
            "theme": "fint",
            "showValues": "0",
            "labelDisplay": "rotate",
            "slantLabels": "1",
            "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
            "showLegend": "1"                   
        },
            "categories": [{
                "category": data.category
            }],
            "dataset": data.dataSet
                
    }
    chart.setChartData(chartData);

    setColumnBackground(chart)
}

실습

  1. 이번 강좌에서는 FusionCharts의 category 값은 변경치 않도록 하겠습니다. Year컬럼을 편집불가로 설정합니다.

     var column = [{
         name: "Year",
         fieldName: "Year",
         width: "50",
         styles: {
             textAlignment: "center"
         },
         header: {
             text: "Year"
         },
         editable : false  //편집불가
     },{
     ...
     
  2. 컬럼에 checkbox를 사용하기 위해 column.header.checkLocation을 설정하고 checkbox의 초기값을 checked로 설정하겠습니다.

     var columns = [{
     ...
     }, {
         name: "GDP",
         fieldName: "GDP",
         width: "130",
         styles: {
             textAlignment: "far",
             numberFormat: "#,##0"
         },
         header: {
             text: "GDP ($100 milion)",
             checkLocation : "left" // 기본값은 none으로 none외에 값으로 지정시 checkbox가 보여진다.
         },
         checked: true // checked
     }, {
     ...
     
  3. 이벤트에 필요한 코드를 추가합니다.

     gridView.onColumnCheckedChanged = function (grid, column, checked) {        
         var chart = getChartFromId('realChart');
    
         var data = generateChartData(dataProvider);
    
         var chartData = {
             "chart": {
                 "caption": "통계청 총생산소득",
                 "subCaption": "www.realgrid.com",
                 "xAxisname": "Year",
                 "yAxisName": "소득 ($)",
                 "numberPrefix": "$",                    
                 //Theme                    
                 "theme": "fint",
                 "showValues": "0",
                 "labelDisplay": "rotate",
                 "slantLabels": "1",
                 "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
                 "showLegend": "1"                   
             },
                 "categories": [{
                     "category": data.category
                 }],
                 "dataset": data.dataSet
                        
         }
         chart.setChartData(chartData);
    
         setColumnBackground(chart)
     }
    
     dataProvider.onRowUpdated = function (provider, row) {
         var chart = getChartFromId('realChart');
         var data = generateChartData(dataProvider);
         var chartData = {
             "chart": {
                 "caption": "통계청 총생산소득",
                 "subCaption": "www.realgrid.com",
                 "xAxisname": "Year",
                 "yAxisName": "소득 ($)",
                 "numberPrefix": "$",                    
                 //Theme                    
                 "theme": "fint",
                 "showValues": "0",
                 "labelDisplay": "rotate",
                 "slantLabels": "1",
                 "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
                 "showLegend": "1"                   
             },
                 "categories": [{
                     "category": data.category
                 }],
                 "dataset": data.dataSet
                        
         }
         chart.setChartData(chartData);
     }
        
     
  4. 데이타 로드 후 FusionCharts를 setup합니다.

     dataProvider.fillJsonData(data);
     setFusionChart(dataProvider);
     

실행화면

  1. RealGrid column.headercheckbox선택/해제 합니다.

  2. checkboxchecked, unchecked됨에 따라 FusionChart의 Serise가 보여지거나 숨겨지는걸 확인하세요.

  3. 그리드의 데이터를 변경 후 FusionCharts의 그래프가 변동되는 걸 확인하세요.

전체 소스코드

SCRIPT
<script type="text/javascript" src="/script/realgridjs-lic.js"></script>
<script type="text/javascript" src="/script/realgridjs_eval.1.0.14.min.js"></script>
<script type="text/javascript" src="/script/realgridjs-api.1.0.14.js"></script>
<script type="text/javascript" src="/script/fusioncharts.js"></script>
<script type="text/javascript" src="/script/fusioncharts.charts.js"></script>
<script type="text/javascript" src="/script/fusioncharts.theme.fint.js"></script>

<script>
var gridView;
var dataProvider;
    
$(document).ready( function() {

    RealGridJS.setTrace(false);
    RealGridJS.setRootContext("/script");
    
    dataProvider = new RealGridJS.LocalDataProvider();
    gridView = new RealGridJS.GridView("realgrid");
    gridView.setDataSource(dataProvider);

    gridView.setSortingOptions({enabled: false})
    
    //다섯 개의 필드를 가진 배열 객체를 생성합니다.
    var fields = [{
        fieldName: "Year"
    }, {
        fieldName: "GDP",
        dataType: "number"
    }, {
        fieldName: "GNI",
        dataType: "number"
    }, {
        fieldName: "PGNI",
        dataType: "number"
    }, {
        fieldName: "DIncome",
        dataType: "number"
    }];
    dataProvider.setFields(fields);
    
    //필드와 연결된 컬럼을 가진 배열 객체를 생성합니다.
    var columns = [{
        name: "Year",
        fieldName: "Year",
        width: "50",
        styles: {
            textAlignment: "center"
        },
        header: {
            text: "Year"
        },
        editable : false //편집불가
    }, {
        name: "GDP",
        fieldName: "GDP",
        width: "130",
        styles: {
            textAlignment: "far",
            numberFormat: "#,##0"
        },
        header: {
            text: "GDP ($100 milion)",
            checkLocation : "left"  // 기본값은 none으로 none외에 값으로 지정시 checkbox가 보여진다.
        },
        checked: true   // checked
 
    }, {
        name: "GNI",
        fieldName: "GNI",
        width: "130",
        styles: {
            textAlignment: "far",
            numberFormat: "#,##0"
        },
        header: {
            text: "GNI ($100 milion)",
            checkLocation: "left"
        },
        checked: true
    }, {
        name: "PGNI",
        fieldName: "PGNI",
        width: "120",
        styles: {
            textAlignment: "far",
            numberFormat: "#,##0"
        },
        header: {
            text: "PGNI ($)",
            checkLocation: "left"
        },
        checked: true
    }, {
        name: "DIncome",
        fieldName: "DIncome",
        width: "120",
        styles: {
            textAlignment: "far",
            numberFormat: "#,##0"
        },
        header: {
            text: "DIncome ($)",
            checkLocation: "left"
        },
        checked: true
    }];
    gridView.setColumns(columns);
    
    gridView.onColumnCheckedChanged = function (grid, column, checked) {        
        var chart = getChartFromId('realChart');
        var data = generateChartData(dataProvider);
        var chartData = {
            "chart": {
                "caption": "통계청 총생산소득",
                "subCaption": "www.realgrid.com",
                "xAxisname": "Year",
                "yAxisName": "소득 ($)",
                "numberPrefix": "$",                    
                //Theme                    
                "theme": "fint",
                "showValues": "0",
                "labelDisplay": "rotate",
                "slantLabels": "1",
                "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
                "showLegend": "1"                   
            },
                "categories": [{
                    "category": data.category
                }],
                "dataset": data.dataSet
                    
        }
        chart.setChartData(chartData);

        setColumnBackground(chart)
    }

    dataProvider.onRowUpdated = function (provider, row) {
        var chart = getChartFromId('realChart');
        var data = generateChartData(dataProvider);
        var chartData = {
            "chart": {
                "caption": "통계청 총생산소득",
                "subCaption": "www.realgrid.com",
                "xAxisname": "Year",
                "yAxisName": "소득 ($)",
                "numberPrefix": "$",                    
                //Theme                    
                "theme": "fint",
                "showValues": "0",
                "labelDisplay": "rotate",
                "slantLabels": "1",
                "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
                "showLegend": "1"                   
            },
                "categories": [{
                    "category": data.category
                }],
                "dataset": data.dataSet
                    
        }
        chart.setChartData(chartData);
    }
        
    var data = [{"Year":"2008","GDP":9309,"GNI":9379,"PGNI":19161}
    ,{"Year":"2009","GDP":8344,"GNI":8381,"PGNI":17041,"DIncome":10057}
    ,{"Year":"2010","GDP":10147,"GNI":10160,"PGNI":20562,"DIncome":11796}
    ,{"Year":"2011","GDP":11147,"GNI":11176,"PGNI":22451,"DIncome":12906}
    ,{"Year":"2012","GDP":11292,"GNI":11355,"PGNI":22708,"DIncome":13150}];
    dataProvider.fillJsonData(data);
    
    setFusionChart(dataProvider);
});
 
function generateChartData(provider) {
    var category = [];
    var colNames = ["GDP", "GNI", "PGNI", "DIncome"];
    var seriseNames = [];
    var dataSet = [];
    var data = { GDP: [], GNI: [], PGNI: [], DIncome: [] };
    var returnVal = {};

    for (var i = 0; i < provider.getRowCount() ; i++) {
        var label = { "label": provider.getValue(i, "year") }
        category.push(label);

        for (var j in colNames) {
            data[colNames[j]].push({ "value": provider.getValue(i, colNames[j]) });
        }
    }

    for (var i = 0 ; i < colNames.length ; i++) {
        if (gridView.getColumnProperty(colNames[i], "checked")) {
            dataSet.push({
                serisename: colNames[i],
                data: data[colNames[i]]
            });
        }
    }

    returnVal.category = category;
    returnVal.dataSet = dataSet;

    return returnVal;
}

function setFusionChart(provider) {
    FusionCharts.ready(function () {

        var chartData = generateChartData(provider);

        var fusioncharts = new FusionCharts({
            id: "realChart",
            type: 'mscolumn2d',
            renderAt: 'fusioncharts',
            width: '100%',
            height: '200',
            dataFormat: 'json',
            dataSource: {
                "chart": {
                    "caption": "통계청 총생산소득",
                    "subCaption": "www.realgrid.com",
                    "xAxisname": "Year",
                    "yAxisName": "소득 ($)",
                    "numberPrefix": "$",                    
                    //Theme                    
                    "theme": "fint",
                    "showValues": "0",
                    "labelDisplay": "rotate",
                    "slantLabels": "1",
                    "paletteColors": "#EED17F,#97CBE7,#ff4868,#B0D67A",
                    "showLegend": "1"                   
                },
                "categories": [{
                    "category": chartData.category
                }],
                "dataset": chartData.dataSet
                    
            }
        });
        fusioncharts.render();

        setColumnBackground(fusioncharts);
    });
}

function setColumnBackground(chart) {
    var colNames = ["GDP", "GNI", "PGNI", "DIncome"];

    var color = chart.getChartAttribute("paletteColors").split(",");

    var colorIdx = 0
    for (var i = 0 ; i < colNames.length ; i++) {
        if (gridView.getColumnProperty(colNames[i], "checked")) {
            gridView.setColumnProperty(colNames[i], "styles", { background: color[colorIdx++] });
        } else {
            gridView.setColumnProperty(colNames[i], "styles", { background: "#00000000" });
        }
    }
}
</script>

</pre>

##### HTML
<div id="fusioncharts" style="width: 100%; height: 200px;"></div>
<div id="realgrid" style="width: 100%; height: 200px;"></div>
--- **관련 데모 페이지** * [Column Selecting](http://demo.realgrid.com/Demo/HighchartsColumnHeaderClicked) * [Column Filtering](http://demo.realgrid.com/Demo/HighchartsColumnFilters) * [Row Selecting](http://demo.realgrid.com/Demo/HighchartsSelection) --- **API 참조** * [LocalDataProvider.onRowUpdated()](/api/LocalDataProvider/onRowUpdated/) * [GridBase.onColumnCheckedChanged()](/api/GridBase/onColumnCheckedChanged/)