웹 UI 라이브러리인 GWC에서 제공하는 Tree 컴포넌트에 대한 예제 코드입니다.
먼저 DOM 구성은 다음과 같습니다.
그리고 CSS 구성은 다음과 같구요.
.center {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 1em;
}
gwc-vscrollview {
width: 22em;
height: 30em;
background: rgba(0,0,0,0.3);
border: 1px solid black;
}
gwc-tree {
width: 100%;
padding: 0.5em 0.5em;
}
.h-center {
display: fex;
justify-content: center;
align-items: center;
}
js 코드는 다음과 같습니다.
window.onload = () => {
// 최상위 폴더(root)
const rootFolder = tree.rootFolder;
// 폴더 추가
const gaFolder = rootFolder.addFolder("아카이브");
const docFolder = rootFolder.addFolder("문서").open();
rootFolder.addFolder("프로그램");
const programFolder = rootFolder.getFolder("프로그램");
const humanGeoFolder = gaFolder.addFolder("인문공간데이터");
const adminGeoFolder = gaFolder.addFolder("행정경계");
// 폴더에 파일 추가
humanGeoFolder.addFile("인구통계.zip", "url(../examples/images/icon7.png)");
humanGeoFolder.addFile("유동인구.zip", "url(../examples/images/icon7.png)");
humanGeoFolder.addFile("유아통계.zip", "url(../examples/images/icon7.png)");
const koreaFolder = adminGeoFolder.addFolder("대한민국");
koreaFolder.addFile("시도.zip", "url(../examples/images/icon3.png)");
koreaFolder.addFile("시군구.zip", "url(../examples/images/icon3.png)");
koreaFolder.addFile("읍면동.zip", "url(../examples/images/icon3.png)");
adminGeoFolder.addFile("서울특별시.zip", "url(../examples/images/icon3.png)");
adminGeoFolder.addFile("경기도.zip", "url(../examples/images/icon3.png)");
docFolder.addFile("레포트1.pdf", "url(../examples/images/icon6.png)");
docFolder.addFile("레포트2.pdf", "url(../examples/images/icon6.png)");
docFolder.addFile("레포트3.pdf", "url(../examples/images/icon6.png)");
programFolder.addFile("VisualSudio.Code.zip", "url(../examples/images/icon5.png)")
programFolder.addFile("PhotoShop.zip", "url(../examples/images/icon5.png)")
programFolder.addFile("리터널_PS5.zip", "url(../examples/images/icon5.png)")
// 폴더 열고 닫기
btnProgramOpenClose.addEventListener("click", () => {
const folder = tree.rootFolder.getFolder("아카이브");
if(folder.isOpen()) folder.close();
else folder.open();
});
// 특정 폴더에 파일 추가
btnAddFile.addEventListener("click", () => {
const folder = tree.rootFolder.getFolder("문서");
const file = folder.getFile("NEW 레포트.pdf");
if(file) {
file.remove();
} else {
const file = folder.addFile("NEW 레포트.pdf", "url(../examples/images/icon6.png)");
// 파일 또는 폴더에 사용자 정의 데이터 추가
file.setData("생성일자", "2022년 2월 10일");
console.log(file.getData("생성일자"));
}
});
// 파일(폴더+파일)에 대한 클릭 이벤트
tree.addEventListener("fileClick", (event) => {
const file = event.detail.file;
const parentFolderName = file.parentFolder.name;
const bFolder = file.isFolder();
const bOpen = file.isOpen();
label.content = `
이름: ${file.name}
부모폴더: ${parentFolderName?parentFolderName:"없음"}
종류: ${bFolder?"폴더":"파일"}
${bFolder?`상태: ${bOpen?"열림":"닫힘"}`:""}
`;
vscrollview.refresh(); // 폴더 열기로 인한 트리 컴포넌트 크기 변경에 따른 스크롤뷰 업데이트
});
// 트리 컴포넌트의 크기가 가변이므로 스크롤뷰를 업데이트 해줌
vscrollview.refresh();
GeoServiceWebComponentManager.instance.update();
};
실행 결과는 다음과 같습니다.
트리의 항목에 대한 팝업 메뉴 기능을 적용할 때에 대한 코드입니다.
// PopupMenu 생성 시작
const popupMenu = gwcCreatePopupMenu();
popupMenu.addMenuItem("menu1", {
text: "생성",
_icon: "images/icon1.png",
onClick: (menuId) => {
gwcMessage(`폴더 생성(${menuId})`);
popupMenu.hide();
}
});
popupMenu.addMenuItem("menu2", {
text: "이름 변경",
_icon: "images/icon2.png",
onClick: (menuId) => {
gwcMessage(`${popupMenu.fileData.name} 이름 변경(${menuId})`);
popupMenu.hide();
}
});
popupMenu.addMenuItem("menu3", {
text: "삭제",
_icon: "images/icon3.png",
onClick: (menuId) => {
gwcMessage(`${popupMenu.fileData.name} 삭제(${menuId})`);
popupMenu.hide();
}
});
popupMenu.addMenuItem("menu4", {
text: "잘라내기",
_icon: "images/icon4.png",
onClick: (menuId) => {
gwcMessage(`${popupMenu.fileData.name} 잘라내기(${menuId})`);
popupMenu.hide();
}
});
popupMenu.addMenuItem("menu5", {
text: "붙여넣기",
_icon: "images/icon5.png",
onClick: (menuId) => {
gwcMessage(`${popupMenu.fileData.name}에 붙여넣기(${menuId})`);
popupMenu.hide();
}
});
// PopupMenu 생성 완료
// 파일(폴더+파일)에 대한 클릭 이벤트
tree.addEventListener("fileClick", (event) => {
const file = event.detail.file;
const contextMenu = event.detail.contextMenu;
if(contextMenu) {
console.log(event.detail.originalEvent);
popupMenu.fileData = file; // fileData는 임의로 부여한 속성으로 팝업 메뉴 실행 시에 참조됨
popupMenu.show(event.detail.originalEvent.clientX, event.detail.originalEvent.clientY);
}
});
위의 코드에 대한 실행 결과는 다음과 같습니다.
트리를 구성하는 항목에 대해서 선택된 항목이라는 피드백을 줄 수 있습니다. 다음 코드를 참고하기 바랍니다.
tree.clearSelection(); // 일단 기존의 선택된 항목에 대해 선택 해제
tree.rootFolder.getFolder("아카이브").selected = true; // 폴더를 얻고 해당 폴더를 선택된 상태로 표시
폴더 또는 파일 항목의 우측에 Tag 정보를 표시할 수 있습니다. 즉, getFolder 또는 getFile을 통해 얻은 item 객체의 tag 속성(get, set)을 설정하면 됩니다. 아래는 파일항목의 우측에 파일의 크기를 표시하는 예시입니다.
tree 컴포넌트는 동일한 계층에 동일한 이름을 가진 항목을 추가할 수 없습니다. 이때 label 속성을 이용해 이름은 다르지만 표시되는 제목만을 변경해 줄 수 있습니다. 코드 예시는 다음과 같습니다.
data.forEach(item => {
const rootFolder = this.#tree.rootFolder;
rootFolder.addFile(item.id, "url(../images/layers.svg)").label = item.title;
});