개발/ASP.NET

[Web Form] 검색 키워드 하이라이트로 표현하기

향포레스트 2023. 3. 5. 22:57
728x90
Replace 메서드를 이용해서 검색어를 하이라이트 스타일이 적용된 HTML 코드로 변경하기

요구사항

컨텐츠 관리하는 사이트의 댓글 관리 화면에서 댓글 내용을 관리자가 입력하는 검색어로 조회할 때 나온 검색 결과에 검색어를 강조 표시를 해주었으면 하는 요청입니다.

구현

HTML

검색 버튼은 웹 서버 컨트롤로 사용하려다가 부트스트랩 스타일에 어울리는 게 없어서 HTML 코드로 입력하고 자바스크립트로 GET 검색 파라미터를 포함하여 링크 이동하는 것으로 만들었습니다.

 

댓글 리스트는 데이터 컨트롤을 리피터를 사용하였습니다. 

<style>
	.text-highlight {
            background-color:rgba(13, 110, 253, 0.7);
            color:white;
            padding:0 3px;
     }
</style>

...

<div class="input-group mb-3">
 <input type="text" id="txtKeyword" runat="server" placeholder="댓글 내용을 검색하세요." class="form-control form-control-lg search-text-border ps-3" />
 <span class="input-group-text search-btn-border text-secondary cursor-pointer" onclick="SearchKeyword()" id="basic-addon1"><i class="fa-solid fa-magnifying-glass"></i></span>
</div>


...

<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-header text-end" id="divBaseStatus" runat="server">
               <div class="d-flex justify-content-between align-items-center">
                   <asp:Panel ID="pnlBaseStatus" runat="server"></asp:Panel>
                   <div>
                       <%--<asp:LinkButton ID="lbtnBaseModify" runat="server">수정</asp:LinkButton>--%>
                       <asp:LinkButton ID="lbtnBaseHide" runat="server">숨김</asp:LinkButton>
                       <asp:LinkButton ID="lbtnBaseRemove" runat="server">삭제</asp:LinkButton>
                   </div>
               </div>
           </div>
           <div class="card-body">
               <div class="d-flex align-items-center">
                   <h6 class="card-title text-start"><%# Eval("댓글작성자") %></h6>
                   <span class="px-3 text-secondary"><%# Eval("작성일시") %></span>
               </div>                        
               <asp:Literal ID="ltrlContent" runat="server"></asp:Literal>
               <p class="text-end text-secondary fs-6">
                   <i class="fa-regular fa-thumbs-up"></i>&nbsp;<%# Eval("좋아요수") %>
                   <span class="mx-1">&nbsp;</span>
                   <span class="text-secondary cursor-pointer" onclick="ToggleChlid(this, <%# Eval("순번") %>, <%# Eval("대댓글수") %>, <%# Eval("댓글아이디") %>);"><i class="fa-regular fa-comment"></i>&nbsp;<asp:Label ID="lblComment" runat="server" Text='<%# Eval("대댓글수") %>'></asp:Label></span>
               </p>
           </div>
           <div class="card-footer bg-white text-start text-secondary d-none" id="divChildList<%# Eval("RowNum") %>">
               <div class="fw-bold mb-2">답글 목록</div>
               <div id="divChlidItems<%# Eval("댓글아이디") %>"></div>
           </div>
       </div>
   </ItemTemplate>
</asp:Repeater>


Javascript

function SearchKeyword() {
        let _MENU = '<%=_MENU %>',
            _KEYWORD = document.getElementById("txtKeyword").value,
            _MODE = '<%= _MODE %>',
            _ORDER = '<%= _ORDER %>';

        <%-- 줄바꿈 주의 --%>
        document.location.href = `page.aspx?m=${_MENU}k=${_KEYWORD}&mode=${_MODE}&o=${_ORDER}`;
}


서버코드

Page_Load

페이지 로드할 때 검색어를 설정해 주고, 엔터키 이벤트로도 조회할 수 있게 초기화하였습니다.

_KEYWORD = Request["k"] ?? "";

if (!IsPostBack)
{
   this.txtKeyword.Value = _KEYWORD;
   _Search();
}

this.txtKeyword.Attributes["onkeypress"] = "if (event.keyCode==13){SearchKeyword(); return false;}";

데이터 가져오기

댓글 리스트 쿼리 호출을 나누고 싶진 않았는데 댓글 테이블 구조 상 나눠서 가져오는 게 쿼리가 그나마 깔끔해져서 서버코드에서 검색어 입력 여부에 따라 SP를 다르게 호출합니다.

 protected override void _Search()
{
        if (_KEYWORD == "")
        {
        	DataSet _dsL = _GetDataSet("BASE");
        
        	// 댓글 리스트
            rptListBase.DataSource = _dsL.Tables[0];
            rptListBase.DataBind();
        }
        else
        {
            DataSet _dsK = _GetDataSet("KEYWORD");

			// 댓글 리스트
			rptListBase.DataSource = _dsK.Tables[0];
            rptListBase.DataBind();
        }
}

RepeaterCommandEvent

검색어가 없을 때 오류가 뜰 수  있기 때문에, 앞에서 값이 있는지 비교를 해줍니다. 검색어 하이라이트 처리는 Replace를 사용합니다. textarea에서 DB 데이터 개행 처리하는 것과 거의 동일합니다.

protected void rptListBase_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    DataRowView drv = e.Item.DataItem as DataRowView;
    Literal ltrlContent = e.Item.FindControl("ltrlContent") as Literal;
    
    string content = drv["댓글내용"].ToString();

    if (_KEYWORD != "")
    {
        var replacement = content.Replace(_KEYWORD, string.Format("<span class=\"text-highlight\">{0}</span>", _KEYWORD));
        content = replacement;
    }
}

완성 화면

참고사이트
https://learn.microsoft.com/ko-kr/dotnet/csharp/how-to/modify-string-contents
728x90