티스토리 뷰

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>통합 트리 탐색기 (라이브러리 제거 버전)</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <style>
        /* [1] 레이아웃 및 스타일 */
        body { font-family: 'Malgun Gothic', sans-serif; margin: 0; display: flex; height: 100vh; background: #f4f7f6; }
        
        /* 왼쪽 사이드바 */
        .sidebar { width: 350px; background: #fff; border-right: 1px solid #ddd; padding: 25px; overflow-y: auto; display: flex; flex-direction: column; }
        
        /* 오른쪽 상세 영역 */
        .content-view { flex: 1; padding: 40px; background: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #666; }

        /* 컨트롤 버튼 및 검색창 */
        .control-btns { display: flex; gap: 5px; margin-bottom: 10px; justify-content: flex-end; }
        .btn { padding: 5px 10px; font-size: 11px; cursor: pointer; border: 1px solid #ddd; background: #fff; border-radius: 4px; }
        .btn:hover { background: #f0f0f0; }
        .search-box input { width: 100%; padding: 12px; margin-bottom: 20px; border: 1px solid #e0e0e0; border-radius: 8px; box-sizing: border-box; outline: none; }

        /* 트리 메뉴 스타일 */
        ul.tree, ul.tree ul { list-style: none; padding-left: 20px; margin: 0; }
        .tree li { margin: 4px 0; }
        .folder, .file { padding: 6px 10px; cursor: pointer; border-radius: 6px; display: inline-block; font-size: 14px; transition: 0.2s; }
        .folder:hover, .file:hover { background: #ecf0f1; }
        
        /* 폴더 상태 제어 */
        .folder + ul { display: block; } /* 초기 상태 전체 열림 */
        .folder.collapsed + ul { display: none; } /* 닫힘 상태 */
        
        /* 하이라이트 및 결과 없음 */
        .highlight { background-color: #ffeaa7 !important; color: #d63031; font-weight: bold; }
        #no-result { display: none; text-align: center; color: #999; padding: 20px; }
    </style>
</head>
<body>

    <div class="sidebar">
        <h2>📂 탐색기</h2>
        
        <div class="control-btns">
            <button id="btn-expand" class="btn">전체 열기 +</button>
            <button id="btn-collapse" class="btn">전체 닫기 -</button>
        </div>

        <div class="search-box">
            <input type="text" id="tree-search" placeholder="파일명 또는 폴더명 검색...">
        </div>

        <div id="no-result">검색 결과가 없습니다.</div>
        <ul class="tree" id="main-tree"></ul>
    </div>

    <div class="content-view" id="detail-pane">
        <div id="empty-state">
            <p style="font-size: 48px; margin-bottom: 10px;">📄</p>
            <p>항목을 선택하면 상세 정보가 여기에 표시됩니다.</p>
        </div>
        <div id="detail-info" style="display: none; width: 100%; max-width: 600px;">
            <h1 id="selected-title" style="color: #333;">파일명</h1>
            <p><strong>유형:</strong> <span id="selected-type"></span></p>
            <div style="margin-top: 20px; padding: 20px; background: #f9f9f9; border: 1px solid #eee; border-radius: 10px;">
                선택한 항목에 대한 세부 내용을 서버에서 불러오는 영역입니다.
            </div>
        </div>
    </div>

<script>
$(document).ready(function() {
    // 1. 가상의 데이터 (원래는 $.getJSON 등으로 가져옴)
    const jsonData = [
        {
            "name": "프로젝트_2026",
            "type": "folder",
            "children": [
                {
                    "name": "기획안",
                    "type": "folder",
                    "children": [
                        { "name": "시장조사_보고서.pdf", "type": "file" },
                        { "name": "아이디어_기획.docx", "type": "file" }
                    ]
                },
                { "name": "일정표.xlsx", "type": "file" }
            ]
        },
        { "name": "회사규정_가이드.pdf", "type": "file" }
    ];

    // 2. [함수] 데이터로부터 HTML 생성 (재귀 호출)
    function createTree(data) {
        let html = "";
        data.forEach(item => {
            if (item.type === "folder") {
                html += `<li>
                            <div class="folder">📂 ${item.name}</div>
                            <ul>${createTree(item.children)}</ul>
                         </li>`;
            } else {
                html += `<li class="file">📄 ${item.name}</li>`;
            }
        });
        return html;
    }

    // 3. 트리 렌더링
    $('#main-tree').html(createTree(jsonData));

    // 4. [이벤트] 폴더 열기/닫기 토글
    $(document).on('click', '.folder', function() {
        $(this).toggleClass('collapsed');
        $(this).next('ul').slideToggle(200);
    });

    // 5. [이벤트] 항목 클릭 시 오른쪽 화면 업데이트
    $(document).on('click', '.folder, .file', function(e) {
        e.stopPropagation();
        const name = $(this).text().replace(/📂|📄/g, '').trim();
        const type = $(this).hasClass('folder') ? '폴더' : '파일';

        $('#empty-state').hide();
        $('#detail-info').show();
        $('#selected-title').text(name);
        $('#selected-type').text(type);
    });

    // 6. [전체 제어] 열기/닫기 버튼
    $('#btn-expand').click(function() {
        $('.folder').removeClass('collapsed').next('ul').slideDown(200);
    });

    $('#btn-collapse').click(function() {
        $('.folder').addClass('collapsed').next('ul').slideUp(200);
    });

    // 7. [검색] 기본 텍스트 기반 필터링 (한글/영문 포함)
    $('#tree-search').on('input', function() {
        const query = $(this).val().toLowerCase().trim();
        const $allLi = $('#main-tree li');

        $('.folder, .file').removeClass('highlight');

        if (!query) {
            $allLi.show();
            $('#no-result').hide();
            return;
        }

        $allLi.hide();
        let foundAny = false;

        $allLi.each(function() {
            const text = $(this).text().toLowerCase();
            if (text.indexOf(query) !== -1) {
                $(this).show();
                $(this).parents('li').show();
                $(this).parents('ul').show().prev('.folder').removeClass('collapsed');
                
                // 검색어와 직접 일치하는 텍스트만 하이라이트
                $(this).children('.folder, .file').each(function() {
                    if($(this).text().toLowerCase().indexOf(query) !== -1) {
                        $(this).addClass('highlight');
                    }
                });
                foundAny = true;
            }
        });

        foundAny ? $('#no-result').hide() : $('#no-result').show();
    });
});
</script>
</body>
</html>

 

전체 열기_닫기_동적 트리 통합 코드.html
0.01MB

 

 

※ 해당 내용은 Google Gmini3.0에서 작성되었습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2026/01   »
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
글 보관함