소스 파일 : /reform/reform_edit_move.js (2020-11-23)     소스 설명 : (개선중) reform 항목 이동하기
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
// (2020.11.23, 차재복, Cha Jae Bok, cjbword@gmailcom)


// (편집자용) 편집용 버튼 생성 유지
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) {

            // 디버깅용 1
            if(xhr.responseText=='' || xhr.responseText=='null') {
                alert('빈문자열 만 또는 null 문자 만 옴');
                console.log(xhr.responseText);
                return;
            }

            let data = JSON.parse(xhr.responseText);

            // 디버깅용 2
            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) {
//                       currentData = currentParentObject[index]; // 현재 노드 정보 기억하기
                       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], '', li_after); 
                    let li = li_create(id, data.nextParentChilds[nextSub_seq]);
                    insertAfter(li_after, li);
                    // 삽입된 li에 이벤트 설정
                    event4Singleli (li);

                // 레벨다운 처리
                } 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 = a_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));

}

JS 키워드 : addEventListener, appendChild, console.log, createElement, dataset, delete, encodeURIComponent, getElementById, hasChildNodes, innerHTML, innerText, insertBefore, item, JSON.parse, JSON.stringify, length, onreadystatechange, open, parentNode, replace, replaceChild, replaceWith, send, sessionStorage, setRequestHeader, target, value, XMLHttpRequest

Copyrightⓒ written by 차재복 (Cha Jae Bok)     (소액후원)

   소스 이력    소스 폴더    소스 언어