- 자바스크립트에서 원시 타입을 제외한 모든 나머지 값들(함수 배열 정규표현식 등)은 객체.
- 객체는 key 와 value 로 구성된 property 의 집합
- 프로퍼티 값이 함수인 경우 일반 함수와 구분하기 위해 메소드라 부름 (자바스크립트의 함수는 일급객체(참고)이므로 값으로 취급 가능)
- 객체는 데이터를 의미하는 프로퍼티와 데이터를 참조하고 조작할 수 있는 동작(메소드)로 구성된 집합
- 프로퍼티 및 메소드를 모두 포함할 수 있어 하나의 단위로 구조화하기 유용
- 프로토타입을 상속받아 객체지향의 상속을 구현한다

[프로퍼티]
- 프로퍼티 키를 중복 선언시 나중에 선언한 프로퍼티가 먼저 선언한 프로퍼티를 덮어씀
- 프로퍼티간 순서를 보장하지 않음

[메소드]
- 프로퍼티 값이 함수인 경우 메소드라 부름
- 객체에 제한되어 있는 함수를 의미

[객체 생성 방법]
1. 객체 리터럴
- 중괄호 사용하여 생성
- 비어있는 객체 생성 가능 ex) var empty = {};

1
2
3
4
5
6
7
var person = { 
    name : 'Lee'
    gender : 'male'
    sayHello : function(){ 
        console.log('My name is' + this.name); 
    } 
cs

 

2. Object 생성자 함수
- new 연산자와 Object 생성자 함수를 호출하여 빈 객체 생성 가능
- 생성자 함수의 이름은 파스칼 케이스를 사용하는게 일반적
- 객체가 소유하고 있지 않은 프로퍼티 키에 값을 할당하면 해당 객체에 프로퍼티를 추가하고 값을 할당, 이미 존재하는 프로퍼티 키에 새로운 값을 할당하면 해당 값으로 변경
* Object 생성자 함수 사용보단 객체 리터럴 사용 (객체 리터럴 사용시 내부적으로 Object 생성자 함수를 사용하여 객체를 생성하므로)

3. 생성자 함수
프로퍼티 값만 다른 객체를 여러개 생성할 때 객체 리터럴 및 Object 생성자 함수를 사용한다면 아래와 같이 코드량이 많아지고 불편

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var person1 = { 
    name : 'Lee'
    gender : 'male'
    sayHello : function(){ 
        console.log('My name is' + this.name); 
    } 
var person2 = { 
    name : 'Kim'
    gender : 'female'
    sayHello : function(){ 
        console.log('My name is' + this.name); 
    } 
cs

이를 아래와 같이 생성자 함수를 사용하면 간편

1
2
3
4
5
6
7
8
9
10
11
function Person(name, gender){ 
    this.name = name
    this.gender = gender; 
    this.sayHello = function(){ 
        console.log('Hi! My name is ' + this.name); 
    } 
var person1 = new Person('Lee''male'); 
var person2 = new Person('Kim''female'); 
person1.sayHello(); 
person2.sayHello(); 
cs

- 생성자 함수명은 대문자로 시작하여 생성자임을 인식하도록 도움을 줌
- 프로퍼티 또는 메소드 앞에 기술한 this는 생성할 인스턴스(비어있는 새로운 객체)를 의미(new 연산자와 함께 함수를 호출시 this 바인딩이 다르게 동작)
- this 에 바인딩되어있는 프로퍼티와 메소드는 외부에서 참조가 가능, 생성자 함수 내에서 선언된 일반 변수는 외부에서 참조 불가 : 생성자 함수 내부에서 자유롭게 접근이 가능하나 외부에서 접근은 불가 (아래 참고)

1
2
3
4
5
6
7
8
9
10
11
function Person(name, gender){ 
    var married = true
    this.name = name
    this.gender = gender; 
    this.sayHello = function(){ 
        console.log('Hi! My name is ' + this.name); 
    } 
var person = new Person('Lee''male'); 
console.log(person.gender); // 'male' 
console.log(person.married); // 'undefined' 
cs

※ 자바의 생성자와 다르게 형식이 정해져 있지 않고, 기존 함수와 동일한 방법으로 선언하고 new 연산자를 붙여 호출하면 생성자 함수로 동작
 생성자 함수가 아닌 일반 함수에 new 연산자를 붙일 경우 생성자 함수처럼 동작 가능하다는 것을 의미. 따라서 생성자 함수의 첫문자는 대문자로 명명하여 혼란 야기를 방지
new 연산자와 함께 함수를 호출하면 this 바인딩이 다르게 동작


[ new 연산자와 함께 생성자 함수 호출시 동작 순서 ]
1. 빈 객체 생성 및 this 바인딩 
- 생성자 함수의 코드가 실행되기 전 비어있는 객체가 생성된다
- 생성자 함수 내에서 사용하는 this 는 이 비어있는 객체를 가리킨다.
- 생성된 빈 객체의 프로토타입 객체는 생성자 함수의 prototype 프로퍼티가 가리키는 객체.
2. this를 통한 프로퍼티 생성
- 생성된 빈 객체에 this를 사용하여 프로퍼티나 메소드 생성 가능
3. 생성된 객체 반환
- this 에 바인딩된 객체 자동 반환


[ 객체 프로퍼티 선언 및 접근 ]
[ 프로퍼티 키 선언 ]
- 프로퍼티 키에 표현식(- 연산자 등)이 존재하는 경우 대괄호로 묶어야 함 otherwise, ReferenceError 발생, 예약어는 당연히 사용하면 안된다
ex: var person = {first-name : 'gildong'} >> ReferenceError

[ 프로퍼티 키 접근 ]
- 마짐표 . 표기법: 프로퍼티 키가 유효(표현식(- 연산자 등)이 있는 경우 무효), 예약어가 아닌 경우 마침표/대괄호 표기법 모두 사용 가능
- 대괄호 [] 표기법: 프로퍼티 키가 유효한 값이 아니거나, 예약어인 경우 대괄호 내에 들어가는 프로퍼티 이름은 반드시 문자열이어야 함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var person = { 
 'first-name''gildong'
  'last-name''Hong'
  gender: 'male'
  110 
console.log(person.first-name); // NaN : undefined - undefined  
console.log(person[first-name]); // ReferenceError 
console.log(person['first-name']); // 'gildong' 대괄호 표기법 대괄호 안이 반드시 문자열, 유효하지 않은 프로퍼티 키는 대괄호를 사용하여 읽음  
console.log(person.gender); // 'male' 유효한 프로퍼티 키는 대괄호, 마짐표 표기법 모두를 사용하여 읽기 가능 
console.log(person[gender]); // ReferenceError 
console.log(person['gender']); // 'male' 대괄호 표기법 대괄호 안이 반드시 문자열, 유효한 프로퍼티 키는 대괄호, 마짐표 표기법 모두를 사용하여 읽기 가능 
console.log(person['1']); //10 대괄호 표기법 대괄호 안이 반드시 문자열, 유효하지 않은 프로퍼티 키는 대괄호를 사용하여 읽음  
console.log(person[1]); //10 
console.log(person.1); //SyntaxError 
cs


[ 프로퍼티 값 수정 ]
- 객체가 갖고 있는 프로퍼티에 새로운 값 할당시 값이 수정됨 
ex) person.gender = 'female';

[ 프로퍼티 생성 ]
- 객체가 소유하고 있지 않은 프로퍼티 키와 값 할당시 새로운 프로퍼티 추가됨
ex) person.age = 30;

[ 프로퍼티 삭제 ]
- delete 키워드를 사용하여 객체 프로퍼티를 삭제, 이때 피연산자는 프로퍼티 키.
ex) delete person.gender;

[ 프로퍼티 값 출력 ]

1
2
3
4
5
6
for(var prop in person){ 
    console.log(prop + ':' +person[prop]); 
for(var idx in array){ 
    console.log(idx + ":" +array[idx]); 
cs

- for in문 사용하여 객체에 포함된 모든 프로퍼티 루프 출력이 가능
- for in문은 array 에서 사용을 삼가. 배열 요소만을 순회하지 않음
for of 사용 (ES6) 

[ pass by reference ]
객체 타입은 원시타입과 달리 동적으로 변화할 수 있으며 어느정도 메모리 공간을 확보해야 하는지 예측 불가하기 때문에 런타임에 메모리 공간을 확보하고 메모리의 힙영역에 저장된다. 

1
2
3
4
5
6
7
var foo = { 
    val : 10 
var bar = foo; 
console.log(foo.val, bar.val); // 10 10 
bar.val = 20
console.log(foo.val, bar.val); // 20 20 
cs

(위의 두 변수 모두 동일한 객체의 참조주소를 참조한다 (java의 참조객체와 동일))

참고 : https://poiemaweb.com/js-object#2-%EA%B0%9D%EC%B2%B4-%EC%83%9D%EC%84%B1-%EB%B0%A9%EB%B2%95

반응형

[scope란?]

참조대상 식별자를 찾아내기 위한 규칙.

특정 변수가 선언되어 있을 때, 해당 변수를 소스 내 어디에서 찾아서 사용할 지를 규정하는 규칙.

 

[전역스코프 vs 지역스코프]

전역스코프 : 코드 내 모든 곳에서 참조 가능.

지역스코프 : 함수 코드 블록 내에서 만들어진 스코프로 함수 자기 자신과 하위 함수에서만 참조 할 수 있다.

※ 최상위 스코프는 window

 

[블록레벨스코프 vs 함수레벨스코프]

블록레벨스코프 block-level scope : if문, for문 과 같은 블록 내에 선언된 변수는 블록 밖에서는 참조가 불가하다. (대부분의 C언어, 자바언어)

함수레벨스코프 function-level-scope : 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 참조가 가능하다. (ECMAScript 6 부터 도입된 let 키워드 사용시 블록 레벨 스코프 사용 가능)

1
2
3
4
5
6
function sample(){
    if(true) {
        var tt = 1;
    }
    console.log(tt);
}
cs

>> javascript 는 함수레벨 스코프이므로, 함수 블록 내에서 선언된 변수는 함수 블록 내에서 참조가 가능. 싱기방기

1
2
3
4
5
6
function sample(){
    if(true) {
        let tt = 1;
    }
    console.log(tt);
}
cs

>> 블록레벨스코프 변수 let 을 사용했으므로 5번라인에서 tt 사용시 에러를 뱉음(java 및 기타 C계열언어와 같이 동작)

 

[동적스코프 vs 렉시컬스코프]

동적스코프 dynamic scope : 호출 시점에 따라 상위 스코프 결정

렉시컬스코프 lexical scope : 함수 선언 위치에 따라 상위 스코프 결정 (js 를 포함한 대부분의 언어가 해당 스코프를 따름)

1
2
3
4
5
6
7
8
9
10
var x = 1;
function foo() {
  var x = 10;
  bar();
}
function bar() {
  console.log(x);
}
foo(); // ?
bar(); // ?
cs

위와 같을 때, 결과는 1출력.

>> javascript 는 렉시컬 스코프를 따르므로 bar가 선언된 위치에 따라 상위 스코프가 결정되며, bar 내의 x 는 bar 의 상위 스코프 내에서 찾게된 전역 변수 x = 1 을 사용

※ 동적스코프 : bar의 상위 스코프는 함수 foo와 전역, 결과 10 출력

렉시컬스코프 : bar의 상위 스코프는 전역, 결과 1 출력

 

추가 예)

window.location.protocol 은 현재 페이지의 protocol (http: or https:) 을 뽑아낼 때 사용가능한 내장함수.

window 를 빼고, location.protocol 까지만 써줘도 window.location.protocol 을 가져올 수 있다.

스코프를 상위로 옮겨가며 탐색하다 계속 찾지 못한다면  window 까지 올라가서 찾아오기 때문.

 

그렇다면 protocol만 써줄 경우 이 케이스는 왜 못찾고 에러를 뱉는가?

> protocol은 window가 아닌 window.location 내에 존재.

> 현재 스코프 내에서 protocol 을 찾지 못한다면 상위 스코프에서 찾기 시작하고 결론적으론 window 까지 올라가서 찾게 될 뿐 window.location 내에서 찾진 않기 때문.

 

 

참고 : https://poiemaweb.com/js-scope

매우 좋은 블로그를 찾았다. 유레카..

반응형

javascript 에서 hoisting 이란 단어 뜻 그대로 끌어올리기라는 의미로써, 변수를 최상단으로 끌어올리는 것을 뜻한다.

이와 같은 자바스크립트에서의 호이스팅이란 특징으로 인해, 

javascript에서 변수는 사용된 이후 선언 될 수 있다. (==변수를 사용한 후 선언 할 수 있다)

 

[case 1]

1
2
3
4
5
$(document).ready(function(){
    var x;
    x = 5;
    console.log(x);
});
cs

변수를 선언 후 변수에 값을 저장한 케이스. 보기에도 문제가 없어보이고 실행 결과도 문제가 없다.

[case 2]

1
2
3
4
5
$(document).ready(function(){
    x = 5;
    console.log(x);
    var x;
});
cs

변수에 값을 저장/사용 후 선언한 케이스

java 같으면 케이스2에서 Exception 을 뱉겠지만, javascript 는 결과 5를 정상적으로 console 에 출력한다.

보기엔 에러가 발생할 것으로 보였던 코드임에도 에러없이 정상 결과가 나온 이유는 바로 hoisting 때문이다.

(var x; 부분(변수 선언부)을 현재 scope에서 최상단으로 끌어올렸기 때문)

(스코프와 관련된 내용은 여기를 참고)

 

그렇다면 호이스팅은 항상 이뤄질까?

자바스크립트는 선언부만 hoisting 할 뿐, 초기화 부분까지 호이스팅하지 않는다.

[case 3]

1
2
3
4
5
$(document).ready(function(){
    console.log(x);
    console.log(y);
    var x = 5;
});
cs

 

위 샘플 소스의 결과는 아래와 같다.

x 는 'undefined'를 콘솔에 출력하고 있고,

y 는 undefined Error 을 던지고 있다.

var x 부분은 hoisting 되었지만 초기화(=5)부분은 호이스팅되지 않았기 때문이다.

y는 스코프내에 선언되어 있지 않으므로 Error 를 뱉고 있다.

[결론]

예상치 못한 hoisting 동작으로 인한 에러를 피하기 위해 변수 선언 및 초기화는 최상단에서 해주자.

 

 

참고 : https://www.w3schools.com/js/js_hoisting.asp

 

 

반응형

typeof 는 js에서 타입을 반환하는 연산자(operator)로써 변수의 타입을 확인할 때 사용한다.

 

typeof 로 아래와 같이 number, string, object, boolean, function 타입을 확인 할 수 있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
console.log(typeof 123);              //number
console.log(typeof "str");             //string
console.log(typeof new Object());      //object
console.log(typeof {test : "test"});   //object
console.log(typeof true);              //boolean
console.log(typeof Symbol());          //symbol
console.log(typeof function(){});      //function
 
console.log(typeof 123 === 'number');               //true
console.log(typeof "str" === 'string');             //true
console.log(typeof new Object() === 'object');      //true
console.log(typeof {test : "test"=== 'object');   //true
console.log(typeof true === 'boolean');             //true
console.log(typeof Symbol() === 'symbol');          //true
console.log(typeof function(){} === 'function');    //true
cs

 

다음과 같은 타입은 주의하여 사용하자.

1
2
3
4
5
6
7
8
console.log(typeof null);                    //object
console.log(typeof new Object(123));        //object
console.log(typeof new Object("123"));        //object
        
console.log(typeof null === 'undefined');                //false
console.log(typeof new Object(123=== 'object');        //true
console.log(typeof new Object(123=== 'number');        //false
console.log(typeof new Object("123"=== 'string');        //false
cs

1. null 은 object (null 은 != null 과 같이 체크 할 것)

2. Object에 담긴 number/string 는 object

 

undefined : 선언은 되어있으나 아무 값도 저장되어 있지 않은 경우

undeclared : 변수 선언 자체가 되어 있지 않은 경우

* undefined , undeclared 모두 typeof 시 undefined로 반환

 

 

참고 : 

typeof document

정리가 잘 되어있는 글 (영어)

정리가 매우 잘 되어있는 글(한글)

반응형

javascript 에서 함수는 1급객체이다.

javascript 에서 함수는 아래와 같은 특징을 지닌다.

 

1. 익명함수로 작성 가능

2. 리턴값으로 사용 가능

3. 매개변수로 사용 가능

4. 변수, 자료구조로 저장 가능

 

위와 같은 특징으로 인해 callback 함수 같은 개..념이 존재.

 

[함수 선언식 vs 함수 표현식]

함수 선언식 : function func(){}

함수 표현식 : var func = function(){}

 

함수선언식으로 소스를 작성해도, 해당 소스 구동시 js 엔진 내에서 함수선언식을 함수표현식으로 바꾼다.

반응형

유저가 페이지를 벗어날 때마다, 특정 처리를 해줘야 하는 상황엔 beforeunload 를 사용.

유저가 페이지를 벗어날 때 처리해 줄 코드와 함께 beforeunload event를 리스너에 등록하여 사용.

※ 뒤로가기, refresh 뿐만 아닌 submit, 브라우저 close 경우에도 beforeunload 리스너가 동작하게 되므로 주의.

 

[ Sample ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$(window).on("beforeunload", callback);
 
function callback(){
    console.log("beforeunload callback !");
    //do something
    return "changes will be lost!";
}
 
function off(){
    console.log("beforeunload turn off !");
    $(window).off("beforeunload");
}
 
<button type="button" onclick="javascript:off();">리스너끄기</button>
cs

 

submit 을 제외한 모든 페이지 전환에 특정 함수를 실행시키고 싶은 경우 :

.off("~") 를 사용하여 submit 시엔 beforeunload 이벤트 핸들러를 제거.

 

[ Example ]

1
2
3
4
5
6
7
8
9
10
11
12
$(document).ready(function () {
    // Warning
    $(window).on('beforeunload'function(){
        //do something
        return "Any changes will be lost";
    });
    // Form Submit
    $(document).on("submit""form"function(event){
        // disable warning
        $(window).off('beforeunload');
    });
}
cs

 

 

반응형

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를 사용할 경우 분기처리를 위해 필요. 

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

 

반응형

+ Recent posts