개발공부/자바스크립트🚀

웹에서 테이블 Row를 엑셀처럼 다루기

wannaDevelopIt 2025. 1. 3. 09:54
728x90

웹에서 테이블에 데이터를 추가하고, 복사하고, 삭제하고 수정할 필요가 있어 해당 로직을 구현하게 되었다.

 

1. 강조(하이라이트)

Table Row에 대해 내가 어떤 row로 작업하는지, 프로그램과 내가 모두 알 수 있도록 하기 위해 필요하다

function fnHighlightRow(row, event) {
	const table = row.closest('table');
	const rows = Array.from(table.querySelectorAll('tr'));
	const currentIndex = rows.indexOf(row);

	if (event.type !== 'mousemove' && event.type === 'mousedown' && !isDragging) {
		isDragging = true;
		if (!event.ctrlKey && event.shiftKey && lastClickedIndex !== -1) {
			// Shift + 클릭: 범위 하이라이트
			highlightRange(rows, lastClickedIndex, currentIndex);
		} else if (event.ctrlKey) {
			// Ctrl + 클릭: 현재 행의 하이라이트 토글
			toggleHighlight(row);
			lastClickedIndex = currentIndex;
		} else {
			// 일반 클릭: 이전 하이라이트 초기화 후 현재 행의 하이라이트 토글
			resetHighlights(rows); // 이전 하이라이트 초기화
			toggleHighlight(row);
			lastClickedIndex = currentIndex; // 마지막 클릭한 인덱스 업데이트
		}
	} else if (event.type === 'mousemove' && isDragging && !event.ctrlKey && !event.shiftKey) {
		// 드래그 중: 범위 하이라이트
		resetHighlights(rows);
		highlightRange(rows, lastClickedIndex, currentIndex);
	} else if (event.type === 'mouseup') {
		isDragging = false; // 드래그 종료
	}
}

shift 클릭으로는 다수의 범위, 컨트롤 + 클릭으로는 해당 row만, 그외의 경우(일반 클릭)에는 기존의 하이라이트를 모두 해제하고 하나의 row에 대해서만 하이라이트하는 로직이다. 또한 드래그에 대해 범위 하이라이트 로직을 적용했다

 

+ index 관련 작업을 통해 Table Row에 유일성을 추가했다

 

그 외 하이라이트 로직 등에 대해서는 각자의 입맛에 맞게 구현하면 될 듯하다

 

2. 복사

function cloneAndInsertHighlightedRows(table, highlightColor) {
	if (!table || !table.rows || table.rows.length === 0) {
		alert('복사할 테이블이 존재하지 않거나 행이 없습니다.');
	}

	const rows = table.rows;
	const newRows = [];
	let lastHighlightedRowIndex = -1;

	// 하이라이트된 행 찾아 복제 및 마지막 하이라이트된 행의 인덱스 찾기
	for (let i = 0; i < rows.length; i++) {
		if (rows[i].style.backgroundColor === highlightColor) {
			const newRow = rows[i].cloneNode(true);
			newRows.push(newRow);
			lastHighlightedRowIndex = i - 1;
		}
	}

	if (newRows.length === 0) {
		alert('복사할 행이 없습니다.');
	}

	const tbody = table.querySelector('tbody') || table;

	// 마지막 하이라이트된 행 바로 다음에 복사된 행들을 삽입
	const insertIndex = lastHighlightedRowIndex + 1;
	for (let i = 9999; i < newRows.length + 9999; i++) {
		try {
			const newRow = newRows[i - 9999].cloneNode(true);
			const newIndex = insertIndex + i;

			updateRowAttributes(newRow, newIndex);

			if (insertIndex < tbody.rows.length) {
				tbody.insertBefore(newRow, tbody.rows[insertIndex + i - 9999]);
			} else {
				tbody.appendChild(newRow);
			}
			// 새로 복제된 행의 색을 별도 표시
			newRow.style.backgroundColor = 'green';
		} catch (error) {
			console.error('행 복사 중 오류 발생:', error);
			alert("행 복사 중 오류가 발생했습니다. 관리자에게 문의하세요.");
		}
	}
}

위에서 처리한 하이라이트 된 row에 대해, 버튼을 통해 해당 로직을 호출한다. 해당 row에 대한 각종 이벤트에 대해 index로 관리하며, 이는 updaterowAttributes() 함수에서 관리한다. 해당 함수 호출 후 새로 만들어진 row에 대해, index가 table.length보다 작은 경우에는 하이라이트 된 행의 마지막 뒤에, 그 외엔 테이블 가장 마지막에 복사한다

 

3. 삭제

function deleteHighlightedRows(table, highlightColor) {
	if (!table || !table.rows || table.rows.length === 0) {
		alert("테이블이 존재하지 않거나 행이 없습니다. 관리자에게 문의하세요.");
	}

	const rows = table.rows;

	// 뒤에서부터 순회하여 하이라이트된 행 삭제
	for (let i = rows.length - 1; i >= 0; i--) {
		if (rows[i].style.backgroundColor === highlightColor) {
			table.deleteRow(i);
		}
	}
}

삭제 로직은 간단하다

 

 

728x90