Using jquery or JS how do you turn a string into a link?
Asked Answered
M

9

7

So I have a piece of HTML that looks something like this...

<p>This is some copy. In this copy is the word hello</p>

I want to turn the word hello into a link using jquery.

<p>This is some copy. In this copy is the word <a href="">hello</a></p>

That in itself is not too hard. My problem is that if the word is already apart of a link like the example below...

<p>In this copy is the <a href="">word hello</a></p>

I don't want that to end up with a link within a link...

<p>In this copy is the <a href="">word <a href="">hello</a></a></p>

Any help would be much appreciated.

Mesothelium answered 10/10, 2012 at 14:3 Comment(2)
Could you not just call parent("a") on the text element and see if does not return null?Aquarist
Can you post the code you're already using?Christianity
K
3

A little regex should do the trick (Update, see below):

$(document).ready(function(){
    var needle = 'hello';
    $('p').each(function(){
        var me = $(this),
            txt = me.html(),
            found = me.find(needle).length;
        if (found != -1) {
            txt = txt.replace(/(hello)(?!.*?<\/a>)/gi, '<a href="">$1</a>');
            me.html(txt);
        }
    });
});

Fiddle: http://jsfiddle.net/G8rKw/

Edit: This version works better:

$(document).ready(function() {
    var needle = 'hello';
    $('p').each(function() {
        var me = $(this),
            txt = me.html(),
            found = me.find(needle).length;
        if (found != -1) {
            txt = txt.replace(/(hello)(?![^(<a.*?>).]*?<\/a>)/gi, '<a href="">$1</a>');
            me.html(txt);
        }
    });
});

Fiddle: http://jsfiddle.net/G8rKw/3/

Edit again: This time, "hello" is passed as a variable to the regex

$(document).ready(function() {
    var needle = 'hello';
    $('p').each(function() {
        var me = $(this),
        txt = me.html(),
        found = me.find(needle).length,
        regex = new RegExp('(' + needle + ')(?![^(<a.*?>).]*?<\/a>)','gi');
        if (found != -1) {
            txt = txt.replace(regex, '<a href="">$1</a>');
            me.html(txt);
        }
    });
});

Fiddle: http://jsfiddle.net/webrocker/MtM3s/

Keiko answered 10/10, 2012 at 16:47 Comment(3)
hm, the regex needs more refinement; if there is 'hello' in front of '<a href="">word hello</a>', it will not be replaced, since /(hello)(?!.*?<\/a>) will look for "hello" not followed by a closing </a> tag -- somehow an opening <a> tag must also be included in this expression to stop the match…Keiko
Added a 2nd version that works with the combinations of originally lined and linkless searchterms in one paragraph.Keiko
Added 3rd version, where "hello" is passed as a variable in the regex.Keiko
C
1

You can do it this way,

Live Demo

$('p').each(function(){    
    if($(this).find('a').length > 0) return;  
    lastSpaceIndex = $(this).text().lastIndexOf(' ');
    if(lastSpaceIndex  == -1)
        lastSpaceIndex = 0;    
    WordToReplace = $(this).text().substring(lastSpaceIndex);
    idx = $(this).text().lastIndexOf(WordToReplace);
    resultstring = $(this).text().substring(0, idx); 
    $(this).html(resultstring);
    $(this).append($( "<a href='#'>" + WordToReplace  + "</a>"));
});​
Cyclotron answered 10/10, 2012 at 14:23 Comment(0)
R
1

This jQuery solution searches for a particular term and doesn't create a link if it finds it's followed by a closing link tag.

var searchTerm = "hello";

$('p:contains("' + searchTerm + '")').each(function(){
    var searchString = $(this).html();
    var searchIndex = searchString.indexOf(searchTerm);
    var startString = searchString.substr(0 , searchIndex);
    var endString = searchString.substr(searchIndex + searchTerm.length);
    if(endString.match(/<\/a>/g)) return;
    $(this).html(startString + "<a href=''>" + searchTerm + "</a>" + endString);
});​

Here's a link to a jsfiddle for it.

Rayleigh answered 10/10, 2012 at 15:32 Comment(2)
Close but fails when you enclose with another word like <p>This is some copy. In this copy the word <a href="">is hello</a></p>Amatol
@Vega Changing to your example, it succeeds - because hello is followed by a closing tag, and it will return - as is desired by Paul. However, if it's <p>This is some copy. In this copy the word <a href="">hello is</a></p> it will fail. I've updated my solution so that it's able to handle that.Rayleigh
A
1

Wrote a simple function to check if the replacing text is enclosed by a link tag. See below,

DEMO: http://jsfiddle.net/wyUYb/4/

function changeToLink (sel, txt) {
   var regEx = new RegExp(txt, 'g');
   $.each($(sel), function (i, el) {
       var linkHTML = $(el).html();
       var idx = linkHTML.indexOf(txt);

       if (idx >= 0) {
           var t = linkHTML.substring(idx);
           //Fix for IE returning tag names in upper case https://mcmap.net/q/1624399/-convert-html-tag-to-lowercase
           t = t.replace(/<\/?[A-Z]+.*?>/g, function (m) { return m.toLowerCase(); })
           var closingA = t.indexOf('</a>');

           t = t.substring(0, closingA);
           if (closingA != -1) {
               t = t.substring(0, closingA); 
               if (t.indexOf('<a') < txt.length) {
                   return;
               }
           }               

           linkHTML = linkHTML.replace(regEx, '<a href="">' + txt + '</a>');
           $(el).html(linkHTML);
       }           
   });
}

Also even if you add a nested link your browser would simply change it to two links. May be because it is not legal to use nested links. See below,

Also documented in W3C for Nested Links

12.2.2 Nested links are illegal

Links and anchors defined by the A element must not be nested; an A element must not contain any other A elements.

Since the DTD defines the LINK element to be empty, LINK elements may not be nested either.

And that is why browser handles nested link as separate links.

http://jsfiddle.net/H44jE/

See the firebug inspect on right bottom of the image.

enter image description here

Amatol answered 10/10, 2012 at 15:32 Comment(0)
E
0

Can you not test for the parent element of the word before turning it into a link?

if (parent != 'a') {
   // do your thing
}

(I don't know what the actual jQuery would be to test this)

EDIT

The following will replace the word in all <p> elements that DO NOT contain a link in them.

May not work exactly as required but hopefully points you in the direction

// get all p elements that contain the word hello but DO NOT have link in them
var elems = $('p:contains("hello")').not(':has(a)');


// replace instances of hello in the selected p elements
$(elems).html($(elems).html().replace(/(hello)/g,'<a href="new">$1</a>'));

Live Demo on JSBin

Eng answered 10/10, 2012 at 14:7 Comment(1)
That is my problem, I don't know the actual jquery either. Because you are selecting a string (the word Hello) rather than a dom element, I don't know how you check its immediate parent.Mesothelium
P
0

Try to user .replace jquery function something like this:

var str = $('p').html().replace('(some)','(to some)');
Poinsettia answered 10/10, 2012 at 14:8 Comment(0)
W
0

You need the jquery :not selector, or .not().

The API docs cover this well, you should be able to select your content, then deselect links within it.

http://api.jquery.com/not-selector/

Whaling answered 10/10, 2012 at 14:21 Comment(0)
S
0

Instead of searching for the word and trying to find its parent, search for the link and check the word it contains:

if($('a').text() === "hello"){
  //already linked
}else{
  //not linked
}
Shaylynn answered 10/10, 2012 at 14:24 Comment(0)
S
0

First keep the words while getting rid of the current anchor tag, if there is one:

$('a').each(function() {
    $(this).replaceWith(this.childNodes);
 });

Then do a replace on the string that you need to work with

$('p').html($('p').text().replace('hello', '<a href="">hello</a>'));
Spock answered 10/10, 2012 at 15:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.