본문 바로가기

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

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

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