Mysql hierarchy sql 계층구조 쿼리 2 : 그리기(Multi selectbox)

 

https://developyo.tistory.com/54

위의 쿼리에서 꺼내온 정보를 화면에 뿌려보자.

 

 

<1: 컨트롤러 코딩>

1. 가이드 목록을 출력하기 위한 controller

1
2
3
4
5
6
7
8
9
10
11
12
@RequestMapping("/loadGuideList.do")
public ModelAndView loadGuideList(HttpServletRequest request, @RequestBody GuideVO param) throws Exception
{    
    ModelAndView mav = new ModelAndView("jsonView");
    
    List<GuideVO> guideList = service.selectGuideList(param);
    
    mav.addObject("guideList", guideList);    //가이드 목록
    mav.addObject("paramsData", param);
    
    return mav;
}
cs

 

2. 멀티 셀렉트박스 목록을 ajax로 불러오기 위한 controller

1
2
3
4
5
6
7
8
9
@RequestMapping("/getNodeList.do")
public ModelAndView getNodeGroup(HttpServletRequest request, @RequestBody NodeVO param) throws Exception
{    
    ModelAndView mav = new ModelAndView("jsonView");
    List<NodeVO> nodes = service.selectNodeList(param);    //가이드 카테고리
    mav.addObject("nodes", nodes);
 
    return mav;
}
cs

 

* Service, DAO, VO 는 별다른 내용이 없으므로 생략..

 

<2: script 코딩>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
var loadData = {
        
        //가이드 목록 호출
        loadGuideList : function () {
            
            var totalSearchFlag = "N";    //가장 낮은 depth 의 선택 값이 전체인 경우 Y
            
            //현재 선택된 node_id 값 set (조회용)
            var nodeCnt = $(".nodeGroup").length;
            
            //조회
            var paramVal = "";
            for(var i=nodeCnt-1; i>=0; i--){
                //제일 우측(낮은 depth) 셀렉트 박스부터 제일 좌측(높은 depth) 로 반복문
                var val = $(".nodeGroup:eq("+i+")").val();
                var node_id = val.split("^")[0];
                if(node_id && node_id != ""){
                    //node_id 가 존재하는 경우(전체 선택이 아닌 경우)
                    paramVal = node_id;
                    break;
                } else {
                    //node_id 가 존재하지 않는 경우(전체 선택인 경우)
                    totalSearchFlag = "Y";
                    continue;
                }
            }
            
            $("form[name=frmGuide] input[name=totalSearchFlag]").val(totalSearchFlag);
            $("form[name=frmGuide] input[name=node_id]").val(paramVal);                    
        
            var params = {
                node_id : $("form[name=frmGuide] input[name=node_id]").val(),
                totalSearchFlag : $("form[name=frmGuide] input[name=totalSearchFlag]").val()
            };
            
             $.ajax({
                type    : "post",
                url        : "/stbcs/ipchk/loadGuideList.do",
                contentType: "application/json",
                dataType:"json",
                data     : JSON.stringify(params),    
                success    : function (data) {
                    drawData.drawGuideList(data);
                }
            }); 
        } ,
        
        //가이드 분류
        loadNodeList : function(selectBox){
                var obj = $(selectBox);
                var tmp = obj.val().split("^");
                var nodeId = tmp[0];
                var leaf_yn = tmp[1];
                var currentIdx = obj.parent(".nodeGrp").index();    //현재 node 의 idx        
                var nodeCnt = $(".nodeGrp").length;    //node 갯수                            
                
                if(nodeCnt > currentIdx){
                    for(var i=nodeCnt; i>=currentIdx; i--){    
                        console.log("remove idx : " + i);   
                        $(".nodeGrp:eq("+i+")").remove();     
                    }
                }
                
                if(leaf_yn == "Y"){
                    //마지막 노드가 아닌 경우 (자식 노드가 있는 경우)
                    var params = {
                            node_id : nodeId
                        };
                    
                    $.ajax({
                        type    : "post",
                        url        : "/getNodeList.do",
                        contentType: "application/json",
                        dataType:"json",
                        data     : JSON.stringify(params),    
                        success    : function (data) {
                            drawData.drawNodeList(data);
                        }
                    });
                }
        } 
}
var drawData = {
    drawNodeList : function (data, currentIdx){
                var nodeGroupTxt = "";
                
                try{
                    var node = data.node;
                    if(node != null && node.length > 0){
                        if($(".nodeGrp").length == 0){
                            nodeGroupTxt += "<span>분류&nbsp;&nbsp;</span>";
                        }
                        nodeGroupTxt += "<div class='selectbox small nodeGrp' style='margin-right:3px;' >";
                        nodeGroupTxt += "<select class='nodeGroup' name='node_id' onchange='javascript:loadData.loadNodeList(this);'>";
                        nodeGroupTxt += "<option value='^N'>전체</option>";
                        
                        $.each(node, function(index, item){
                            nodeGroupTxt += "<option value=" + item.node_id+"^"+item.leaf_yn + ">" + item.node_nm + "</option>";
                        });
                        
                        nodeGroupTxt += "</select>";
                        nodeGroupTxt += "</div>";
                    }
                } catch (error) {
                } finally {
                    $("#guideSearchDiv").append(nodeGroupTxt);
                }        
        }
}
cs

 

※ Multi selectbox

94line : selectbox에 onchange 이벤트를 걸어 selectbox 값이 변화할 때, 자신의 loadNodeList(this) 함수를 호출한다.

57~62line : 총 selectbox 갯수가 현재 선택된 selectbox의 index보다 큰 경우 현재 선택된 selectbox 보다 낮은 depth(우측에있는)의 selectbox를 지운다.

ex: 1, 2, 3 depth 의 selectbox 를 특정 값으로 선택해 놓고, 1번째 selectbox 의 값을 다른값으로 바꿔버린 경우 2, 3번째 selectbox tag는 .remove()로 제거한다 (remove는 싱크(동기)방식이므로 ajax 호출 순서가 보장된다)

64~80line :

selectbox에서 선택된 값이 자식노드가 있는 경우(leaf_yn == 'Y') 특정 노드를 기준으로 한 자식 노드 목록을 가져오기 위해 getNodeList.do ajax 호출

84~108line : ajax 호출을 통해 가져온 노드 목록을 selectbox로 표현

98line : 조작시 필요한 값인 노드아이디와 자식노드유무 데이터를 ^ 문자를 구분으로하여 value 값으로 넣어준다(option value = node_id^leaf_yn)

106line : 멀티셀렉트박스가 위치할 곳에 만들어준 selectbox를 .append 로 붙여넣는다

 

※ 가이드 목록(Multi selectbox 를 조건으로 걸어 조회한 결과 리스트)

4~46 line : 가이드 목록 ajax 호출

13~26 line :

가장 낮은 depth(제일 오른쪽)의 selectbox 부터 가장 높은 depth (제일 왼쪽)의 selectbox 까지 for 문을 돈다.

node_id^leaf_yn (노드아이디^자식노드존재유무) 값이 담겨있는 option value 를 꺼낸다.

node_id 가 존재하는 경우 전체 조회가 아니므로 해당 값을 server 쪽에 ajax 로 전달하면 된다. (for문을 끝낸다)

node_id 가 존재하지 않는 경우 전체 조회이므로 서버에 전달할 전체 조회 flag 값(totalSearchFlag)를 Y 로 바꿔준 후, for문을 계속 돌린다(continue;)

* 전체 조회 flag 값(totalSearchFlag)은 subquery(3-2 쿼리작성부분의 3번 쿼리) 를 사용할 경우 필요 없다. foreach를 사용할 경우 분기처리를 위해 필요. 

* 조회한 가이드 목록을 화면에 그리는 코딩은 별다를게 없으므로 생략..

 

반응형

[ submit, replace, href 차이 ]

submit 

페이지 이동시 다음페이지로 데이터 전송

document.id.action="/test.do";

document.id.submit();

 

href

데이터 전송없이 페이지만 이동

location.href="/test.do";

 

replace

데이터 전송없이 페이지만 이동(새로운 페이지로 변경)

location.replace("/test.do");

 

※ href와 replace의 차이

href : 속성, 뒤로가기 가능

replace : 메소드, 뒤로가기 불가

 

https://yuchae.tistory.com/223

https://opentutorials.org/module/2919/22904

 

 

반응형

jQuery API jqPlot 을 사용하여 그래프 그리기

 

jqPlot 을 사용하여 통계 데이터를 가로/세로형 막대그래프, 선형그래프, 원형그래프 등으로 쉽게 표현 할 수 있다.

* 세로형 선형그래프를 아래와 같이 구현해 보았다.

 

 

1. js import

1
2
3
4
5
6
7
8
9
10
<link rel="stylesheet" type="text/css" href="${rq.getContextPath()}/resources/css/jquery.jqplot.css">
 
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/jquery.jqplot.min.js"></script>
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/jquery.jqplot.js"></script>
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/plugins/jqplot.enhancedLegendRenderer.js"></script>
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/plugins/jqplot.barRenderer.js"></script>
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/plugins/jqplot.highlighter.js"></script>
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/plugins/jqplot.categoryAxisRenderer.js"></script>
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/plugins/jqplot.cursor.js"></script>
<script type="text/javascript" src="${rq.getContextPath()}/resources/js/jqplot/plugins/jqplot.pointLabels.js"></script>
cs

jqPlot 을 사용하기 위해 관련 js를 import 한다.

 

 

2. 데이터 set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
fn_csCntChart : function () {
 
            var barData1 = [];
            var barData2 = [];
            var ticks = [];
            var labels = ['전체건수''1인당 처리건수'];
            
            <c:forEach var="list" items="${statsList}" >
                barData1.push("${list.cnt}");
                barData2.push("${list.cntPerEmp}")
                ticks.push("${list.graphDt}");
            </c:forEach>    
            
            var csCntMaxValue = Math.max.apply(null, barData1);        //전체 데이터 중 최대 값
            
            if(ticks.length > 1){
                csCntMaxValue = csCntMaxValue*1.2;    //전체 데이터 최대 값 * 1.2
            }else{
                csCntMaxValue = 10000;    //모든 데이터 값이 0인 경우 차트 최대값을 10000으로 set
            }
                   
            var campChart = $.jqplot('chartArea', [barData1, barData2], {
                //차트 속성 설정
            }
cs

6 Line: 데이터의 범례(각각의 그래프가 의미하는 정보 : 전체건수, 1인당 처리건수)는 lables 배열에 담는다

9 Line: 서버에서 전달한 statsList 데이터(list)에서 cnt (전체건수) 값을 barData1 array에 담는다.

10 Line:서버에서 전달한 statsList 데이터(list)에서 cntPerEmp(1인당 처리건수) 값을 barData2 array에 담는다.

11 Line : 데이터의 기준점(그리드에서 가로축)이 되는 날짜(graphDt)를 ticks 배열에 담는다.

            ticks 는 차트 옵션을 지정할 때 사용한다.

14 ~ 20 Line :

그리드 세로축의 최대값을 제한.

전체건수와 1인당 처리건수 중 전체건수의 값이 당연히 클 것임으로 list 중 전체건수의 최대 값을 뽑아낸 후  1.2를 곱한 값을 세로축의 최대값으로 사용한다.

만약 조회된 데이터가 없는 경우 세로축의 최대값을 1만으로 제한한다.

22 Line:

'chartArea' : 차트를 그릴 태그 id (id가 'chartArea' 인 tag에 완성된 차트가 그려지게 된다)

array barData1, barData2 를 array 에 다시 담아 jqplot 의 파라미터로 전달한다.

   

 

 

3. 차트 옵션 지정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
var campChart = $.jqplot('campChartMonth', [barData1, barData2], {
            animate: true,
            animateReplot: true,
            cursor: {
                          show: true,
                          zoom: false,
                          looseZoom: false,
                          showTooltip: false
                    },
            series:[
                      {
                          color : 'blue',
                          renderer: $.jqplot.LineRenderer,
                      } ,
                      {
                          color : 'red',
                          renderer: $.jqplot.LineRenderer,
                      }
                    ],
            axesDefaults: {
                  pad: 0
            },
 
            /*그래프 범례*/
            legend: {
                 renderer: $.jqplot.EnhancedLegendRenderer,
                  show: true,
                  location's',
                  labels: labels,
                  rendererOptions:{
                        numberRows :1    
                     },
                    placement: 'outsideGrid',                 
            },    
            axes: {
                    xaxis: {
                                renderer: $.jqplot.CategoryAxisRenderer,
                              ticks: ticks,
                              drawMajorGridlines: false,
                              drawMinorGridlines: true,
                              drawMajorTickMarks: false,
                            },
                    yaxis: {
                                max: csCntMaxValue,
                                min: 0,
                                tickOptions: {
                                    formatString: "%'d"
                                },
                                rendererOptions: {
                                    forceTickAt0: true
                                }
                            },
                },
                highlighter: {
                                show: true
                                showLabel: true
                                tooltipAxes: 'y',
                                sizeAdjust: 7.5 , tooltipLocation : 'ne'
                            },
            }); 
cs

series : 각각의 선형그래프 관련 설정 (첫번째 그래프선을 blue로, 두번째 그래프선을 red 색상으로 지정)

          그래프의 형태는 선형그래프로 지정 (LineRenderer) (막대그래프는 BarRenderer)

legend : 그래프 범례 관련 설정 (위치를 그래프와 겹치지 않도록 바깥에 설정 (placement : outsideGrid))

            범례를 한줄로 설정 (rendererOptions : numberRows 1)

axes :

그리드 관련 설정 

xaxis : x 축 ( 세로형 선형그래프이므로 x 축에 ticks : ticks(graphDt 값을 담고있는 배열) 선언으로 데이터의 기준점(날짜기준(graphDt))을 셋팅 )

yaxis : y 축

 

 

* 가로형 그래프로 그릴 경우 x 축 y 축 설정을 반대로 주고,

그래프 데이터를 인자값으로 넘길 때 2차원 배열형태를 조금 더 신경 써서 만들어야 한다.

 

 

 

참고 : 아래 사이트에 예제를 비롯한 각각의 옵션들이 친절하고 자세하게 설명이 되어있다. 영어로...

http://www.jqplot.com/examples/barTest.php

 

Bar Charts

 

www.jqplot.com

 

 

반응형

CSS 적용 우선 순위

1. 사용자 스타일 시트 우선

!important 선언을 한 사용자 스타일  > !important 선언을 한 작성자 스타일 >
작성자 스타일 > 사용자 스타일 > User Agent 선언 (브라우저 자체의 선언)

 

2. 계산결과가 높을 수록 우선 적용된다.

a = 선택자중 ID의 수를 세어 100자리에 놓는다,

b = 선택자중 가상 클래스와 클래스의 수를 세어 10자리에 놓는다.

c = 선택자중 엘리먼트의 수를 세어 1의 자리에 놓는다.

  a b c 계산결과
*{} 0 0 0 0
li{} 0 0 1 1
ul li{} 0 0 2 2
li.num{} 0 1 1 11
li.num.last{} 0 2 1 21
p#wrap{} 1 0 1 101

 

3. 가장 마지막에 지정된 스타일이 우선 적용된다.

<style type="text/css">

  p.test{color:black;}

</style>

<p class="test" style="color:red;">TEST</p>

 

위 경우 동일한 p 태그의 test 클래스에 red 색상 css 가 선언되어있다.

p 태그가 마지막에 지정된 스타일이므로 TEST 문구는 red 속성이 적용된다.

 

 

*생활코딩 사이트 내용 정리.

https://opentutorials.org/module/484/4149

 

반응형

'front > html, css' 카테고리의 다른 글

[CSS] padding 순서  (2) 2019.07.04

td{padding : 1px 2px 3px 4px;}

 

: 상 우 하 좌

시계방향순서

반응형

'front > html, css' 카테고리의 다른 글

[CSS] 적용 우선 순위  (0) 2019.07.10

+ Recent posts