开发者

javascript highlighting of characters

How do you highlight (or give any special markup) special characters like ‘’“”‛‟′″˝? Thanks. Using a find and replace .innerHTML.replace() doesn't work as it ruins the event handlers and the DOM.


I've tried the following, but that just ends up with the span's in plain text instead of code.

function highlightText(node, find, rep){
    if(node){
        node= node.firstChild;
        while(node!= null){
            if(node.nodeType== 3){
                node.data= node.data.replace(find, rep);
            }
            else highlightText(node, find, rep);
            node= node.nextSibling;
        }
    }
    return true;
}

highlightText(document.body,/‘/g, "<span style='background: red; color: white;'>‘</span>")
highlightText(document.body,/’/g, "<span style='background: red; color: white;'>’</span>")
highlightText(document.body,/“/g, "<span style='background: red; color: white;'>“</span>")
highlightText(document.body,/”/g, "<span style='background: red; color: white;'>”</span>")
highlightText(document.body,/‛/g, "<span style='background: red; color: white;'>‛</span>")
highlightText(document.body,/‟/g, "<span style='background: red; color: white;'>‟</span>")
highlightText(document.body,/′/g, "<span style='background: red; color: white;'>′</span>")
highlightText(document.body,/″/g, "<span style='background: red; color: white;'&g开发者_如何学Ct;″</span>")
highlightText(document.body,/˝/g, "<span style='background: red; color: white;'>˝</span>")


Here's some code that works in all major browsers. I've posted variations of this code on Stack Overflow before (here, here and here, for example), and made it nice and generic so I (or anyone else) don't have to change it much to reuse it.

jsFiddle example: http://jsfiddle.net/eh8FE/

Code:

// Reusable generic function
function surroundInElement(el, regex, surrounderCreateFunc) {
    // script and style elements are left alone
    if (!/^(script|style)$/.test(el.tagName)) {
        var child = el.lastChild;
        while (child) {
            if (child.nodeType == 1) {
                surroundInElement(child, regex, surrounderCreateFunc);
            } else if (child.nodeType == 3) {
                surroundMatchingText(child, regex, surrounderCreateFunc);
            }
            child = child.previousSibling;
        }
    }
}

// Reusable generic function
function surroundMatchingText(textNode, regex, surrounderCreateFunc) {
    var parent = textNode.parentNode;
    var result, surroundingNode, matchedTextNode, matchLength, matchedText;
    while ( textNode && (result = regex.exec(textNode.data)) ) {
        matchedTextNode = textNode.splitText(result.index);
        matchedText = result[0];
        matchLength = matchedText.length;
        textNode = (matchedTextNode.length > matchLength) ?
            matchedTextNode.splitText(matchLength) : null;
        surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true));
        parent.insertBefore(surroundingNode, matchedTextNode);
        parent.removeChild(matchedTextNode);
    }
}

// This function does the surrounding for every matched piece of text
// and can be customized  to do what you like
function createSpan(matchedTextNode) {
    var el = document.createElement("span");
    el.style.backgroundColor = "red";
    el.style.color = "white";
    el.appendChild(matchedTextNode);
    return el;
}

// The main function
function wrapSpecialChars(container) {
    surroundInElement(container, /[‘’“”‛‟′″˝]+/, createSpan);
}

wrapSpecialChars(document.body);


The only way to change the formatting of any text in HTML is by defining the style on an HTML element that surrounds the text. So, if you want to highlight only certain characters, those characters will have to be each wrapped with an HTML element, usually a span, though you could maybe be more semantic.

So, I'm not sure what you mean by "ruins event handlers and the DOM", but you are going to have to modify the DOM to highlight characters. There is no way around that.

I understand that if you replace a whole tree of innerHTML, those nodes will be removed and then new ones will be added. However, we can't really give you alternatives without knowing what you are already dealing with.


If you really want to highlight some characters across the whole page, you have to do it non-destructively:

  1. Create a function that operates recursively
  2. Iterate over all child nodes of the node taken as a parameter
  3. If the node is an element, call self recursively with the new node
  4. If the node is a text node, replace that text node with HTML, wrapping the characters in the span you want.
  5. Call the above function with the root node of the content you want to replace.


You can use special object function for this. JQuery can help you to do it in a short way.

For example you can change styles of objects to highlight when page is loaded. There is a main idea here.

<body onload='highlight()'>
...
</body>

where

function highlightSpan( content )
{
  return "<span style='background: yellow'>" + content + "</span>";
}

function hightlight()
{
  var highlightChars = "‘’“”‛‟′″˝";
  // change body content (and highlight chars)

  var bodyContent = $( "body" ).html();

  for( var i = 0; i < highlightChars.length; i++ )
  {
     var highlightChar = highlightChars[ i ];
     bodyContent = bodyContent.replace( highlightChar, highlightSpan( highlightChar ) );
  }

  $( "body" ).html( bodyContent );

}

You can use document.getElementsByTagName( "body" )[0].innerHTML instead of $( "body" ).html().

May be replace() will replace only one matching first character. So you can use replace( /(‘|’|“|”|‛|‟|′|″)/g, highlightSpan( something ) ); instead. And solve problem with ~ which is a special regexp character.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜