개발/JavaScript
검색 키워드 하이라이트로 표현하기
향포레스트
2023. 3. 5. 23:35
728x90
Javascript의 배열 특정 요소를 포함 여부를 알 수 있는 includes 메서드와 문자열 치환할 수 있는 replace, repalceAll 메서드 사용하기
배경
요구사항
- 댓글의 대댓글은 [펼침] 버튼 클릭할 때 대댓글 리스트를 조회한다.
- 댓글에 대한 검색어를 포함한 조회 시 결과는 대댓글인 경우 대댓글의 부모인 댓글에 대한 정보를 보여준다.
- 대댓글 리스트에서도 검색 키워드 하이라이트로 강조 표시한다.
화면구상
중첩된 리피터를 사용하여 대댓글을 표현하려고 했지만, 댓글 테이블이 레벨에 관한 필드가 없었고 테이블 반환 함수에 임시 테이블을 생성하여 레벨을 만들어서 사용하고 있었습니다. 부모 댓글 연번에 대한 정보만 있는데, 대댓글에 대한 대댓글인 경우에는 다른 부모 댓글의 연번을 저장하기 때문에 중첩된 리피터를 이용하기에는 한계가 있을 것 같았습니다. DB를 수정하기에는 다른 분도 개발하고 있기 때문에 많이 진행하셨기 때문에 설계 변경 요청은 하지는 않았습니다.
데이터를 모두 다 가져오는 게 관리자가 작업하기 편할 것 같다는 건 개인적인 생각이고 요구사항은 대댓글은 필요할 때 리스트를 가져오는 것이기 때문에 더 중첩된 리피터를 사용하지 않았습니다.
Javascript ajax를 이용하여 비동기로 대댓글 리스트와 하이라이트를 구현하는 방향으로 정하였습니다.
구현
HTML
댓글 데이터 컨트롤 안에 ajax로 생성할 element를 넣어주었습니다.
<asp:Repeater ID="rptListBase" runat="server" OnItemDataBound="rptListBase_ItemDataBound" OnItemCommand="rptListBase_ItemCommand">
<ItemTemplate>
<div class="card border-light mb-3 w-100">
...
<div class="card-footer bg-white text-start text-secondary d-none" id="divChildList<%# Eval("인덱스") %>">
<div class="fw-bold mb-2">답글 목록</div>
<div id="divChlidItems<%# Eval("댓글아이디") %>"></div>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
Javascript
초기화 메서드
- 댓글의 대댓글은 [펼침] 버튼 클릭할 때 대댓글 리스트를 조회한다.
등록된 답글이 있으면 비교 조건을 추가하였습니다. [펼침]을 다시 클릭하면 대댓글 리스트의 내용을 모두 지웁니다.
function ToggleChlid(obj, rownum, cnt, commentId) {
if (cnt === 0) {
alert('등록된 답글이 없습니다.');
} else {
if (댓글펼침) GetChlidComments(commentId);
else document.getElementById(`divChlidItems${commentId}`).innerHTML = "";
}
}
대댓글 리스트 조회 메서드
등록된 답글이 있을 때 대댓글의 리스트를 가져옵니다. includes 메서드를 사용하여 대댓글 리스트 중에 검색어가 포함되어 있는지 비교해야 합니다. 비교하는 과정을 건너뛸 시 replace가 적용되지 않습니다. 그리고 검색어가 빈칸이 아닌 경우라는 조건도 추가해야 합니다. 왜냐하면 replace는 type이 문자열이어야 하기 때문에 데이터가 문자열로 잘 들어오는지 확인해야 합니다.
function GetChlidComments(commentId) {
let keyword = '<%= _KEYWORD %>',
dataJSON = JSON.stringify(내용물);
$.ajax({
url: "/WebService.asmx/GetChlidComments",
data: dataJSON,
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: (data) => {
if (data.d != null && data.d.length > 0) {
let box = document.getElementById(`divChlidItems${commentId}`);
$.map(data.d, (item, index) => {
let div = document.createElement("div"),
content = item.Content;
if (keyword !== "") {
if (content.includes(keyword)) {
content = content.replaceAll(keyword, `<span class='text-highlight'>${keyword}</span>`);
}
}
div.setAttribute("id", `divChlidItem${index}`);
div.innerHTML = `댓글리스트생성`;
box.appendChild(div);
});
}
}
});
}
완성
참고사이트
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
728x90