最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Highlight Text in textarea when a Hashtag typed followed by one or more character - Stack Overflow

programmeradmin1浏览0评论

I want to be able to let the user wile typing in the text area if he typed a hash-tag followed by one or more character as he type the text get highlighted till he hits space.

The thing is i want to achieve something like Facebook's new hash-tag feature, I've done the logic the coding but still not able to achieve it visually.

The approach i tried is by using Jquery as follows:

<textarea id="txtArea">Here is my #Hash</textarea>

$("#txtArea").onkeyup(function(){

var result = $("#txtArea").match(/ #[\w]+/g);

//result = '#Hash'
});

But i couldn't plete & i don't know where to go from here so any solution, advice, plugin that i could use i'll be very grateful.

I want to be able to let the user wile typing in the text area if he typed a hash-tag followed by one or more character as he type the text get highlighted till he hits space.

The thing is i want to achieve something like Facebook's new hash-tag feature, I've done the logic the coding but still not able to achieve it visually.

The approach i tried is by using Jquery as follows:

<textarea id="txtArea">Here is my #Hash</textarea>

$("#txtArea").onkeyup(function(){

var result = $("#txtArea").match(/ #[\w]+/g);

//result = '#Hash'
});

But i couldn't plete & i don't know where to go from here so any solution, advice, plugin that i could use i'll be very grateful.

Share Improve this question edited Aug 4, 2013 at 21:39 tereško 58.5k25 gold badges100 silver badges150 bronze badges asked Jun 22, 2013 at 21:28 Ibrahim AhmedIbrahim Ahmed 2,3454 gold badges23 silver badges35 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6

I don't believe there is any way to highlight words (other than one single highlight) within a basic textarea as it does not accept markup, you could turn the textarea into a small Rich Text editor, but that seems a little overplicated. I would probably go for similar approach to the editor here on SO, and have a preview window below so that you can see what is being marked. You could use something like this, of course you may want to change how it works a little to suit your exact needs. It should at least give you some ideas.

CSS

#preview {
    height: 2em;
    width: 12em;
    border-style: solid;
    border-width: 1px;
}
.hashSymbol {
    color: #f90;
}

HTML

<textarea id="userInput"></textarea>
<div id="preview"></div>

Javascript

/*jslint maxerr: 50, indent: 4, browser: true */

(function () {
    "use strict";

    function walkTheDOM(node, func) {
        func(node);
        node = node.firstChild;
        while (node) {
            walkTheDOM(node, func);
            node = node.nextSibling;
        }
    }

    function getTextNodes(element) {
        var nodes = [];

        walkTheDOM(element, function (node) {
            if (node.nodeType === 3) {
                nodes.push(node);
            }
        });

        return nodes;
    }

    function escapeRegex(string) {
        return string.replace(/[\[\](){}?*+\^$\\.|]/g, "\\$&");
    }

    function highlight(element, string, classname) {
        var nodes = getTextNodes(element),
            length = nodes.length,
            stringLength = string.length,
            rx = new RegExp("\\B" + escapeRegex(string)),
            i = 0,
            index,
            text,
            newContent,
            span,
            node;

        while (i < length) {
            node = nodes[i];
            newContent = document.createDocumentFragment();
            text = node.nodeValue;
            index = text.search(rx);
            while (index !== -1) {
                newContent.appendChild(document.createTextNode(text.slice(0, index)));
                text = text.slice(index + stringLength);
                span = document.createElement("span");
                span.className = classname;
                span.appendChild(document.createTextNode(string));
                newContent.appendChild(span);
                index = text.search(rx);
            }

            newContent.appendChild(document.createTextNode(text));
            node.parentNode.replaceChild(newContent, node);
            i += 1;
        }
    }

    function addEvent(elem, event, fn) {
        if (typeof elem === "string") {
            elem = document.getElementById(elem);
        }

        function listenHandler(e) {
            var ret = fn.apply(null, arguments);

            if (ret === false) {
                e.stopPropagation();
                e.preventDefault();
            }

            return ret;
        }

        function attachHandler() {
            window.event.target = window.event.srcElement;

            var ret = fn.call(elem, window.event);

            if (ret === false) {
                window.event.returnValue = false;
                window.event.cancelBubble = true;
            }

            return ret;
        }

        if (elem.addEventListener) {
            elem.addEventListener(event, listenHandler, false);
        } else {
            elem.attachEvent("on" + event, attachHandler);
        }
    }

    function emptyNode(node) {
        while (node.firstChild) {
            node.removeChild(node.firstChild);
        }
    }

    function toPreviewHighlight(e, to) {
        if (typeof to === "string") {
            to = document.getElementById(to);
        }

        var value = e.target.value,
            tags = value.match(/\B#\w+/g) || [],
            index = tags.length - 1,
            lookup = {},
            fragment,
            length,
            tag;

        while (index >= 0) {
            tag = tags[index];
            if (!tag.length || tag === "#" || tag.charAt(0) !== "#" || lookup[tag]) {
                tags.splice(index, 1);
            } else {
                lookup[tag] = true;
            }

            index -= 1;
        }

        fragment = document.createDocumentFragment();
        fragment.appendChild(document.createTextNode(value));
        index = 0;
        length = tags.length;
        while (index < length) {
            tag = tags[index];
            highlight(fragment, tag, "hashSymbol");
            index += 1;
        }

        emptyNode(to);
        to.appendChild(fragment);
    }

    addEvent("userInput", "keyup", function (e) {
        toPreviewHighlight(e, "preview");
    });
}());

On jsfiddle

This code is slightly modified from other questions and answers here on SO (resusing code is good)

if text contains '@' change color of '@'

How to extract value between # and space in textarea value

Using JavaScript, I want to use XPath to look for the presence of a string, then refresh the page based on that

发布评论

评论列表(0)

  1. 暂无评论