테스트 사이트 - 개발 중인 베타 버전입니다

제가 초보라서 타이틀제목을 수정하려고 하는데 부탁드립니다. 채택완료

민규갤러리 11년 전 조회 5,050
9999000-12.gif
 
1번째 사이트 제목 타이틀 수정하려고하는데 도저히 못찾아서 그런데 어느 쪽을 수정해야 하는데 부탁드립니다.
 
00023.gif
2.수정이라는 빨간 게시판과 포이트충전 사이(ㅣ)에 색깔을 수정하려고 하는데 찾다 찾다 못찾아서 어디을 수정해야하는데
경로 부탁드립니다.
댓글을 작성하려면 로그인이 필요합니다.

답변 3개

채택된 답변
+20 포인트
A
11년 전
타이틀은 head.php 안에 </tile>안에 들어가는 글씨가 타이틀이 뒤구요.. <div> </div> <div>|는.. 그누보드 5이고 기본 세팅된 메뉴바라면 설치폴더 아래 /css/default.css에 있습니다..</div> </div> <!-- 좋아요/싫어요 및 액션 버튼 --> <div class="flex items-center justify-between pt-4 border-t border-gray-200 dark:border-gray-700"> <div class="flex items-center space-x-4"> <div class="text-sm text-gray-500 dark:text-gray-400"> 로그인 후 평가할 수 있습니다 </div> </div> </div> </div> <!-- 댓글 섹션 (답변 카드 안에 포함) --> <div class="mx-6 mb-6"> <div class="relative"> <!-- 연결선 표시 --> <div class="absolute -top-3 left-8 w-px h-6 bg-gradient-to-b from-gray-300 to-transparent dark:from-gray-600"></div> <div class="px-6 py-4 bg-gray-50 dark:bg-gray-900/50 rounded-lg border border-gray-200 dark:border-gray-700"> <!-- 댓글 목록 --> <!-- 디버깅: 답변 7978의 전체 댓글 구조 --> <!-- 댓글 수: 1, 대댓글 그룹 수: 0 --> <div class="mb-4"> <div class="flex items-center gap-2 mb-4"> <svg class="w-4 h-4 text-gray-600 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-4 4z"></path> </svg> <h4 class="text-sm font-semibold text-gray-700 dark:text-gray-300">답변에 대한 댓글 1개</h4> </div> <div class="space-y-3"> <div id="c_8021" class="relative "> <div class="bg-white dark:bg-gray-800 rounded-lg border border-gray-100 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600 transition-all duration-200"> <div class="p-4"> <div class="flex items-start justify-between mb-3"> <div class="flex items-center gap-3"> <div class="w-8 h-8 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white text-sm font-medium"> � </div> <div> <div class="font-medium text-sm text-gray-900 dark:text-white"> 민규갤러리 </div> <div class="text-xs text-gray-500 dark:text-gray-400" title="2014-01-21 (화) 11:53:14"> 11년 전 </div> </div> </div> </div> <div class="text-sm text-gray-700 dark:text-gray-300 comment-content leading-relaxed"> 감하합니다. 적용다 되었습니다.<br /> ㅣ는 head.php 파일에 있네요^^ <br /> /* menu styles */<br /> #jsddm{margin:0;padding:0;margin-left:5px;}<br /> #jsddm li{float:left;list-style:none;font-size:13px;font-family:Gulim;font- weight:bold;}<br /> #jsddm li a{display:block;background:none;padding:5px 30px 5px 12px;text- decoration:none;border-right:1px solid <br /> #72767a;width:auto;color:#eaffed;white-space:nowrap;}<br /> <br /> 감사합니다. 좋은 하루되세요^^ </div> <!-- 댓글 액션 버튼 --> <div class="flex items-center gap-2 mt-3 pt-2 border-t border-gray-100 dark:border-gray-700"> </div> <!-- 댓글 수정 폼 (숨김) --> <div class="comment-edit-form hidden mt-3"> <textarea class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm resize-none" rows="3" placeholder="댓글을 수정하세요...">감하합니다. 적용다 되었습니다. ㅣ는 head.php 파일에 있네요^^ /* menu styles */ #jsddm{margin:0;padding:0;margin-left:5px;} #jsddm li{float:left;list-style:none;font-size:13px;font-family:Gulim;font- weight:bold;} #jsddm li a{display:block;background:none;padding:5px 30px 5px 12px;text- decoration:none;border-right:1px solid #72767a;width:auto;color:#eaffed;white-space:nowrap;} 감사합니다. 좋은 하루되세요^^</textarea> <div class="flex justify-end gap-2 mt-2"> <button type="button" class="comment-save-btn px-3 py-1.5 bg-qa-btn-primary-bg-light hover:bg-qa-btn-primary-hover-light dark:bg-qa-btn-primary-bg-dark dark:hover:bg-qa-btn-primary-hover-dark text-white rounded-lg text-sm font-medium transition-colors" data-comment-id="8021">저장</button> <button type="button" class="comment-cancel-btn px-3 py-1.5 bg-gray-500 hover:bg-gray-600 text-white rounded-lg text-sm font-medium transition-colors">취소</button> </div> </div> <!-- 대댓글 작성 폼 (숨김) --> <div class="reply-form hidden mt-3 bg-gray-50 dark:bg-gray-700 rounded-lg p-3"> <div class="flex items-center gap-2 mb-2"> <svg class="w-3 h-3 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"></path> </svg> <span class="text-xs text-gray-600 dark:text-gray-300 reply-target"></span> </div> <form class="reply-form-element" data-parent-id="7978" data-comment-id="8021"> <input type="hidden" name="_token" value="6j7dRSpoACdxcXfh05SlivT6UXV6da7KvlGKqrQM" autocomplete="off"> <textarea name="wr_content" placeholder="답글을 작성하세요..." rows="2" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 dark:bg-gray-600 dark:text-white text-sm resize-none" required></textarea> <div class="flex justify-end gap-2 mt-2"> <button type="button" class="reply-cancel-btn px-3 py-1.5 bg-gray-500 hover:bg-gray-600 text-white rounded text-sm font-medium transition-colors">취소</button> <button type="submit" class="px-3 py-1.5 bg-qa-btn-primary-bg-light hover:bg-qa-btn-primary-hover-light dark:bg-qa-btn-primary-bg-dark dark:hover:bg-qa-btn-primary-hover-dark text-white rounded text-sm font-medium transition-colors">답글 등록</button> </div> </form> </div> </div> </div> </div> <!-- 대댓글 표시 --> <!-- 디버깅: 댓글 1, 답변ID 7978, 대댓글 있음: 아니오 --> </div> </div> <!-- 댓글 작성 폼 --> <div class="text-center py-3"> <p class="text-sm text-gray-500 dark:text-gray-400"> 댓글을 작성하려면 <a href="/login" class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">로그인</a>이 필요합니다. </p> </div> </div> </div> </div> </div> <div id="answer_272978" class="bg-white dark:bg-gray-800 rounded-xl shadow-sm hover:shadow-lg transition-all duration-300 overflow-hidden border border-gray-200 dark:border-gray-700"> <div class="p-6"> <!-- 답변 작성자 정보 --> <div class="flex items-center justify-between mb-5"> <div class="flex items-center space-x-4"> <div class="relative inline-block" style="width: 48px; height: 48px;"> <!-- SVG 아바타 사용 (기본값) --> <svg width="48" height="48" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="rounded-full"> <!-- 배경 원 (그라데이션) --> <defs> <linearGradient id="grad-avatar-69192a78e8ea57.90319832" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:hsl(50, 80%, 56%);stop-opacity:1" /> <stop offset="100%" style="stop-color:hsl(80, 80%, 51%);stop-opacity:1" /> </linearGradient> </defs> <circle cx="50" cy="50" r="50" fill="url(#grad-avatar-69192a78e8ea57.90319832)" /> <!-- 닉네임 첫 글자 --> <text x="50" y="50" font-size="45" fill="white" text-anchor="middle" dy=".35em" font-weight="bold" font-family="sans-serif"> 이 </text> </svg> </div> <div> <div class="flex items-center space-x-2"> <a href="https://new-sir.gnuboard.net/profile/caf9fb54-d958-4efd-a729-8327df80f5ae" class="font-semibold text-gray-900 dark:text-white hover:text-blue-600 dark:hover:text-blue-400 transition-colors"> 이오씨 </a> </div> <div class="text-sm text-gray-500 dark:text-gray-400">7년 전</div> </div> </div> <!-- 답변 액션 버튼들 --> <div class="flex items-center space-x-2"> </div> </div> <!-- 답변 내용 --> <div class="prose prose-lg max-w-none dark:prose-invert text-gray-800 dark:text-gray-200 leading-relaxed mb-6 qa-content"> <p>많은 도움이 되었습니다. 감사합니다.</p> </div> <!-- 좋아요/싫어요 및 액션 버튼 --> <div class="flex items-center justify-between pt-4 border-t border-gray-200 dark:border-gray-700"> <div class="flex items-center space-x-4"> <div class="text-sm text-gray-500 dark:text-gray-400"> 로그인 후 평가할 수 있습니다 </div> </div> </div> </div> <!-- 댓글 섹션 (답변 카드 안에 포함) --> <div class="mx-6 mb-6"> <div class="relative"> <!-- 연결선 표시 --> <div class="absolute -top-3 left-8 w-px h-6 bg-gradient-to-b from-gray-300 to-transparent dark:from-gray-600"></div> <div class="px-6 py-4 bg-gray-50 dark:bg-gray-900/50 rounded-lg border border-gray-200 dark:border-gray-700"> <!-- 댓글 목록 --> <!-- 디버깅: 답변 272978의 전체 댓글 구조 --> <!-- 댓글 작성 폼 --> <div class="text-center py-3"> <p class="text-sm text-gray-500 dark:text-gray-400"> 댓글을 작성하려면 <a href="/login" class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">로그인</a>이 필요합니다. </p> </div> </div> </div> </div> </div> <div id="answer_7983" class="bg-white dark:bg-gray-800 rounded-xl shadow-sm hover:shadow-lg transition-all duration-300 overflow-hidden border border-gray-200 dark:border-gray-700"> <div class="p-6"> <!-- 답변 작성자 정보 --> <div class="flex items-center justify-between mb-5"> <div class="flex items-center space-x-4"> <div class="relative inline-block" style="width: 48px; height: 48px;"> <!-- SVG 아바타 사용 (기본값) --> <svg width="48" height="48" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="rounded-full"> <!-- 배경 원 (그라데이션) --> <defs> <linearGradient id="grad-avatar-69192a78e924d5.70075119" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:hsl(90, 60%, 59%);stop-opacity:1" /> <stop offset="100%" style="stop-color:hsl(120, 60%, 54%);stop-opacity:1" /> </linearGradient> </defs> <circle cx="50" cy="50" r="50" fill="url(#grad-avatar-69192a78e924d5.70075119)" /> <!-- 닉네임 첫 글자 --> <text x="50" y="50" font-size="45" fill="white" text-anchor="middle" dy=".35em" font-weight="bold" font-family="sans-serif"> f </text> </svg> </div> <div> <div class="flex items-center space-x-2"> <a href="https://new-sir.gnuboard.net/profile/90a9feaf-efeb-41f2-bcba-4a4bdb2e604b" class="font-semibold text-gray-900 dark:text-white hover:text-blue-600 dark:hover:text-blue-400 transition-colors"> fm25 </a> </div> <div class="text-sm text-gray-500 dark:text-gray-400">11년 전</div> </div> </div> <!-- 답변 액션 버튼들 --> <div class="flex items-center space-x-2"> </div> </div> <!-- 답변 내용 --> <div class="prose prose-lg max-w-none dark:prose-invert text-gray-800 dark:text-gray-200 leading-relaxed mb-6 qa-content"> 2. 그림 파일이 아닐까 싶습니다. 이미지 폴더를 찾아보세요. </div> <!-- 좋아요/싫어요 및 액션 버튼 --> <div class="flex items-center justify-between pt-4 border-t border-gray-200 dark:border-gray-700"> <div class="flex items-center space-x-4"> <div class="text-sm text-gray-500 dark:text-gray-400"> 로그인 후 평가할 수 있습니다 </div> </div> </div> </div> <!-- 댓글 섹션 (답변 카드 안에 포함) --> <div class="mx-6 mb-6"> <div class="relative"> <!-- 연결선 표시 --> <div class="absolute -top-3 left-8 w-px h-6 bg-gradient-to-b from-gray-300 to-transparent dark:from-gray-600"></div> <div class="px-6 py-4 bg-gray-50 dark:bg-gray-900/50 rounded-lg border border-gray-200 dark:border-gray-700"> <!-- 댓글 목록 --> <!-- 디버깅: 답변 7983의 전체 댓글 구조 --> <!-- 댓글 작성 폼 --> <div class="text-center py-3"> <p class="text-sm text-gray-500 dark:text-gray-400"> 댓글을 작성하려면 <a href="/login" class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">로그인</a>이 필요합니다. </p> </div> </div> </div> </div> </div> </div> <!-- 답변 페이징 --> </div> <!-- Error Messages --> <!-- Answer Form --> <div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-6 text-center"> <p class="text-gray-600 dark:text-gray-400 mb-4">답변을 작성하려면 로그인이 필요합니다.</p> <a href="https://new-sir.gnuboard.net/login?redirect=https%3A%2F%2Fnew-sir.gnuboard.net%2Fquestions%2F7902" class="inline-block px-6 py-2 bg-qa-btn-primary-bg-light dark:bg-qa-btn-primary-bg-dark hover:bg-qa-btn-primary-hover-light dark:hover:bg-qa-btn-primary-hover-dark text-qa-btn-primary-text-light dark:text-qa-btn-primary-text-dark rounded-lg transition-colors"> 로그인 </a> </div> </div> <!-- Sidebar Component --> <!-- Sidebar --> <aside class="hidden lg:block w-80 flex-shrink-0 self-start"> <!-- 지금 질문하기 버튼 --> <div class="mb-4"> <a href="https://new-sir.gnuboard.net/questions/create" class="flex items-center justify-center gap-2 w-full px-4 py-3 bg-gradient-to-r from-qa-gradient-from-light to-qa-gradient-to-light dark:from-qa-gradient-from-dark dark:to-qa-primary-dark hover:from-qa-accent-light hover:to-qa-primary-light dark:hover:from-qa-primary-dark dark:hover:to-qa-gradient-to-dark text-qa-btn-primary-text-light dark:text-qa-btn-primary-text-dark font-medium rounded-lg shadow-md transition-all duration-200"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path> </svg> 지금 질문하기 </a> </div> <!-- 질문하는방법 --> <div class="bg-qa-card-bg-light dark:bg-qa-card-bg-dark rounded-lg shadow-sm p-6 mb-4"> <h3 class="text-lg font-bold text-qa-heading-light dark:text-qa-heading-dark mb-4"> <a href="https://new-sir.gnuboard.net/questions/howto" class="hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark transition-colors"> 질문하는방법 </a> </h3> <div class="space-y-3 text-sm"> <div class="flex justify-between items-center"> <a href="https://new-sir.gnuboard.net/questions" class="text-qa-link-light dark:text-qa-link-dark hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark">모든질문</a> <span class="font-semibold text-qa-heading-light dark:text-qa-heading-dark">129,285</span> </div> <div class="flex justify-between items-center"> <a href="https://new-sir.gnuboard.net/questions?unanswered=1" class="text-qa-link-light dark:text-qa-link-dark hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark">답변없는질문</a> <span class="font-semibold text-qa-heading-light dark:text-qa-heading-dark">8</span> </div> <div class="flex justify-between items-center"> <a href="https://new-sir.gnuboard.net/questions?unadopted=1" class="text-qa-link-light dark:text-qa-link-dark hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark">미채택된질문</a> <span class="font-semibold text-qa-heading-light dark:text-qa-heading-dark">18,376</span> </div> <div class="flex justify-between items-center"> <a href="https://new-sir.gnuboard.net/questions?adopted=1" class="text-qa-link-light dark:text-qa-link-dark hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark">채택된질문</a> <span class="font-semibold text-qa-heading-light dark:text-qa-heading-dark">101,681</span> </div> </div> <h4 class="text-sm font-semibold text-qa-heading-light dark:text-qa-heading-dark mt-6 mb-3">모든답변</h4> <div class="space-y-3 text-sm"> <div class="flex items-center gap-2"> <span class="inline-flex items-center justify-center w-6 h-6 bg-qa-icon-badge-bg-light dark:bg-qa-icon-badge-bg-dark text-xs font-medium text-qa-icon-badge-text-light dark:text-qa-icon-badge-text-dark rounded">5</span> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C5" class="text-qa-link-light dark:text-qa-link-dark hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark">그누보드5</a> <span class="ml-auto font-semibold text-qa-heading-light dark:text-qa-heading-dark">62,905</span> </div> <div class="flex justify-between items-center pl-8"> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%98%81%EC%B9%B4%ED%8A%B85" class="text-qa-link-light dark:text-qa-link-dark hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark">영카트5</a> <span class="font-semibold text-qa-heading-light dark:text-qa-heading-dark">17,535</span> </div> </div> <h4 class="text-sm font-semibold text-qa-heading-light dark:text-qa-heading-dark mt-6 mb-3"> <a href="https://new-sir.gnuboard.net/questions/tags" class="hover:text-qa-link-hover-light dark:hover:text-qa-link-hover-dark transition-colors"> 태그전체보기 </a> </h4> <div class="space-y-3 text-sm"> </div> </div> <!-- 관심태그 --> <div class="bg-qa-card-bg-light dark:bg-qa-card-bg-dark rounded-lg shadow-sm p-6 mb-4"> <h3 class="text-lg font-bold text-qa-heading-light dark:text-qa-heading-dark mb-4">관심태그</h3> <div class="flex flex-wrap gap-2"> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%98%81%EC%B9%B4%ED%8A%B85" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #영카트5 </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C4" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누보드4 </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%98%81%EC%B9%B4%ED%8A%B84" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #영카트4 </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%A0%95%EA%B7%9C%EC%8B%9D" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #정규식 </a> <a href="https://new-sir.gnuboard.net/questions?tag=%ED%85%8C%EB%A7%88" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #테마 </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C5" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누보드5 </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EB%84%A4%EC%9D%B4%EB%B2%84%ED%8E%98%EC%9D%B4" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #네이버페이 </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EC%BB%A4%EB%A8%B8%EC%8A%A4" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누커머스 </a> <a href="https://new-sir.gnuboard.net/questions?tag=php" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #php </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C6" class="inline-flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-full transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누보드6 </a> </div> </div> <!-- 인기태그 --> <div class="bg-qa-card-bg-light dark:bg-qa-card-bg-dark rounded-lg shadow-sm p-6"> <h3 class="text-lg font-bold text-qa-heading-light dark:text-qa-heading-dark mb-4">인기태그</h3> <div class="flex flex-wrap gap-2"> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C5" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누보드5 <span class="text-[10px] opacity-75">(62,905)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%98%81%EC%B9%B4%ED%8A%B85" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #영카트5 <span class="text-[10px] opacity-75">(17,535)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=php" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #php <span class="text-[10px] opacity-75">(15,830)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C4" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누보드4 <span class="text-[10px] opacity-75">(10,649)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B2%8C%EC%8B%9C%ED%8C%90" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #게시판 <span class="text-[10px] opacity-75">(3,273)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=javascript" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #javascript <span class="text-[10px] opacity-75">(2,678)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EB%B3%B4%EB%93%9C" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누보드 <span class="text-[10px] opacity-75">(2,463)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=css" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #css <span class="text-[10px] opacity-75">(2,129)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=mysql" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #mysql <span class="text-[10px] opacity-75">(1,556)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%98%81%EC%B9%B4%ED%8A%B8" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #영카트 <span class="text-[10px] opacity-75">(1,295)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EB%AA%A8%EB%B0%94%EC%9D%BC" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #모바일 <span class="text-[10px] opacity-75">(1,293)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EA%B7%B8%EB%88%84%EC%BB%A4%EB%A8%B8%EC%8A%A4" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-interest-bg-light dark:bg-qa-tag-interest-bg-dark text-qa-tag-interest-text-light dark:text-qa-tag-interest-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #그누커머스 <span class="text-[10px] opacity-75">(1,178)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=html" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #html <span class="text-[10px] opacity-75">(1,133)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=jquery" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #jquery <span class="text-[10px] opacity-75">(1,027)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%B5%9C%EC%8B%A0%EA%B8%80" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #최신글 <span class="text-[10px] opacity-75">(970)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #자바스크립트 <span class="text-[10px] opacity-75">(953)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=DB" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #DB <span class="text-[10px] opacity-75">(850)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EB%A1%9C%EA%B7%B8%EC%9D%B8" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #로그인 <span class="text-[10px] opacity-75">(821)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%9D%B4%EB%AF%B8%EC%A7%80" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #이미지 <span class="text-[10px] opacity-75">(785)</span> </a> <a href="https://new-sir.gnuboard.net/questions?tag=%EC%97%AC%EB%B6%84%ED%95%84%EB%93%9C" class="inline-flex items-center gap-1 px-2.5 py-1 text-xs rounded transition-colors bg-qa-tag-bg-light dark:bg-qa-tag-bg-dark text-qa-tag-text-light dark:text-qa-tag-text-dark hover:bg-qa-tag-hover-light dark:hover:bg-qa-tag-hover-dark " title="태그 추가"> #여분필드 <span class="text-[10px] opacity-75">(784)</span> </a> </div> </div> </aside> </div> </div> <!-- Share Modal --> <div id="share-modal" class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden"> <div class="flex items-center justify-center min-h-screen p-4"> <div class="bg-white dark:bg-gray-800 rounded-lg max-w-md w-full p-6"> <div class="flex items-center justify-between mb-4"> <h3 class="text-lg font-medium text-gray-900 dark:text-white">공유하기</h3> <button onclick="closeShareModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> </svg> </button> </div> <div class="flex items-center gap-4"> <a href="#" id="facebook-share" target="_blank" class="flex items-center justify-center w-12 h-12 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"> <i class="fa fa-facebook"></i> </a> <a href="#" id="twitter-share" target="_blank" class="flex items-center justify-center w-12 h-12 bg-blue-400 text-white rounded-lg hover:bg-blue-500 transition-colors"> <i class="fa fa-twitter"></i> </a> <button onclick="copyToClipboard()" class="flex items-center justify-center w-12 h-12 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors"> <i class="fa fa-link"></i> </button> </div> </div> </div> </div> <!-- 신고 모달 다이얼로그 --> <div id="sir_react_singod" style="display: none;"> <p>이 게시물을 신고 하시겠습니까?<br>신고사유를 선택해주세요.</p> <ul class="space-y-2"> <li> <input type="radio" name="rdo_reason" id="rdo_reason_ad" value="광고"> <label for="rdo_reason_ad" class="ml-2">광고성 게시물</label> </li> <li> <input type="radio" name="rdo_reason" id="rdo_reason_ob" value="음란"> <label for="rdo_reason_ob" class="ml-2">음란성 게시물</label> </li> <li> <input type="radio" name="rdo_reason" id="rdo_reason_ha" value="혐오"> <label for="rdo_reason_ha" class="ml-2">상대방 비방 및 혐오</label> </li> <li> <input type="radio" name="rdo_reason" id="rdo_reason_etc" value="기타"> <label for="rdo_reason_etc" class="ml-2">기타</label> <div class="mt-2"> <label for="sg_reason" class="block text-sm text-gray-600 dark:text-gray-400">기타 신고사유</label> <input type="text" name="sg_reason" id="sg_reason" class="mt-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white" placeholder="10글자 이상 입력해주세요"> </div> </li> </ul> </div> <script> document.addEventListener('DOMContentLoaded', function() { // 좋아요 기능 const voteGoodBtn = document.getElementById('vote-good-btn'); if (voteGoodBtn) { voteGoodBtn.addEventListener('click', function() { const wrId = this.dataset.wrId; const countSpan = this.querySelector('.vote-good-count'); const textSpan = this.querySelector('.vote-good-text'); const isVoted = textSpan.textContent === '좋아요됨'; if (this.disabled) return; this.disabled = true; this.classList.add('opacity-50'); fetch(`/questions/${wrId}/vote`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ type: 'good' }) }) .then(response => response.json()) .then(data => { if (data.success) { countSpan.textContent = data.good_count; if (data.user_vote === null) { // 취소된 경우 textSpan.textContent = '좋아요'; this.classList.remove('bg-blue-100', 'dark:bg-blue-900', 'text-blue-700', 'dark:text-blue-300'); this.classList.add('bg-green-100', 'dark:bg-green-900', 'text-green-700', 'dark:text-green-300', 'hover:bg-green-200', 'dark:hover:bg-green-800'); } else { // 투표된 경우 textSpan.textContent = '좋아요됨'; this.classList.remove('bg-green-100', 'dark:bg-green-900', 'text-green-700', 'dark:text-green-300', 'hover:bg-green-200', 'dark:hover:bg-green-800'); this.classList.add('bg-blue-100', 'dark:bg-blue-900', 'text-blue-700', 'dark:text-blue-300'); } console.log('Success message:', data.message); showMessage(data.message, 'success'); } else { console.log('Error message:', data.error); showMessage(data.error || '좋아요에 실패했습니다.', 'error'); } this.disabled = false; this.classList.remove('opacity-50'); }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); this.disabled = false; this.classList.remove('opacity-50'); }); }); } // 싫어요 기능 const voteNogoodBtn = document.getElementById('vote-nogood-btn'); if (voteNogoodBtn) { voteNogoodBtn.addEventListener('click', function() { const wrId = this.dataset.wrId; const countSpan = this.querySelector('.vote-nogood-count'); const textSpan = this.querySelector('.vote-nogood-text'); const isVoted = textSpan.textContent === '싫어요됨'; if (this.disabled) return; this.disabled = true; this.classList.add('opacity-50'); fetch(`/questions/${wrId}/vote`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ type: 'nogood' }) }) .then(response => response.json()) .then(data => { if (data.success) { countSpan.textContent = data.nogood_count; if (data.user_vote === null) { // 취소된 경우 textSpan.textContent = '싫어요'; this.classList.remove('bg-orange-100', 'dark:bg-orange-900', 'text-orange-700', 'dark:text-orange-300'); this.classList.add('bg-red-100', 'dark:bg-red-900', 'text-red-700', 'dark:text-red-300', 'hover:bg-red-200', 'dark:hover:bg-red-800'); } else { // 투표된 경우 textSpan.textContent = '싫어요됨'; this.classList.remove('bg-red-100', 'dark:bg-red-900', 'text-red-700', 'dark:text-red-300', 'hover:bg-red-200', 'dark:hover:bg-red-800'); this.classList.add('bg-orange-100', 'dark:bg-orange-900', 'text-orange-700', 'dark:text-orange-300'); } console.log('Success message:', data.message); showMessage(data.message, 'success'); } else { console.log('Error message:', data.error); showMessage(data.error || '싫어요에 실패했습니다.', 'error'); } this.disabled = false; this.classList.remove('opacity-50'); }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); this.disabled = false; this.classList.remove('opacity-50'); }); }); } // 스크랩 기능 const scrapBtn = document.getElementById('scrap-btn'); if (scrapBtn) { scrapBtn.addEventListener('click', function() { const wrId = this.dataset.wrId; const countSpan = this.querySelector('.scrap-count'); this.disabled = true; this.classList.add('opacity-50'); fetch(`/questions/${wrId}/scrap`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.success) { countSpan.textContent = `(${data.count})`; const textSpan = this.querySelector('.scrap-text'); const iconSpan = this.querySelector('i'); // 스크랩된 상태로 변경 textSpan.textContent = '스크랩됨'; iconSpan.className = 'fa fa-bookmark mr-1'; this.classList.remove('bg-gray-100', 'dark:bg-gray-700', 'text-gray-700', 'dark:text-gray-300', 'hover:bg-gray-200', 'dark:hover:bg-gray-600'); this.classList.add('bg-yellow-100', 'dark:bg-yellow-900', 'text-yellow-700', 'dark:text-yellow-300'); // 스크랩 후 버튼 비활성화 this.disabled = true; showMessage(data.message, 'success'); } else { showMessage(data.error || '스크랩에 실패했습니다.', 'error'); } this.disabled = false; this.classList.remove('opacity-50'); }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); this.disabled = false; this.classList.remove('opacity-50'); }); }); } // 신고 기능 document.querySelectorAll('button[id^=qa_singo-]').forEach(button => { button.addEventListener('click', function() { const idParts = this.id.split('-'); const bo_table = idParts[1]; const wr_id = idParts[2]; const radios_reason = ["#rdo_reason_ad", "#rdo_reason_ob", "#rdo_reason_ha", "#rdo_reason_etc"]; // 모달 다이얼로그 표시 const modal = document.getElementById('sir_react_singod'); modal.style.display = 'block'; modal.style.position = 'fixed'; modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.backgroundColor = 'white'; modal.style.padding = '20px'; modal.style.borderRadius = '8px'; modal.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)'; modal.style.zIndex = '1000'; modal.style.minWidth = '400px'; // 배경 오버레이 const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; overlay.style.zIndex = '999'; document.body.appendChild(overlay); // 신고하기 버튼 const reportBtn = document.createElement('button'); reportBtn.textContent = '신고하기'; reportBtn.className = 'px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 mr-2'; reportBtn.addEventListener('click', function() { let r_checked = false; let reason = ''; radios_reason.forEach(radioId => { if (document.querySelector(radioId).checked) { r_checked = true; if (radioId === '#rdo_reason_etc') { const customReason = document.getElementById('sg_reason').value.trim(); if (customReason.length < 10) { alert('기타 선택시 신고사유를 10글자 이상 입력하십시오.'); return; } reason = customReason; } else { reason = document.querySelector(radioId).value; } } }); if (!r_checked) { alert('신고사유를 선택하세요.'); return; } // 신고 요청 fetch(`/questions/${wr_id}/singo`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ bo_table: bo_table, reason: reason, q_mode: 'singo' }) }) .then(response => response.json()) .then(data => { if (data.error) { alert(data.error); return; } // 모달 닫기 modal.style.display = 'none'; document.body.removeChild(overlay); // 신고 카운트 업데이트 const countElement = document.querySelector(`#qa_singo-${bo_table}-${wr_id} .singo-count`); if (countElement) { countElement.textContent = data.count; } // 버튼 비활성화 button.disabled = true; button.classList.add('opacity-50'); alert(data.message); }) .catch(error => { console.error('Error:', error); alert('신고 처리 중 오류가 발생했습니다.'); }); }); // 취소 버튼 const cancelBtn = document.createElement('button'); cancelBtn.textContent = '취소'; cancelBtn.className = 'px-4 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600'; cancelBtn.addEventListener('click', function() { modal.style.display = 'none'; document.body.removeChild(overlay); }); // 기존 버튼들 제거 const existingButtons = modal.querySelectorAll('button'); existingButtons.forEach(btn => btn.remove()); // 버튼들 추가 const buttonContainer = document.createElement('div'); buttonContainer.className = 'mt-4 text-right'; buttonContainer.appendChild(reportBtn); buttonContainer.appendChild(cancelBtn); modal.appendChild(buttonContainer); // 오버레이 클릭 시 닫기 overlay.addEventListener('click', function() { modal.style.display = 'none'; document.body.removeChild(overlay); }); }); }); // 공유 기능 const shareBtn = document.getElementById('share-btn'); if (shareBtn) { shareBtn.addEventListener('click', function() { const shareModal = document.getElementById('share-modal'); const currentUrl = window.location.href; const title = document.title; // SNS 공유 링크 설정 const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(currentUrl)}`; const twitterUrl = `https://twitter.com/intent/tweet?url=${encodeURIComponent(currentUrl)}&text=${encodeURIComponent(title)}`; document.getElementById('facebook-share').href = facebookUrl; document.getElementById('twitter-share').href = twitterUrl; shareModal.classList.remove('hidden'); }); } // 메시지 표시 함수 }); // 공유 모달 닫기 function closeShareModal() { document.getElementById('share-modal').classList.add('hidden'); } // 클립보드에 복사 function copyToClipboard() { navigator.clipboard.writeText(window.location.href).then(function() { showMessage('링크가 클립보드에 복사되었습니다.', 'success'); closeShareModal(); }); } // Image preview function function previewImage(imageUrl, filename) { // Create modal overlay const overlay = document.createElement('div'); overlay.className = 'fixed inset-0 bg-black bg-opacity-75 z-50 flex items-center justify-center p-4'; overlay.onclick = function() { document.body.removeChild(overlay); }; // Create modal content const modal = document.createElement('div'); modal.className = 'bg-white dark:bg-gray-800 rounded-lg max-w-4xl max-h-full overflow-auto'; modal.onclick = function(e) { e.stopPropagation(); }; modal.innerHTML = ` <div class="p-4 border-b border-gray-200 dark:border-gray-700"> <div class="flex items-center justify-between"> <h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">${filename}</h3> <button onclick="document.body.removeChild(this.closest('.fixed'))" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"> <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> </svg> </button> </div> </div> <div class="p-4"> <img src="${imageUrl}" alt="${filename}" class="max-w-full h-auto rounded-lg shadow-lg"> </div> `; overlay.appendChild(modal); document.body.appendChild(overlay); } // 메시지 표시 함수 function showMessage(message, type = 'info') { console.log('showMessage called:', message, type); // 기존 메시지 제거 const existingMessage = document.querySelector('.message-toast'); if (existingMessage) { existingMessage.remove(); } // 새 메시지 생성 const messageDiv = document.createElement('div'); messageDiv.className = 'message-toast fixed top-4 right-4 z-50 px-6 py-3 rounded-lg shadow-lg transition-all duration-300'; if (type === 'success') { messageDiv.className += ' bg-green-500 text-white'; } else if (type === 'error') { messageDiv.className += ' bg-red-500 text-white'; } else { messageDiv.className += ' bg-blue-500 text-white'; } messageDiv.textContent = message; document.body.appendChild(messageDiv); console.log('Message displayed:', messageDiv); // 3초 후 자동 제거 setTimeout(() => { if (messageDiv.parentNode) { messageDiv.style.opacity = '0'; messageDiv.style.transform = 'translateX(100%)'; setTimeout(() => { if (messageDiv.parentNode) { messageDiv.parentNode.removeChild(messageDiv); } }, 300); } }, 3000); } // 답변 작성 폼 처리 document.addEventListener('DOMContentLoaded', function() { // 답변 작성 폼 const answerForm = document.getElementById('answer-form-element'); if (answerForm) { answerForm.addEventListener('submit', function(e) { e.preventDefault(); // 기본 폼 제출 방지 // 중복 제출 방지 const submitBtn = this.querySelector('button[type="submit"]'); if (submitBtn.disabled) { return; } // 버튼 비활성화 submitBtn.disabled = true; submitBtn.textContent = '등록 중...'; // CKEditor 내용 가져오기 const content = CKEDITOR.instances.wr_content ? CKEDITOR.instances.wr_content.getData() : ''; // FormData 생성 const formData = new FormData(); formData.append('_token', document.querySelector('input[name="_token"]').value); formData.append('wr_qa_id', document.querySelector('input[name="wr_qa_id"]').value); formData.append('wr_content', content); // AJAX 요청 fetch('https://new-sir.gnuboard.net/questions/answer', { method: 'POST', body: formData, headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } }) .then(response => response.json()) .then(data => { if (data.success) { // 성공 메시지 표시 showMessage('답변이 등록되었습니다.', 'success'); // 페이지 새로고침하여 새 답변 표시 window.location.reload(); } else { // 에러 메시지 표시 showMessage(data.message || '답변 등록 중 오류가 발생했습니다.', 'error'); // 버튼 복원 submitBtn.disabled = false; submitBtn.textContent = '답변 등록'; } }) .catch(error => { console.error('Error:', error); showMessage('답변 등록 중 오류가 발생했습니다.', 'error'); // 버튼 복원 submitBtn.disabled = false; submitBtn.textContent = '답변 등록'; }); }); } // URL 프래그먼트 처리 function handleFragment() { const hash = window.location.hash; if (hash === '#new-answer') { // URL에서 프래그먼트 제거 (히스토리 정리) history.replaceState(null, null, window.location.pathname + window.location.search); setTimeout(() => { // 답변 목록에서 가장 최근 답변 찾기 const answers = document.querySelectorAll('.answer-item'); if (answers.length > 0) { const lastAnswer = answers[answers.length - 1]; lastAnswer.scrollIntoView({ behavior: 'smooth', block: 'start' }); // 새 답변에 하이라이트 효과 추가 lastAnswer.style.backgroundColor = '#fef3c7'; lastAnswer.style.transition = 'background-color 0.3s ease'; setTimeout(() => { lastAnswer.style.backgroundColor = ''; }, 3000); } }, 500); } } // 페이지 로드 시 프래그먼트 처리 handleFragment(); // 해시 변경 이벤트 리스너 (브라우저 뒤로가기/앞으로가기 대응) window.addEventListener('hashchange', handleFragment); }); // 답변 좋아요/싫어요 기능 document.addEventListener('DOMContentLoaded', function() { // 답변 좋아요 버튼 document.querySelectorAll('.vote-good-btn').forEach(button => { if (button.id !== 'vote-good-btn') { // 질문 좋아요 버튼 제외 button.addEventListener('click', function() { const wrId = this.dataset.wrId; const countSpan = this.querySelector('.vote-good-count'); const textSpan = this.querySelector('.vote-good-text'); const isVoted = textSpan.textContent === '좋아요됨'; if (this.disabled) return; this.disabled = true; this.classList.add('opacity-50'); fetch(`/questions/${wrId}/vote`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ type: 'good' }) }) .then(response => response.json()) .then(data => { if (data.success) { countSpan.textContent = data.good_count; if (data.user_vote === null) { // 취소된 경우 textSpan.textContent = '좋아요'; this.classList.remove('bg-blue-100', 'dark:bg-blue-700', 'text-blue-700', 'dark:text-blue-300'); this.classList.add('bg-gray-100', 'dark:bg-gray-700', 'text-gray-700', 'dark:text-gray-300', 'hover:bg-gray-200', 'dark:hover:bg-gray-600'); } else { // 투표된 경우 textSpan.textContent = '좋아요됨'; this.classList.remove('bg-gray-100', 'dark:bg-gray-700', 'text-gray-700', 'dark:text-gray-300', 'hover:bg-gray-200', 'dark:hover:bg-gray-600'); this.classList.add('bg-blue-100', 'dark:bg-blue-700', 'text-blue-700', 'dark:text-blue-300'); } showMessage(data.message, 'success'); } else { showMessage(data.error || '좋아요에 실패했습니다.', 'error'); } this.disabled = false; this.classList.remove('opacity-50'); }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); this.disabled = false; this.classList.remove('opacity-50'); }); }); } }); // 답변 싫어요 버튼 document.querySelectorAll('.vote-nogood-btn').forEach(button => { if (button.id !== 'vote-nogood-btn') { // 질문 싫어요 버튼 제외 button.addEventListener('click', function() { const wrId = this.dataset.wrId; const countSpan = this.querySelector('.vote-nogood-count'); const textSpan = this.querySelector('.vote-nogood-text'); const isVoted = textSpan.textContent === '싫어요됨'; if (this.disabled) return; this.disabled = true; this.classList.add('opacity-50'); fetch(`/questions/${wrId}/vote`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ type: 'nogood' }) }) .then(response => response.json()) .then(data => { if (data.error === '') { countSpan.textContent = data.count; if (data.cancle_vote === 'cancle') { // 취소된 경우 textSpan.textContent = '싫어요'; this.classList.remove('bg-orange-100', 'dark:bg-orange-700', 'text-orange-700', 'dark:text-orange-300'); this.classList.add('bg-gray-100', 'dark:bg-gray-700', 'text-gray-700', 'dark:text-gray-300', 'hover:bg-gray-200', 'dark:hover:bg-gray-600'); } else { // 투표된 경우 textSpan.textContent = '싫어요됨'; this.classList.remove('bg-gray-100', 'dark:bg-gray-700', 'text-gray-700', 'dark:text-gray-300', 'hover:bg-gray-200', 'dark:hover:bg-gray-600'); this.classList.add('bg-orange-100', 'dark:bg-orange-700', 'text-orange-700', 'dark:text-orange-300'); } showMessage(data.message, 'success'); } else { showMessage(data.error || '싫어요에 실패했습니다.', 'error'); } this.disabled = false; this.classList.remove('opacity-50'); }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); this.disabled = false; this.classList.remove('opacity-50'); }); }); } }); // 채택 버튼 document.querySelectorAll('.adopt-btn').forEach(button => { button.addEventListener('click', function() { const questionId = this.dataset.questionId; const answerId = this.dataset.answerId; if (!confirm('이 답변을 채택하시겠습니까?\n\n채택된 답변은 변경할 수 없습니다.')) { return; } fetch(`/questions/${questionId}/adopt/${answerId}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } }) .then(response => response.json()) .then(data => { if (data.success) { showMessage(data.message, 'success'); // 페이지 새로고침하여 채택 상태 반영 setTimeout(() => { location.reload(); }, 1500); } else { showMessage(data.error || '채택에 실패했습니다.', 'error'); } }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); }); }); }); // 채택 취소 버튼 document.querySelectorAll('.unadopt-btn').forEach(button => { button.addEventListener('click', function() { const questionId = this.dataset.questionId; if (!confirm('채택을 취소하시겠습니까?\n\n채택된 답변 작성자에게 지급된 포인트가 회수됩니다.')) { return; } fetch(`/questions/${questionId}/unadopt`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } }) .then(response => response.json()) .then(data => { if (data.success) { showMessage(data.message, 'success'); // 페이지 새로고침하여 채택 취소 상태 반영 setTimeout(() => { location.reload(); }, 1500); } else { showMessage(data.error || '채택 취소에 실패했습니다.', 'error'); } }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); }); }); }); // 댓글 작성 document.querySelectorAll('.comment-form-element').forEach(form => { form.addEventListener('submit', function(e) { e.preventDefault(); // 중복 제출 방지 const submitBtn = this.querySelector('button[type="submit"]'); if (submitBtn.disabled) { return; } const parentId = this.dataset.parentId; const content = this.querySelector('textarea[name="wr_content"]').value.trim(); if (!content) { showMessage('댓글 내용을 입력해주세요.', 'error'); return; } // 버튼 비활성화 submitBtn.disabled = true; submitBtn.textContent = '등록 중...'; const formData = new FormData(); formData.append('wr_qa_id', parentId); formData.append('wr_content', content); formData.append('_token', document.querySelector('meta[name="csrf-token"]').getAttribute('content')); fetch('/questions/comment', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.success) { showMessage(data.message, 'success'); // 페이지 새로고침하여 댓글 반영 setTimeout(() => { location.reload(); }, 1000); } else { showMessage(data.error || '댓글 등록에 실패했습니다.', 'error'); // 실패 시 버튼 다시 활성화 submitBtn.disabled = false; submitBtn.textContent = '댓글 등록'; } }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); // 오류 시 버튼 다시 활성화 submitBtn.disabled = false; submitBtn.textContent = '댓글 등록'; }); }); }); // 댓글 수정 document.querySelectorAll('.edit-comment-btn').forEach(button => { button.addEventListener('click', function() { const commentContainer = this.closest('.relative'); const commentContent = commentContainer.querySelector('.comment-content'); const editForm = commentContainer.querySelector('.comment-edit-form'); const textarea = editForm.querySelector('textarea'); // 편집 모드로 전환 commentContent.classList.add('hidden'); editForm.classList.remove('hidden'); textarea.focus(); }); }); // 댓글 저장 document.querySelectorAll('.comment-save-btn').forEach(button => { button.addEventListener('click', function() { const commentId = this.dataset.commentId; const commentContainer = this.closest('.relative'); const textarea = commentContainer.querySelector('textarea'); const newContent = textarea.value.trim(); if (!newContent) { showMessage('댓글 내용을 입력해주세요.', 'error'); return; } fetch(`/questions/comment/${commentId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }, body: JSON.stringify({ wr_content: newContent }) }) .then(response => response.json()) .then(data => { if (data.success) { showMessage(data.message, 'success'); // 페이지 새로고침하여 수정된 댓글 반영 setTimeout(() => { location.reload(); }, 1000); } else { showMessage(data.error || '댓글 수정에 실패했습니다.', 'error'); } }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); }); }); }); // 댓글 수정 취소 document.querySelectorAll('.comment-cancel-btn').forEach(button => { button.addEventListener('click', function() { const commentContainer = this.closest('.relative'); const commentContent = commentContainer.querySelector('.comment-content'); const editForm = commentContainer.querySelector('.comment-edit-form'); const textarea = editForm.querySelector('textarea'); // 원래 내용으로 복원 textarea.value = commentContent.textContent.trim(); // 편집 모드 해제 editForm.classList.add('hidden'); commentContent.classList.remove('hidden'); }); }); // 댓글 삭제 document.querySelectorAll('.delete-comment-btn').forEach(button => { button.addEventListener('click', function() { const commentId = this.dataset.commentId; if (!confirm('정말로 이 댓글을 삭제하시겠습니까?')) { return; } fetch(`/questions/comment/${commentId}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } }) .then(response => response.json()) .then(data => { if (data.success) { showMessage(data.message, 'success'); // 페이지 새로고침하여 삭제된 댓글 반영 setTimeout(() => { location.reload(); }, 1000); } else { showMessage(data.error || '댓글 삭제에 실패했습니다.', 'error'); } }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); }); }); }); // 대댓글 답글 버튼 클릭 document.querySelectorAll('.reply-comment-btn').forEach(button => { button.addEventListener('click', function() { const commentId = this.getAttribute('data-comment-id'); const commentAuthor = this.getAttribute('data-comment-author'); const replyForm = this.closest('.relative').querySelector('.reply-form'); const replyTarget = replyForm.querySelector('.reply-target'); // 다른 대댓글 폼들 숨기기 document.querySelectorAll('.reply-form').forEach(form => { if (form !== replyForm) { form.classList.add('hidden'); } }); // 현재 대댓글 폼 토글 replyForm.classList.toggle('hidden'); // 답글 대상 표시 replyTarget.textContent = `${commentAuthor}님에게 답글`; // 폼이 보이면 textarea에 포커스 if (!replyForm.classList.contains('hidden')) { const textarea = replyForm.querySelector('textarea'); textarea.focus(); } }); }); // 대댓글 취소 버튼 document.querySelectorAll('.reply-cancel-btn').forEach(button => { button.addEventListener('click', function() { const replyForm = this.closest('.reply-form'); const textarea = replyForm.querySelector('textarea'); // 내용 초기화 textarea.value = ''; // 폼 숨기기 replyForm.classList.add('hidden'); }); }); // 대댓글 등록 document.querySelectorAll('.reply-form-element').forEach(form => { form.addEventListener('submit', function(e) { e.preventDefault(); // 중복 제출 방지 const submitBtn = this.querySelector('button[type="submit"]'); if (submitBtn.disabled) { return; } const formData = new FormData(this); const parentId = this.getAttribute('data-parent-id'); const commentId = this.getAttribute('data-comment-id'); const textarea = this.querySelector('textarea[name="wr_content"]'); const content = textarea.value.trim(); if (!content) { showMessage('답글 내용을 입력해주세요.', 'error'); return; } // 버튼 비활성화 submitBtn.disabled = true; submitBtn.textContent = '등록 중...'; // 답글 대상 정보 추가 formData.append('wr_comment_reply', commentId); formData.append('wr_qa_id', parentId); formData.append('parent_id', parentId); fetch(`/questions/comment`, { method: 'POST', body: formData, headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(response => response.json()) .then(data => { if (data.success) { showMessage('답글이 등록되었습니다.', 'success'); textarea.value = ''; this.closest('.reply-form').classList.add('hidden'); // 페이지 새로고침으로 새 답글 표시 setTimeout(() => { location.reload(); }, 1000); } else { showMessage(data.error || '답글 등록 중 오류가 발생했습니다.', 'error'); // 실패 시 버튼 다시 활성화 submitBtn.disabled = false; submitBtn.textContent = '답글 등록'; } }) .catch(error => { console.error('Error:', error); showMessage('네트워크 오류가 발생했습니다.', 'error'); // 오류 시 버튼 다시 활성화 submitBtn.disabled = false; submitBtn.textContent = '답글 등록'; }); }); }); }); // 프래그먼트 식별자 스크롤 처리 document.addEventListener('DOMContentLoaded', function() { // URL에 프래그먼트가 있는지 확인 if (window.location.hash) { const hash = window.location.hash.substring(1); // # 제거 const targetElement = document.getElementById(hash); if (targetElement) { // 약간의 지연 후 스크롤 (페이지 로딩 완료 후) setTimeout(() => { const headerHeight = 120; // 헤더 높이 + 여백 const elementPosition = targetElement.offsetTop; const offsetPosition = elementPosition - headerHeight; window.scrollTo({ top: offsetPosition, behavior: 'smooth' }); }, 100); } } }); // 답변 정렬 기능 document.addEventListener('DOMContentLoaded', function() { const sortSelect = document.getElementById('qa_sort_select'); if (sortSelect) { sortSelect.addEventListener('change', function() { const sortValue = this.value; const currentUrl = new URL(window.location); currentUrl.searchParams.set('vsst', sortValue); currentUrl.searchParams.set('vpage', '1'); // 정렬 변경 시 첫 페이지로 currentUrl.hash = '#qa_answer'; window.location.href = currentUrl.toString(); }); } }); // 답변 삭제 기능 document.addEventListener('DOMContentLoaded', function() { document.querySelectorAll('.delete-answer-btn').forEach(button => { button.addEventListener('click', function() { const answerId = this.getAttribute('data-answer-id'); if (confirm('정말로 이 답변을 삭제하시겠습니까?')) { fetch(`/questions/${answerId}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } }) .then(response => response.json()) .then(data => { if (data.success) { // 답변 요소 제거 const answerElement = document.getElementById(`answer_${answerId}`); if (answerElement) { answerElement.remove(); } // 답변 수 업데이트 (전체 답변 수에서 1 감소) const answerCountElement = document.querySelector('h2'); if (answerCountElement) { const currentCount = parseInt(answerCountElement.textContent.match(/\d+/)[0]); answerCountElement.textContent = `답변 ${currentCount - 1}개`; } // 페이지 새로고침 (전체 답변 수와 페이징을 정확히 반영하기 위해) setTimeout(() => { window.location.reload(); }, 1000); showMessage('답변이 삭제되었습니다.', 'success'); } else { showMessage(data.message || '답변 삭제 중 오류가 발생했습니다.', 'error'); } }) .catch(error => { console.error('Error:', error); showMessage('답변 삭제 중 오류가 발생했습니다.', 'error'); }); } }); }); }); // 미채택 완료 function closeWithoutAdopt(questionId) { if (!confirm('답변을 채택하지 않고 질문을 완료하시겠습니까?\n\n이 작업은 취소할 수 없습니다.')) { return; } fetch(`/questions/${questionId}/close-without-adopt`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.success) { showMessage('질문이 미채택 완료되었습니다.', 'success'); setTimeout(() => { window.location.reload(); }, 1500); } else { showMessage(data.error || '처리에 실패했습니다.', 'error'); } }) .catch(error => { console.error('Error:', error); showMessage('처리 중 오류가 발생했습니다.', 'error'); }); } // 재등록 function reregisterQuestion(questionId) { if (!confirm('이 질문을 재등록하시겠습니까?\n\n재등록하면 새로운 답변을 받을 수 있습니다.')) { return; } fetch(`/questions/${questionId}/reregister`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Content-Type': 'application/json', 'Accept': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.success) { showMessage('질문이 재등록되었습니다.', 'success'); if (data.redirect) { setTimeout(() => { window.location.href = data.redirect; }, 1500); } else { setTimeout(() => { window.location.reload(); }, 1500); } } else { showMessage(data.error || '처리에 실패했습니다.', 'error'); } }) .catch(error => { console.error('Error:', error); showMessage('처리 중 오류가 발생했습니다.', 'error'); }); } // Prism.js용 코드 복사 기능 function copyCodePrism(button) { // 버튼의 부모 요소에서 코드 블록 찾기 const wrapper = button.closest('.code-block-wrapper'); const codeBlock = wrapper.querySelector('code'); const codeText = codeBlock.textContent; // 클립보드에 복사 navigator.clipboard.writeText(codeText).then(() => { // 버튼 텍스트 임시 변경 const originalHTML = button.innerHTML; const originalStyle = { background: button.style.background, borderColor: button.style.borderColor, color: button.style.color }; button.innerHTML = '<svg style="width: 14px; height: 14px; display: inline-block; vertical-align: middle; margin-right: 4px;" fill="currentColor" viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></svg> Copied!'; button.style.background = 'rgba(72, 187, 120, 0.7)'; button.style.borderColor = 'rgba(72, 187, 120, 0.9)'; button.style.color = '#fff'; // 2초 후 원래 상태로 복구 setTimeout(() => { button.innerHTML = originalHTML; button.style.background = originalStyle.background; button.style.borderColor = originalStyle.borderColor; button.style.color = originalStyle.color; }, 2000); }).catch(err => { console.error('Failed to copy code:', err); // Fallback: 전통적인 복사 방법 사용 const textArea = document.createElement('textarea'); textArea.value = codeText; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); // 성공 표시 const originalHTML = button.innerHTML; button.innerHTML = '<span style="margin-right: 4px;">✓</span> Copied!'; setTimeout(() => { button.innerHTML = originalHTML; }, 2000); } catch (err) { alert('코드 복사에 실패했습니다.'); } document.body.removeChild(textArea); }); } </script> </main> <!-- Footer --> <footer class="bg-brand-bg-light dark:bg-brand-bg-dark"> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4"> <div class="flex flex-col sm:flex-row justify-between items-center gap-4"> <!-- Footer Text (Left/Center) --> <div class="text-center sm:text-left text-sm text-brand-neutral-light dark:text-brand-neutral-dark"> <p class="hidden md:block">(주)에스아이알소프트 | 사업자등록번호: 217-81-36347 | 대표: 홍석명</p> <p class="hidden md:block mt-1">서울특별시 강남구 테헤란로 322 한신인터밸리24 서관 1402호</p> <p class="mt-3 font-semibold">© 2025 SIRSOFT. All rights reserved.</p> </div> </div> </div> </footer> <!-- Floating Action Buttons --> <script> function toggleDarkMode() { const html = document.documentElement; const isDark = html.classList.contains('dark'); if (isDark) { html.classList.remove('dark'); localStorage.setItem('darkMode', 'false'); } else { html.classList.add('dark'); localStorage.setItem('darkMode', 'true'); } } function toggleProfileMenu() { const dropdown = document.getElementById('profileDropdown'); dropdown.classList.toggle('hidden'); } // Close profile dropdown when clicking outside document.addEventListener('click', function(event) { const dropdown = document.getElementById('profileDropdown'); const button = event.target.closest('button[onclick="toggleProfileMenu()"]'); if (!button && !dropdown?.contains(event.target)) { dropdown?.classList.add('hidden'); } }); function toggleMobileMenu() { const mobileMenu = document.getElementById('mobileMenu'); const hamburgerIcon = document.getElementById('hamburgerIcon'); const closeIcon = document.getElementById('closeIcon'); // 요소가 존재하는지 확인 if (!mobileMenu || !hamburgerIcon || !closeIcon) { console.error('Mobile menu elements not found:', { mobileMenu: !!mobileMenu, hamburgerIcon: !!hamburgerIcon, closeIcon: !!closeIcon }); return; } if (mobileMenu.classList.contains('hidden')) { // Open menu mobileMenu.classList.remove('hidden'); mobileMenu.style.opacity = '0'; mobileMenu.style.transform = 'translateY(-10px)'; setTimeout(() => { mobileMenu.style.transition = 'opacity 200ms ease-out, transform 200ms ease-out'; mobileMenu.style.opacity = '1'; mobileMenu.style.transform = 'translateY(0)'; }, 10); // Switch icons hamburgerIcon.classList.add('hidden'); closeIcon.classList.remove('hidden'); } else { // Close menu mobileMenu.style.opacity = '0'; mobileMenu.style.transform = 'translateY(-10px)'; setTimeout(() => { mobileMenu.classList.add('hidden'); mobileMenu.style.transition = ''; }, 200); // Switch icons hamburgerIcon.classList.remove('hidden'); closeIcon.classList.add('hidden'); } } function closeMobileMenu() { const mobileMenu = document.getElementById('mobileMenu'); const hamburgerIcon = document.getElementById('hamburgerIcon'); const closeIcon = document.getElementById('closeIcon'); mobileMenu?.classList.add('hidden'); hamburgerIcon?.classList.remove('hidden'); closeIcon?.classList.add('hidden'); // 모든 서브메뉴 닫기 document.querySelectorAll('.submenu').forEach(submenu => { submenu.style.maxHeight = '0'; }); document.querySelectorAll('.mobile-menu-item button svg').forEach(arrow => { arrow.classList.remove('rotate-180'); }); } function toggleMobileSubmenu(button) { // 부모 컨테이너에서 submenu 찾기 (버튼의 부모의 다음 형제) const parent = button.closest('.mobile-menu-item'); const submenu = parent.querySelector('.submenu'); const arrow = button.querySelector('svg'); if (!submenu) return; // 현재 상태 확인 const isOpen = submenu.style.maxHeight && submenu.style.maxHeight !== '0px'; if (isOpen) { // 닫기: max-height를 0으로 submenu.style.maxHeight = '0'; arrow.classList.remove('rotate-180'); } else { // 먼저 다른 열린 서브메뉴들을 모두 닫기 (한 번에 하나만 열리도록) document.querySelectorAll('.submenu').forEach(otherSubmenu => { if (otherSubmenu !== submenu) { otherSubmenu.style.maxHeight = '0'; const otherArrow = otherSubmenu.closest('.mobile-menu-item')?.querySelector('button svg'); if (otherArrow) { otherArrow.classList.remove('rotate-180'); } } }); // 열기: 실제 높이로 max-height 설정 const innerDiv = submenu.querySelector('div'); submenu.style.maxHeight = innerDiv.scrollHeight + 'px'; arrow.classList.add('rotate-180'); } } // Close mobile menu when clicking outside document.addEventListener('click', function(event) { const mobileMenu = document.getElementById('mobileMenu'); const menuButton = event.target.closest('button[onclick="toggleMobileMenu()"]'); const menuLink = event.target.closest('#mobileMenu'); if (!menuButton && !menuLink && !mobileMenu?.classList.contains('hidden')) { closeMobileMenu(); } }); </script> <!-- Alpine.js --> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <!-- Floating Action Buttons --> <!-- Attendance Check Float Button --> <!-- Prism.js JavaScript --> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script> <!-- Core languages --> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-markup.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-css.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-clike.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js"></script> <!-- PHP requires markup-templating --> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-markup-templating.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-php.min.js"></script> <!-- Other languages --> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-sql.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-bash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-json.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js"></script> <!-- Plugins --> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/line-numbers/prism-line-numbers.min.js"></script> <script> // Prism.js 초기화 및 하이라이팅 새로고침 document.addEventListener('DOMContentLoaded', function() { // Prism.js 하이라이팅 적용 if (typeof Prism !== 'undefined') { Prism.highlightAll(); } }); </script> </body> </html>