Rekovni
Rekovni

Reputation: 7344

How to search through every part of HTML

I'm trying to ignore any links in a part of HTML, and get anything that does not have a link to do my function.

What I have so far is:

$(document).ready(function() {
     // search through paragraphs
     $("p").each(function() {
          // if there is not a link
          if (!$(this).find('a').hasClass('external-link')) {
                 // do my function
          }
     })
})

My problem I am having, is that if there is a link in a line, but also something I want to capture in the same line it does not work, as it ignores the entire line.

Here is link to a working JSFiddle, which hopefully will let you see what I am trying to do.

Thank you in advance


Edit:

I may have worded the question slightly confusingly.

An example of what I am trying to achieve is:

<p>Link to ignore: <a href="http://www.bbc.co.uk" class="external-link" rel="nofollow">news</a>
Link to create: news </p>

My code would search through the <p> tags for "news", and then create a link to the website. However, I do not want to create a link on top of an existing link. My current code, would ignore everything within the <p> tags, because there is a link there already.

Upvotes: 4

Views: 150

Answers (3)

Jay Blanchard
Jay Blanchard

Reputation: 34406

I took a different approach and extended jQuery's function prototype -

$.fn.extend({
    replace: function (options) {
        var defaults = {
                search: ''
            };
        options = $.extend(defaults, options);

        return this.each(function () {
            var string = $(this).html();
            //var regex = /(search)/g;
            var regex = /(^|\s)news/;
            //var regex = new RegExp("(^|\s)" + options.search);
            console.log(regex);
            var replace_text = string.replace(regex, '<a href = "https://www.bbc.co.uk/$1">$&</a>');
            $(this).html(replace_text);
        });
    }
});


$('p').replace({search: 'news'});

EXAMPLE

$('p').replace();

Changing the regex slightly to account for a space (instead of a greater than bracket) at the beginning of 'news' allows a single neat call to the extended function. Also updated to make the function more useful, allowing the user to pass arguments to the function. Still not perfect - a work in progress.

Upvotes: 1

adeneo
adeneo

Reputation: 318162

Here's one way to ignore the anchors so you don't create new anchors inside existing anchors.
This targets the textNodes only

$(document).ready(function () {
    $("p").contents().each(function(_, node) {
        if ( node.nodeType && node.nodeType === 3 ) {
            var regex = /(news)/g;
            var value = node.nodeValue.replace(regex, '<a href="https://www.bbc.co.uk/$1">$$&</a>');
            if (value.match(regex)) {
                var wrap  = document.createElement('span');
                wrap.innerHTML = value
                node.parentNode.insertBefore(wrap, node);
                node.parentNode.removeChild(node);
            }
        }
    });
});

FIDDLE

To keep the dollarsign, you have to do $$ as the dollarsign has special meaning in a regular expression.

Upvotes: 2

scrappedcola
scrappedcola

Reputation: 10572

You could do this by looking at the childnodes of each p and grabbing the ones that do not have a class of external-link:

var otherText = [];
$("p").each(function(){
    console.log(this.childNodes);
    var kids = this.childNodes;
    for(var i = 0; i < kids.length; i++)
    {
        if(!($(kids[i]).hasClass("external-link")))
        {
            otherText.push(kids[i]); //or do what you want with the node here
        }
    }
});
console.log("other Text", otherText);

jsFiddle

Upvotes: 0

Related Questions