Wrap tags around http text

前端 未结 3 942
感动是毒
感动是毒 2020-11-27 07:35

How do I find every word on a page beginning with http:// and wrap tags around it?

Can I use something like regex perhaps?

3条回答
  •  醉话见心
    2020-11-27 08:21

    I disagree heavily that jQuery can be much use in finding a solution here. Granted you have to get down and dirty with some of the textNode element attributes but putting the DOM back together again after you split your matched node can be made a wee bit easier using the jQuery library.

    The following code is documented inline to explain the action taken. I've written it as a jQuery plugin in case you just want to take this and move it around elsewhere. This way you can scope which elements you want to convert URLs for or you can simply use the $("body") selector.

    (function($) {
        $.fn.anchorTextUrls = function() {
            // Test a text node's contents for URLs and split and rebuild it with an achor
            var testAndTag = function(el) {
                // Test for URLs along whitespace and punctuation boundaries (don't look too hard or you will be consumed)
                var m = el.nodeValue.match(/(https?:\/\/.*?)[.!?;,]?(\s+|"|$)/);
    
                // If we've found a valid URL, m[1] contains the URL
                if (m) {
                    // Clone the text node to hold the "tail end" of the split node
                    var tail = $(el).clone()[0];
    
                    // Substring the nodeValue attribute of the text nodes based on the match boundaries
                    el.nodeValue = el.nodeValue.substring(0, el.nodeValue.indexOf(m[1]));
                    tail.nodeValue = tail.nodeValue.substring(tail.nodeValue.indexOf(m[1]) + m[1].length);
    
                    // Rebuild the DOM inserting the new anchor element between the split text nodes
                    $(el).after(tail).after($("").attr("href", m[1]).html(m[1]));
    
                    // Recurse on the new tail node to check for more URLs
                    testAndTag(tail);
                }
    
                // Behave like a function
                return false;
            }
    
            // For each element selected by jQuery
            this.each(function() {
                // Select all descendant nodes of the element and pick out only text nodes
                var textNodes = $(this).add("*", this).contents().filter(function() {
                    return this.nodeType == 3
                });
    
    
                // Take action on each text node
                $.each(textNodes, function(i, el) {
                    testAndTag(el);
                });
            });
        }
    }(jQuery));
    
    $("body").anchorTextUrls(); //Sample call
    

    Please keep in mind that given the way I wrote this to populate the textNodes array, the method will find ALL descendant text nodes, not just immediate children text nodes. If you want it to replace URLs only amongst the text within a specific selector, remove the .add("*", this) call that adds all the descendants of the selected element.

    Here's a fiddle example.

提交回复
热议问题