// (2024.12.3, 차재복, Cha Jae Bok, http://www.ktword.co.kr)
// (DOM Tree 구성 요소)
// ol : [ class = tree, type = (word,source,manual,db_table), lrType(left,right), moveType(copyWord,moveWord,moveNode)
// , id = (subtree 산하 children의 fetch를 위한 id) ]
// li : [ child = (자식 노드 수), id = (현재 id) ]
// span : [ class = collapse ]
// span : [ class = non-collapse ]
// 아래 요소들이 경우에 따라 선택됨
// bullet : class = bullet (이벤트), class = nobullet
// name : class = title
// colon : class = colon
// desc : class = desc
// span 또는 button : edit 전용
// div : 해당 노드 상세 해설 보여주기용
// 자식 ol : 주로, 재귀 호출 fetchDataCreateOl(out)
// 기능 : 서버로부터 데이터 가져오고, ol 생성 및 데이터 표출 후, 주어진 out에 ol을 자식으로 추가
// 호출 : [index.js, view.js] collapseSpanHandle()
// [navi_base.js] collapseEvent()
// [navi_search.js] asynctodo()
function fetchDataCreateOl(out) {
// ajax promise 호출 (서버로부터 데이터 가져오기)
let typeParms = {'type' : out.dataset.type, 'lrType' : out.dataset.lrType, 'moveType' : out.dataset.moveType};
// (type:word,file,manual,db_table),(lrType:left,right),(moveType:copyWord,moveWord,moveNode)
let choice = 'treeView';
let id = out.dataset.id;
// spinner 이미지 보이기
/*
// const spinner1 = document.getElementById('spinner1');
const spinner = out.closest('div').querySelector('.spinner');
if(spinner) fadeIn(spinner);
*/
// ajax promise 호출
let url = '/test/navigation/naviFetch.php?type='+typeParms.type+'&choice='+choice+'&id='+id;
let method = 'get';
return ajaxPromise(url, method) // common_utils.js
.then(
response => {
// (개발,디버깅중)
// console.log(response.data);
if(response.err_msg) alert(response.err_msg);
let ol = ol_create(response.data, typeParms, id); // navi_base.js
// 중복 생성 방지
if (out.querySelector('ol.tree')) {
ol.remove();
ol = null;
return;
}
out.appendChild(ol);
out.style.display = 'block';
// spinner 이미지 숨기기기
// if(spinner) fadeOut(spinner);
},
error => {
alert(error);
}
)
.finally(() => {
// 중복 요청 방지 플래그 해제
// isRequestInProgress = false;
});
}
// 기능 : ol 요소 생성
// 호출 : [navi_base.js] fetchDataCreateOl()
function ol_create(childrenData, typeParms, id) {
// childrenData[i] = {id,name,child,desc,parent,item_type}
// - word : {id,name,desc,item_type,child}
// - manual : {id,name,desc,child}
// typeParms = type 또는 {type:(word,source,manual,table),lrType:(left,right),moveType(copyWord,moveWord,moveNode)}
//console.log(childrenData);
// type 확인 설정
let type = (typeParms!='object' ? typeParms : typeParms.type);
// ol 생성
let ol = document.createElement('ol');
ol.setAttribute('class','tree');
ol.style.padding = '5px 0px 5px 20px'; // ol 내 li들을 들여쓰기(20px)
ol.dataset.id = id;
// 현재 생성된 ol 하에 li 요소들 생성
for(let index in childrenData) {
// 다중 선택
if(glob_var.user_type == '종합관리자') childrenData[index].mChoiceName = childrenData.mChoiceName;
// li 생성
let li = li_create(childrenData[index], type); // navi_base.js
// ol 요소에 매 li 마다 자식 노드로 붙임
ol.appendChild(li);
}
return ol;
}
// 기능 : li 요소 생성
// 호출 : [navi_base.js] ol_create()
function li_create(liData, typeParms) {
// liData : (parent, id, name, child, item_type, seq, id_list)
// typeParms = type 또는 {type:(word,file,manual,table),lrType:(left,right),moveType(copyWord,moveWord,moveNode)}
// 필드 구분 : bullet, name, colon, desc, moreShow, edit
// console.log(liData);
// type 확인 설정
let type = (typeof typeParms!='object' ? typeParms : typeParms.type);
// li 생성
let li = document.createElement('li');
// li 중심으로, 각종 현재 상태 정보들을 저장
li.dataset.type = type;
li.dataset.lrType = (typeParms.lrType ? typeParms.lrType : '');
li.dataset.moveType = (typeParms.moveType ? typeParms.moveType : '');
li.dataset.parent = liData.parent;
li.dataset.child = liData.child;
li.dataset.seq = liData.seq;
li.dataset.idlist = liData.idlist;
li.dataset.section = '0'; // detail view 내 최초 section 번호
// (tree node=>id),(word node=>no) 구분 설정
li.dataset.itemtype = liData.item_type;
if(liData.item_type == 'no') li.dataset.no = liData.id;
else li.dataset.id = liData.id;
li.style.listStyleType = 'none';
li.style.padding = '4px';
// collapse span 생성
let collapse = document.createElement('span');
li.appendChild(collapse);
collapse.dataset.child = liData.child;
if(liData.item_type == 'no') collapse.dataset.no = liData.id;
else collapse.dataset.id = liData.id;
collapse.setAttribute('class','collapse');
collapse.style.display = 'inline-block';
collapse.style.cursor = 'pointer';
// 현재 프로그램 상태 보여주기
if(glob_var.user_type == '종합관리자')
collapse.title = (liData.item_type === 'no' ? 'no:' : 'id:') + liData.id
+ ', seq:' + liData.seq
+ ', child:' + liData.child
+ ', itemtype:' + liData.item_type
+ ', idlist:' + liData.idlist
+ ', type:' + type
+ ', lrType:' + typeParms.lrType
+ ', moveType:' + typeParms.moveType
+ ', navi_base.js,navi_base_moreShow.js';
// collapse 이벤트 생성
if(type == 'word' && liData.item_type == 'no')
collapse.addEventListener('click', detailSeparateView, false); // navi_base_moreShow.js
else if(type == 'source' && liData.child == '0')
collapse.addEventListener('click', (e) => {
detailSourceView(collapse); // navi_base_moreShow.js
}, false);
else // ▷ (축소) ▽ (확장)
collapse.addEventListener('click', collapseEvent); // navi_base.js
// li 산하에, 각 항목들 생성하고, 선택적으로 collapse 수용
// bullet 생성
let bullet = document.createElement('a');
bullet.dataset.child = liData.child;
bullet.href = '#'+liData.id;
bullet.style.textDecoration = 'none';
if(liData.item_type == 'no') bullet.dataset.no = liData.id;
else bullet.dataset.id = liData.id;
bullet.setAttribute('class','bullet');
if(liData.child > 0) {
bullet.style.color = 'red';
bullet.innerText = '▷';
} else {
bullet.innerText = '▷';
}
// name span 생성
let name = document.createElement('span');
name.dataset.child = liData.child;
name.setAttribute('class','title');
name.style.marginLeft = '5px';
if(liData.item_type == 'no') {
name.style.paddingBottom = '3px';
name.style.borderBottom = '1px dashed red';
}
let text = document.createTextNode(liData.name);
name.appendChild(text);
let colon,desc;
if(!typeParms.lrType) {
// colon span 생성
colon = document.createElement('span');
colon.setAttribute('class','colon');
colon.style.margin = '0px 15px';
if(liData.desc) colon.innerHTML = ' : ';
else colon.innerHTML = ' ';
// desc span 생성
desc = document.createElement('span');
desc.setAttribute('class','desc');
if(liData.desc) desc.innerHTML = liData.desc;
else desc.innerHTML = '';
}
//alert(colon);
// 조건에 따라 항목별 위치 설정 (자식 첨가)
collapse.appendChild(bullet);
collapse.appendChild(name);
if(type == 'word' || type == 'source') {
if(colon) collapse.appendChild(colon);
if(desc) collapse.appendChild(desc);
} else {
if(colon) li.appendChild(colon);
if(desc) li.appendChild(desc);
}
// edit (종합관리자용)
if(glob_var.user_type == '종합관리자') {
// type별로 각각 다른 편집 버튼 및 기능 구현 (type = word, source, manual, db_table)
if(!typeParms.lrType)
variousEditByType(li, liData, type); // navi_base_edit.js
else {
if(typeParms.lrType=='left') {
let titleBtn = itemTitleEdit(li, liData, type); // navi_base_edit.js
li.appendChild(titleBtn);
let wordEditSpan = wordEdit(li, liData, type); // navi_edit_word.js
li.appendChild(wordEditSpan);
}
multiChoiceMove(li, liData, typeParms); // navi_edit_multi.js
}
}
// 말단 노드 상세 내역 (용어해설,소스코드 등) 보여주기 div
if( !typeParms.lrType && (type == 'word' && liData.item_type == 'no')
|| (type == 'source' && liData.child == '0') ){
let div = document.createElement('div');
div.setAttribute('class','detail_view');
div.style.display = 'none';
div.style.marginTop = '10px';
div.dataset.id = liData.parent;
div.dataset.no = liData.id;
li.appendChild(div);
}
return li;
}
// 기능 : collapse 이벤트 처리기 (ver.2)
// 호출 : [navi_base.js] li_create()
function collapseEvent(e) {
e.preventDefault();
// 중복 요청 방지
// if (isRequestInProgress) return;
// isRequestInProgress = true;
if (this.dataset.child <= 0) return;
// child ol 찾기
const childOl = this.parentNode.querySelector('ol.tree');
// bullet
const bullet = this.querySelector('a');
if (bullet.innerText == '▷') {
bullet.innerText = '▽';
// 자식 ol 이미 생성되었으면 단지 보이게 만 함
if (childOl)
childOl.style.display = 'block';
// 자식 ol 생성 안되었으면 생성시킴
else {
const li = this.closest('li');
fetchDataCreateOl(li); // navi_bace.js
}
} else if (bullet.innerText == '▽') {
bullet.innerText = '▷';
childOl.style.display = 'none';
}
}