Оберните <a>теги вокруг текста http - PullRequest
2 голосов
/ 01 марта 2011

Как мне найти каждое слово на странице, начинающееся с http: //, и обернуть вокруг него теги?

Можно ли использовать что-то вроде регулярного выражения?

Ответы [ 3 ]

5 голосов
/ 01 марта 2011

Я сильно не согласен с тем, что jQuery может быть очень полезен при поиске решения здесь.Конечно, вам придется разбираться с некоторыми атрибутами элемента textNode, но повторное объединение DOM после разделения вашего совпавшего узла может быть упрощено с помощью библиотеки jQuery.

Следующий кодзадокументировано, чтобы объяснить предпринятые действия.Я написал его как плагин jQuery на случай, если вы просто захотите взять его и перенести в другое место.Таким образом, вы можете указать, для каких элементов вы хотите конвертировать URL-адреса, или вы можете просто использовать селектор $ ("body"). textNodes массив, метод найдет ВСЕ дочерние текстовые узлы, а не только непосредственные дочерние текстовые узлы.Если вы хотите, чтобы он заменял URL-адреса только среди текста в определенном селекторе, удалите вызов .add ("*", this), который добавляет всех потомков выбранного элемента.

Вот скрипка пример .

3 голосов
/ 01 марта 2011

Это одна из тех немногих вещей, с которыми jQuery не сильно вам помогает. В основном вам нужно пройтись по дереву DOM и изучить текстовые узлы (nodeType === 3); если вы найдете текстовый узел, содержащий целевой текст, который вы хотите обернуть («http: // .....», какие бы правила вы не хотели применить), тогда вы разделяете текстовый узел (используя splitText) на три части (часть до строки, часть, которая является строкой, и часть, которая следует за строкой), затем поместите элемент a вокруг второй из них.

Звучит немного сложно, но на самом деле все не так плохо. Это просто функция обхода рекурсивного спуска (для работы через DOM), совпадение с регулярным выражением для поиска вещей, которые вы хотите заменить, а затем пара вызовов splitText, createElement, insertBefore, appendChild.

Вот пример, который ищет фиксированную строку; просто добавьте соответствие регулярному выражению для "http://":

walk(document.body, "foo");

function walk(node, targetString) {
  var child;

  switch (node.nodeType) {
    case 1: // Element
      for (child = node.firstChild;
           child;
           child = child.nextSibling) {
        walk(child, targetString);
      }
      break;

    case 3: // Text node
      handleText(node, targetString);
      break;
  }
}

function handleText(node, targetString) {
  var start, targetNode, followingNode, wrapper;

  // Does the text contain our target string?
  // (This would be a regex test in your http://... case)
  start = node.nodeValue.indexOf(targetString);
  if (start >= 0) {
    // Split at the beginning of the match
    targetNode = node.splitText(start);

    // Split at the end of the match
    followingNode = targetNode.splitText(targetString.length);

    // Wrap the target in an element; in this case, we'll
    // use a `span` with a class, but you'd use an `a`.
    // First we create the wrapper and insert it in front
    // of the target text.
    wrapper = document.createElement('span');
    wrapper.className = "wrapper";
    targetNode.parentNode.insertBefore(wrapper, targetNode);

    // Now we move the target text inside it
    wrapper.appendChild(targetNode);

    // Clean up any empty nodes (in case the target text
    // was at the beginning or end of a text ndoe)
    if (node.nodeValue.length == 0) {
      node.parentNode.removeChild(node);
    }
    if (followingNode.nodeValue.length == 0) {
      followingNode.parentNode.removeChild(followingNode);
    }
  }
}

Живой пример


Обновление : Выше не обрабатывается, если было несколько совпадений в одном текстовом узле (doh!). И, черт возьми, я сделал регулярное выражение & mdash; Вы должны будете откорректировать регулярное выражение и, вероятно, выполнить некоторую постобработку для каждого совпадения, потому что то, что здесь слишком упрощено. Но это только начало:

// The regexp should have a capture group that
// will be the href. In our case below, we just
// make it the whole thing, but that's up to you.
// THIS REGEXP IS ALMOST CERTAINLY TOO SIMPLISTIC
// AND WILL NEED ADJUSTING (for instance: what if
// the link appears at the end of a sentence and
// it shouldn't include the ending puncutation?).
walk(document.body, /(http:\/\/[^ ]+)/i);

function walk(node, targetRe) {
  var child;

  switch (node.nodeType) {
    case 1: // Element
      for (child = node.firstChild;
           child;
           child = child.nextSibling) {
        walk(child, targetRe);
      }
      break;

    case 3: // Text node
      handleText(node, targetRe);
      break;
  }
}

function handleText(node, targetRe) {
  var match, targetNode, followingNode, wrapper;

  // Does the text contain our target string?
  // (This would be a regex test in your http://... case)
  match = targetRe.exec(node.nodeValue);
  if (match) {
    // Split at the beginning of the match
    targetNode = node.splitText(match.index);

    // Split at the end of the match.
    // match[0] is the full text that was matched.
    followingNode = targetNode.splitText(match[0].length);

    // Wrap the target in an `a` element.
    // First we create the wrapper and insert it in front
    // of the target text. We use the first capture group
    // as the `href`.
    wrapper = document.createElement('a');
    wrapper.href = match[1];
    targetNode.parentNode.insertBefore(wrapper, targetNode);

    // Now we move the target text inside it
    wrapper.appendChild(targetNode);

    // Clean up any empty nodes (in case the target text
    // was at the beginning or end of a text ndoe)
    if (node.nodeValue.length == 0) {
      node.parentNode.removeChild(node);
    }
    if (followingNode.nodeValue.length == 0) {
      followingNode.parentNode.removeChild(followingNode);
    }

    // Continue with the next match in the node, if any
    match = followingNode
      ? targetRe.exec(followingNode.nodeValue)
      : null;
  }
}

Живой пример

0 голосов
/ 01 марта 2011

Я не практически, но вы можете попробовать это

$('a([href^="http://"])').each( function(){
        //perform your task
    })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...