[TAB 구현 심화_2]_Spring에서 tab 구현해보기 (feat 자료구조)

2022. 2. 17. 17:11[프론트엔드]_/[Javascript]_ES6

728x90
반응형

저번에 뒤로가기를 구현했을 때 stack 구조를 이용하여 구현하였습니다.

이번에는 탭을 끄고 난뒤 탭이 닫혀있으면 rule에 의하여 닫힌 탭은 content 부분에서 사라지고 나머지 탭이 보여지는 기능을 만들어 보고자 합니다.

- 우선 linkedList 를 이용하면 될꺼라 생각해서 시도해 보았으나, 코드가 복잡해지고 구현이 안되었습니다. 이번 포스트는 원인분석과 과정을 써보았습니다.


다음 포스트에는 다른방법으로 시도해 볼 것입니다.

 

1] 기본적인 linklist 구조

class Node {
    constructor(data, next = null) {
        //data와 next를 넣고 next의 디폴트는 null로 지정 왜냐하면 linkedlist의 tail(마지막은) null로 끝나기때문
        this.data = data;
        this.next = next;
    }
}

class LinkedList {
    constructor() {
        this.head = null; //처음에 데이터가 없다면 head는 null이다.
        this.size = 0; //리스트의 크기를 찾기위해 사용 디폴트는 0으로 지정.
    }

    // Insert first node - 첫번째 삽입
    insertFirst(data) {
        this.head = new Node(data, this.head) //head에 새로운 node가 들어가고 기존의 해드는 next로 밀려난다.
        this.size++;
    }

    // Insert last node - 마지막 삽입
    insertLast(data) {
        let node = new Node(data);
        let current;

        // if empty, make head
        if (!this.head) {
            this.head = node;
        } else {
            current = this.head;

            while (current.next) { //this.head에 next가 있다면 즉, next가 null이아니라면
                current = current.next; // current는 current.next가 되고
            }

            current.next = node; //결국 current.next가 새로넣은 node가 된다?
        }
        this.size++; //length 는 1증가
    }

    // Insert at index - 중간 삽입
    insertAt(data, index) {
        tabcount++;
        // If index is out of range ~ 인덱스가 size 범위 넘어서면 아무것도 리턴 하지 않는다.
        if (index > 0 && index > this.size) {
            return;
        }

        // If first index
        if (index === 0) {
            this.head = new Node(data, this.head) //즉, index 0에 삽입시 해당 노드를 넣고 다 한칸식 뒤로 미룸
            this.size++
            return;

        }

        const node = new Node(data);
        let current, previous;

        // Set current first
        current = this.head;
        let count = 0;

        while (count < index) {
            previous = current; //node before index
            count++;
            current = current.next; //node after index
        }

        node.next = current;
        previous.next = node;

        this.size++;
    }

    // Get at index
    getAt(index) {
        let current = this.head;
        let count = 0;

        while (current) {
            //해당 data의 값을 가져오기 위해 index와 값이 같아질때까지 loop한다.
            if (count == index) {
                console.log(current.data);
            }
            count++;
            current = current.next;
        }
        return null;
    }

    // Remove at index
    removeAt(index) {
        if (index > 0 && index > this.size) {
            return;
        }

        let current = this.head; //current는 현재 첫번째 노드임
        let previous;
        let count = 0;

        // Remove first
        if (index === 0) {
            this.head = current.next;
        } else {
            //loop를 통해 해당 index의 연결고리를 끊는다.
            while (count < index) {
                count++;
                previous = current;
                current = current.next;
            }
            previous.next = current.next;
        }

        this.size--;
    }

    // Clear list ~ 메모리자체에는 데이터가 남아있겠지만 보여주기 위해서 func 만들었다.
    clearList() {
        this.head = null;
        this.size = 0;
    }
    // Print list data ~ data값만 따로
    printListData() {
        let current = this.head; // 현재 노드를 나타냄

        while (current) {
            console.log(current.data);
            current = current.next;
        }
    }
}

위의 linklist 자료구조를 생성자를 통해 받아서 사용합니다.

const linkedList = new LinkedList();

 

이전의 코드는 다음 포스트를 참고하시면 됩니다.

https://yn971106.tistory.com/56

 

[TAB 구현 심화_1]_Spring에서 tab 구현해보기 (feat json객체)

목표] 메뉴 1, 메뉴 2를 선택하면 바로 아래부분에 a태그와 button을 가진 template이 추가되며 글로벌 변수에 open인지 close인지 상태를 저장한다. 메뉴의 종류에 따라 contents부분이 해당 jsp파일의 내

yn971106.tistory.com

 

메뉴 1번에만 시도해 보았습니다.

제가 생각한 방법은 history 처럼 메뉴를 담고있는 linked구조를 가지고있는 자료구조에 담고 index를 이용해서 순서를 판별하고, 닫기버튼을 클릭시 해당 content와 메뉴가 닫히는 구조를 생각하였습니다.

 

function createTemplate(tabname){
    let createnode = document.createElement('li');

    switch (tabname){
        case 'menu1':
             let url1 = 'menu/' + tabname + '.do';
             let count = tabcount;
            createnode.classList.add(tabname);
            let template1 = `<span><a href="javascript:void(0);" id="menu1opener">menu1</a>
            <button id='closetabbtn'>닫기</button>
            <span>`
            createnode.innerHTML = template1;
            tabnode.appendChild(createnode);

            let oldElement = contentview.querySelector('#insidecontent');
            let content = createTabMenu(count,url1,oldElement)

            if(count == 0){
                linkedList.insertFirst(content)
            }else{

            linkedList.insertAt(content,count)
            }

            $('#menu1opener').click(function (){
                let oldElement = contentview.querySelector('#insidecontent');

                contentview.replaceChild(history[url1].content,oldElement);
            });

            let closebtn = document.querySelector('button#closetabbtn')
            closebtn.onclick = function () {
                let oldElement = contentview.querySelector('#insidecontent');

                const close = document.querySelectorAll('.menu1')
                close.forEach(function (close) {
                    close.remove();
                })  // 유용하네.
                $('.menu1content').empty();
                $globalVariable.setValue('tab1', 'close');

                //content 제거
                if(count ==0){
                    debugger;
                  //  linkedList.removeAt(count);
                    let first = linkedList.head.data[count].content
                    contentview.replaceChild(first,oldElement);

                }else{
                    contentview.replaceChild(tablist[count].content,oldElement);
                }


            }
        break;

메뉴 1을 만드는 해당 코드]

 

위의 선언한 createTabMenu 함수에

count -> 순서를 지정하기 위해 변수 선언

url1 -> 해당 content를 가리키는 url 주소

oldElement -> 메뉴버튼을 클릭하기 전 content를 담아두는객체

 

를 전달하고 linklist에 저장하게 됩니다.

 

그리고 해당 메뉴 1이 눌렀을 경우에 만약 count가 0 즉 처음에 눌렸다면 저장된 정보를 링크리스트의 첫번째 해드에 집어넣는 함수를 실행하고

그렇지 않다면 count = index 에 컨텐츠를 집어넣도록 하였습니다.

 

메뉴 1을 닫았을 때]

content 제거 윗부분은 지난 포스트 내용과 같고

아래에 count가 0 즉 처음으로 들어왔을 경우에는 해당 count의 첫번째 요소를 가져오고 이를 교체하도록 하였고

그렇지 않고 이후에 들어온 메뉴를 닫았을 때는 해당 count에 맞는 컨텐츠를 바꾸도록 하였습니다.

 

이렇게 코드를 작성하고 실행하였더니.

 

에서 메뉴 1을 닫을 경우

의도한 대로 나옵니다.

 

그러나 오류가 있습니다.

 

이와같이 마지막이 메뉴 1번이 아니고  메뉴 1번을 닫을시에 문제가 발생합니다.

위의 상황에서는 메뉴2번이 먼저 들어오고 메뉴 1번이 들어왔습니다. 그리고 마지막에 3번이 오면서 연결구조에 저장은 되었으나. 메뉴 1을 닫기를 클릭하는 순간 메뉴 1이 기억하고 있는 앞의 content인 메뉴 2의 내용이 출력되게 됩니다.

반만 성공하였으며, 다음에는 다른방법으로 시도하여 오류가 발생하지 않도록 해보겠습니다.

728x90
반응형