다른 명령
새 문서: <source lang=html> <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>도움말 시스템</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"> <style> body { font-family: 'Noto Sans KR', sans-serif; line-height: 1.6; margin: 0; padding: 20px;... |
편집 요약 없음 |
||
| (같은 사용자의 중간 판 2개는 보이지 않습니다) | |||
| 1번째 줄: | 1번째 줄: | ||
<source lang=html> | |||
<!DOCTYPE html> | |||
<html lang="ko"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
<title>도움말 시스템</title> | |||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"> | |||
<style> | |||
body { | |||
font-family: 'Noto Sans KR', sans-serif; | |||
line-height: 1.6; | |||
margin: 0; | |||
padding: 20px; | |||
background-color: #f5f5f5; | |||
color: #333; | |||
} | |||
.container { | |||
max-width: 1000px; | |||
margin: 0 auto; | |||
background-color: white; | |||
padding: 20px; | |||
border-radius: 8px; | |||
box-shadow: 0 2px 10px rgba(0,0,0,0.1); | |||
} | |||
h1 { | |||
text-align: center; | |||
color: #2c3e50; | |||
margin-bottom: 30px; | |||
} | |||
.search-box { | |||
display: flex; | |||
margin-bottom: 20px; | |||
} | |||
#search-input { | |||
flex: 1; | |||
padding: 10px; | |||
border: 1px solid #ddd; | |||
border-radius: 4px 0 0 4px; | |||
font-size: 16px; | |||
} | |||
#search-btn { | |||
padding: 10px 15px; | |||
background-color: #3498db; | |||
color: white; | |||
border: none; | |||
border-radius: 0 4px 4px 0; | |||
cursor: pointer; | |||
transition: background-color 0.3s; | |||
} | |||
#search-btn:hover { | |||
background-color: #2980b9; | |||
} | |||
.help-nav { | |||
display: flex; | |||
margin-bottom: 20px; | |||
} | |||
.help-categories { | |||
width: 250px; | |||
border-right: 1px solid #ddd; | |||
padding-right: 15px; | |||
} | |||
.category { | |||
cursor: pointer; | |||
padding: 8px 10px; | |||
border-radius: 4px; | |||
transition: background-color 0.3s; | |||
} | |||
.category:hover { | |||
background-color: #f0f0f0; | |||
} | |||
.category.active { | |||
background-color: #e6f2ff; | |||
color: #3498db; | |||
font-weight: bold; | |||
} | |||
.help-content { | |||
flex: 1; | |||
padding-left: 20px; | |||
} | |||
.topic { | |||
display: none; | |||
border-bottom: 1px solid #eee; | |||
padding-bottom: 15px; | |||
margin-bottom: 15px; | |||
} | |||
.topic h3 { | |||
color: #2c3e50; | |||
margin-bottom: 10px; | |||
} | |||
.topic.active { | |||
display: block; | |||
} | |||
#search-results { | |||
display: none; | |||
} | |||
.result-item { | |||
cursor: pointer; | |||
padding: 10px; | |||
border-radius: 4px; | |||
transition: background-color 0.3s; | |||
margin-bottom: 10px; | |||
} | |||
.result-item:hover { | |||
background-color: #f0f0f0; | |||
} | |||
.highlight { | |||
background-color: #ffff99; | |||
font-weight: bold; | |||
} | |||
.back-btn { | |||
display: none; | |||
padding: 8px 15px; | |||
background-color: #3498db; | |||
color: white; | |||
border: none; | |||
border-radius: 4px; | |||
cursor: pointer; | |||
margin-bottom: 15px; | |||
} | |||
.back-btn:hover { | |||
background-color: #2980b9; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div class="container"> | |||
<h1>도움말 시스템</h1> | |||
<div class="search-box"> | |||
<input type="text" id="search-input" placeholder="도움말 검색..."> | |||
<button id="search-btn"><i class="fas fa-search"></i> 검색</button> | |||
</div> | |||
<button class="back-btn" id="back-to-help">도움말 목록으로 돌아가기</button> | |||
<div id="search-results"> | |||
<h2>검색 결과</h2> | |||
<div id="results-list"></div> | |||
</div> | |||
<div class="help-nav" id="help-content"> | |||
<div class="help-categories"> | |||
<h2>카테고리</h2> | |||
<div class="category active" data-category="getting-started">시작하기</div> | |||
<div class="category" data-category="account">계정 관리</div> | |||
<div class="category" data-category="features">주요 기능</div> | |||
<div class="category" data-category="troubleshooting">문제 해결</div> | |||
</div> | |||
<div class="help-content"> | |||
<!-- 시작하기 카테고리 --> | |||
<div class="topic active" data-category="getting-started" id="intro"> | |||
<h3>프로그램 소개</h3> | |||
<p>이 프로그램은 사용자가 쉽게 작업을 수행할 수 있도록 설계되었습니다. 주요 기능과 인터페이스에 대한 설명을 제공합니다.</p> | |||
</div> | |||
<div class="topic" data-category="getting-started" id="installation"> | |||
<h3>설치 방법</h3> | |||
<p>프로그램을 설치하기 위한 단계별 지침을 제공합니다.</p> | |||
<ol> | |||
<li>웹사이트에서 설치 파일을 다운로드합니다.</li> | |||
<li>다운로드한 파일을 실행합니다.</li> | |||
<li>설치 마법사의 지시를 따릅니다.</li> | |||
<li>설치가 완료되면 프로그램을 실행합니다.</li> | |||
</ol> | |||
</div> | |||
<!-- 계정 관리 카테고리 --> | |||
<div class="topic" data-category="account" id="create-account"> | |||
<h3>계정 생성</h3> | |||
<p>새 계정을 만들기 위한 절차를 설명합니다.</p> | |||
</div> | |||
<div class="topic" data-category="account" id="login"> | |||
<h3>로그인</h3> | |||
<p>프로그램에 로그인하는 방법을 설명합니다.</p> | |||
</div> | |||
<div class="topic" data-category="account" id="password"> | |||
<h3>비밀번호 재설정</h3> | |||
<p>비밀번호를 잊어버렸을 때 재설정하는 방법을 안내합니다.</p> | |||
</div> | |||
<!-- 주요 기능 카테고리 --> | |||
<div class="topic" data-category="features" id="feature1"> | |||
<h3>기능 1: 데이터 관리</h3> | |||
<p>데이터를 효율적으로 관리하는 방법을 설명합니다.</p> | |||
</div> | |||
<div class="topic" data-category="features" id="feature2"> | |||
<h3>기능 2: 보고서 생성</h3> | |||
<p>다양한 보고서를 생성하고 내보내는 방법을 안내합니다.</p> | |||
</div> | |||
<!-- 문제 해결 카테고리 --> | |||
<div class="topic" data-category="troubleshooting" id="error-codes"> | |||
<h3>오류 코드 해석</h3> | |||
<p>일반적인 오류 코드와 해결 방법을 제공합니다.</p> | |||
</div> | |||
<div class="topic" data-category="troubleshooting" id="connection"> | |||
<h3>연결 문제</h3> | |||
<p>네트워크 연결 문제를 해결하는 방법을 안내합니다.</p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |||
<script> | |||
$(document).ready(function() { | |||
// 카테고리 클릭 이벤트 | |||
$('.category').click(function() { | |||
// 활성화된 카테고리 변경 | |||
$('.category').removeClass('active'); | |||
$(this).addClass('active'); | |||
// 선택된 카테고리의 토픽만 보이게 설정 | |||
var category = $(this).data('category'); | |||
$('.topic').hide(); | |||
$('.topic[data-category="' + category + '"]').first().show(); | |||
}); | |||
// 검색 기능 | |||
$('#search-btn').click(performSearch); | |||
$('#search-input').keypress(function(e) { | |||
if(e.which == 13) { // Enter key | |||
performSearch(); | |||
} | |||
}); | |||
// 뒤로가기 버튼 | |||
$('#back-to-help').click(function() { | |||
$('#search-results').hide(); | |||
$('#help-content').show(); | |||
$(this).hide(); | |||
}); | |||
function performSearch() { | |||
var query = $('#search-input').val().toLowerCase(); | |||
if(query.trim() === '') return; | |||
var results = []; | |||
// 모든 토픽에서 검색 | |||
$('.topic').each(function() { | |||
var topicTitle = $(this).find('h3').text(); | |||
var topicContent = $(this).text(); | |||
var topicId = $(this).attr('id'); | |||
if(topicTitle.toLowerCase().includes(query) || | |||
topicContent.toLowerCase().includes(query)) { | |||
results.push({ | |||
id: topicId, | |||
title: topicTitle, | |||
content: $(this).find('p').first().text(), | |||
category: $(this).data('category') | |||
}); | |||
} | |||
}); | |||
// 검색 결과 표시 | |||
displaySearchResults(results, query); | |||
} | |||
function displaySearchResults(results, query) { | |||
var resultsList = $('#results-list'); | |||
resultsList.empty(); | |||
if(results.length === 0) { | |||
resultsList.append('<p>검색 결과가 없습니다.</p>'); | |||
} else { | |||
$.each(results, function(i, result) { | |||
var resultItem = $('<div class="result-item" data-id="' + result.id + '" data-category="' + result.category + '">' + | |||
'<h3>' + highlightText(result.title, query) + '</h3>' + | |||
'<p>' + highlightText(result.content, query) + '</p>' + | |||
'</div>'); | |||
resultsList.append(resultItem); | |||
}); | |||
// 검색 결과 항목 클릭 이벤트 | |||
$('.result-item').click(function() { | |||
var id = $(this).data('id'); | |||
var category = $(this).data('category'); | |||
// 해당 카테고리 활성화 | |||
$('.category').removeClass('active'); | |||
$('.category[data-category="' + category + '"]').addClass('active'); | |||
// 해당 토픽 보이기 | |||
$('.topic').hide(); | |||
$('#' + id).show(); | |||
// 검색 결과 숨기기, 도움말 내용 보이기 | |||
$('#search-results').hide(); | |||
$('#help-content').show(); | |||
}); | |||
} | |||
// 도움말 내용 숨기고 검색 결과 표시 | |||
$('#help-content').hide(); | |||
$('#search-results').show(); | |||
$('#back-to-help').show(); | |||
} | |||
function highlightText(text, query) { | |||
if (!query) return text; | |||
var regex = new RegExp('(' + query + ')', 'gi'); | |||
return text.replace(regex, '<span class="highlight">$1</span>'); | |||
} | |||
}); | |||
</script> | |||
</body> | |||
</html> | |||
</source> | |||
=== 검색기능 추가 (개선) === | |||
<source lang=html> | <source lang=html> | ||
<!DOCTYPE html> | <!DOCTYPE html> | ||
| 193번째 줄: | 511번째 줄: | ||
align-items: center; | align-items: center; | ||
margin-bottom: 15px; | margin-bottom: 15px; | ||
} | |||
.topic-content { | |||
margin-top: 15px; | |||
} | } | ||
</style> | </style> | ||
| 240번째 줄: | 561번째 줄: | ||
<div class="topic active" data-category="getting-started" id="intro"> | <div class="topic active" data-category="getting-started" id="intro"> | ||
<h3>프로그램 소개</h3> | <h3>프로그램 소개</h3> | ||
<p>이 프로그램은 사용자가 쉽게 작업을 수행할 수 있도록 설계되었습니다. 주요 기능과 인터페이스에 대한 설명을 제공합니다.</p> | <div class="topic-content"> | ||
<p>이 프로그램은 사용자가 쉽게 작업을 수행할 수 있도록 설계되었습니다. 주요 기능과 인터페이스에 대한 설명을 제공합니다.</p> | |||
<p>사용자 친화적인 인터페이스와 함께 다양한 기능을 탐색하고 활용할 수 있습니다. 이 도움말 시스템은 프로그램 사용 중에 발생할 수 있는 모든 질문에 대한 답변을 제공합니다.</p> | |||
</div> | |||
</div> | </div> | ||
<div class="topic" data-category="getting-started" id="installation"> | <div class="topic" data-category="getting-started" id="installation"> | ||
<h3>설치 방법</h3> | <h3>설치 방법</h3> | ||
<p>프로그램을 설치하기 위한 단계별 지침을 제공합니다.</p> | <div class="topic-content"> | ||
<p>프로그램을 설치하기 위한 단계별 지침을 제공합니다.</p> | |||
<ol> | |||
<li>웹사이트에서 설치 파일을 다운로드합니다.</li> | |||
<li>다운로드한 파일을 실행합니다.</li> | |||
<li>설치 마법사의 지시를 따릅니다.</li> | |||
<li>설치가 완료되면 프로그램을 실행합니다.</li> | |||
</ol> | |||
<p>설치 중 문제가 발생하면 '문제 해결' 섹션을 참조하시기 바랍니다.</p> | |||
</div> | |||
</div> | </div> | ||
<div class="topic" data-category="getting-started" id="system-requirements"> | <div class="topic" data-category="getting-started" id="system-requirements"> | ||
<h3>시스템 요구사항</h3> | <h3>시스템 요구사항</h3> | ||
<p>프로그램을 실행하기 위한 최소 시스템 요구사항입니다:</p> | <div class="topic-content"> | ||
<p>프로그램을 실행하기 위한 최소 시스템 요구사항입니다:</p> | |||
<ul> | |||
<li>운영체제: Windows 10 이상 / macOS 10.14 이상 / Linux (Ubuntu 18.04 이상)</li> | |||
<li>프로세서: 2GHz 이상의 듀얼 코어 프로세서</li> | |||
<li>메모리: 4GB RAM</li> | |||
<li>저장공간: 500MB 이상의 여유 공간</li> | |||
</ | <li>인터넷 연결: 초기 설정 및 업데이트를 위한 인터넷 연결 필요</li> | ||
</ul> | |||
</div> | |||
</div> | </div> | ||
| 271번째 줄: | 598번째 줄: | ||
<div class="topic" data-category="account" id="create-account"> | <div class="topic" data-category="account" id="create-account"> | ||
<h3>계정 생성</h3> | <h3>계정 생성</h3> | ||
<p>새 계정을 만들기 위한 절차를 설명합니다.</p> | <div class="topic-content"> | ||
<p>새 계정을 만들기 위한 절차를 설명합니다.</p> | |||
<ol> | |||
<li>프로그램 실행 후 '계정 생성' 버튼을 클릭합니다.</li> | |||
<li>필요한 정보(이름, 이메일, 비밀번호)를 입력합니다.</li> | |||
<li>이메일 인증을 완료합니다.</li> | |||
<li>계정 설정을 확인하고 완료합니다.</li> | |||
</ol> | |||
<p>계정 생성 시 강력한 비밀번호를 사용하는 것을 권장합니다.</p> | |||
</div> | |||
</div> | </div> | ||
<div class="topic" data-category="account" id="login"> | <div class="topic" data-category="account" id="login"> | ||
<h3>로그인</h3> | <h3>로그인</h3> | ||
<p>프로그램에 로그인하는 방법을 설명합니다.</p> | <div class="topic-content"> | ||
<p>프로그램에 로그인하는 방법을 설명합니다.</p> | |||
<ol> | |||
<li>프로그램을 실행하면 로그인 화면이 표시됩니다.</li> | |||
<li>등록된 이메일과 비밀번호를 입력합니다.</li> | |||
<li>'로그인' 버튼을 클릭합니다.</li> | |||
</ol> | |||
<p>'자동 로그인' 옵션을 선택하면 다음 실행 시 자동으로 로그인됩니다. 공용 컴퓨터에서는 이 옵션을 사용하지 마세요.</p> | |||
</div> | |||
</div> | </div> | ||
<div class="topic" data-category="account" id="password"> | <div class="topic" data-category="account" id="password"> | ||
<h3>비밀번호 재설정</h3> | <h3>비밀번호 재설정</h3> | ||
<p>비밀번호를 잊어버렸을 때 재설정하는 방법을 안내합니다.</p> | <div class="topic-content"> | ||
<p>비밀번호를 잊어버렸을 때 재설정하는 방법을 안내합니다.</p> | |||
<ol> | |||
<li>로그인 화면에서 '비밀번호 찾기' 링크를 클릭합니다.</li> | |||
<li>등록된 이메일 주소를 입력합니다.</li> | |||
<li>이메일로 전송된 링크를 통해 새 비밀번호를 설정합니다.</li> | |||
</ol> | |||
<p>비밀번호 재설정 이메일이 오지 않는 경우, 스팸 폴더를 확인하거나 지원팀에 문의하세요.</p> | |||
</div> | |||
</div> | </div> | ||
<div class="topic" data-category="account" id="profile-settings"> | |||
<h3>프로필 설정</h3> | <h3>프로필 설정</h3> | ||
<p>사용자 프로필 정보를 업데이트하는 방법을 안내합니다.</p> | <div class="topic-content"> | ||
<p>사용자 프로필 정보를 업데이트하는 방법을 안내합니다.</p> | |||
<ol> | |||
<li>로그인 후 오른쪽 상단의 프로필 아이콘을 클릭합니다.</li> | |||
<li>'설정' 또는 '프로필 관리'를 선택합니다.</li> | |||
<li>개인 정보, 알림 설정, 테마 등을 변경할 수 있습니다.</li> | |||
</ | <li>'저장' 버튼을 클릭하여 변경사항을 적용합니다.</li> | ||
</ol> | |||
</div> | |||
</div> | </div> | ||
| 317번째 줄: | 652번째 줄: | ||
<div class="topic" data-category="features" id="feature1"> | <div class="topic" data-category="features" id="feature1"> | ||
<h3>기능 1: 데이터 관리</h3> | <h3>기능 1: 데이터 관리</h3> | ||
<p>데이터를 | <div class="topic-content"> | ||
<p>데이터를 효율적으로 관리하는 방법을 설명합니다.</p> | |||
<h4>데이터 추가</h4> | |||
<ol> | |||
<li>'데이터 관리' 메뉴에서 '새 데이터' 버튼을 클릭합니다.</li> | |||
<li>필요한 정보를 입력하고 '저장' 버튼을 클릭합니다.</li> | |||
</ol> | |||
<h4>데이터 편집</h4> | |||
<ol> | |||
<li>목록에서 편집할 항목을 선택합니다.</li> | |||
<li>'편집' 버튼을 클릭하거나 항목을 더블 클릭합니다.</li> | |||
<li>정보를 수정하고 '저장' 버튼을 클릭합니다.</li> | |||
</ol> | |||
<h4>데이터 삭제</h4> | |||
<ol> | |||
<li>목록에서 삭제할 항목을 선택합니다.</li> | |||
<li>'삭제' 버튼을 클릭합니다.</li> | |||
<li>확인 대화 상자에서 '예'를 선택하여 삭제를 확인합니다.</li> | |||
</ol> | |||
<p>데이터는 자동으로 저장되지만, 중요한 변경 후에는 '백업' 기능을 사용하는 것이 좋습니다.</p> | |||
</div> | |||
</div> | |||
<div class="topic" data-category="features" id="feature2"> | |||
<h3>기능 2: 보고서 생성</h3> | |||
<div class="topic-content"> | |||
<p>다양한 보고서를 생성하고 내보내는 방법을 안내합니다.</p> | |||
<h4>보고서 유형</h4> | |||
<ul> | |||
<li><strong>요약 보고서</strong>: 주요 데이터의 요약 정보를 보여줍니다.</li> | |||
<li><strong>상세 보고서</strong>: 모든 데이터 항목에 대한 자세한 정보를 포함합니다.</li> | |||
<li><strong>분석 보고서</strong>: 데이터 분석 결과와 그래프를 포함합니다.</li> | |||
</ul> | |||
<h4>보고서 생성 방법</h4> | |||
<ol> | |||
<li>'보고서' 메뉴를 선택합니다.</li> | |||
<li>원하는 보고서 유형을 선택합니다.</li> | |||
<li>필요한 매개변수(기간, 데이터 범위 등)를 설정합니다.</li> | |||
<li>'생성' 버튼을 클릭합니다.</li> | |||
</ol> | |||
<h4>보고서 내보내기</h4> | |||
<ol> | |||
<li>생성된 보고서 화면에서 '내보내기' 버튼을 클릭합니다.</li> | |||
<li>원하는 형식(PDF, Excel, CSV)을 선택합니다.</li> | |||
<li>파일 이름과 저장 위치를 지정합니다.</li> | |||
<li>'저장' 버튼을 클릭합니다.</li> | |||
</ol> | |||
</div> | |||
</div> | |||
<div class="topic" data-category="features" id="feature3"> | |||
<h3>기능 3: 자동화 기능</h3> | |||
<div class="topic-content"> | |||
<p>반복적인 작업을 자동화하는 기능에 대해 설명합니다.</p> | |||
<h4>자동화 설정</h4> | |||
<ol> | |||
<li>'설정' 메뉴에서 '자동화' 탭을 선택합니다.</li> | |||
<li>'새 자동화' 버튼을 클릭합니다.</li> | |||
<li>트리거(시간, 이벤트 등)와 수행할 작업을 설정합니다.</li> | |||
<li>'저장' 버튼을 클릭하여 자동화를 활성화합니다.</li> | |||
</ol> | |||
<h4>자동화 템플릿</h4> | |||
<p>자주 사용하는 자동화 설정을 템플릿으로 저장하고 재사용할 수 있습니다:</p> | |||
<ol> | |||
<li>자동화 설정 후 '템플릿으로 저장' 옵션을 선택합니다.</li> | |||
<li>템플릿 이름을 지정하고 '저장'을 클릭합니다.</li> | |||
<li>새 자동화 생성 시 '템플릿에서 불러오기'를 선택하여 사용합니다.</li> | |||
</ol> | |||
</div> | |||
</div> | |||
<!-- 문제 해결 카테고리 --> | |||
<div class="topic" data-category="troubleshooting" id="error-codes"> | |||
<h3>오류 코드 해석</h3> | |||
<div class="topic-content"> | |||
<p>일반적인 오류 코드와 해결 방법을 제공합니다.</p> | |||
<table border="1" style="width: 100%; border-collapse: collapse;"> | |||
<tr style="background-color: #f2f2f2;"> | |||
<th style="padding: 8px; text-align: left;">오류 코드</th> | |||
<th style="padding: 8px; text-align: left;">설명</th> | |||
<th style="padding: 8px; text-align: left;">해결 방법</th> | |||
</tr> | |||
<tr> | |||
<td style="padding: 8px;">ERR-001</td> | |||
<td style="padding: 8px;">데이터베이스 연결 실패</td> | |||
<td style="padding: 8px;">네트워크 연결을 확인하고 프로그램을 다시 시작하세요.</td> | |||
</tr> | |||
<tr> | |||
<td style="padding: 8px;">ERR-002</td> | |||
<td style="padding: 8px;">인증 오류</td> | |||
<td style="padding: 8px;">로그아웃 후 다시 로그인하세요. 문제가 지속되면 비밀번호를 재설정하세요.</td> | |||
</tr> | |||
<tr> | |||
<td style="padding: 8px;">ERR-003</td> | |||
<td style="padding: 8px;">파일 접근 오류</td> | |||
<td style="padding: 8px;">파일이 다른 프로그램에 의해 사용 중인지 확인하고, 권한 설정을 확인하세요.</td> | |||
</tr> | |||
<tr> | |||
<td style="padding: 8px;">ERR-004</td> | |||
<td style="padding: 8px;">메모리 부족</td> | |||
<td style="padding: 8px;">다른 프로그램을 종료하고 다시 시도하세요.</td> | |||
</tr> | |||
</table> | |||
</div> | |||
</div> | |||
<div class="topic" data-category="troubleshooting" id="connection"> | |||
<h3>연결 문제</h3> | |||
<div class="topic-content"> | |||
<p>네트워크 연결 문제를 해결하는 방법을 안내합니다.</p> | |||
<h4>기본 연결 문제 해결</h4> | |||
<ol> | |||
<li>인터넷 연결이 활성화되어 있는지 확인합니다.</li> | |||
<li>방화벽 설정에서 프로그램이 차단되지 않았는지 확인합니다.</li> | |||
<li>프로그램을 종료하고 다시 시작합니다.</li> | |||
<li>컴퓨터를 재시작하고 문제가 해결되는지 확인합니다.</li> | |||
</ol> | |||
<h4>서버 연결 문제</h4> | |||
<ol> | |||
<li>'설정' 메뉴에서 '연결' 탭을 선택합니다.</li> | |||
<li>'서버 테스트' 버튼을 클릭하여 서버 연결을 확인합니다.</li> | |||
<li>서버 주소가 올바른지 확인합니다.</li> | |||
<li>프록시 설정이 필요한 경우 올바르게 구성되어 있는지 확인합니다.</li> | |||
</ol> | |||
<p>지속적인 연결 문제가 발생하는 경우, 지원팀에 문의하세요.</p> | |||
</div> | |||
</div> | |||
<div class="topic" data-category="troubleshooting" id="performance"> | |||
<h3>성능 최적화</h3> | |||
<div class="topic-content"> | |||
<p>프로그램 성능을 향상시키기 위한 팁을 제공합니다.</p> | |||
<h4>캐시 정리</h4> | |||
<ol> | |||
<li>'설정' 메뉴에서 '유지 관리' 탭을 선택합니다.</li> | |||
<li>'캐시 정리' 버튼을 클릭합니다.</li> | |||
<li>프로그램을 다시 시작합니다.</li> | |||
</ol> | |||
<h4>메모리 사용 최적화</h4> | |||
<ol> | |||
<li>사용하지 않는 기능을 비활성화합니다.</li> | |||
<li>대용량 파일 작업 시 '메모리 최적화' 옵션을 활성화합니다.</li> | |||
<li>정기적으로 프로그램을 다시 시작하여 메모리를 정리합니다.</li> | |||
</ol> | |||
<h4>하드웨어 요구사항 확인</h4> | |||
<p>프로그램이 느리게 실행된다면 시스템 사양이 최소 요구사항을 충족하는지 확인하세요.</p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |||
<script> | |||
$(document).ready(function() { | |||
// 전역 변수 | |||
let helpTopics = {}; | |||
let categoryLabels = { | |||
'getting-started': '시작하기', | |||
'account': '계정 관리', | |||
'features': '주요 기능', | |||
'troubleshooting': '문제 해결' | |||
}; | |||
let searchIndex = []; | |||
let searchSuggestions = [ | |||
"설치", "로그인", "비밀번호", "계정", "오류", | |||
"보고서", "데이터", "자동화", "성능", "연결" | |||
]; | |||
// 초기화: 모든 도움말 토픽 정보 수집 | |||
function initHelpSystem() { | |||
$('.topic').each(function() { | |||
const id = $(this).attr('id'); | |||
const category = $(this).data('category'); | |||
const title = $(this).find('h3').text(); | |||
const content = $(this).text(); | |||
const keywords = extractKeywords(title + ' ' + content); | |||
helpTopics[id] = { | |||
id: id, | |||
category: category, | |||
title: title, | |||
content: content, | |||
keywords: keywords, | |||
element: $(this) | |||
}; | |||
// 검색 인덱스 구축 | |||
searchIndex.push({ | |||
id: id, | |||
text: title + ' ' + content, | |||
keywords: keywords, | |||
category: category, | |||
title: title | |||
}); | |||
}); | |||
} | |||
// 키워드 추출 (기본 구현) | |||
function extractKeywords(text) { | |||
// 텍스트에서 공통 단어 제외하고 단어 추출 | |||
const commonWords = ["그리고", "하지만", "또는", "그런", "이런", "저런", "이", "그", "저", "및", "등", "를", "을", "에", "의", "에서"]; | |||
let words = text.toLowerCase().split(/\s+/); | |||
words = words.filter(word => word.length > 1 && !commonWords.includes(word)); | |||
return [...new Set(words)]; // 중복 제거 | |||
} | |||
// 카테고리 클릭 이벤트 | |||
$('.category').click(function() { | |||
// 활성화된 카테고리 변경 | |||
$('.category').removeClass('active'); | |||
$(this).addClass('active'); | |||
// 선택된 카테고리의 토픽만 보이게 설정 | |||
const category = $(this).data('category'); | |||
$('.topic').hide(); | |||
$(`.topic[data-category="${category}"]`).first().show().addClass('active'); | |||
}); | |||
// 검색 기능 | |||
$('#search-btn').click(performSearch); | |||
$('#search-input').on('input', function() { | |||
if ($(this).val().trim() !== '') { | |||
$('.search-clear').show(); | |||
} else { | |||
$('.search-clear').hide(); | |||
} | |||
}).keypress(function(e) { | |||
if(e.which == 13) { // Enter key | |||
performSearch(); | |||
} | |||
}); | |||
// 검색창 클리어 버튼 | |||
$('#clear-search').click(function() { | |||
$('#search-input').val('').focus(); | |||
$(this).hide(); | |||
}); | |||
// 뒤로가기 버튼 | |||
$('#back-to-help').click(function() { | |||
$('#search-results').hide(); | |||
$('#help-content').show(); | |||
$(this).hide(); | |||
// 검색 상태 초기화 | |||
$('.search-filter').removeClass('active'); | |||
$('.search-filter[data-filter="all"]').addClass('active'); | |||
}); | |||
// 검색 필터 클릭 이벤트 | |||
$('.search-filter').click(function() { | |||
$('.search-filter').removeClass('active'); | |||
$(this).addClass('active'); | |||
filterSearchResults($(this).data('filter')); | |||
}); | |||
// 검색 실행 함수 | |||
function performSearch() { | |||
const query = $('#search-input').val().trim().toLowerCase(); | |||
if(query === '') return; | |||
// 검색 결과 찾기 | |||
const results = searchTopics(query); | |||
// 검색 결과 표시 | |||
displaySearchResults(results, query); | |||
// 검색 기록 저장 (로컬 스토리지 이용) | |||
saveSearchHistory(query); | |||
// 추천 검색어 표시 | |||
showSearchSuggestions(); | |||
} | |||
// 토픽 검색 함수 | |||
function searchTopics(query) { | |||
if (!query) return []; | |||
const results = []; | |||
const queryWords = query.toLowerCase().split(/\s+/).filter(word => word.length > 1); | |||
// 각 검색 인덱스 항목에 대해 점수 계산 | |||
searchIndex.forEach(item => { | |||
let score = 0; | |||
const text = item.text.toLowerCase(); | |||
// 제목에 정확히 일치하면 높은 점수 | |||
if (item.title.toLowerCase().includes(query)) { | |||
score += 10; | |||
} | |||
// 전체 구문이 텍스트에 포함되어 있으면 점수 추가 | |||
if (text.includes(query)) { | |||
score += 5; | |||
} | |||
// 각 단어별 매칭 점수 계산 | |||
queryWords.forEach(word => { | |||
// 제목에 단어가 있으면 높은 점수 | |||
if (item.title.toLowerCase().includes(word)) { | |||
score += 3; | |||
} | |||
// 키워드에 단어가 있으면 점수 추가 | |||
if (item.keywords.includes(word)) { | |||
score += 2; | |||
} | |||
// 내용에 단어가 있으면 점수 추가 | |||
if (text.includes(word)) { | |||
score += 1; | |||
} | |||
}); | |||
// 일정 점수 이상인 경우만 결과에 포함 | |||
if (score > 0) { | |||
results.push({ | |||
id: item.id, | |||
title: item.title, | |||
category: item.category, | |||
score: score, | |||
matches: findMatches(text, query) | |||
}); | |||
} | |||
}); | |||
// 점수 기준 내림차순 정렬 | |||
return results.sort((a, b) => b.score - a.score); | |||
} | |||
// 텍스트에서 매칭되는 문맥 찾기 | |||
function findMatches(text, query) { | |||
const matches = []; | |||
const words = query.toLowerCase().split(/\s+/).filter(word => word.length > 1); | |||
// 전체 쿼리 매칭 | |||
let index = text.toLowerCase().indexOf(query); | |||
if (index !== -1) { | |||
const start = Math.max(0, index - 30); | |||
const end = Math.min(text.length, index + query.length + 30); | |||
matches.push(text.substring(start, end).trim()); | |||
} | |||
// 개별 단어 매칭 | |||
else if (words.length > 0) { | |||
for (const word of words) { | |||
index = text.toLowerCase().indexOf(word); | |||
if (index !== -1) { | |||
const start = Math.max(0, index - 20); | |||
const end = Math.min(text.length, index + word.length + 20); | |||
let snippet = text.substring(start, end).trim(); | |||
// 중복 방지 | |||
if (!matches.includes(snippet)) { | |||
matches.push(snippet); | |||
if (matches.length >= 2) break; // 최대 2개 매칭 문맥만 보여줌 | |||
} | |||
} | |||
} | |||
} | |||
return matches; | |||
} | |||
// 검색 결과 표시 함수 | |||
function displaySearchResults(results, query) { | |||
const resultsList = $('#results-list'); | |||
resultsList.empty(); | |||
// 검색 상태 업데이트 | |||
$('#search-status').text(`${results.length}개의 결과가 있습니다.`); | |||
if(results.length === 0) { | |||
resultsList.append(` | |||
<div class="no-results"> | |||
<p>"${query}"에 대한 검색 결과가 없습니다.</p> | |||
<p>다른 검색어를 시도하거나 카테고리에서 직접 찾아보세요.</p> | |||
</div> | |||
`); | |||
} else { | |||
$.each(results, function(i, result) { | |||
const topic = helpTopics[result.id]; | |||
const categoryLabel = categoryLabels[result.category]; | |||
let snippets = ''; | |||
if (result.matches && result.matches.length > 0) { | |||
snippets = '<p class="result-context">' + | |||
result.matches.map(match => '... ' + highlightText(match, query) + ' ...').join('<br>') + | |||
'</p>'; | |||
} | |||
const resultItem = $(` | |||
<div class="result-item" data-id="${result.id}" data-category="${result.category}"> | |||
<h3>${highlightText(result.title, query)} <span class="category-badge">${categoryLabel}</span></h3> | |||
${snippets} | |||
</div> | |||
`); | |||
resultsList.append(resultItem); | |||
}); | |||
// 검색 결과 항목 클릭 이벤트 | |||
$('.result-item').click(function() { | |||
const id = $(this).data('id'); | |||
const category = $(this).data('category'); | |||
// 해당 카테고리 활성화 | |||
$('.category').removeClass('active'); | |||
$(`.category[data-category="${category}"]`).addClass('active'); | |||
// 모든 토픽 숨기기 | |||
$('.topic').removeClass('active').hide(); | |||
// 해당 토픽 보이기 | |||
$(`#${id}`).addClass('active').show(); | |||
// 검색 결과 숨기기, 도움말 내용 보이기 | |||
$('#search-results').hide(); | |||
$('#help-content').show(); | |||
}); | |||
} | |||
// 도움말 내용 숨기고 검색 결과 표시 | |||
$('#help-content').hide(); | |||
$('#search-results').show(); | |||
$('#back-to-help').show(); | |||
} | |||
// 검색 결과 필터링 | |||
function filterSearchResults(filter) { | |||
if (filter === 'all') { | |||
$('.result-item').show(); | |||
} else { | |||
$('.result-item').hide(); | |||
$(`.result-item[data-category="${filter}"]`).show(); | |||
} | |||
// 표시된 결과 개수 업데이트 | |||
const visibleCount = $('.result-item:visible').length; | |||
$('#search-status').text(`${visibleCount}개의 결과가 표시되었습니다.`); | |||
} | |||
// 텍스트에서 검색어 하이라이트 | |||
function highlightText(text, query) { | |||
if (!query) return text; | |||
const words = query.toLowerCase().split(/\s+/).filter(word => word.length > 1); | |||
let highlightedText = text; | |||
// 전체 구문 하이라이트 | |||
const regex = new RegExp('(' + escapeRegExp(query) + ')', 'gi'); | |||
highlightedText = highlightedText.replace(regex, '<span class="highlight">$1</span>'); | |||
// 개별 단어 하이라이트 (전체 구문이 이미 하이라이트 되지 않은 경우) | |||
words.forEach(word => { | |||
const wordRegex = new RegExp('(' + escapeRegExp(word) + ')', 'gi'); | |||
highlightedText = highlightedText.replace(wordRegex, function(match) { | |||
// 이미 하이라이트 태그 안에 있으면 변경하지 않음 | |||
if (match.indexOf('<span class="highlight">') !== -1) return match; | |||
return '<span class="highlight">' + match + '</span>'; | |||
}); | |||
}); | |||
return highlightedText; | |||
} | |||
// 정규식 특수문자 이스케이프 | |||
function escapeRegExp(string) { | |||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |||
} | |||
// 검색 기록 저장 | |||
function saveSearchHistory(query) { | |||
let history = localStorage.getItem('searchHistory'); | |||
history = history ? JSON.parse(history) : []; | |||
// 중복 방지 및 최근 검색어 앞으로 | |||
const index = history.indexOf(query); | |||
if (index !== -1) { | |||
history.splice(index, 1); | |||
} | |||
history.unshift(query); | |||
// 최대 10개 저장 | |||
if (history.length > 10) { | |||
history = history.slice(0, 10); | |||
} | |||
localStorage.setItem('searchHistory', JSON.stringify(history)); | |||
} | |||
// 검색 추천어 표시 | |||
function showSearchSuggestions() { | |||
const suggestionEl = $('#search-suggestion'); | |||
suggestionEl.empty(); | |||
// 최근 검색어 불러오기 | |||
let history = localStorage.getItem('searchHistory'); | |||
history = history ? JSON.parse(history) : []; | |||
if (history.length > 0) { | |||
suggestionEl.append('<p>최근 검색어: '); | |||
for (let i = 0; i < Math.min(5, history.length); i++) { | |||
suggestionEl.append(`<span class="suggestion-item">${history[i]}</span>`); | |||
} | |||
suggestionEl.append('</p>'); | |||
} | |||
// 인기 검색어/추천 검색어 | |||
suggestionEl.append('<p>추천 검색어: '); | |||
for (let i = 0; i < Math.min(5, searchSuggestions.length); i++) { | |||
suggestionEl.append(`<span class="suggestion-item">${searchSuggestions[i]}</span>`); | |||
} | |||
suggestionEl.append('</p>'); | |||
// 추천 검색어 클릭 이벤트 | |||
$('.suggestion-item').click(function() { | |||
$('#search-input').val($(this).text()); | |||
performSearch(); | |||
}); | |||
} | |||
// 초기화 | |||
initHelpSystem(); | |||
}); | |||
</script> | |||
</body> | |||
</html> | |||
</source> | |||
=== 네비게이션 + 내용 스크롤 기능 추가 === | |||
<source lang=html> | |||
<!doctype html> | |||
<html lang="ko"> | |||
<head> | |||
<meta charset="utf-8"> | |||
<title>프로그램 도움말 (커스텀 스크롤바 + 섹션 내비게이션)</title> | |||
<meta name="viewport" content="width=device-width,initial-scale=1"> | |||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |||
<style> | |||
html, body { | |||
height: 100%; | |||
margin: 0; | |||
font-family: Arial, "Malgun Gothic", "맑은 고딕", sans-serif; | |||
background: #f5f7fa; | |||
color: #333; | |||
} | |||
.container { | |||
display: flex; | |||
height: 100vh; | |||
overflow: hidden; | |||
} | |||
.sidebar { | |||
width: 300px; | |||
background: #ffffff; | |||
border-right: 1px solid #e0e6ef; | |||
padding: 20px; | |||
box-sizing: border-box; | |||
overflow-y: auto; | |||
} | |||
.search-box { margin-bottom: 12px; } | |||
.search-box input { | |||
width: 100%; | |||
padding: 8px 10px; | |||
border: 1px solid #ccd6e6; | |||
border-radius: 4px; | |||
box-sizing: border-box; | |||
} | |||
.toc { list-style: none; padding: 0; margin: 0; } | |||
.toc li { | |||
padding: 10px 8px; | |||
border-radius: 4px; | |||
cursor: pointer; | |||
color: #223; | |||
} | |||
.toc li:hover { background: #f0f6ff; } | |||
.toc li.active { | |||
background: #e6f0ff; | |||
font-weight: bold; | |||
border-left: 3px solid #1976d2; | |||
} | |||
.content { | |||
flex: 1; | |||
display: flex; | |||
flex-direction: column; | |||
background: transparent; | |||
} | |||
/* 내부 스크롤을 담당하는 래퍼 */ | |||
.content-scroll { | |||
padding: 24px; | |||
box-sizing: border-box; | |||
overflow-y: auto; | |||
-webkit-overflow-scrolling: touch; | |||
position: relative; | |||
} | |||
.help-title { margin: 0 0 12px 0; font-size: 22px; } | |||
.thumb { | |||
width: 320px; | |||
max-width: 100%; | |||
border: 1px solid #d6dfe9; | |||
padding: 6px; | |||
background: #fff; | |||
border-radius: 6px; | |||
box-shadow: 0 1px 3px rgba(0,0,0,0.05); | |||
cursor: pointer; | |||
display: block; | |||
margin-bottom: 12px; | |||
} | |||
.meta { margin-top: 10px; color: #667; font-size: 13px; } | |||
.desc { margin-top: 16px; line-height: 1.6; } | |||
/* 섹션 스타일 */ | |||
.section { | |||
padding: 14px; | |||
margin-bottom: 18px; | |||
background: #fff; | |||
border: 1px solid #e6eef8; | |||
border-radius: 6px; | |||
box-shadow: 0 1px 2px rgba(0,0,0,0.03); | |||
} | |||
.section h2 { | |||
margin: 0 0 8px 0; | |||
font-size: 18px; | |||
} | |||
/* modal */ | |||
.modal-backdrop { | |||
display: none; | |||
position: fixed; | |||
inset: 0; | |||
background: rgba(0,0,0,0.5); | |||
justify-content: center; | |||
align-items: center; | |||
z-index: 999; | |||
} | |||
.modal { | |||
background: #fff; | |||
padding: 12px; | |||
border-radius: 6px; | |||
max-width: 90%; | |||
max-height: 90%; | |||
overflow: auto; | |||
} | |||
.modal img { max-width: 100%; height: auto; display: block; } | |||
/* 스크롤바 커스텀: WebKit (Chrome, Safari, Edge) */ | |||
.content-scroll::-webkit-scrollbar { | |||
width: 12px; | |||
} | |||
.content-scroll::-webkit-scrollbar-track { | |||
background: #f0f4fb; | |||
border-radius: 6px; | |||
} | |||
.content-scroll::-webkit-scrollbar-thumb { | |||
background: linear-gradient(180deg, #93c5fd, #1976d2); | |||
border-radius: 6px; | |||
border: 3px solid #f0f4fb; /* thumb 둘레를 트랙과 분리 */ | |||
} | |||
.sidebar::-webkit-scrollbar { | |||
width: 8px; | |||
} | |||
.sidebar::-webkit-scrollbar-thumb { | |||
background: rgba(100,120,150,0.3); | |||
border-radius: 4px; | |||
} | |||
/* 파이어폭스용 스크롤바 색상 지정 */ | |||
@supports (scrollbar-color: red blue) { | |||
.content-scroll { | |||
scrollbar-width: thin; | |||
scrollbar-color: #1976d2 #f0f4fb; | |||
} | |||
.sidebar { | |||
scrollbar-width: thin; | |||
scrollbar-color: rgba(100,120,150,0.3) transparent; | |||
} | |||
} | |||
/* small screen */ | |||
@media (max-width: 700px) { | |||
.container { flex-direction: column; } | |||
.sidebar { | |||
width: 100%; | |||
height: 180px; | |||
border-right: none; | |||
border-bottom: 1px solid #e0e6ef; | |||
} | |||
.content { height: calc(100vh - 180px); } | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div class="container"> | |||
<aside class="sidebar"> | |||
<div class="search-box"> | |||
<input id="help-search" type="text" placeholder="검색어 입력 (예: 설치, 사용, 설정)"> | |||
</div> | |||
<ul id="toc" class="toc"></ul> | |||
</aside> | |||
<main class="content"> | |||
<div class="content-scroll" id="content-scroll"> | |||
<h1 id="help-title" class="help-title">도움말</h1> | |||
<img id="help-thumb" class="thumb" src="" alt="썸네일" style="display:none;" title="클릭하면 확대됨"> | |||
<div id="help-meta" class="meta"></div> | |||
<!-- 섹션들이 이 안에 들어갑니다 --> | |||
<div id="help-sections"></div> | |||
<div id="help-desc" class="desc" style="display:none;"></div> | |||
</div> | |||
</main> | |||
</div> | |||
<!-- modal --> | |||
<div id="modal-backdrop" class="modal-backdrop"> | |||
<div class="modal"> | |||
<img id="modal-img" src="" alt="상세 이미지"> | |||
</div> | |||
</div> | |||
<script> | |||
// 예시 데이터: 각 도움말 항목에 여러 섹션을 포함 | |||
var helpData = [ | |||
{ | |||
id: "install", | |||
title: "설치 방법", | |||
thumb: "https://via.placeholder.com/640x360.png?text=설치+썸네일", | |||
meta: "최종 수정: 2025-08-01 · 난이도: 기본", | |||
sections: [ | |||
{sid: "install-1", title: "사전 준비", html: "<p>시스템 요구사항을 확인하세요. 최소 RAM 4GB 이상, 디스크 200MB 이상.</p>"}, | |||
{sid: "install-2", title: "설치 파일 다운로드", html: "<p>공식 사이트에서 설치 파일을 다운로드합니다.</p>"}, | |||
{sid: "install-3", title: "설치 과정", html: "<ol><li>다운로드한 파일 실행</li><li>설치 경로 선택</li><li>설치 완료 후 재시작</li></ol>"}, | |||
{sid: "install-4", title: "문제 해결 팁", html: "<p>권한 문제가 발생하면 관리자 권한으로 실행하십시오.</p>"} | |||
] | |||
}, | |||
{ | |||
id: "usage", | |||
title: "기본 사용법", | |||
thumb: "https://via.placeholder.com/640x360.png?text=기본+사용법+썸네일", | |||
meta: "최종 수정: 2025-07-20 · 난이도: 초급", | |||
sections: [ | |||
{sid: "usage-1", title: "새 문서 만들기", html: "<p>파일 → 새로 만들기 또는 단축키 Ctrl+N</p>"}, | |||
{sid: "usage-2", title: "저장", html: "<p>저장: Ctrl+S 또는 파일 → 저장</p>"}, | |||
{sid: "usage-3", title: "도움말 열기", html: "<p>도움말: F1</p>"} | |||
] | |||
}, | |||
{ | |||
id: "settings", | |||
title: "환경 설정", | |||
thumb: "https://via.placeholder.com/640x360.png?text=설정+썸네일", | |||
meta: "최종 수정: 2025-06-10 · 난이도: 중급", | |||
sections: [ | |||
{sid: "settings-1", title: "인터페이스", html: "<p>테마, 글꼴 크기 등을 변경할 수 있습니다.</p>"}, | |||
{sid: "settings-2", title: "언어 설정", html: "<p>한국어/영어 등 언어를 선택합니다.</p>"}, | |||
{sid: "settings-3", title: "업데이트", html: "<p>자동 업데이트를 켜거나 끌 수 있습니다.</p>"} | |||
] | |||
}, | |||
{ | |||
id: "long", | |||
title: "매우 긴 도움말 예시", | |||
thumb: "https://via.placeholder.com/640x360.png?text=긴+내용+썸네일", | |||
meta: "최종 수정: 2025-08-25 · 난이도: 고급", | |||
sections: (function(){ | |||
var s = []; | |||
for (var i=1;i<=30;i++){ | |||
s.push({ | |||
sid: "long-"+i, | |||
title: "긴 섹션 " + i, | |||
html: "<p>문단 "+i+": Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus lacinia odio vitae vestibulum vestibulum.</p>" | |||
}); | |||
} | |||
return s; | |||
})() | |||
} | |||
]; | |||
// 전체 TOC 렌더링 (목록에는 항목별 섹션 링크도 포함) | |||
function renderTOC(list) { | |||
var $toc = $("#toc"); | |||
$toc.empty(); | |||
list.forEach(function(item, idx){ | |||
var $li = $("<li>").attr("data-id", item.id); | |||
var $title = $("<div>").text((idx+1)+". "+item.title); | |||
$li.append($title); | |||
// 각 항목의 섹션 목록(축소형) 추가 | |||
if (item.sections && item.sections.length) { | |||
var $sub = $("<ul>").css({paddingLeft: "14px", marginTop: "8px"}); | |||
item.sections.forEach(function(sec){ | |||
var $sli = $("<li>") | |||
.addClass("toc-sub") | |||
.css({padding: "6px 4px", cursor: "pointer", fontSize: "13px", color:"#445"}) | |||
.attr("data-parent", item.id) | |||
.attr("data-sid", sec.sid) | |||
.text("· " + sec.title); | |||
$sub.append($sli); | |||
}); | |||
$li.append($sub); | |||
} | |||
$toc.append($li); | |||
}); | |||
} | |||
// 도움말 항목 표시: 섹션들을 DOM에 생성 | |||
function showHelp(id) { | |||
var item = helpData.find(function(i){ return i.id === id; }); | |||
if (!item) return; | |||
$("#help-title").text(item.title); | |||
$("#help-meta").text(item.meta); | |||
if (item.thumb) { | |||
$("#help-thumb").attr("src", item.thumb).show(); | |||
} else { | |||
$("#help-thumb").hide(); | |||
} | |||
// 섹션들 렌더링 | |||
var $secWrap = $("#help-sections"); | |||
$secWrap.empty(); | |||
if (item.sections && item.sections.length) { | |||
item.sections.forEach(function(sec){ | |||
var $sec = $("<div>").addClass("section").attr("id", sec.sid); | |||
$sec.append($("<h2>").text(sec.title)); | |||
$sec.append($("<div>").html(sec.html)); | |||
$secWrap.append($sec); | |||
}); | |||
} else { | |||
$("#help-desc").show().html(item.desc || ""); | |||
} | |||
// TOC 활성화 (상위 항목) | |||
$("#toc li").removeClass("active"); | |||
$("#toc li[data-id='"+id+"']").addClass("active"); | |||
// 내용 스크롤을 맨 위로 이동 | |||
var $scroll = $("#content-scroll"); | |||
$scroll.stop().animate({scrollTop: 0}, 200); | |||
} | |||
// 특정 섹션으로 부드럽게 스크롤 | |||
function scrollToSection(sid) { | |||
var $scroll = $("#content-scroll"); | |||
var $target = $("#" + sid); | |||
if (!$target.length) return; | |||
// 목표 요소의 offsetTop 상대값을 계산 (content-scroll 내부에서의 위치) | |||
var targetOffset = $target.position().top; // position() 은 부모 상대 위치 반환 | |||
// 약간의 여백 추가 | |||
var scrollTo = $scroll.scrollTop() + targetOffset - 12; | |||
$scroll.stop().animate({scrollTop: scrollTo}, 400); | |||
} | |||
// 검색(간단 필터) | |||
function filterTOC(keyword) { | |||
var kw = (keyword||"").trim().toLowerCase(); | |||
if (!kw) { | |||
renderTOC(helpData); | |||
return; | |||
} | |||
var filtered = helpData.filter(function(it){ | |||
var inTitle = it.title.toLowerCase().indexOf(kw) !== -1; | |||
var inSections = (it.sections||[]).some(function(s){ return s.title.toLowerCase().indexOf(kw) !== -1 || s.html.toLowerCase().indexOf(kw) !== -1; }); | |||
return inTitle || inSections; | |||
}); | |||
renderTOC(filtered); | |||
} | |||
$(function(){ | |||
renderTOC(helpData); | |||
if (helpData.length) showHelp(helpData[0].id); | |||
// 상위 항목 클릭: 항목 전체 표시 | |||
$(document).on("click", "#toc > li", function(e){ | |||
// 클릭이 서브 항목 쪽인지 필터 | |||
if ($(e.target).closest(".toc-sub").length) return; | |||
var id = $(this).attr("data-id"); | |||
showHelp(id); | |||
}); | |||
// 서브 섹션 클릭: 해당 섹션으로 내부 스크롤 | |||
$(document).on("click", ".toc-sub", function(){ | |||
var parentId = $(this).attr("data-parent"); | |||
var sid = $(this).attr("data-sid"); | |||
// 만약 현재 보이는 항목이 아니면 먼저 상위 항목 렌더 | |||
var activeId = $("#toc li.active").attr("data-id"); | |||
if (activeId !== parentId) { | |||
showHelp(parentId); | |||
// 렌더 후 약간의 지연을 두고 스크롤 | |||
setTimeout(function(){ scrollToSection(sid); }, 60); | |||
} else { | |||
scrollToSection(sid); | |||
} | |||
}); | |||
// 검색 입력 | |||
$("#help-search").on("input", function(){ | |||
filterTOC($(this).val()); | |||
}); | |||
// 썸네일 클릭 -> 모달 열기 | |||
$("#help-thumb").on("click", function(){ | |||
var src = $(this).attr("src"); | |||
$("#modal-img").attr("src", src); | |||
$("#modal-backdrop").css("display","flex"); | |||
}); | |||
// 모달 닫기 | |||
$("#modal-backdrop").on("click", function(e){ | |||
if (e.target === this) { | |||
$("#modal-backdrop").hide(); | |||
} | |||
}); | |||
$(document).on("keydown", function(e){ | |||
if (e.key === "Escape") $("#modal-backdrop").hide(); | |||
}); | |||
}); | |||
</script> | |||
</body> | |||
</html> | |||
</source> | </source> | ||
2025년 8월 28일 (목) 12:16 기준 최신판
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>도움말 시스템</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<style>
body {
font-family: 'Noto Sans KR', sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 1000px;
margin: 0 auto;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #2c3e50;
margin-bottom: 30px;
}
.search-box {
display: flex;
margin-bottom: 20px;
}
#search-input {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px 0 0 4px;
font-size: 16px;
}
#search-btn {
padding: 10px 15px;
background-color: #3498db;
color: white;
border: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
transition: background-color 0.3s;
}
#search-btn:hover {
background-color: #2980b9;
}
.help-nav {
display: flex;
margin-bottom: 20px;
}
.help-categories {
width: 250px;
border-right: 1px solid #ddd;
padding-right: 15px;
}
.category {
cursor: pointer;
padding: 8px 10px;
border-radius: 4px;
transition: background-color 0.3s;
}
.category:hover {
background-color: #f0f0f0;
}
.category.active {
background-color: #e6f2ff;
color: #3498db;
font-weight: bold;
}
.help-content {
flex: 1;
padding-left: 20px;
}
.topic {
display: none;
border-bottom: 1px solid #eee;
padding-bottom: 15px;
margin-bottom: 15px;
}
.topic h3 {
color: #2c3e50;
margin-bottom: 10px;
}
.topic.active {
display: block;
}
#search-results {
display: none;
}
.result-item {
cursor: pointer;
padding: 10px;
border-radius: 4px;
transition: background-color 0.3s;
margin-bottom: 10px;
}
.result-item:hover {
background-color: #f0f0f0;
}
.highlight {
background-color: #ffff99;
font-weight: bold;
}
.back-btn {
display: none;
padding: 8px 15px;
background-color: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-bottom: 15px;
}
.back-btn:hover {
background-color: #2980b9;
}
</style>
</head>
<body>
<div class="container">
<h1>도움말 시스템</h1>
<div class="search-box">
<input type="text" id="search-input" placeholder="도움말 검색...">
<button id="search-btn"><i class="fas fa-search"></i> 검색</button>
</div>
<button class="back-btn" id="back-to-help">도움말 목록으로 돌아가기</button>
<div id="search-results">
<h2>검색 결과</h2>
<div id="results-list"></div>
</div>
<div class="help-nav" id="help-content">
<div class="help-categories">
<h2>카테고리</h2>
<div class="category active" data-category="getting-started">시작하기</div>
<div class="category" data-category="account">계정 관리</div>
<div class="category" data-category="features">주요 기능</div>
<div class="category" data-category="troubleshooting">문제 해결</div>
</div>
<div class="help-content">
<!-- 시작하기 카테고리 -->
<div class="topic active" data-category="getting-started" id="intro">
<h3>프로그램 소개</h3>
<p>이 프로그램은 사용자가 쉽게 작업을 수행할 수 있도록 설계되었습니다. 주요 기능과 인터페이스에 대한 설명을 제공합니다.</p>
</div>
<div class="topic" data-category="getting-started" id="installation">
<h3>설치 방법</h3>
<p>프로그램을 설치하기 위한 단계별 지침을 제공합니다.</p>
<ol>
<li>웹사이트에서 설치 파일을 다운로드합니다.</li>
<li>다운로드한 파일을 실행합니다.</li>
<li>설치 마법사의 지시를 따릅니다.</li>
<li>설치가 완료되면 프로그램을 실행합니다.</li>
</ol>
</div>
<!-- 계정 관리 카테고리 -->
<div class="topic" data-category="account" id="create-account">
<h3>계정 생성</h3>
<p>새 계정을 만들기 위한 절차를 설명합니다.</p>
</div>
<div class="topic" data-category="account" id="login">
<h3>로그인</h3>
<p>프로그램에 로그인하는 방법을 설명합니다.</p>
</div>
<div class="topic" data-category="account" id="password">
<h3>비밀번호 재설정</h3>
<p>비밀번호를 잊어버렸을 때 재설정하는 방법을 안내합니다.</p>
</div>
<!-- 주요 기능 카테고리 -->
<div class="topic" data-category="features" id="feature1">
<h3>기능 1: 데이터 관리</h3>
<p>데이터를 효율적으로 관리하는 방법을 설명합니다.</p>
</div>
<div class="topic" data-category="features" id="feature2">
<h3>기능 2: 보고서 생성</h3>
<p>다양한 보고서를 생성하고 내보내는 방법을 안내합니다.</p>
</div>
<!-- 문제 해결 카테고리 -->
<div class="topic" data-category="troubleshooting" id="error-codes">
<h3>오류 코드 해석</h3>
<p>일반적인 오류 코드와 해결 방법을 제공합니다.</p>
</div>
<div class="topic" data-category="troubleshooting" id="connection">
<h3>연결 문제</h3>
<p>네트워크 연결 문제를 해결하는 방법을 안내합니다.</p>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
// 카테고리 클릭 이벤트
$('.category').click(function() {
// 활성화된 카테고리 변경
$('.category').removeClass('active');
$(this).addClass('active');
// 선택된 카테고리의 토픽만 보이게 설정
var category = $(this).data('category');
$('.topic').hide();
$('.topic[data-category="' + category + '"]').first().show();
});
// 검색 기능
$('#search-btn').click(performSearch);
$('#search-input').keypress(function(e) {
if(e.which == 13) { // Enter key
performSearch();
}
});
// 뒤로가기 버튼
$('#back-to-help').click(function() {
$('#search-results').hide();
$('#help-content').show();
$(this).hide();
});
function performSearch() {
var query = $('#search-input').val().toLowerCase();
if(query.trim() === '') return;
var results = [];
// 모든 토픽에서 검색
$('.topic').each(function() {
var topicTitle = $(this).find('h3').text();
var topicContent = $(this).text();
var topicId = $(this).attr('id');
if(topicTitle.toLowerCase().includes(query) ||
topicContent.toLowerCase().includes(query)) {
results.push({
id: topicId,
title: topicTitle,
content: $(this).find('p').first().text(),
category: $(this).data('category')
});
}
});
// 검색 결과 표시
displaySearchResults(results, query);
}
function displaySearchResults(results, query) {
var resultsList = $('#results-list');
resultsList.empty();
if(results.length === 0) {
resultsList.append('<p>검색 결과가 없습니다.</p>');
} else {
$.each(results, function(i, result) {
var resultItem = $('<div class="result-item" data-id="' + result.id + '" data-category="' + result.category + '">' +
'<h3>' + highlightText(result.title, query) + '</h3>' +
'<p>' + highlightText(result.content, query) + '</p>' +
'</div>');
resultsList.append(resultItem);
});
// 검색 결과 항목 클릭 이벤트
$('.result-item').click(function() {
var id = $(this).data('id');
var category = $(this).data('category');
// 해당 카테고리 활성화
$('.category').removeClass('active');
$('.category[data-category="' + category + '"]').addClass('active');
// 해당 토픽 보이기
$('.topic').hide();
$('#' + id).show();
// 검색 결과 숨기기, 도움말 내용 보이기
$('#search-results').hide();
$('#help-content').show();
});
}
// 도움말 내용 숨기고 검색 결과 표시
$('#help-content').hide();
$('#search-results').show();
$('#back-to-help').show();
}
function highlightText(text, query) {
if (!query) return text;
var regex = new RegExp('(' + query + ')', 'gi');
return text.replace(regex, '<span class="highlight">$1</span>');
}
});
</script>
</body>
</html>
검색기능 추가 (개선)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>도움말 시스템</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<style>
body {
font-family: 'Noto Sans KR', sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 1000px;
margin: 0 auto;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
text-align: center;
color: #2c3e50;
margin-bottom: 30px;
}
.search-box {
display: flex;
margin-bottom: 20px;
position: relative;
}
#search-input {
flex: 1;
padding: 10px 40px 10px 15px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
#search-btn {
padding: 10px 15px;
background-color: #3498db;
color: white;
border: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
transition: background-color 0.3s;
}
#search-btn:hover {
background-color: #2980b9;
}
.search-clear {
position: absolute;
right: 120px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: #999;
cursor: pointer;
font-size: 16px;
display: none;
}
.help-nav {
display: flex;
margin-bottom: 20px;
}
.help-categories {
width: 250px;
border-right: 1px solid #ddd;
padding-right: 15px;
}
.category {
cursor: pointer;
padding: 8px 10px;
border-radius: 4px;
transition: background-color 0.3s;
margin-bottom: 5px;
}
.category:hover {
background-color: #f0f0f0;
}
.category.active {
background-color: #e6f2ff;
color: #3498db;
font-weight: bold;
}
.help-content {
flex: 1;
padding-left: 20px;
}
.topic {
display: none;
border-bottom: 1px solid #eee;
padding-bottom: 15px;
margin-bottom: 15px;
}
.topic h3 {
color: #2c3e50;
margin-bottom: 10px;
}
.topic.active {
display: block;
}
#search-results {
display: none;
}
.result-item {
cursor: pointer;
padding: 10px;
border-radius: 4px;
transition: background-color 0.3s;
margin-bottom: 15px;
border-left: 3px solid #3498db;
background-color: #f9f9f9;
}
.result-item:hover {
background-color: #f0f0f0;
}
.highlight {
background-color: #ffff99;
font-weight: bold;
}
.back-btn {
display: none;
padding: 8px 15px;
background-color: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-bottom: 15px;
}
.back-btn:hover {
background-color: #2980b9;
}
.search-status {
margin-top: 10px;
font-style: italic;
color: #666;
}
.no-results {
text-align: center;
padding: 20px;
background-color: #f9f9f9;
border-radius: 4px;
margin-top: 20px;
}
.search-suggestion {
margin-top: 10px;
}
.search-suggestion span {
cursor: pointer;
color: #3498db;
margin-right: 10px;
text-decoration: underline;
}
.search-filters {
display: flex;
margin: 10px 0;
flex-wrap: wrap;
}
.search-filter {
background-color: #f0f0f0;
padding: 5px 10px;
border-radius: 15px;
margin-right: 10px;
margin-bottom: 5px;
font-size: 14px;
cursor: pointer;
transition: background-color 0.3s;
}
.search-filter:hover, .search-filter.active {
background-color: #3498db;
color: white;
}
.category-badge {
display: inline-block;
padding: 2px 8px;
background-color: #e6f2ff;
color: #3498db;
border-radius: 10px;
font-size: 12px;
margin-left: 10px;
}
.search-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.topic-content {
margin-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<h1>도움말 시스템</h1>
<div class="search-box">
<input type="text" id="search-input" placeholder="도움말 검색...">
<button class="search-clear" id="clear-search"><i class="fas fa-times"></i></button>
<button id="search-btn"><i class="fas fa-search"></i> 검색</button>
</div>
<button class="back-btn" id="back-to-help">도움말 목록으로 돌아가기</button>
<div id="search-results">
<div class="search-info">
<h2>검색 결과</h2>
<div class="search-status" id="search-status"></div>
</div>
<div class="search-filters" id="search-filters">
<div class="search-filter active" data-filter="all">전체</div>
<div class="search-filter" data-filter="getting-started">시작하기</div>
<div class="search-filter" data-filter="account">계정 관리</div>
<div class="search-filter" data-filter="features">주요 기능</div>
<div class="search-filter" data-filter="troubleshooting">문제 해결</div>
</div>
<div id="results-list"></div>
<div class="search-suggestion" id="search-suggestion"></div>
</div>
<div class="help-nav" id="help-content">
<div class="help-categories">
<h2>카테고리</h2>
<div class="category active" data-category="getting-started">시작하기</div>
<div class="category" data-category="account">계정 관리</div>
<div class="category" data-category="features">주요 기능</div>
<div class="category" data-category="troubleshooting">문제 해결</div>
</div>
<div class="help-content">
<!-- 시작하기 카테고리 -->
<div class="topic active" data-category="getting-started" id="intro">
<h3>프로그램 소개</h3>
<div class="topic-content">
<p>이 프로그램은 사용자가 쉽게 작업을 수행할 수 있도록 설계되었습니다. 주요 기능과 인터페이스에 대한 설명을 제공합니다.</p>
<p>사용자 친화적인 인터페이스와 함께 다양한 기능을 탐색하고 활용할 수 있습니다. 이 도움말 시스템은 프로그램 사용 중에 발생할 수 있는 모든 질문에 대한 답변을 제공합니다.</p>
</div>
</div>
<div class="topic" data-category="getting-started" id="installation">
<h3>설치 방법</h3>
<div class="topic-content">
<p>프로그램을 설치하기 위한 단계별 지침을 제공합니다.</p>
<ol>
<li>웹사이트에서 설치 파일을 다운로드합니다.</li>
<li>다운로드한 파일을 실행합니다.</li>
<li>설치 마법사의 지시를 따릅니다.</li>
<li>설치가 완료되면 프로그램을 실행합니다.</li>
</ol>
<p>설치 중 문제가 발생하면 '문제 해결' 섹션을 참조하시기 바랍니다.</p>
</div>
</div>
<div class="topic" data-category="getting-started" id="system-requirements">
<h3>시스템 요구사항</h3>
<div class="topic-content">
<p>프로그램을 실행하기 위한 최소 시스템 요구사항입니다:</p>
<ul>
<li>운영체제: Windows 10 이상 / macOS 10.14 이상 / Linux (Ubuntu 18.04 이상)</li>
<li>프로세서: 2GHz 이상의 듀얼 코어 프로세서</li>
<li>메모리: 4GB RAM</li>
<li>저장공간: 500MB 이상의 여유 공간</li>
<li>인터넷 연결: 초기 설정 및 업데이트를 위한 인터넷 연결 필요</li>
</ul>
</div>
</div>
<!-- 계정 관리 카테고리 -->
<div class="topic" data-category="account" id="create-account">
<h3>계정 생성</h3>
<div class="topic-content">
<p>새 계정을 만들기 위한 절차를 설명합니다.</p>
<ol>
<li>프로그램 실행 후 '계정 생성' 버튼을 클릭합니다.</li>
<li>필요한 정보(이름, 이메일, 비밀번호)를 입력합니다.</li>
<li>이메일 인증을 완료합니다.</li>
<li>계정 설정을 확인하고 완료합니다.</li>
</ol>
<p>계정 생성 시 강력한 비밀번호를 사용하는 것을 권장합니다.</p>
</div>
</div>
<div class="topic" data-category="account" id="login">
<h3>로그인</h3>
<div class="topic-content">
<p>프로그램에 로그인하는 방법을 설명합니다.</p>
<ol>
<li>프로그램을 실행하면 로그인 화면이 표시됩니다.</li>
<li>등록된 이메일과 비밀번호를 입력합니다.</li>
<li>'로그인' 버튼을 클릭합니다.</li>
</ol>
<p>'자동 로그인' 옵션을 선택하면 다음 실행 시 자동으로 로그인됩니다. 공용 컴퓨터에서는 이 옵션을 사용하지 마세요.</p>
</div>
</div>
<div class="topic" data-category="account" id="password">
<h3>비밀번호 재설정</h3>
<div class="topic-content">
<p>비밀번호를 잊어버렸을 때 재설정하는 방법을 안내합니다.</p>
<ol>
<li>로그인 화면에서 '비밀번호 찾기' 링크를 클릭합니다.</li>
<li>등록된 이메일 주소를 입력합니다.</li>
<li>이메일로 전송된 링크를 통해 새 비밀번호를 설정합니다.</li>
</ol>
<p>비밀번호 재설정 이메일이 오지 않는 경우, 스팸 폴더를 확인하거나 지원팀에 문의하세요.</p>
</div>
</div>
<div class="topic" data-category="account" id="profile-settings">
<h3>프로필 설정</h3>
<div class="topic-content">
<p>사용자 프로필 정보를 업데이트하는 방법을 안내합니다.</p>
<ol>
<li>로그인 후 오른쪽 상단의 프로필 아이콘을 클릭합니다.</li>
<li>'설정' 또는 '프로필 관리'를 선택합니다.</li>
<li>개인 정보, 알림 설정, 테마 등을 변경할 수 있습니다.</li>
<li>'저장' 버튼을 클릭하여 변경사항을 적용합니다.</li>
</ol>
</div>
</div>
<!-- 주요 기능 카테고리 -->
<div class="topic" data-category="features" id="feature1">
<h3>기능 1: 데이터 관리</h3>
<div class="topic-content">
<p>데이터를 효율적으로 관리하는 방법을 설명합니다.</p>
<h4>데이터 추가</h4>
<ol>
<li>'데이터 관리' 메뉴에서 '새 데이터' 버튼을 클릭합니다.</li>
<li>필요한 정보를 입력하고 '저장' 버튼을 클릭합니다.</li>
</ol>
<h4>데이터 편집</h4>
<ol>
<li>목록에서 편집할 항목을 선택합니다.</li>
<li>'편집' 버튼을 클릭하거나 항목을 더블 클릭합니다.</li>
<li>정보를 수정하고 '저장' 버튼을 클릭합니다.</li>
</ol>
<h4>데이터 삭제</h4>
<ol>
<li>목록에서 삭제할 항목을 선택합니다.</li>
<li>'삭제' 버튼을 클릭합니다.</li>
<li>확인 대화 상자에서 '예'를 선택하여 삭제를 확인합니다.</li>
</ol>
<p>데이터는 자동으로 저장되지만, 중요한 변경 후에는 '백업' 기능을 사용하는 것이 좋습니다.</p>
</div>
</div>
<div class="topic" data-category="features" id="feature2">
<h3>기능 2: 보고서 생성</h3>
<div class="topic-content">
<p>다양한 보고서를 생성하고 내보내는 방법을 안내합니다.</p>
<h4>보고서 유형</h4>
<ul>
<li><strong>요약 보고서</strong>: 주요 데이터의 요약 정보를 보여줍니다.</li>
<li><strong>상세 보고서</strong>: 모든 데이터 항목에 대한 자세한 정보를 포함합니다.</li>
<li><strong>분석 보고서</strong>: 데이터 분석 결과와 그래프를 포함합니다.</li>
</ul>
<h4>보고서 생성 방법</h4>
<ol>
<li>'보고서' 메뉴를 선택합니다.</li>
<li>원하는 보고서 유형을 선택합니다.</li>
<li>필요한 매개변수(기간, 데이터 범위 등)를 설정합니다.</li>
<li>'생성' 버튼을 클릭합니다.</li>
</ol>
<h4>보고서 내보내기</h4>
<ol>
<li>생성된 보고서 화면에서 '내보내기' 버튼을 클릭합니다.</li>
<li>원하는 형식(PDF, Excel, CSV)을 선택합니다.</li>
<li>파일 이름과 저장 위치를 지정합니다.</li>
<li>'저장' 버튼을 클릭합니다.</li>
</ol>
</div>
</div>
<div class="topic" data-category="features" id="feature3">
<h3>기능 3: 자동화 기능</h3>
<div class="topic-content">
<p>반복적인 작업을 자동화하는 기능에 대해 설명합니다.</p>
<h4>자동화 설정</h4>
<ol>
<li>'설정' 메뉴에서 '자동화' 탭을 선택합니다.</li>
<li>'새 자동화' 버튼을 클릭합니다.</li>
<li>트리거(시간, 이벤트 등)와 수행할 작업을 설정합니다.</li>
<li>'저장' 버튼을 클릭하여 자동화를 활성화합니다.</li>
</ol>
<h4>자동화 템플릿</h4>
<p>자주 사용하는 자동화 설정을 템플릿으로 저장하고 재사용할 수 있습니다:</p>
<ol>
<li>자동화 설정 후 '템플릿으로 저장' 옵션을 선택합니다.</li>
<li>템플릿 이름을 지정하고 '저장'을 클릭합니다.</li>
<li>새 자동화 생성 시 '템플릿에서 불러오기'를 선택하여 사용합니다.</li>
</ol>
</div>
</div>
<!-- 문제 해결 카테고리 -->
<div class="topic" data-category="troubleshooting" id="error-codes">
<h3>오류 코드 해석</h3>
<div class="topic-content">
<p>일반적인 오류 코드와 해결 방법을 제공합니다.</p>
<table border="1" style="width: 100%; border-collapse: collapse;">
<tr style="background-color: #f2f2f2;">
<th style="padding: 8px; text-align: left;">오류 코드</th>
<th style="padding: 8px; text-align: left;">설명</th>
<th style="padding: 8px; text-align: left;">해결 방법</th>
</tr>
<tr>
<td style="padding: 8px;">ERR-001</td>
<td style="padding: 8px;">데이터베이스 연결 실패</td>
<td style="padding: 8px;">네트워크 연결을 확인하고 프로그램을 다시 시작하세요.</td>
</tr>
<tr>
<td style="padding: 8px;">ERR-002</td>
<td style="padding: 8px;">인증 오류</td>
<td style="padding: 8px;">로그아웃 후 다시 로그인하세요. 문제가 지속되면 비밀번호를 재설정하세요.</td>
</tr>
<tr>
<td style="padding: 8px;">ERR-003</td>
<td style="padding: 8px;">파일 접근 오류</td>
<td style="padding: 8px;">파일이 다른 프로그램에 의해 사용 중인지 확인하고, 권한 설정을 확인하세요.</td>
</tr>
<tr>
<td style="padding: 8px;">ERR-004</td>
<td style="padding: 8px;">메모리 부족</td>
<td style="padding: 8px;">다른 프로그램을 종료하고 다시 시도하세요.</td>
</tr>
</table>
</div>
</div>
<div class="topic" data-category="troubleshooting" id="connection">
<h3>연결 문제</h3>
<div class="topic-content">
<p>네트워크 연결 문제를 해결하는 방법을 안내합니다.</p>
<h4>기본 연결 문제 해결</h4>
<ol>
<li>인터넷 연결이 활성화되어 있는지 확인합니다.</li>
<li>방화벽 설정에서 프로그램이 차단되지 않았는지 확인합니다.</li>
<li>프로그램을 종료하고 다시 시작합니다.</li>
<li>컴퓨터를 재시작하고 문제가 해결되는지 확인합니다.</li>
</ol>
<h4>서버 연결 문제</h4>
<ol>
<li>'설정' 메뉴에서 '연결' 탭을 선택합니다.</li>
<li>'서버 테스트' 버튼을 클릭하여 서버 연결을 확인합니다.</li>
<li>서버 주소가 올바른지 확인합니다.</li>
<li>프록시 설정이 필요한 경우 올바르게 구성되어 있는지 확인합니다.</li>
</ol>
<p>지속적인 연결 문제가 발생하는 경우, 지원팀에 문의하세요.</p>
</div>
</div>
<div class="topic" data-category="troubleshooting" id="performance">
<h3>성능 최적화</h3>
<div class="topic-content">
<p>프로그램 성능을 향상시키기 위한 팁을 제공합니다.</p>
<h4>캐시 정리</h4>
<ol>
<li>'설정' 메뉴에서 '유지 관리' 탭을 선택합니다.</li>
<li>'캐시 정리' 버튼을 클릭합니다.</li>
<li>프로그램을 다시 시작합니다.</li>
</ol>
<h4>메모리 사용 최적화</h4>
<ol>
<li>사용하지 않는 기능을 비활성화합니다.</li>
<li>대용량 파일 작업 시 '메모리 최적화' 옵션을 활성화합니다.</li>
<li>정기적으로 프로그램을 다시 시작하여 메모리를 정리합니다.</li>
</ol>
<h4>하드웨어 요구사항 확인</h4>
<p>프로그램이 느리게 실행된다면 시스템 사양이 최소 요구사항을 충족하는지 확인하세요.</p>
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
// 전역 변수
let helpTopics = {};
let categoryLabels = {
'getting-started': '시작하기',
'account': '계정 관리',
'features': '주요 기능',
'troubleshooting': '문제 해결'
};
let searchIndex = [];
let searchSuggestions = [
"설치", "로그인", "비밀번호", "계정", "오류",
"보고서", "데이터", "자동화", "성능", "연결"
];
// 초기화: 모든 도움말 토픽 정보 수집
function initHelpSystem() {
$('.topic').each(function() {
const id = $(this).attr('id');
const category = $(this).data('category');
const title = $(this).find('h3').text();
const content = $(this).text();
const keywords = extractKeywords(title + ' ' + content);
helpTopics[id] = {
id: id,
category: category,
title: title,
content: content,
keywords: keywords,
element: $(this)
};
// 검색 인덱스 구축
searchIndex.push({
id: id,
text: title + ' ' + content,
keywords: keywords,
category: category,
title: title
});
});
}
// 키워드 추출 (기본 구현)
function extractKeywords(text) {
// 텍스트에서 공통 단어 제외하고 단어 추출
const commonWords = ["그리고", "하지만", "또는", "그런", "이런", "저런", "이", "그", "저", "및", "등", "를", "을", "에", "의", "에서"];
let words = text.toLowerCase().split(/\s+/);
words = words.filter(word => word.length > 1 && !commonWords.includes(word));
return [...new Set(words)]; // 중복 제거
}
// 카테고리 클릭 이벤트
$('.category').click(function() {
// 활성화된 카테고리 변경
$('.category').removeClass('active');
$(this).addClass('active');
// 선택된 카테고리의 토픽만 보이게 설정
const category = $(this).data('category');
$('.topic').hide();
$(`.topic[data-category="${category}"]`).first().show().addClass('active');
});
// 검색 기능
$('#search-btn').click(performSearch);
$('#search-input').on('input', function() {
if ($(this).val().trim() !== '') {
$('.search-clear').show();
} else {
$('.search-clear').hide();
}
}).keypress(function(e) {
if(e.which == 13) { // Enter key
performSearch();
}
});
// 검색창 클리어 버튼
$('#clear-search').click(function() {
$('#search-input').val('').focus();
$(this).hide();
});
// 뒤로가기 버튼
$('#back-to-help').click(function() {
$('#search-results').hide();
$('#help-content').show();
$(this).hide();
// 검색 상태 초기화
$('.search-filter').removeClass('active');
$('.search-filter[data-filter="all"]').addClass('active');
});
// 검색 필터 클릭 이벤트
$('.search-filter').click(function() {
$('.search-filter').removeClass('active');
$(this).addClass('active');
filterSearchResults($(this).data('filter'));
});
// 검색 실행 함수
function performSearch() {
const query = $('#search-input').val().trim().toLowerCase();
if(query === '') return;
// 검색 결과 찾기
const results = searchTopics(query);
// 검색 결과 표시
displaySearchResults(results, query);
// 검색 기록 저장 (로컬 스토리지 이용)
saveSearchHistory(query);
// 추천 검색어 표시
showSearchSuggestions();
}
// 토픽 검색 함수
function searchTopics(query) {
if (!query) return [];
const results = [];
const queryWords = query.toLowerCase().split(/\s+/).filter(word => word.length > 1);
// 각 검색 인덱스 항목에 대해 점수 계산
searchIndex.forEach(item => {
let score = 0;
const text = item.text.toLowerCase();
// 제목에 정확히 일치하면 높은 점수
if (item.title.toLowerCase().includes(query)) {
score += 10;
}
// 전체 구문이 텍스트에 포함되어 있으면 점수 추가
if (text.includes(query)) {
score += 5;
}
// 각 단어별 매칭 점수 계산
queryWords.forEach(word => {
// 제목에 단어가 있으면 높은 점수
if (item.title.toLowerCase().includes(word)) {
score += 3;
}
// 키워드에 단어가 있으면 점수 추가
if (item.keywords.includes(word)) {
score += 2;
}
// 내용에 단어가 있으면 점수 추가
if (text.includes(word)) {
score += 1;
}
});
// 일정 점수 이상인 경우만 결과에 포함
if (score > 0) {
results.push({
id: item.id,
title: item.title,
category: item.category,
score: score,
matches: findMatches(text, query)
});
}
});
// 점수 기준 내림차순 정렬
return results.sort((a, b) => b.score - a.score);
}
// 텍스트에서 매칭되는 문맥 찾기
function findMatches(text, query) {
const matches = [];
const words = query.toLowerCase().split(/\s+/).filter(word => word.length > 1);
// 전체 쿼리 매칭
let index = text.toLowerCase().indexOf(query);
if (index !== -1) {
const start = Math.max(0, index - 30);
const end = Math.min(text.length, index + query.length + 30);
matches.push(text.substring(start, end).trim());
}
// 개별 단어 매칭
else if (words.length > 0) {
for (const word of words) {
index = text.toLowerCase().indexOf(word);
if (index !== -1) {
const start = Math.max(0, index - 20);
const end = Math.min(text.length, index + word.length + 20);
let snippet = text.substring(start, end).trim();
// 중복 방지
if (!matches.includes(snippet)) {
matches.push(snippet);
if (matches.length >= 2) break; // 최대 2개 매칭 문맥만 보여줌
}
}
}
}
return matches;
}
// 검색 결과 표시 함수
function displaySearchResults(results, query) {
const resultsList = $('#results-list');
resultsList.empty();
// 검색 상태 업데이트
$('#search-status').text(`${results.length}개의 결과가 있습니다.`);
if(results.length === 0) {
resultsList.append(`
<div class="no-results">
<p>"${query}"에 대한 검색 결과가 없습니다.</p>
<p>다른 검색어를 시도하거나 카테고리에서 직접 찾아보세요.</p>
</div>
`);
} else {
$.each(results, function(i, result) {
const topic = helpTopics[result.id];
const categoryLabel = categoryLabels[result.category];
let snippets = '';
if (result.matches && result.matches.length > 0) {
snippets = '<p class="result-context">' +
result.matches.map(match => '... ' + highlightText(match, query) + ' ...').join('<br>') +
'</p>';
}
const resultItem = $(`
<div class="result-item" data-id="${result.id}" data-category="${result.category}">
<h3>${highlightText(result.title, query)} <span class="category-badge">${categoryLabel}</span></h3>
${snippets}
</div>
`);
resultsList.append(resultItem);
});
// 검색 결과 항목 클릭 이벤트
$('.result-item').click(function() {
const id = $(this).data('id');
const category = $(this).data('category');
// 해당 카테고리 활성화
$('.category').removeClass('active');
$(`.category[data-category="${category}"]`).addClass('active');
// 모든 토픽 숨기기
$('.topic').removeClass('active').hide();
// 해당 토픽 보이기
$(`#${id}`).addClass('active').show();
// 검색 결과 숨기기, 도움말 내용 보이기
$('#search-results').hide();
$('#help-content').show();
});
}
// 도움말 내용 숨기고 검색 결과 표시
$('#help-content').hide();
$('#search-results').show();
$('#back-to-help').show();
}
// 검색 결과 필터링
function filterSearchResults(filter) {
if (filter === 'all') {
$('.result-item').show();
} else {
$('.result-item').hide();
$(`.result-item[data-category="${filter}"]`).show();
}
// 표시된 결과 개수 업데이트
const visibleCount = $('.result-item:visible').length;
$('#search-status').text(`${visibleCount}개의 결과가 표시되었습니다.`);
}
// 텍스트에서 검색어 하이라이트
function highlightText(text, query) {
if (!query) return text;
const words = query.toLowerCase().split(/\s+/).filter(word => word.length > 1);
let highlightedText = text;
// 전체 구문 하이라이트
const regex = new RegExp('(' + escapeRegExp(query) + ')', 'gi');
highlightedText = highlightedText.replace(regex, '<span class="highlight">$1</span>');
// 개별 단어 하이라이트 (전체 구문이 이미 하이라이트 되지 않은 경우)
words.forEach(word => {
const wordRegex = new RegExp('(' + escapeRegExp(word) + ')', 'gi');
highlightedText = highlightedText.replace(wordRegex, function(match) {
// 이미 하이라이트 태그 안에 있으면 변경하지 않음
if (match.indexOf('<span class="highlight">') !== -1) return match;
return '<span class="highlight">' + match + '</span>';
});
});
return highlightedText;
}
// 정규식 특수문자 이스케이프
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
// 검색 기록 저장
function saveSearchHistory(query) {
let history = localStorage.getItem('searchHistory');
history = history ? JSON.parse(history) : [];
// 중복 방지 및 최근 검색어 앞으로
const index = history.indexOf(query);
if (index !== -1) {
history.splice(index, 1);
}
history.unshift(query);
// 최대 10개 저장
if (history.length > 10) {
history = history.slice(0, 10);
}
localStorage.setItem('searchHistory', JSON.stringify(history));
}
// 검색 추천어 표시
function showSearchSuggestions() {
const suggestionEl = $('#search-suggestion');
suggestionEl.empty();
// 최근 검색어 불러오기
let history = localStorage.getItem('searchHistory');
history = history ? JSON.parse(history) : [];
if (history.length > 0) {
suggestionEl.append('<p>최근 검색어: ');
for (let i = 0; i < Math.min(5, history.length); i++) {
suggestionEl.append(`<span class="suggestion-item">${history[i]}</span>`);
}
suggestionEl.append('</p>');
}
// 인기 검색어/추천 검색어
suggestionEl.append('<p>추천 검색어: ');
for (let i = 0; i < Math.min(5, searchSuggestions.length); i++) {
suggestionEl.append(`<span class="suggestion-item">${searchSuggestions[i]}</span>`);
}
suggestionEl.append('</p>');
// 추천 검색어 클릭 이벤트
$('.suggestion-item').click(function() {
$('#search-input').val($(this).text());
performSearch();
});
}
// 초기화
initHelpSystem();
});
</script>
</body>
</html>
네비게이션 + 내용 스크롤 기능 추가
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>프로그램 도움말 (커스텀 스크롤바 + 섹션 내비게이션)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
html, body {
height: 100%;
margin: 0;
font-family: Arial, "Malgun Gothic", "맑은 고딕", sans-serif;
background: #f5f7fa;
color: #333;
}
.container {
display: flex;
height: 100vh;
overflow: hidden;
}
.sidebar {
width: 300px;
background: #ffffff;
border-right: 1px solid #e0e6ef;
padding: 20px;
box-sizing: border-box;
overflow-y: auto;
}
.search-box { margin-bottom: 12px; }
.search-box input {
width: 100%;
padding: 8px 10px;
border: 1px solid #ccd6e6;
border-radius: 4px;
box-sizing: border-box;
}
.toc { list-style: none; padding: 0; margin: 0; }
.toc li {
padding: 10px 8px;
border-radius: 4px;
cursor: pointer;
color: #223;
}
.toc li:hover { background: #f0f6ff; }
.toc li.active {
background: #e6f0ff;
font-weight: bold;
border-left: 3px solid #1976d2;
}
.content {
flex: 1;
display: flex;
flex-direction: column;
background: transparent;
}
/* 내부 스크롤을 담당하는 래퍼 */
.content-scroll {
padding: 24px;
box-sizing: border-box;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
position: relative;
}
.help-title { margin: 0 0 12px 0; font-size: 22px; }
.thumb {
width: 320px;
max-width: 100%;
border: 1px solid #d6dfe9;
padding: 6px;
background: #fff;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
cursor: pointer;
display: block;
margin-bottom: 12px;
}
.meta { margin-top: 10px; color: #667; font-size: 13px; }
.desc { margin-top: 16px; line-height: 1.6; }
/* 섹션 스타일 */
.section {
padding: 14px;
margin-bottom: 18px;
background: #fff;
border: 1px solid #e6eef8;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0,0,0,0.03);
}
.section h2 {
margin: 0 0 8px 0;
font-size: 18px;
}
/* modal */
.modal-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
justify-content: center;
align-items: center;
z-index: 999;
}
.modal {
background: #fff;
padding: 12px;
border-radius: 6px;
max-width: 90%;
max-height: 90%;
overflow: auto;
}
.modal img { max-width: 100%; height: auto; display: block; }
/* 스크롤바 커스텀: WebKit (Chrome, Safari, Edge) */
.content-scroll::-webkit-scrollbar {
width: 12px;
}
.content-scroll::-webkit-scrollbar-track {
background: #f0f4fb;
border-radius: 6px;
}
.content-scroll::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #93c5fd, #1976d2);
border-radius: 6px;
border: 3px solid #f0f4fb; /* thumb 둘레를 트랙과 분리 */
}
.sidebar::-webkit-scrollbar {
width: 8px;
}
.sidebar::-webkit-scrollbar-thumb {
background: rgba(100,120,150,0.3);
border-radius: 4px;
}
/* 파이어폭스용 스크롤바 색상 지정 */
@supports (scrollbar-color: red blue) {
.content-scroll {
scrollbar-width: thin;
scrollbar-color: #1976d2 #f0f4fb;
}
.sidebar {
scrollbar-width: thin;
scrollbar-color: rgba(100,120,150,0.3) transparent;
}
}
/* small screen */
@media (max-width: 700px) {
.container { flex-direction: column; }
.sidebar {
width: 100%;
height: 180px;
border-right: none;
border-bottom: 1px solid #e0e6ef;
}
.content { height: calc(100vh - 180px); }
}
</style>
</head>
<body>
<div class="container">
<aside class="sidebar">
<div class="search-box">
<input id="help-search" type="text" placeholder="검색어 입력 (예: 설치, 사용, 설정)">
</div>
<ul id="toc" class="toc"></ul>
</aside>
<main class="content">
<div class="content-scroll" id="content-scroll">
<h1 id="help-title" class="help-title">도움말</h1>
<img id="help-thumb" class="thumb" src="" alt="썸네일" style="display:none;" title="클릭하면 확대됨">
<div id="help-meta" class="meta"></div>
<!-- 섹션들이 이 안에 들어갑니다 -->
<div id="help-sections"></div>
<div id="help-desc" class="desc" style="display:none;"></div>
</div>
</main>
</div>
<!-- modal -->
<div id="modal-backdrop" class="modal-backdrop">
<div class="modal">
<img id="modal-img" src="" alt="상세 이미지">
</div>
</div>
<script>
// 예시 데이터: 각 도움말 항목에 여러 섹션을 포함
var helpData = [
{
id: "install",
title: "설치 방법",
thumb: "https://via.placeholder.com/640x360.png?text=설치+썸네일",
meta: "최종 수정: 2025-08-01 · 난이도: 기본",
sections: [
{sid: "install-1", title: "사전 준비", html: "<p>시스템 요구사항을 확인하세요. 최소 RAM 4GB 이상, 디스크 200MB 이상.</p>"},
{sid: "install-2", title: "설치 파일 다운로드", html: "<p>공식 사이트에서 설치 파일을 다운로드합니다.</p>"},
{sid: "install-3", title: "설치 과정", html: "<ol><li>다운로드한 파일 실행</li><li>설치 경로 선택</li><li>설치 완료 후 재시작</li></ol>"},
{sid: "install-4", title: "문제 해결 팁", html: "<p>권한 문제가 발생하면 관리자 권한으로 실행하십시오.</p>"}
]
},
{
id: "usage",
title: "기본 사용법",
thumb: "https://via.placeholder.com/640x360.png?text=기본+사용법+썸네일",
meta: "최종 수정: 2025-07-20 · 난이도: 초급",
sections: [
{sid: "usage-1", title: "새 문서 만들기", html: "<p>파일 → 새로 만들기 또는 단축키 Ctrl+N</p>"},
{sid: "usage-2", title: "저장", html: "<p>저장: Ctrl+S 또는 파일 → 저장</p>"},
{sid: "usage-3", title: "도움말 열기", html: "<p>도움말: F1</p>"}
]
},
{
id: "settings",
title: "환경 설정",
thumb: "https://via.placeholder.com/640x360.png?text=설정+썸네일",
meta: "최종 수정: 2025-06-10 · 난이도: 중급",
sections: [
{sid: "settings-1", title: "인터페이스", html: "<p>테마, 글꼴 크기 등을 변경할 수 있습니다.</p>"},
{sid: "settings-2", title: "언어 설정", html: "<p>한국어/영어 등 언어를 선택합니다.</p>"},
{sid: "settings-3", title: "업데이트", html: "<p>자동 업데이트를 켜거나 끌 수 있습니다.</p>"}
]
},
{
id: "long",
title: "매우 긴 도움말 예시",
thumb: "https://via.placeholder.com/640x360.png?text=긴+내용+썸네일",
meta: "최종 수정: 2025-08-25 · 난이도: 고급",
sections: (function(){
var s = [];
for (var i=1;i<=30;i++){
s.push({
sid: "long-"+i,
title: "긴 섹션 " + i,
html: "<p>문단 "+i+": Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus lacinia odio vitae vestibulum vestibulum.</p>"
});
}
return s;
})()
}
];
// 전체 TOC 렌더링 (목록에는 항목별 섹션 링크도 포함)
function renderTOC(list) {
var $toc = $("#toc");
$toc.empty();
list.forEach(function(item, idx){
var $li = $("<li>").attr("data-id", item.id);
var $title = $("<div>").text((idx+1)+". "+item.title);
$li.append($title);
// 각 항목의 섹션 목록(축소형) 추가
if (item.sections && item.sections.length) {
var $sub = $("<ul>").css({paddingLeft: "14px", marginTop: "8px"});
item.sections.forEach(function(sec){
var $sli = $("<li>")
.addClass("toc-sub")
.css({padding: "6px 4px", cursor: "pointer", fontSize: "13px", color:"#445"})
.attr("data-parent", item.id)
.attr("data-sid", sec.sid)
.text("· " + sec.title);
$sub.append($sli);
});
$li.append($sub);
}
$toc.append($li);
});
}
// 도움말 항목 표시: 섹션들을 DOM에 생성
function showHelp(id) {
var item = helpData.find(function(i){ return i.id === id; });
if (!item) return;
$("#help-title").text(item.title);
$("#help-meta").text(item.meta);
if (item.thumb) {
$("#help-thumb").attr("src", item.thumb).show();
} else {
$("#help-thumb").hide();
}
// 섹션들 렌더링
var $secWrap = $("#help-sections");
$secWrap.empty();
if (item.sections && item.sections.length) {
item.sections.forEach(function(sec){
var $sec = $("<div>").addClass("section").attr("id", sec.sid);
$sec.append($("<h2>").text(sec.title));
$sec.append($("<div>").html(sec.html));
$secWrap.append($sec);
});
} else {
$("#help-desc").show().html(item.desc || "");
}
// TOC 활성화 (상위 항목)
$("#toc li").removeClass("active");
$("#toc li[data-id='"+id+"']").addClass("active");
// 내용 스크롤을 맨 위로 이동
var $scroll = $("#content-scroll");
$scroll.stop().animate({scrollTop: 0}, 200);
}
// 특정 섹션으로 부드럽게 스크롤
function scrollToSection(sid) {
var $scroll = $("#content-scroll");
var $target = $("#" + sid);
if (!$target.length) return;
// 목표 요소의 offsetTop 상대값을 계산 (content-scroll 내부에서의 위치)
var targetOffset = $target.position().top; // position() 은 부모 상대 위치 반환
// 약간의 여백 추가
var scrollTo = $scroll.scrollTop() + targetOffset - 12;
$scroll.stop().animate({scrollTop: scrollTo}, 400);
}
// 검색(간단 필터)
function filterTOC(keyword) {
var kw = (keyword||"").trim().toLowerCase();
if (!kw) {
renderTOC(helpData);
return;
}
var filtered = helpData.filter(function(it){
var inTitle = it.title.toLowerCase().indexOf(kw) !== -1;
var inSections = (it.sections||[]).some(function(s){ return s.title.toLowerCase().indexOf(kw) !== -1 || s.html.toLowerCase().indexOf(kw) !== -1; });
return inTitle || inSections;
});
renderTOC(filtered);
}
$(function(){
renderTOC(helpData);
if (helpData.length) showHelp(helpData[0].id);
// 상위 항목 클릭: 항목 전체 표시
$(document).on("click", "#toc > li", function(e){
// 클릭이 서브 항목 쪽인지 필터
if ($(e.target).closest(".toc-sub").length) return;
var id = $(this).attr("data-id");
showHelp(id);
});
// 서브 섹션 클릭: 해당 섹션으로 내부 스크롤
$(document).on("click", ".toc-sub", function(){
var parentId = $(this).attr("data-parent");
var sid = $(this).attr("data-sid");
// 만약 현재 보이는 항목이 아니면 먼저 상위 항목 렌더
var activeId = $("#toc li.active").attr("data-id");
if (activeId !== parentId) {
showHelp(parentId);
// 렌더 후 약간의 지연을 두고 스크롤
setTimeout(function(){ scrollToSection(sid); }, 60);
} else {
scrollToSection(sid);
}
});
// 검색 입력
$("#help-search").on("input", function(){
filterTOC($(this).val());
});
// 썸네일 클릭 -> 모달 열기
$("#help-thumb").on("click", function(){
var src = $(this).attr("src");
$("#modal-img").attr("src", src);
$("#modal-backdrop").css("display","flex");
});
// 모달 닫기
$("#modal-backdrop").on("click", function(e){
if (e.target === this) {
$("#modal-backdrop").hide();
}
});
$(document).on("keydown", function(e){
if (e.key === "Escape") $("#modal-backdrop").hide();
});
});
</script>
</body>
</html>