// (2020.11.25, 차재복, Cha Jae Bok, http://www.ktword.co.kr)
// (편집자용) 편집용 버튼 생성 유지
function move_btn (data) {
// 버튼 요소 생성 및 스타일 설정
let btn = document.createElement('button');
btn.id = 'move_btn_'+data.id;
btn.setAttribute('style','margin-left:20px; padding:0px; font-size:9px; font-style:italic');
// (편집자용) 호출 내역 보여주기
btn.title = 'reform_edit_move.js \n'+'move_btn() \n'+'reform.'+data.id;
// 버튼 요소 내 텍스트 'Move ∨' 요소 설정
const move_text = document.createTextNode('Move ∨');
btn.appendChild(move_text);
// 버튼 요소에 이벤트리스너 설정
btn.addEventListener('click', function(e) {
const div_name = 'move_div_';
// 'move_div_(id)' 명칭을 갖는 요소 검색/선택
let div_id = document.getElementById(div_name+data.id);
if (div_id) { // 하부 div의 show/hide
itemShowHide(div_id, btn); // common_utils.js
} else {
// 편집용 div 생성
let div = move_div(data, div_name); // reform_edit_move.js
insertAfter(e.target, div); // common_utils.js
// 클릭 요소 (∨,∧) 바꿈
btn.innerHTML = btn.innerText.replace('∨','∧');
}
});
return btn;
}
// (편집자용) id move div
function move_div (data) {
// container div 요소 생성
let div = document.createElement('div');
// div 요소의 스타일 설정
div.style.padding = '0';
// div 요소에 정보 저장
div.id = 'move_div_'+data.id;
div.dataset.id = data.id;
div.dataset.parent = data.parent;
div.dataset.sub_seq = data.sub_seq;
div.dataset.path2node = data.path2node;
// id 위로 이동 버튼
let id_up = document.createElement('button');
id_up.ch = 'id_up';
let id_up_text = document.createTextNode('위로');
id_up.appendChild(id_up_text);
id_up.addEventListener('click', id_move_gen_ajax); // 이벤트리스너 등록 추가 (id_move_gen_ajax 실행)
div.appendChild(id_up);
// id 아래로 이동 버튼
let id_down = document.createElement('button');
id_down.ch = 'id_down';
let id_down_text = document.createTextNode('아래로');
id_down.appendChild(id_down_text);
id_down.addEventListener('click', id_move_gen_ajax); // 이벤트리스너 등록 추가 (id_move_gen_ajax 실행)
div.appendChild(id_down);
// id 맨 처음으로 이동 버튼
let id_first = document.createElement('button');
id_first.ch = 'id_first';
let id_first_text = document.createTextNode('처음');
id_first.appendChild(id_first_text);
id_first.addEventListener('click', id_move_gen_ajax); // 이벤트리스너 등록 추가 (id_move_gen_ajax 실행)
div.appendChild(id_first);
// id 맨 마지막으로 이동 버튼
let id_last = document.createElement('button');
id_last.ch = 'id_last';
let id_last_text = document.createTextNode('끝');
id_last.appendChild(id_last_text);
id_last.addEventListener('click', id_move_gen_ajax); // 이벤트리스너 등록 추가 (id_move_gen_ajax 실행)
div.appendChild(id_last);
// id 레벨업 버튼
let id_level_up = document.createElement('button');
id_level_up.ch = 'id_level_up';
let id_level_up_text = document.createTextNode('레벨업');
id_level_up.appendChild(id_level_up_text);
id_level_up.addEventListener('click', id_move_gen_ajax); // 이벤트리스너 등록 추가 (id_move_gen_ajax 실행)
div.appendChild(id_level_up);
// id 레벨다운 버튼
let id_level_down = document.createElement('button');
id_level_down.ch = 'id_level_down';
let id_level_down_text = document.createTextNode('레벨다운');
id_level_down.appendChild(id_level_down_text);
id_level_down.addEventListener('click', id_move_gen_ajax); // 이벤트리스너 등록 추가 (id_move_gen_ajax 실행)
div.appendChild(id_level_down);
// 결과 div 리턴
return div;
}
// (편집자용) id move update
function id_move_gen_ajax() {
// 전달변수 설정
let ch = this.ch; // choice 종류
let id = this.closest('div').dataset.id; // 현재 노드의 id
let parent = this.closest('div').dataset.parent; // 현재 노드의 부모 노드 id
let sub_seq = this.closest('div').dataset.sub_seq // 현재 노드의 sub_seq
let path2node = this.closest('div').dataset.path2node; // 현재 노드의 path2node
let carrier_id, text;
carrier_id = this.carrier_id; // 값을 갖는 carrier id
if (carrier_id) text = document.getElementById(carrier_id).value; // text : 생성용 텍스트
// (디버깅용)
if (ch=='id_delete') {
if(!confirm('삭제 여부')) return;
}
// (디버깅용)
// if (!confirm('parent='+parent+', id='+id+', ch='+ch+', text='+text)) return;
let xhr = new XMLHttpRequest();
let method = 'POST';
let url = '../reform/reform_update.php';
xhr.open(method, url);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
/* // (디버깅용)
if(xhr.responseText=='' || xhr.responseText=='null') {
alert('빈문자열 만 또는 null 문자 만 옴');
console.log(xhr.responseText);
return;
}
*/
// JSON.parse 및 예외처리
let data;
try {
data = JSON.parse(xhr.responseText);
} catch (e) {
console.log(xhr.responseText);
alert('서버에서 반환된 데이터 내 에러 추정...console.log 확인 필요');
return;
}
// (디버깅용)
if (data.err_msg) {
alert('서버 db 처리 중 에러 발생\n'+data.err_msg);
return;
}
// 주요 노드별 위치
let parentOl = document.getElementById('olid_'+parent);
let parentLi = parentOl.parentNode;
let currentLi = document.getElementById('lid_'+id);
// 현재 노드의 부모의 sesseionStorage
let currentParentObject = JSON.parse(sessionStorage.getItem('sid_' + parent));
// 이동 전에 현재 노드 DOM 요소 미리 제거
if (ch=='id_up' || ch=='id_down' || ch=='id_first' || ch=='id_last' || ch=='id_level_up' || ch=='id_level_down')
parentOl.removeChild(currentLi);
// 위로,아래로 이동
if (ch=='id_up' || ch=='id_down') {
// 디버깅용
// console.log(data);
// 현재 parent 노드 산하 ol을 대체할 신규 ol 생성
let createdOl = ol_create(parent, data.nextParentChilds, parentLi); // (id, data, out)
// 현재 parent 노드 산하의 old ol을 created ol로 교체
parentOl.replaceWith(createdOl);
// 교체된 ol 산하 li 모두에 이벤트 설정
event4li (createdOl);
// 서버로부터 받은 nextParentChilds를 현재 parent 산하 자식정보로써 sessionStorage에 저장
let targetParentSession = JSON.stringify(data.nextParentChilds);
sessionStorage.setItem('sid_' + parent, targetParentSession);
// 맨처음으로 이동
} else if (ch=='id_first') {
// 현재 parent 노드의 최초 노드 다음에 생성된 li 노드를 삽입
let li = li_create(id, data.nextParentChilds[1]);
parentOl.insertBefore(li, parentOl.firstChild)
// 삽입된 li에 이벤트 설정
event4Singleli (li);
// 서버로부터 받은 nextParentChilds를 현재 parent 산하 자식정보로써 sessionStorage에 저장
let targetParentSession = JSON.stringify(data.nextParentChilds);
sessionStorage.setItem('sid_' + parent, targetParentSession);
// 맨끝으로 이동
} else if (ch=='id_last') {
// 레벨업,레벨다운 이동
} else if (ch=='id_level_up' || ch=='id_level_down') {
// 변수 설정
let nextParentId = data.next_parent;
let nextSub_seq = data.sub_seq;
// 현재 노드의 parent의 sessionStorage로부터 해당 id 만 제거 후 다시 저장
for (let index in currentParentObject ) {
if(currentParentObject[index].id==id) {
delete currentParentObject[index];
}
}
let deletedStorage = JSON.stringify(currentParentObject);
sessionStorage.setItem('sid_' + parent, deletedStorage);
// 서버로부터 받은 nextParentChilds를 nextParentId로써 sessionStorage에 저장
let targetParentSession = JSON.stringify(data.nextParentChilds);
sessionStorage.setItem('sid_' + nextParentId, targetParentSession);
// 레벨업 처리
if (ch=='id_level_up') {
// 현재 노드의 상위 레벨에서, 현재 노드의 parent 노드 다음에 현재 노드를 삽입
let li_after = document.getElementById('lid_'+parent);
let li = li_create(id, data.nextParentChilds[nextSub_seq]);
insertAfter(li_after, li);
// 직후 삽입된 li에 이벤트 설정
event4Singleli (li);
// 기존 있던 자리에서, 자식이 하나도 없는 경우
if (!parentOl.hasChildNodes()) {
// 기존 부모 ol 삭제
parentLi.removeChild(parentOl)
// 현재 직전 li의 a 부여 취소
if(parentLi.firstChild.nodeName == 'A') {
let a = navi_create(parent, '0'); // parent:parent id, '0':자식없음 -> ex_run/navi_testing.js
parentLi.replaceChild(a, parentLi.firstChild);
}
}
// 레벨다운 처리
} else if (ch=='id_level_down') {
// 현재 노드 직전 노드의 하위 레벨의 li 및 ol 찾음
let targetLi = document.getElementById('lid_'+nextParentId);
let oldOl = document.getElementById('olid_'+nextParentId);
// 해당 li 하부에 기존 ol 노드가 있다면 삭제
if(oldOl) targetLi.removeChild( oldOl );
// 해당 li 하부에 ol 생성
let targetParentObject = data.nextParentChilds;
let createdOl = ol_create(nextParentId, targetParentObject, targetLi);
targetLi.appendChild(createdOl);
// createdOl의 산하 li들에 이벤트 설정
event4li (createdOl);
// 해당 li의 a 부여 여부
if(targetLi.firstChild.nodeName != 'A') {
let a = navi_create(parent, nextParentId, Object.keys(data.nextParentChilds).length);
targetLi.replaceChild(a, targetLi.firstChild);
a.innerText = '▽';
event4Singleli (targetLi);
}
}
// 현재 노드 삭제
} else if (ch == 'id_delete') {
// 현재 노드 제거
parentOl.removeChild(currentLi);
if (data.ok == true) alert('삭제 성공 ; 형제수='+data.sibling);
// 현재 부모 내 자식이 하나도 없는 경우
if (!parentOl.hasChildNodes()) {
// 현재 부모 sessionStorage의 sub_seq,child 수정
currentParentObject[sub_seq].child = '0'; // '0':자식없음
let currentParentSession = JSON.stringify(currentParentObject);
sessionStorage.setItem('sid_' + parent, currentParentSession);
// 부모 ol 삭제
parentLi.removeChild(parentOl)
// 부모 li의 a 부여 취소
if(parentLi.firstChild.nodeName == 'A') {
let a = navi_create(parent, '0'); // parent:parent id, '0':자식없음 -> ex_run/navi_testing.js
parentLi.replaceChild(a, parentLi.firstChild);
}
}
// 자식 노드 생성
} else if (ch == 'id_child') {
// 현재 li의 a 부여
if(currentLi.firstChild.nodeName != 'A') {
let a = navi_create(id, '1'); // id:parent id, '1':자식없음 -> ex_run/navi_testing.js
currentLi.replaceChild(a, currentLi.firstChild);
a.innerText = '▽';
event4Singleli(currentLi); // -> ex_run/navi_testing.js
}
// 서버로부터 받은 nextParentChilds로부터 현재 노드의 신규 자식 노드 생성
let ol_created = ol_create(id, data.nextParentChilds, currentLi); // (id, data, out)
currentLi.appendChild(ol_created);
// 현재 부모 sessionStorage에서 현재 노드의 child 필드 수정
currentParentObject[sub_seq].child = '1';
let currentParentSession = JSON.stringify(currentParentObject);
sessionStorage.setItem('sid_' + parent, currentParentSession);
// 서버로부터 받은 nextParentChilds를 현재 노드 산하 자식정보로써 sessionStorage에 저장
let currentTargetSession = JSON.stringify(data.nextParentChilds);
sessionStorage.setItem('sid_' + id, currentTargetSession);
// gen_del_div 사라짐
const gen_del_div = document.getElementById('gen_del_div_'+id);
itemShowHide(gen_del_div, this); // -> base_utils/common_utils.js
// 이전,이후 노드 생성
} else if (ch == 'id_prepend' || ch == 'id_append') { // ch == 'id_prepend'
// 서버로부터 받은 nextParentChilds로부터 현재 노드의 이전 및 이후 노드 생성
let li = li_create(parent, data.nextParentChilds[data.sub_seq]); // (par_id, data)
if (ch == 'id_prepend') {
parentOl.insertBefore(li, currentLi); // (newNode, referenceNode)
} else if (ch == 'id_append') {
insertAfter(currentLi, li); // (referenceNode, newNode)
}
// 서버로부터 받은 nextParentChilds를 현재 parent의 산하 자식정보로써 sessionStorage에 저장
let currentParentSession = JSON.stringify(data.nextParentChilds);
sessionStorage.setItem('sid_' + parent, currentParentSession);
// gen_del_div 사라짐
const gen_del_div = document.getElementById('gen_del_div_'+id);
itemShowHide(gen_del_div, this); // -> base_utils/common_utils.js
}
}
};
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send('id='+id+'&ch='+ch+'&text='+encodeURIComponent(text));
}
"본 웹사이트 내 모든 저작물은 원출처를 밝히는 한 자유롭게 사용(상업화포함) 가능합니다"