JavaScript에서 텍스트 강조 표시

13984 단어 htmljavascript
이 게시물은 원래 https://tomekdev.com/posts/highlight-text-in-javascript에 게시되었습니다. 여기에서 GIF로 보는 것은 거기에서 대화식입니다. ✌️


search with typo tolerance 에 대한 이전 게시물에서 오타에 대한 관용을 강화하여 페이지의 검색 기능을 개선할 수 있는 방법에 대한 아이디어를 보여주기 위해 몇 가지 대화형 요소를 추가했습니다. 결과 내에서 일치하는 텍스트를 강조 표시한 방법이 궁금할 수 있습니다. 여기 있습니다.

아주 복잡하지는 않지만 여러분이 모를 수도 있는 아주 좋은 힌트를 드리겠습니다 :) 여기 데모가 있습니다. 아래 GIF를 보고(또는 내 웹 사이트를 방문하여 재생) 단어가 어떻게 강조 표시되는지 관찰하십시오.



요령은 검색된 텍스트의 모든 항목을 같은 텍스트로 바꾸지만 이번에는 <mark>로 래핑하는 것입니다. 또한 highlight CSS 클래스를 <mark>에 추가하여 적절하게 스타일을 지정할 수 있습니다. 이를 위해 JS 라이브러리가 필요하지 않습니다. 작업을 수행하는 코드는 다음과 같습니다.

const $box = document.getElementById('box');
const $search = document.getElementById('search');

$search.addEventListener('input', (event) => {
  const searchText = event.target.value;
  const regex = new RegExp(searchText, 'gi');

  let text = $box.innerHTML;
  text = text.replace(/(<mark class="highlight">|<\/mark>)/gim, '');

  const newText = text.replace(regex, '<mark class="highlight">$&</mark>');
  $box.innerHTML = newText;
});

$box가 텍스트를 포함하는 요소(전체 페이지일 수 있음)이고 $search가 입력이라고 가정해 보겠습니다. 8행에서 우리는 $box에서 현재 HTML을 가져오고 다음 행에서 모든 현재 하이라이트를 제거합니다. 우리는 스스로 청소하기 위해 그렇게합니다. 이전 검색(또는 부분 검색)을 화면에 유지하고 싶지 않습니다. HTML 구조와 CSS 스타일을 볼 수 있도록play with that on codepen 할 수 있습니다(여기서 .highlight만 중요함).

잠재적으로 놓칠 수 있기 전에 언급한 힌트는 $& 메서드의 두 번째 인수에 있는 replace입니다. 이것은 일치하는 하위 문자열을 거기에 삽입하도록 replacer 메소드에 지시하는 특수 대체 패턴입니다.

단순히 이런 것을 사용하지 않는 이유는 무엇입니까? 검색된 텍스트를 삽입하시겠습니까?

// ...
const searchText = event.target.value;
// ...
const newText = text.replace(
  regex,
  `<mark class="highlight">${searchText}</mark>`
);


그렇게함으로써 우리는 편지의 경우에 문제가 생길 것입니다. 대부분의 검색/찾기 기능은 대소문자를 구분하지 않으므로 문제를 일으키고 싶지 않습니다. 검색된 텍스트를 해당 텍스트가 포함된 <mark>로 간단히 래핑하는 아래 예를 고려하십시오.



이상하지 않나요? 다행히 일치하는 텍스트의 대소문자를 유지하기 위해 매우 영리할 필요는 없습니다. $& 메서드와 함께 replace를 사용하기만 하면 됩니다.

반응 구현



React는 요즘 사람들이 사용하는 가장 인기 있는 프레임워크 라이브러리인 것 같습니다. 그러나 어떤 프런트 엔드 프레임워크를 사용하든 검색 및 강조 표시 기능이 있는 구성 요소에 대한 인수로 text를 전달할 것입니다. 목록에서 검색 가능한 항목의 레이블일 수도 있습니다.

DOM 요소에서 원시 텍스트를 가져올 필요가 없기 때문에 작업이 약간 단순화됩니다. 그리고 우리는 스스로 청소할 필요가 없습니다. 래핑 부분에 집중하고 렌더링은 렌더링 엔진에 맡길 수 있습니다.

import React, { Component } from 'react';

export default class HighlightText extends Component {
  constructor(props) {
    super(props);
    this.state = { searchText: '' };
    this.search = this.search.bind(this);
  }

  search(event) {
    this.setState({ searchText: event.target.value });
  }

  _getText(text, searchText) {
    return searchText ? this._getTextWithHighlights(text, searchText) : text;
  }

  _getTextWithHighlights(text, searchText) {
    const regex = new RegExp(searchText, 'gi');
    const newText = text.replace(regex, `<mark class="highlight">$&</mark>`);
    return <span dangerouslySetInnerHTML={{ __html: newText }} />;
  }

  render() {
    const { cite, text } = this.props;
    const { searchText } = this.state;
    const textToShow = this._getText(text, searchText);

    return (
      <div className="container">
        <div className="search-container">
          <label htmlFor="search">Search within quoted text</label>
          <input
            id="search"
            placeholder="Type `web` for example"
            type="search"
            autoComplete="off"
            onChange={this.search}
            value={searchText}
          />
        </div>
        <blockquote cite={cite}>{textToShow}</blockquote>
      </div>
    );
  }
}


(link to sandbox 그걸 가지고 놀고 싶다면)

이 구현에서 가장 중요한 행은 20행과 21행입니다. 첫 번째 행은 강조 구현의 핵심이고 두 번째 행은 요소 내에 위험한 HTML 콘텐츠를 설정했는지 확인합니다.

래핑된 검색 텍스트의 무엇이 그렇게 위험한가요?



모든 프레임워크는 원시 HTML을 화면에 표시하려는 경우 삭제해야 합니다. 여기서 우리는 내용이 괜찮다고 확신합니다. 사용자가 제공하지만 컴퓨터 외에는 표시되지 않으므로 정의상 안전합니다.

렌더링 엔진이 래핑된 요소를 표시하도록 하는 방법을 찾으려면 "html safe + framework name"을 검색하십시오.

행운을 빕니다!


편집: 원래 게시물에서 강조 표시된 텍스트를 <span> 로 래핑했습니다. 아래 댓글 덕분에 의미적으로 더 나은 <mark>로 변경했습니다🙌

좋은 웹페이지 즐겨찾기