자바 스크립트를 사용하여 텍스트를 강조 표시하는 방법


98

누군가가 웹 페이지의 텍스트를 강조 할 수있는 자바 스크립트 기능으로 나를 도울 수 있습니까? 그리고 요구 사항은-한 번만 강조 표시하는 것입니다. 검색의 경우처럼 텍스트의 모든 항목을 강조 표시하는 것과는 다릅니다.


4
함수의 코드를 게시하면 도움을 드릴 수 있습니다. 그러한 기능을 생성 해달라고 요청하면 ... 그럴 가능성이 적습니다. 스스로 무언가를해야합니다. 무언가를 시작하고 막히면 돌아 오십시오.
Felix Kling 2011

7
YEs 나는 How to Ask를 읽었고 스스로 뭔가를했지만 막혔고 그것이 내가 물은 이유입니다. 저는 Android에서 작업하고 javasript에 대한 지식이 거의 없기 때문에 혼자서 할 수 없습니다. 이전에는 작업을 수행했지만 특정 제한 없이는 다른 자바 스크립트를 사용하고있었습니다. 이 질문을 할 때 올바른 단어를 사용하지 않았을 수 있으며 죄송하지만 다른 생각은하지 마십시오.
Ankit 2011

1
이 플러그인은 github.com/julmot/jmHighlight 입니다. 키워드를 개별적으로 또는 용어로 강조 표시 할 수 있으며 사용자 정의 요소 및 클래스 이름과 일치하는 것을 강조 표시 할 수 있으며 분음 부호를 검색 할 수도 있습니다. 맨 위에 일치를 검색 할 컨텍스트를 필터링 할 수 있습니다.
친구

1
체크 아웃 다음 정규식 방법 ... stackoverflow.com/a/45519242/2792959

나는 여기에에 관한 기사를 준비 exhesham.com/2017/11/20/...
헤샴 야신

답변:


101

jquery 강조 효과를 사용할 수 있습니다 .

그러나 원시 자바 스크립트 코드에 관심이 있으시면 제가 얻은 것을 살펴보십시오. HTML에 붙여 넣기를 복사하고 파일을 열고 "강조 표시"를 클릭하십시오. 그러면 "fox"라는 단어가 강조 표시됩니다. 성능면에서는 이것이 작은 텍스트와 한 번의 반복 (지정한 것처럼)에 대해 할 것이라고 생각합니다.

function highlight(text) {
  var inputText = document.getElementById("inputText");
  var innerHTML = inputText.innerHTML;
  var index = innerHTML.indexOf(text);
  if (index >= 0) { 
   innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
   inputText.innerHTML = innerHTML;
  }
}
.highlight {
  background-color: yellow;
}
<button onclick="highlight('fox')">Highlight</button>

<div id="inputText">
  The fox went over the fence
</div>

편집 :

사용 replace

나는이 답변이 인기를 얻었음을 알았습니다. 쉽게 교체 할 수 있습니다.

"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");

또는 여러 번 발생하는 경우 (질문과 관련이 없지만 주석으로 요청 됨) global교체 정규식에 추가하기 만하면 됩니다.

"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");

호기심 많은 댓글 작성자에게 도움이되기를 바랍니다.

HTML을 전체 웹 페이지로 대체

전체 웹 페이지의 HTML을 대체하려면 innerHTML문서 본문을 참조해야합니다 .

document.body.innerHTML


답장을 보내 주셔서 감사 많은하지만 당신은 자바 스크립트 자체에 색상을 지정하는 방법을 말해 줄 수
ANKIT

당신은 대체 할 수 "<span class='highlight'>""<span style='color: " + color + ";'>"같은 색이어야 뭔가var color = "#ff0000";
Yaniro

@guy mograbi
Naqvi

4
간단한 "교체"를 사용하는 것은 나쁜 생각 입니다. 나는 여기에 그 이유를 설명했다 : stackoverflow.com/a/32758672/3894981
dude

2
이것은 HTML 태그 / 속성 등을 강조하기 때문에 좋은 생각이 아닙니다. 예를 들어 <img src="fox.jpg" /> 다음과 같은 경우에 어떤 일이 발생 <img src="<span class='highlight'>fox</span>.jpg" />
합니까?

47

여기에 제공된 솔루션은 매우 나쁩니다.

  1. 정규식을 사용할 수 없습니다. 그렇게하면 html 태그에서 검색 / 강조 표시하기 때문입니다.
  2. 정규식은 UTF * (비 라틴 / 영어 문자가있는 모든 것)에서 제대로 작동하지 않기 때문에 사용할 수 없습니다.
  3. innerHTML.replace를 수행 할 수 없습니다. 문자에 특수 HTML 표기법이있을 때 작동하지 않기 때문입니다 (예 : &amp;for & &lt;, &gt;for>, &auml;for >, for ä, &ouml;for ö &uuml;for ü &szlig;for ß 등).

해야 할 일 :

루프가 HTML 문서를 통해 얻을 모든 텍스트 노드를 찾을 수 textContent와 하이라이트 텍스트의 위치를 얻을 수 indexOf(선택 사양으로 toLowerCase는 대소 문자를 구분해야하는 경우)하기 전에, APPEND 모든 것을 indexof같은 textNode, APPEND 하이라이트 범위와 일치하는 텍스트, 나머지 텍스트 노드에 대해 반복합니다 (강조 문자열은 textContent문자열 에서 여러 번 나타날 수 있음 ).

이에 대한 코드는 다음과 같습니다.

var InstantSearch = {

    "highlight": function (container, highlightText)
    {
        var internalHighlighter = function (options)
        {

            var id = {
                container: "container",
                tokens: "tokens",
                all: "all",
                token: "token",
                className: "className",
                sensitiveSearch: "sensitiveSearch"
            },
            tokens = options[id.tokens],
            allClassName = options[id.all][id.className],
            allSensitiveSearch = options[id.all][id.sensitiveSearch];


            function checkAndReplace(node, tokenArr, classNameAll, sensitiveSearchAll)
            {
                var nodeVal = node.nodeValue, parentNode = node.parentNode,
                    i, j, curToken, myToken, myClassName, mySensitiveSearch,
                    finalClassName, finalSensitiveSearch,
                    foundIndex, begin, matched, end,
                    textNode, span, isFirst;

                for (i = 0, j = tokenArr.length; i < j; i++)
                {
                    curToken = tokenArr[i];
                    myToken = curToken[id.token];
                    myClassName = curToken[id.className];
                    mySensitiveSearch = curToken[id.sensitiveSearch];

                    finalClassName = (classNameAll ? myClassName + " " + classNameAll : myClassName);

                    finalSensitiveSearch = (typeof sensitiveSearchAll !== "undefined" ? sensitiveSearchAll : mySensitiveSearch);

                    isFirst = true;
                    while (true)
                    {
                        if (finalSensitiveSearch)
                            foundIndex = nodeVal.indexOf(myToken);
                        else
                            foundIndex = nodeVal.toLowerCase().indexOf(myToken.toLowerCase());

                        if (foundIndex < 0)
                        {
                            if (isFirst)
                                break;

                            if (nodeVal)
                            {
                                textNode = document.createTextNode(nodeVal);
                                parentNode.insertBefore(textNode, node);
                            } // End if (nodeVal)

                            parentNode.removeChild(node);
                            break;
                        } // End if (foundIndex < 0)

                        isFirst = false;


                        begin = nodeVal.substring(0, foundIndex);
                        matched = nodeVal.substr(foundIndex, myToken.length);

                        if (begin)
                        {
                            textNode = document.createTextNode(begin);
                            parentNode.insertBefore(textNode, node);
                        } // End if (begin)

                        span = document.createElement("span");
                        span.className += finalClassName;
                        span.appendChild(document.createTextNode(matched));
                        parentNode.insertBefore(span, node);

                        nodeVal = nodeVal.substring(foundIndex + myToken.length);
                    } // Whend

                } // Next i 
            }; // End Function checkAndReplace 

            function iterator(p)
            {
                if (p === null) return;

                var children = Array.prototype.slice.call(p.childNodes), i, cur;

                if (children.length)
                {
                    for (i = 0; i < children.length; i++)
                    {
                        cur = children[i];
                        if (cur.nodeType === 3)
                        {
                            checkAndReplace(cur, tokens, allClassName, allSensitiveSearch);
                        }
                        else if (cur.nodeType === 1)
                        {
                            iterator(cur);
                        }
                    }
                }
            }; // End Function iterator

            iterator(options[id.container]);
        } // End Function highlighter
        ;


        internalHighlighter(
            {
                container: container
                , all:
                    {
                        className: "highlighter"
                    }
                , tokens: [
                    {
                        token: highlightText
                        , className: "highlight"
                        , sensitiveSearch: false
                    }
                ]
            }
        ); // End Call internalHighlighter 

    } // End Function highlight

};

그런 다음 다음과 같이 사용할 수 있습니다.

function TestTextHighlighting(highlightText)
{
    var container = document.getElementById("testDocument");
    InstantSearch.highlight(container, highlightText);
}

다음은 HTML 문서의 예입니다.

<!DOCTYPE html>
<html>
    <head>
        <title>Example of Text Highlight</title>
        <style type="text/css" media="screen">
            .highlight{ background: #D3E18A;}
            .light{ background-color: yellow;}
        </style>
    </head>
    <body>
        <div id="testDocument">
            This is a test
            <span> This is another test</span>
            äöüÄÖÜäöüÄÖÜ
            <span>Test123&auml;&ouml;&uuml;&Auml;&Ouml;&Uuml;</span>
        </div>
    </body>
</html>

그건 그렇고, 당신이 데이터베이스에서 검색하는 경우 LIKE,
예를 들어, WHERE textField LIKE CONCAT('%', @query, '%')[당신이, 당신은 전체 텍스트 검색 또는 루씬을 사용해야하지 말아야한다, 당신은, 그런 식으로 모든 문자를 이스케이프 \ 및 SQL-탈출 문을 추가 할 수 있습니다 LIKE 표현식 인 특수 문자를 찾을 수 있습니다.

예 :

WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'

및 @query의 값이 아닌 '%completed%'하지만'%\c\o\m\p\l\e\t\e\d%'

(테스트 완료, SQL-Server 및 PostgreSQL 및 ESCAPE를 지원하는 다른 모든 RDBMS 시스템에서 작동)


수정 된 typescript 버전 :

namespace SearchTools 
{


    export interface IToken
    {
        token: string;
        className: string;
        sensitiveSearch: boolean;
    }


    export class InstantSearch 
    {

        protected m_container: Node;
        protected m_defaultClassName: string;
        protected m_defaultCaseSensitivity: boolean;
        protected m_highlightTokens: IToken[];


        constructor(container: Node, tokens: IToken[], defaultClassName?: string, defaultCaseSensitivity?: boolean)
        {
            this.iterator = this.iterator.bind(this);
            this.checkAndReplace = this.checkAndReplace.bind(this);
            this.highlight = this.highlight.bind(this);
            this.highlightNode = this.highlightNode.bind(this);    

            this.m_container = container;
            this.m_defaultClassName = defaultClassName || "highlight";
            this.m_defaultCaseSensitivity = defaultCaseSensitivity || false;
            this.m_highlightTokens = tokens || [{
                token: "test",
                className: this.m_defaultClassName,
                sensitiveSearch: this.m_defaultCaseSensitivity
            }];
        }


        protected checkAndReplace(node: Node)
        {
            let nodeVal: string = node.nodeValue;
            let parentNode: Node = node.parentNode;
            let textNode: Text = null;

            for (let i = 0, j = this.m_highlightTokens.length; i < j; i++)
            {
                let curToken: IToken = this.m_highlightTokens[i];
                let textToHighlight: string = curToken.token;
                let highlightClassName: string = curToken.className || this.m_defaultClassName;
                let caseSensitive: boolean = curToken.sensitiveSearch || this.m_defaultCaseSensitivity;

                let isFirst: boolean = true;
                while (true)
                {
                    let foundIndex: number = caseSensitive ?
                        nodeVal.indexOf(textToHighlight)
                        : nodeVal.toLowerCase().indexOf(textToHighlight.toLowerCase());

                    if (foundIndex < 0)
                    {
                        if (isFirst)
                            break;

                        if (nodeVal)
                        {
                            textNode = document.createTextNode(nodeVal);
                            parentNode.insertBefore(textNode, node);
                        } // End if (nodeVal)

                        parentNode.removeChild(node);
                        break;
                    } // End if (foundIndex < 0)

                    isFirst = false;


                    let begin: string = nodeVal.substring(0, foundIndex);
                    let matched: string = nodeVal.substr(foundIndex, textToHighlight.length);

                    if (begin)
                    {
                        textNode = document.createTextNode(begin);
                        parentNode.insertBefore(textNode, node);
                    } // End if (begin)

                    let span: HTMLSpanElement = document.createElement("span");

                    if (!span.classList.contains(highlightClassName))
                        span.classList.add(highlightClassName);

                    span.appendChild(document.createTextNode(matched));
                    parentNode.insertBefore(span, node);

                    nodeVal = nodeVal.substring(foundIndex + textToHighlight.length);
                } // Whend

            } // Next i 

        } // End Sub checkAndReplace 


        protected iterator(p: Node)
        {
            if (p == null)
                return;

            let children: Node[] = Array.prototype.slice.call(p.childNodes);

            if (children.length)
            {
                for (let i = 0; i < children.length; i++)
                {
                    let cur: Node = children[i];

                    // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
                    if (cur.nodeType === Node.TEXT_NODE) 
                    {
                        this.checkAndReplace(cur);
                    }
                    else if (cur.nodeType === Node.ELEMENT_NODE) 
                    {
                        this.iterator(cur);
                    }
                } // Next i 

            } // End if (children.length) 

        } // End Sub iterator


        public highlightNode(n:Node)
        {
            this.iterator(n);
        } // End Sub highlight 


        public highlight()
        {
            this.iterator(this.m_container);
        } // End Sub highlight 


    } // End Class InstantSearch 


} // End Namespace SearchTools 

용법:

let searchText = document.getElementById("txtSearchText");
let searchContainer = document.body; // document.getElementById("someTable");
let highlighter = new SearchTools.InstantSearch(searchContainer, [
    {
        token: "this is the text to highlight" // searchText.value,
        className: "highlight", // this is the individual highlight class
        sensitiveSearch: false
    }
]);


// highlighter.highlight(); // this would highlight in the entire table
// foreach tr - for each td2 
highlighter.highlightNode(td2); // this highlights in the second column of table

훌륭한 대답 .. 방법은 과잉처럼 보이지만 간결합니다! 내 경우에는 결과가 DOM에 지연로드 되므로 (수천 개의 결과 가있을 있으므로) 해당 방법으로 속도 테스트를 수행하는 데 확실히 관심 이있을 것입니다.이 방법이 지연로드에 높은 지연 시간을 추가하는지 궁금합니다.
Pogrindis

5
죄송합니다. 귀하의 주장 중 어느 것도 사실이 아닙니다. 1. 절대적으로 RegExp를 사용할 수 있습니다. HTML 값이 아닌 요소의 텍스트 값을 검색해야합니다. 2. mark.js에 구현 된대로 분음 부호 문자와 함께 RegExp를 절대적으로 사용할 수 있습니다 . 3. HTML 표기법은 브라우저 DOM에서 실제 문자로 변환되므로 절대적으로 사용하십시오!
친구

1
@julmot; To 1 : 즉, 모든 요소를 ​​반복해야한다는 의미입니다. 바로 제가하는 일입니다. 서식을 잃어 버리는 것에 신경 쓰지 않는 한, document.body.innerText에서 검색 할 수 있습니다. 이것은 상당히 느릴 것입니다. 3. DOM이 아니라 텍스트 요소의 innerText 또는 textContent 속성에 있습니다. 다시 말하면 텍스트 요소를 반복해야 함을 의미합니다. regEx AFAIK로는 할 수 없습니다. 2 : mark.js를 모르지만 jQuery.each를 수행하는 모든 것을 피할 것입니다.
Stefan Steiger

1
@StefanSteiger 1. 그런 다음 RegExp로 검색 할 수 없다고 말한 것처럼 결정 관계를 수정해야합니다. 이것은 사실이 아닙니다. 2. jQuery.each를 사용하지 않습니다. 그렇게 생각하는 이유는 무엇입니까? 3. 이것은 적어도 Firefox에서는 사실이 아닙니다. &auml;예를 들어를 사용하는 경우에도 실제 문자로 변환됩니다 innerHTML.
dude

1
안녕하세요 @StefanSteiger 사실 저는 귀하의 솔루션을 사용하고 있습니다. 이것은 완벽합니다. 그러나 두 개의 스팬이 있고 하나의 스팬에는 Diploma MSBTE와 같은 데이터가 있고 두 번째 스팬에는 데이터 2012가있는 P In이있는 경우와 같은 몇 가지 문제가 있습니다. 이제 강조하려는 문자열이 Diploma MSBTE 2012 인 경우이 전체 문자열이 작동하지 않는지 확인했습니다. 일치하는 모든 것이 한 범위에 있으면 작동하지만 텍스트 내용이 diff 태그에 있으면 작동하지 않습니다. 이것에 대해 말씀해 주시겠습니까?
ganeshk

41

직접 만든 하이라이트 기능을 사용하는 것이 나쁜 생각 인 이유

처음부터 자신 만의 하이라이트 기능을 구축하는 것이 좋지 않은 이유는 다른 사람들이 이미 해결 한 문제에 부딪 힐 것이기 때문입니다. 과제 :

  • DOM 이벤트를 파괴하지 않고 DOM 재생성을 반복하지 않고 일치를 강조하기 위해 HTML 요소가있는 텍스트 노드를 제거해야합니다 (예 :이 경우 innerHTML).
  • 강조 표시된 요소를 제거하려면 콘텐츠와 함께 HTML 요소를 제거하고 추가 검색을 위해 분할 된 텍스트 노드를 결합해야합니다. 이는 모든 하이 라이터 플러그인이 텍스트 노드 내부에서 일치 항목을 검색하고 키워드가 여러 텍스트 노드로 분할되면 찾을 수 없기 때문에 필요합니다.
  • 또한 생각하지 않은 상황에서 플러그인이 작동하는지 확인하기 위해 테스트를 빌드해야합니다. 그리고 저는 브라우저 간 테스트에 대해 이야기하고 있습니다!

복잡하게 들리나요? 강조 표시, 분음 부호 매핑, 동의어 매핑, iframe 내부 검색, 분리 된 단어 검색 등에서 일부 요소를 무시하는 것과 같은 일부 기능을 원하는 경우 이는 점점 더 복잡해집니다.

기존 플러그인 사용

잘 구현 된 기존 플러그인을 사용할 때 위에 언급 된 것에 대해 걱정할 필요가 없습니다. Sitepoint 의 기사 10 jQuery 텍스트 하이 라이터 플러그인은 인기있는 하이 라이터 플러그인 을 비교합니다.

mark.js 살펴보기

mark.js 는 순수한 JavaScript로 작성된 플러그인이지만 jQuery 플러그인으로도 사용할 수 있습니다. 다음과 같은 옵션이있는 다른 플러그인보다 더 많은 기회를 제공하도록 개발되었습니다.

  • 전체 용어 대신 개별적으로 키워드 검색
  • 지도 분음 부호 (예 : "justo"가 "justò"와 일치해야하는 경우)
  • 맞춤 요소 내 일치 무시
  • 맞춤 강조 표시 요소 사용
  • 사용자 지정 강조 표시 클래스 사용
  • 맞춤 동의어 매핑
  • iframe 내에서도 검색
  • 찾을 수없는 용어 받기

데모

또는 이 바이올린을 볼 수 있습니다 .

사용 예 :

// Highlight "keyword" in the specified context
$(".context").mark("keyword");

// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);

GitHub에서 무료로 개발 된 오픈 소스입니다 ( 프로젝트 참조 ).


4
텍스트를 강조하는 것만으로는 jQuery를 포함시킬 충분한 이유가 아닙니다.
Roy

10
@Roy 나는 이것을 마음에 새겼다. 좋은 소식은 v6.0.0부터 mark.js 는 jQuery 종속성을 포기하고 이제 선택적으로 jQuery 플러그인으로 사용할 수 있도록합니다.
dude

다음을 제외하고는 모두 사실입니다. 등록 된 이벤트 핸들러를 가져올 수 없기 때문에 첫 번째 지점은 불가능하며, 가능하더라도 익명 함수를 설정할 수 없습니다 ... 두 번째 : mark.js는 두 태그 사이의 텍스트도 찾지 못합니다. <span> s </ span> ed가 sed를 찾지 못합니다 ... 셋째 : 아직 테스트하지 않은 브라우저 (새 버전 포함)가 나올 때마다 중단 될 수 있습니다. 얼마나 많은 테스트를 작성하더라도 항상 사실입니다. 17kb에서는 마크가 너무 큽니다.
Stefan Steiger 2018 년

@StefanSteiger를 언급하는 점은 무엇입니까? 그 정보 없이는 첫 번째 요점까지 말할 수 없습니다. 그러나 두 번째 주석은 잘못되었습니다. mark.js는 acrossElements옵션을 사용하여 태그간에 일치하는 항목을 찾을 수 있습니다 . 그리고 세 번째 주석에; mark.js는 제공하는 기능에 비해 크지 않습니다. 그리고 아니요, mark.js가 예를 들어 Chrome 30을 시작하고 크로스 브라우저 단위 테스트가있는 모든 최신 버전에서 테스트되었으므로 향후 버전에 문제가 없었기 때문에 미래에 문제가 발생할 가능성은 거의 없습니다.
친구

@dude : 첫 단락 뒤의 세 가지 요점. 아, 좋아, 내가 본 데모에서 그 옵션이 누락되었습니다. 이 경우 이해가 될 수 있습니다. 하지만 그래도 너무 큽니다.
Stefan Steiger

10
function stylizeHighlightedString() {

    var text = window.getSelection();

    // For diagnostics
    var start = text.anchorOffset;
    var end = text.focusOffset - text.anchorOffset;

    range = window.getSelection().getRangeAt(0);

    var selectionContents = range.extractContents();
    var span = document.createElement("span");

    span.appendChild(selectionContents);

    span.style.backgroundColor = "yellow";
    span.style.color = "black";

    range.insertNode(span);
}

3
Mohit, SO에 오신 것을 환영합니다. 코드에 대한 설명이 좋을 것입니다!
Nippey

다른 노드를 만들지 않고 텍스트를 선택하는 방법이 있어야하지 않습니까?
Dave Gregory

@ user191433 질문은 텍스트를 선택하는 것뿐만 아니라 스타일을 적용하는 것입니다. 이를 위해서는 노드가 필요합니다.
Christophe

자바 스크립트 span.style.backgroundColor = "yellow";가 CSS로 번역 된다는 알림 / 팁 style="background-color: yellow;"-camelCase와 점선 표기법의 미묘한 차이가 처음에는 나를 괴롭 혔습니다.
MarkHu

1
stackoverflow.com/questions/7991474/… 에있는 PS Mohit의 답변 은이 코드의보다 간소화 된 변형입니다. (예를 들어 여기서는 진단 / 비 기능인 시작 및 종료 변수를 생략합니다.)
MarkHu

7

다음은 내 정규식 순수 JavaScript 솔루션입니다.

function highlight(text) {
    document.body.innerHTML = document.body.innerHTML.replace(
        new RegExp(text + '(?!([^<]+)?<)', 'gi'),
        '<b style="background-color:#ff0;font-size:100%">$&</b>'
    );
}

강조 표시하려는 텍스트 블록에 HTML 태그가 포함되어있을 때 이것은 완벽하게 작동합니다.
John Chapman

정규식 파이프 기호를 통해 여러 단어를 받아들이도록 함수를 조정할 수도 있습니다. 예one|two|three
Klemen Tušar

텍스트 끝에 문자가 있으면 텍스트를 대체하지 않습니다 >. (?!([^<]+)?<)작동 하도록 정규식을 수정하십시오 .
Archie Reyes

요청에 따라 수정되었습니다.
Klemen Tušar

완전한! 이것은 나를 위해 최고
마르코 burrometo

5

xmlhttp 요청을 통해 많은 텍스트가 들어옵니다. 이 텍스트는 html 형식입니다. 나는 모든 사건을 강조해야한다.

str='<img src="brown fox.jpg" title="The brown fox" />'
    +'<p>some text containing fox.</p>'

문제는 태그에서 텍스트를 강조 표시 할 필요가 없다는 것입니다. 예를 들어 여우를 강조해야합니다.

이제 다음으로 바꿀 수 있습니다.

var word="fox";
word="(\\b"+ 
    word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
        + "\\b)";
var r = new RegExp(word,"igm");
str.replace(r,"<span class='hl'>$1</span>")

질문에 대답하려면 regexp 옵션에서 g를 생략하고 첫 번째 항목 만 대체되지만 여전히 img src 속성에있는 항목이며 이미지 태그를 파괴합니다.

<img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span 
class='hl'>fox</span> />

이것이 내가 해결 한 방법이지만 정규 표현식에서 놓친 더 좋은 방법이 있는지 궁금합니다.

str='<img src="brown fox.jpg" title="The brown fox" />'
    +'<p>some text containing fox.</p>'
var word="fox";
word="(\\b"+ 
    word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
    + "\\b)";
var r = new RegExp(word,"igm");
str.replace(/(>[^<]+<)/igm,function(a){
    return a.replace(r,"<span class='hl'>$1</span>");
});

이것은 <img src="word">또는 <a href="word">.
yvesmancera 2015 년

1
황금률 : 절대로. 사용하다. 정규병. 식. 에. 음식물. 약. 와. XML.
ScottMcGready

5

다른 솔루션 중 어느 것도 내 요구 사항에 맞지 않으며 Stefan Steiger의 솔루션이 예상대로 작동했지만 너무 장황했습니다.

다음은 내 시도입니다.

/**
 * Highlight keywords inside a DOM element
 * @param {string} elem Element to search for keywords in
 * @param {string[]} keywords Keywords to highlight
 * @param {boolean} caseSensitive Differenciate between capital and lowercase letters
 * @param {string} cls Class to apply to the highlighted keyword
 */
function highlight(elem, keywords, caseSensitive = false, cls = 'highlight') {
  const flags = caseSensitive ? 'gi' : 'g';
  // Sort longer matches first to avoid
  // highlighting keywords within keywords.
  keywords.sort((a, b) => b.length - a.length);
  Array.from(elem.childNodes).forEach(child => {
    const keywordRegex = RegExp(keywords.join('|'), flags);
    if (child.nodeType !== 3) { // not a text node
      highlight(child, keywords, caseSensitive, cls);
    } else if (keywordRegex.test(child.textContent)) {
      const frag = document.createDocumentFragment();
      let lastIdx = 0;
      child.textContent.replace(keywordRegex, (match, idx) => {
        const part = document.createTextNode(child.textContent.slice(lastIdx, idx));
        const highlighted = document.createElement('span');
        highlighted.textContent = match;
        highlighted.classList.add(cls);
        frag.appendChild(part);
        frag.appendChild(highlighted);
        lastIdx = idx + match.length;
      });
      const end = document.createTextNode(child.textContent.slice(lastIdx));
      frag.appendChild(end);
      child.parentNode.replaceChild(frag, child);
    }
  });
}

// Highlight all keywords found in the page
highlight(document.body, ['lorem', 'amet', 'autem']);
.highlight {
  background: lightpink;
}
<p>Hello world lorem ipsum dolor sit amet, consectetur adipisicing elit. Est vel accusantium totam, ipsum delectus et dignissimos mollitia!</p>
<p>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam, corporis.
  <small>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium autem voluptas perferendis dolores ducimus velit error voluptatem, qui rerum modi?</small>
</p>

또한 키워드에 정규식 에서 이스케이프해야하는 특수 문자가있을 수있는 경우 escape-string-regexp 와 같은 것을 사용하는 것이 좋습니다 .

const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);

이것은 나를 위해 잘 작동했지만 "표시를 해제"하는 방법도 필요합니다.
jwzumwalt

4

간단한 TypeScript 예제

참고 : 많은 부분에서 @Stefan에 동의하지만 간단한 일치 강조 표시 만 필요했습니다 .

module myApp.Search {
    'use strict';

    export class Utils {
        private static regexFlags = 'gi';
        private static wrapper = 'mark';

        private static wrap(match: string): string {
            return '<' + Utils.wrapper + '>' + match + '</' + Utils.wrapper + '>';
        }

        static highlightSearchTerm(term: string, searchResult: string): string {
            let regex = new RegExp(term, Utils.regexFlags);

            return searchResult.replace(regex, match => Utils.wrap(match));
        }
    }
}

그리고 실제 결과를 구성합니다.

module myApp.Search {
    'use strict';

    export class SearchResult {
        id: string;
        title: string;

        constructor(result, term?: string) {
            this.id = result.id;
            this.title = term ? Utils.highlightSearchTerm(term, result.title) : result.title;
        }
    }
}

3

HTML5부터는 <mark></mark>태그를 사용하여 텍스트를 강조 할 수 있습니다 . 자바 스크립트를 사용하여 이러한 태그 사이에 일부 텍스트 / 키워드를 래핑 할 수 있습니다. 다음은 텍스트를 표시하고 표시 해제하는 방법에 대한 간단한 예입니다.

JSFIDDLE 데모


innerHTML위험합니다. 이벤트를 삭제합니다.
친구

2
예를 들어 JSFIDDLE "Lorem"을 입력하면 첫 번째 인스턴스 만 표시되기 때문에이 방법도 제대로 작동하지 않습니다.
agm1984

1
키워드의 모든 항목을 바꾸면됩니다. 여기 정규식 세계적으로 예입니다 jsfiddle.net/de5q704L/73는
카스퍼 Taeymans

2

2019 년으로 빠르게 진행되는 Web API는 이제 기본적으로 텍스트 강조 표시를 지원합니다.

const selection = document.getSelection();
selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);

그리고 당신은 갈 수 있습니다! anchorNode선택 시작 노드이고 focusNode선택 종료 노드입니다. 그리고 텍스트 노드 인 offset경우 각 노드에서 시작 및 끝 문자의 인덱스입니다. 다음은 문서입니다.

라이브 데모 도 있습니다.


오 이거 훌륭 해요. 다음과 같이 사용하면됩니다. selection.setBaseAndExtent (desiredNode, 0, desiredNode, 1); 필요한 유일한 노드를 강조 표시합니다. 그리고 그것은 Gutenberg와 함께 작동합니다
tonyAndr

1

나도, 당신은 내가 배운 것을 시도 할 수 있는지 궁금 게시 할 수 있습니다.

나는 사용했다 :

function highlightSelection() {
			var userSelection = window.getSelection();
			for(var i = 0; i < userSelection.rangeCount; i++) {
				highlightRange(userSelection.getRangeAt(i));
			}
			
		}
			
			function highlightRange(range) {
			    var newNode = document.createElement("span");
			    newNode.setAttribute(
			       "style",
			       "background-color: yellow; display: inline;"
			    );
			    range.surroundContents(newNode);
			}
<html>
	<body contextmenu="mymenu">

		<menu type="context" id="mymenu">
			<menuitem label="Highlight Yellow" onclick="highlightSelection()" icon="/images/comment_icon.gif"></menuitem>
		</menu>
		<p>this is text, select and right click to high light me! if you can`t see the option, please use this<button onclick="highlightSelection()">button </button><p>

http://henriquedonati.com/projects/Extension/extension.html에서 시도해 볼 수도 있습니다.

xc


0

페이지로드시 강조 표시되도록하려면 새로운 방법이 있습니다.

그냥 추가 #:~:text=Highlight%20These

이 링크에 액세스하십시오

/programming/38588721#:~:text=Highlight%20a%20text


-1

범위 유형 에 서라운드 컨텐츠 () 메소드 사용 . 유일한 인수는 해당 Range를 래핑하는 요소입니다.

function styleSelected() {
  bg = document.createElement("span");
  bg.style.backgroundColor = "yellow";
  window.getSelection().getRangeAt(0).surroundContents(bg);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.