// (2022.8.31, 차재복, Cha Jae Bok, http://www.ktword.co.kr)
// navi 메뉴의 subtree별 DOM 구조 : div[treeDiv] > span[subMenu] > ①a[bullet] ②span[title] ③div[treeDiv]
function startDropdown(topElement) {
// dropdown start div 찾음
// let startDropdown = topElem.getElementById('dropdownDiv');
let startDropdown = topElement.querySelector('div#dropdownDiv');
if(startDropdown) {
// menutype에 따라, 서브메뉴 선택 처리
let pathDivs = startDropdown.getElementsByClassName('treeDiv');
for(let i=0; i<pathDivs.length; i++) {
// menutype에 따라, div별로 처리
chooseSubMenu(pathDivs[i]); // short_navi.js
}
}
}
// 기능 : mobile 여부에 따라, 다른 이벤트 메뉴 설정
function chooseSubMenu(out) {
let menuType = out.dataset.menutype;
let menus = out.querySelectorAll('span.subMenu');
if(menus.length < 1) return;
// 찾아낸 sub Menu별로, mobile 여부에 따라, 각 항목별 다른 이벤트 설정
for(let i=0; i<menus.length; i++) {
if(menuType == 'clickMenu') clickMenuEvent(menus[i]); // short_navi.js
if(menuType == 'moverMenu') moverMenuEvent(menus[i]); // short_navi.js
}
}
// 기능 : mouse click 때, sub menu 나타나는 이벤트
function clickMenuEvent(menu) {
// mouse click 이벤트리스너 생성
menu.addEventListener('click', function(e) {
// 최하단 이벤트 하나 만 가능, 이벤트의 상단 진행 금지
e.stopPropagation();
// 현재 이외 주위 노드(span) 있으면 disable 시킴
let siblings = this.parentNode.querySelectorAll('span.subMenu');
if(siblings.length > 1) {
for(let i=0; i < siblings.length; i++) {
if(siblings[i].dataset.id != this.dataset.id) {
let childDiv = siblings[i].querySelector('div.treeDiv');
if(childDiv) childDiv.style.display = 'none';
normalMenu(siblings[i]); // short_navi.js
}
}
}
let childDiv = this.querySelector('div.treeDiv');
// 이미 자식 div 있으면,
if (childDiv) { // toggle 효과
// div 만 숨기기
if (childDiv.style.display == 'flex') {
childDiv.style.display = 'none';
normalMenu(this); // short_navi.js
// div 만 나타내기 및 강조
} else {
childDiv.style.display = 'flex';
strongMenu(this); // short_navi.js
}
return;
// 자식 div 없으면, 새로이 div 생성하고 셋팅
} else {
strongMenu(this); // short_navi.js
// div 생성
let out = document.createElement('div');
// div에 menutype 및 class=treeDiv 설정
out.dataset.menutype = 'clickMenu';
out.setAttribute('class','treeDiv');
// span 맨끝 자식으로 div 붙임
menu.appendChild(out);
// 스타일 지정
out = setStyle(out); // short_navi.js
// out 위치 셋팅
out.style.top = ( this.dataset.direction=='v' ? this.getBoundingClientRect().height : 0 )+'px';
out.style.left = ( this.dataset.direction=='v' ? 0 : this.clientWidth )+'px';
// scroll 조절
// let location = this.offsetTop;
// window.scrollTo({top:location, behavior:'smooth'});
fillOut(this.dataset.id, out); // short_navi.js
}
}, false); // 이벤트 전파를 버블링(상위 방향)으로 셋팅
}
// mouse over 때, sub menu가 나타나는 이벤트
function moverMenuEvent(menu) {
// menu 산하에 자식 노드를 미리 생성하고 붙여둠
let out = document.createElement('div');
// div에 우선적으로 inline-block 셋팅 (줄바꿈 방지)
out.style.display = 'inline-block';
// div에 menutype 및 class=treeDiv 설정
out.dataset.menutype = 'moverMenu';
out.setAttribute('class','treeDiv');
menu.appendChild(out);
// mouseover 이벤트리스너 생성
menu.addEventListener('mouseover', function(e) {
// 선택된 menu 강조
strongMenu(this); // short_navi.js
// out 스타일 지정
out = setStyle(out); // short_navi.js
// out 위치 셋팅
out.style.top = ( this.dataset.direction=='v' ? this.getBoundingClientRect().height : 0 )+'px';
out.style.left = ( this.dataset.direction=='v' ? 0 : this.clientWidth )+'px';
// out 내부 자식 있으면 복귀
if(out.hasChildNodes()) return false;
// out 내부 자식 없으면 표출
else {
// out 내부에 링크 데이터 표출 및 submenu 이벤트 설정
fillOut(this.dataset.id, out);
}
}, true); // 이벤트 전파를 캡쳐링(하위 방향)으로 셋팅
// mouseoout 이벤트리스너 생성
menu.addEventListener('mouseout', function(e) {
// menu 글자 강조된 것을 제거
normalMenu(this); // short_navi.js
// 화면에서 사라짐
this.querySelector('div.treeDiv').style.display = 'none';
});
}
// menu span 미 선택 비 강조
function normalMenu(span) {
span.style.backgroundColor = 'white';
let bullet = span.querySelector('span.bullet');
bullet.innerHTML = bullet.innerText.replace('▽','▷');
}
// menu span 선택 강조
function strongMenu(span) {
span.style.backgroundColor = 'gainsboro';
let bullet = span.querySelector('span.bullet');
bullet.innerText = bullet.innerText.replace('▷','▽');
}
// menu div 스타일링
function setStyle(out){
out.style.margin = '0px';
out.style.padding = '5px 0px 5px';
out.style.backgroundColor = 'white';
out.style.border = '1px gray solid';
out.style.maxWidth = 'max-content';
out.style.whiteSpace = 'pre';
out.style.zIndex = '3';
out.style.position = 'absolute';
out.style.display = 'flex';
out.style.flexDirection = 'column';
out.style.alignItems = 'stretch';
return out;
}
// menu 내 항목 리스트 (서버에서 ajax promise 형태로 가져와서, 이들을 표출)
function fillOut(id, out) {
// ajax promise 호출 (서버로부터 데이터 가져오기)
let url = '/test/navigation/naviFetch.php?choice=treeView&id=' + id;
let method = 'get';
ajaxPromise(url, method) // common_utils.js
// 가져온 결과에 대한 데이터 가공
.then(
response => {
// 만일, out 하부에 자식 노드 있으면, 복귀
if(out.hasChildNodes()) return out;
// 서버로부터 가져온 데이터를 가지고 out에 표출
out = dispListInOut (response.data, out); // short_navi.js
// mobile 여부에 따라, out 내 해당 sunMenu class 항목 찾기,div 생성,이벤트 설정
chooseSubMenu(out); // short_navi.js
},
error => {
alert(error);
}
);
}
// menu 내 항목 리스트의 세부 표출 내용
function dispListInOut (data, out) {
let cnt = 1;
for (const value of data) {
const menuSpan = document.createElement('span');
menuSpan.style.position = 'relative';
menuSpan.style.display = 'block';
menuSpan.style.padding = '3px 7px 3px';
menuSpan.style.margin = '0px';
menuSpan.dataset.direction = 'h';
if(value.item_type=='no') {
let a = document.createElement('a');
let href = '/test/view/view.php';
// 만일, top div data-href가 있으면, href를 셋팅한 것으로 씀
let topDivHref = out.closest('div[data-href]');
if(topDivHref) href = topDivHref.dataset.href;
a.href = href + '?no='+value.id;
a.innerHTML = " " + cnt + ". " + value.name;
menuSpan.appendChild(a);
cnt += 1;
} else {
menuSpan.dataset.id = value.id;
menuSpan.setAttribute('class','subMenu');
let bulletSpan = document.createElement('span');
bulletSpan.setAttribute('class','bullet');
bulletSpan.innerText = '▷';
menuSpan.appendChild(bulletSpan);
let textSpan = document.createElement('span');
textSpan.setAttribute('class','title');
textSpan.innerHTML = ' ' + value.name;
menuSpan.appendChild(textSpan);
}
out.appendChild(menuSpan);
}
return out;
}
"본 웹사이트 내 모든 저작물은 원출처를 밝히는 한 자유롭게 사용(상업화포함) 가능합니다"