tvolodimir
1/28/2014 - 10:59 AM

textDecorator.html

<!DOCTYPE html>
<html>
<head>
    <title>abc abcd</title>
    <script>
        function ReplaceNode(textNode, eNode) {
            textNode.parentNode.replaceChild(textNode, eNode);
        }

        function DecorateText(node, match, offset) {
            var e = document.createElement("span");
            e.style.color = "#ff0000";
            //e.textContent = match;
            e.appendChild(document.createTextNode(match));
            return e;
        }

        function replaceText(textElement, postion, length, element) {
            if (textElement.nodeType == 3) {
                var text = textElement.nodeValue;
                if (postion < 0 || (postion + length) > text.length || length < 0) {
                    return false;
                }
                var fragment = document.createDocumentFragment();

                if (postion > 0) {
                    fragment.appendChild(document.createTextNode(text.substr(0, postion)));
                }

                fragment.appendChild(element);

                if ((postion + length + 1) < text.length) {
                    fragment.appendChild(document.createTextNode(text.substr(postion + length + 1)));
                }

                textElement.parent.replaceChild(fragment, textElement);
                return fragment;
            }
            return false;
        }

        function replaceText2(textElement, postion, length, element) {
            if (textElement.nodeType == 3) {
                var text = textElement.nodeValue;
                if (postion < 0 || (postion + length) > text.length || length < 0) {
                    return false;
                }

                var newTextNode = textElement.splitText(postion);
                newTextNode.data = newTextNode.data.substr(length);

                textElement.parentNode.insertBefore(element, textElement.nextSibling);

                return newTextNode;
            }
            return false;
        }

        var matchText = function (node, regex, decorator, excludeElements) {
            excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas', 'head']);
            var child = node.firstChild;
            do {
                switch (child.nodeType) {
                    case 1:
                        if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) {
                            continue;
                        }
                        matchText(child, regex, decorator, excludeElements);
                        break;
                    case 3:
                        if (regex.test(child.data)) {
                            var globalOffset = 0;
                            child.data.replace(regex, function (all) {
                                var offset = arguments[arguments.length - 2] + globalOffset;
                                child = replaceText2(child, offset, all.length, decorator(child, all, offset));
                                globalOffset -= (offset + all.length);
                            });
                        }
                        break;
                }
            }
            while (child = child.nextSibling);

            return node;
        };

        function init() {
            matchText(document, new RegExp("\\b" + 'abc' + "\\b", "g"), DecorateText);
        }
    </script>
</head>
<body onload="init()">
<p>1 abc abcd abc 123 abc</p>

<div>
    2 abc abcd abc 123
    <div>3 abc abcd abc 123</div>
</div>
</body>
</html>