2009-11-21 1 views
0

J'ai converti html en une chaîne, je suis capable d'utiliser replace dans cette chaîne pour envelopper le texte avec un lien, et je peux remettre ce code HTML dans l'ID d'origine.Comment rechercher/remplacer du texte avec un wrapper "a href" en JavaScript?

Mon problème est que ma méthode de remplacement va à l'intérieur liens existants sur la page. Cela pourrait créer des liens imbriqués, ce qui est un problème. Est-ce que quelqu'un sait comment empêcher la méthode de remplacer le texte qui est déjà dans un lien?

J'ai en ce moment:

keyword = "matching phrase"; 
keywordLink = "<a href='http://myurl.com'/>" + keyword + "</a>"; 
sasser = sasser.replace(keyword, keywordLink); 
sasDom.innerHTML = sasser; 

Je cherche, dans le code pseudo:

... (keyword [if the next " < " sign is not followed by "/a>", regardless of how far away it is], keywordLink); 

Répondre

2

Vous ne pouvez pas faire ce genre de chose avec regex du tout. Travailler sur les objets de document qui sont déjà bien analysés dans une structure pour vous.

Voici un éditeur de mots-clés adapté de this question.

// Find text in descendents of an element, in reverse document order 
// pattern must be a regexp with global flag 
// 
function findTextExceptInLinks(element, pattern, callback) { 
    for (var childi= element.childNodes.length; childi-->0;) { 
     var child= element.childNodes[childi]; 
     if (child.nodeType===1) { 
      if (child.tagName.toLowerCase()!=='a') 
       findTextExceptInLinks(child, pattern, callback); 
     } else if (child.nodeType===3) { 
      var matches= []; 
      var match; 
      while (match= pattern.exec(child.data)) 
       matches.push(match); 
      for (var i= matches.length; i-->0;) 
       callback.call(window, child, matches[i]); 
     } 
    } 
} 

findTextExceptInLinks(document.body, /\bmatching phrase\b/g, function(node, match) { 
    node.splitText(match.index+match[0].length); 
    var a= document.createElement('a'); 
    a.href= 'http://www.example.com/myurl'; 
    a.appendChild(node.splitText(match.index)); 
    node.parentNode.insertBefore(a, node.nextSibling); 
}); 

eta re commentaires: Voici une version de la même chose en utilisant la correspondance de texte brut plutôt que regex:

function findPlainTextExceptInLinks(element, substring, callback) { 
    for (var childi= element.childNodes.length; childi-->0;) { 
     var child= element.childNodes[childi]; 
     if (child.nodeType===1) { 
      if (child.tagName.toLowerCase()!=='a') 
       findPlainTextExceptInLinks(child, substring, callback); 
     } else if (child.nodeType===3) { 
      var index= child.data.length; 
      while (true) { 
       index= child.data.lastIndexOf(substring, index); 
       if (index===-1) 
        break; 
       callback.call(window, child, index) 
      } 
     } 
    } 
} 

var substring= 'matching phrase'; 
findPlainTextExceptInLinks(document.body, substring, function(node, index) { 
    node.splitText(index+substring.length); 
    var a= document.createElement('a'); 
    a.href= 'http://www.example.com/myurl'; 
    a.appendChild(node.splitText(index)); 
    node.parentNode.insertBefore(a, node.nextSibling); 
}); 
+0

Bobince - merci beaucoup! Cette solution est fantastique, et j'apprécie grandement que vous preniez le temps de l'afficher. J'ai un problème relativement simple maintenant ... Je n'arrive pas à utiliser une variable comme expression correspondante. Voici ce que j'essaie: findTextExceptInLinks (document.body, "/ \ b" + variable + "\ b/g", fonction (noeud, correspondance) { – Matrym

+0

findTextExceptInLinks (document.body, "/ \ b" + variable + "\ b/g", fonction (noeud, correspondance) { – Matrym

+0

@google: essayez de passer 'new RegExp ('\\ b' + variable + '\\ b', 'g')' –

1

Si vous ne me dérange pas en utilisant JQuery, vous pouvez utiliser sa fonction wrap() pour envelopper éléments texte ou html dans les balises spécifiées.

+0

Est-ce que le travail pour envelopper seulement une partie du texte à l'intérieur des balises, aussi? – Franz

+0

En y réfléchissant, cela ne vous empêchera probablement pas d'avoir des balises de lien imbriquées, ou le sera-t-il? – Franz

0

je le ferais en trois étapes:

1) avec <a [^>]+>matching phrase</a> remplacer $1some_other_phrase</a>

2) remplacer matching phrase avec <a...>keyword</a>

3) remplacer some_other_phrase avec matching phrase